Spaces:
Running
Running
from flask import Flask, render_template, request, jsonify, Response, stream_with_context | |
from google import genai | |
from google.genai import types | |
import os | |
from PIL import Image | |
import io | |
import base64 | |
import json | |
import logging | |
# Configuration du logging | |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') | |
logger = logging.getLogger(__name__) | |
app = Flask(__name__) | |
# Récupération de la clé API depuis les variables d'environnement | |
GOOGLE_API_KEY = os.environ.get("GEMINI_API_KEY") | |
if not GOOGLE_API_KEY: | |
logger.error("La clé API Gemini n'est pas configurée dans les variables d'environnement") | |
# Initialisation du client Gemini | |
try: | |
client = genai.Client(api_key=GOOGLE_API_KEY) | |
except Exception as e: | |
logger.error(f"Erreur lors de l'initialisation du client Gemini: {e}") | |
def index(): | |
return render_template('index.html') | |
def maintenance(): | |
return render_template('maj.html') | |
def process_image(image_data): | |
"""Traite l'image et retourne sa représentation base64""" | |
try: | |
img = Image.open(io.BytesIO(image_data)) | |
buffered = io.BytesIO() | |
img.save(buffered, format="PNG") | |
img_str = base64.b64encode(buffered.getvalue()).decode() | |
return img_str | |
except Exception as e: | |
logger.error(f"Erreur lors du traitement de l'image: {e}") | |
raise | |
def stream_gemini_response(model_name, image_str, thinking_budget=None): | |
"""Génère et diffuse la réponse du modèle Gemini""" | |
mode = 'starting' | |
config_kwargs = {} | |
if thinking_budget: | |
config_kwargs["thinking_config"] = types.ThinkingConfig(thinking_budget=thinking_budget) | |
try: | |
response = client.models.generate_content_stream( | |
model=model_name, | |
contents=[ | |
{'inline_data': {'mime_type': 'image/png', 'data': image_str}}, | |
"Résous ça en français with rendering latex" | |
], | |
config=types.GenerateContentConfig(**config_kwargs) | |
) | |
for chunk in response: | |
if not hasattr(chunk, 'candidates') or not chunk.candidates: | |
continue | |
for part in chunk.candidates[0].content.parts: | |
if hasattr(part, 'thought') and part.thought: | |
if mode != "thinking": | |
yield f'data: {json.dumps({"mode": "thinking"})}\n\n' | |
mode = "thinking" | |
else: | |
if mode != "answering": | |
yield f'data: {json.dumps({"mode": "answering"})}\n\n' | |
mode = "answering" | |
if hasattr(part, 'text') and part.text: | |
yield f'data: {json.dumps({"content": part.text})}\n\n' | |
except Exception as e: | |
logger.error(f"Erreur pendant la génération avec le modèle {model_name}: {e}") | |
yield f'data: {json.dumps({"error": str(e)})}\n\n' | |
def solve(): | |
"""Endpoint utilisant le modèle Pro avec capacité de réflexion étendue""" | |
if 'image' not in request.files: | |
return jsonify({'error': 'Aucune image fournie'}), 400 | |
try: | |
image_data = request.files['image'].read() | |
img_str = process_image(image_data) | |
return Response( | |
stream_with_context(stream_gemini_response( | |
model_name="gemini-2.5-pro-exp-03-25", | |
image_str=img_str, | |
thinking_budget=8000 | |
)), | |
mimetype='text/event-stream', | |
headers={ | |
'Cache-Control': 'no-cache', | |
'X-Accel-Buffering': 'no' | |
} | |
) | |
except Exception as e: | |
logger.error(f"Erreur dans /solve: {e}") | |
return jsonify({'error': str(e)}), 500 | |
def solved(): | |
"""Endpoint utilisant le modèle Flash (plus rapide)""" | |
if 'image' not in request.files: | |
return jsonify({'error': 'Aucune image fournie'}), 400 | |
try: | |
image_data = request.files['image'].read() | |
img_str = process_image(image_data) | |
return Response( | |
stream_with_context(stream_gemini_response( | |
model_name="gemini-2.5-flash-preview-04-17", | |
image_str=img_str | |
)), | |
mimetype='text/event-stream', | |
headers={ | |
'Cache-Control': 'no-cache', | |
'X-Accel-Buffering': 'no' | |
} | |
) | |
except Exception as e: | |
logger.error(f"Erreur dans /solved: {e}") | |
return jsonify({'error': str(e)}), 500 | |
if __name__ == '__main__': | |
# En production, modifiez ces paramètres | |
app.run(host='0.0.0.0', port=5000, debug=False) |