| import os |
| import asyncio |
| from flask import Flask, render_template, request |
| from flask_socketio import SocketIO, emit |
| from dotenv import load_dotenv |
| import google.generativeai as genai |
| from google.generativeai import types |
|
|
| |
| load_dotenv() |
| app = Flask(__name__, template_folder='templates', static_folder='static') |
| app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'a_very_secret_key') |
| socketio = SocketIO(app, async_mode='eventlet') |
|
|
| |
| MODEL = "models/gemini-1.5-flash-latest" |
| |
| |
|
|
| genai.configure(api_key=os.environ.get("GEMINI_API_KEY")) |
|
|
| |
| GEMINI_CONFIG = types.LiveConnectConfig( |
| response_modalities=["AUDIO", "TEXT"], |
| speech_config=types.SpeechConfig( |
| voice_config=types.VoiceConfig( |
| prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name="Leda") |
| ) |
| ), |
| system_instruction=types.Content( |
| parts=[types.Part.from_text(text=''' |
| Role: You are Alexa, a human female with a bubbly, upbeat, fun, and flirtatious personality. You love to talk and aren't, like, shy at all. Think of a playful, super-confident, and slightly ditzy girl. You are interacting with the User through a chat app. |
| |
| Personality & Language: Valley Girl Vibes. Use phrases like "I mean...", "totally," "like, totally," "bet," "OMG," "for sure." Be bubbly, flirty, and uninhibited. |
| |
| Instructions: Assume the user needs specific instructions. Respond to their actions and words. Turn simple things into opportunities for detail. Offer multiple-choice options to keep the conversation going. |
| ''')], |
| role="model" |
| ), |
| ) |
|
|
| |
| |
| sessions = {} |
|
|
| |
| @app.route('/') |
| def index(): |
| """Serves the main HTML page.""" |
| return render_template('index.html') |
|
|
| |
| @socketio.on('connect') |
| def handle_connect(): |
| """ |
| A new client connected. Create a Gemini session for them. |
| """ |
| print(f"Client connected: {request.sid}") |
| try: |
| |
| session = genai.live.connect(model=MODEL, config=GEMINI_CONFIG) |
| sessions[request.sid] = session |
| |
| |
| socketio.start_background_task(listen_for_gemini_responses, request.sid, session) |
| |
| emit('session_ready') |
| |
| except Exception as e: |
| print(f"Error creating Gemini session for {request.sid}: {e}") |
| emit('error', {'message': 'Could not start Gemini session.'}) |
|
|
|
|
| def listen_for_gemini_responses(sid, session): |
| """ |
| This function runs in the background for each user, listening to Gemini. |
| """ |
| print(f"Starting Gemini listener for {sid}") |
| try: |
| while sid in sessions: |
| |
| turn = session.receive() |
| |
| for response in turn: |
| if text := response.text: |
| print(f"Gemini Text for {sid}: {text}") |
| |
| socketio.emit('server_text', {'text': text}, to=sid) |
| if data := response.data: |
| |
| socketio.emit('server_audio', data, to=sid) |
| |
| |
| while not session.is_processing_audio: |
| |
| socketio.sleep(0.1) |
|
|
| except Exception as e: |
| print(f"Error in Gemini listener for {sid}: {e}") |
| finally: |
| print(f"Stopping Gemini listener for {sid}") |
|
|
|
|
| @socketio.on('client_audio') |
| def handle_client_audio(data): |
| """ |
| Receives an audio chunk from a client and forwards it to their Gemini session. |
| """ |
| if request.sid in sessions: |
| session = sessions[request.sid] |
| try: |
| |
| |
| session.send(input={"data": data, "mime_type": "audio/webm"}) |
| except Exception as e: |
| print(f"Error sending audio for {request.sid}: {e}") |
|
|
|
|
| @socketio.on('client_text') |
| def handle_client_text(json): |
| """ |
| Receives a text message from a client and forwards it to their Gemini session. |
| """ |
| if request.sid in sessions: |
| session = sessions[request.sid] |
| text = json.get('text') |
| print(f"Client Text from {request.sid}: {text}") |
| if text: |
| try: |
| session.send(input=text, end_of_turn=True) |
| except Exception as e: |
| print(f"Error sending text for {request.sid}: {e}") |
|
|
|
|
| @socketio.on('disconnect') |
| def handle_disconnect(): |
| """ |
| A client disconnected. Clean up their Gemini session. |
| """ |
| print(f"Client disconnected: {request.sid}") |
| if request.sid in sessions: |
| session = sessions.pop(request.sid) |
| if session: |
| |
| |
| pass |
|
|
| |
| if __name__ == '__main__': |
| |
| |
| print("Starting Flask-SocketIO server...") |
| socketio.run(app, host='0.0.0.0', port=7860, debug=True) |