-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
import os
from flask import Flask, render_template_string, request, jsonify
import requests
import time
app = Flask(name)
--- Configuration ---
Note: In this environment, the API key is handled automatically.
We initialize it as an empty string for the request logic.
API_KEY = ""
MODEL_NAME = "gemini-2.5-flash-preview-09-2025"
API_URL = f"https://generativelanguage.googleapis.com/v1beta/models/{MODEL_NAME}:generateContent?key={API_KEY}"
--- HTML Template (Embedded for Single-File Portability) ---
HTML_TEMPLATE = """
<title>AI Assistant</title> <script src="https://cdn.tailwindcss.com"></script> <style> .chat-container { height: calc(100vh - 160px); } .message-bubble { max-width: 80%; word-wrap: break-word; } ::-webkit-scrollbar { width: 6px; } ::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 10px; } </style>Gemini Flask AI
Online <!-- Chat Window -->
<div class="bg-white rounded-2xl shadow-xl overflow-hidden border border-slate-200">
<div id="chat-window" class="chat-container overflow-y-auto p-4 space-y-4">
<!-- Welcome Message -->
<div class="flex justify-start">
<div class="message-bubble bg-slate-100 text-slate-800 p-4 rounded-2xl rounded-tl-none shadow-sm">
Hello! I'm your AI assistant powered by Flask and Gemini. How can I help you today?
</div>
</div>
</div>
<!-- Input Area -->
<div class="p-4 border-t border-slate-100 bg-white">
<form id="chat-form" class="flex gap-2">
<input
type="text"
id="user-input"
placeholder="Type your message..."
class="flex-1 p-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-all"
autocomplete="off"
>
<button
type="submit"
id="send-btn"
class="bg-indigo-600 text-white px-6 py-3 rounded-xl font-medium hover:bg-indigo-700 transition-colors disabled:opacity-50"
>
Send
</button>
</form>
</div>
</div>
</div>
<script>
const chatWindow = document.getElementById('chat-window');
const chatForm = document.getElementById('chat-form');
const userInput = document.getElementById('user-input');
const sendBtn = document.getElementById('send-btn');
function appendMessage(text, isUser) {
const wrapper = document.createElement('div');
wrapper.className = `flex ${isUser ? 'justify-end' : 'justify-start'}`;
const bubble = document.createElement('div');
bubble.className = `message-bubble p-4 rounded-2xl shadow-sm ${
isUser
? 'bg-indigo-600 text-white rounded-tr-none'
: 'bg-slate-100 text-slate-800 rounded-tl-none'
}`;
bubble.innerText = text;
wrapper.appendChild(bubble);
chatWindow.appendChild(wrapper);
chatWindow.scrollTop = chatWindow.scrollHeight;
}
chatForm.onsubmit = async (e) => {
e.preventDefault();
const message = userInput.value.trim();
if (!message) return;
// Update UI
appendMessage(message, true);
userInput.value = '';
userInput.disabled = true;
sendBtn.disabled = true;
// Fetch AI Response
try {
const response = await fetch('/ask', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message })
});
const data = await response.json();
if (data.error) {
appendMessage("Error: " + data.error, false);
} else {
appendMessage(data.response, false);
}
} catch (err) {
appendMessage("Failed to connect to server.", false);
} finally {
userInput.disabled = false;
sendBtn.disabled = false;
userInput.focus();
}
};
</script>
--- Helper Function: Call Gemini API ---
def call_gemini_api(prompt):
payload = {
"contents": [{
"parts": [{"text": prompt}]
}],
"systemInstruction": {
"parts": [{"text": "You are a helpful, concise AI assistant integrated into a Flask web application."}]
}
}
# Implement exponential backoff for reliability
retries = 5
for i in range(retries):
try:
response = requests.post(API_URL, json=payload)
response.raise_for_status()
data = response.json()
return data.get('candidates', [{}])[0].get('content', {}).get('parts', [{}])[0].get('text', "No response.")
except Exception:
if i == retries - 1:
return "I'm having trouble connecting to my brain right now. Please try again later."
time.sleep(2 ** i)
return "Something went wrong."
--- Routes ---
@app.route('/')
def home():
return render_template_string(HTML_TEMPLATE)
@app.route('/ask', methods=['POST'])
def ask():
user_data = request.json
user_message = user_data.get('message', '')
if not user_message:
return jsonify({"error": "Empty message"}), 400
ai_response = call_gemini_api(user_message)
return jsonify({"response": ai_response})
if name == 'main':
# Setting host to 0.0.0.0 makes it accessible on the local network
app.run(debug=True, port=5000)