ErnestMind_2.5 / model_handler.py
ernestmindres's picture
Update model_handler.py
fe280ca verified
import os
import sys
import json
from google import genai
from google.genai.errors import APIError
# Importation de genai.types.Part pour construire la partie fichier
from google.genai.types import Part
from config import GEMINI_API_KEY_INTERNAL, GEMINI_MODEL_NAME, DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE
# --- Configuration du Client Gemini ---
# Le prompt système (System Instruction) pour guider le modèle
SYSTEM_PROMPT = "Vous êtes un assistant IA appler Ernestmind et tu as ete entrener pas l'entreprise ErnestMind AI, expert en programmation, développement web (full-stack), et résolution de problèmes techniques. Répondez de manière concise, précise et professionnelle selon la langue utilisateur, en utilisant la mise en forme Markdown appropriée (blocs de code si nécessaire)."
# Instance du client et indicateur de chargement
client = None
MODEL_LOADED_SUCCESSFULLY = False
def get_model_instance():
"""
Initialise ou retourne l'instance du client Gemini.
"""
global client, MODEL_LOADED_SUCCESSFULLY
if client is None:
try:
# Utilisation de la clé interne pour initialiser le client
client = genai.Client(api_key=GEMINI_API_KEY_INTERNAL)
MODEL_LOADED_SUCCESSFULLY = True
print(f"INFO: Client Gemini initialisé. Modèle configuré pour utiliser {GEMINI_MODEL_NAME}.")
except Exception as e:
print(f"ALERTE: Échec de l'initialisation du client Gemini: {e}", file=sys.stderr)
MODEL_LOADED_SUCCESSFULLY = False
return client
# Initialisation du client lors du chargement du module
get_model_instance()
def generate_code_response(prompt: str, user_id: str, file_data: tuple[bytes, str] | None = None, max_tokens: int = DEFAULT_MAX_TOKENS, temperature: float = DEFAULT_TEMPERATURE):
"""
Génère une réponse en streaming en utilisant l'API Gemini, supportant le multimodal.
file_data est un tuple (contenu_binaire: bytes, mime_type: str) ou None.
"""
if not MODEL_LOADED_SUCCESSFULLY or client is None:
yield "Erreur: La clé API Gemini est manquante ou invalide. Le service est désactivé."
return
# Configuration de la requête
config = {
"systemInstruction": SYSTEM_PROMPT,
"temperature": temperature,
"maxOutputTokens": max_tokens,
}
# --- Construction du contenu multimodal ---
contents = []
if file_data:
file_bytes, mime_type = file_data
# Créer la partie fichier pour l'API Gemini
try:
file_part = Part.from_bytes(data=file_bytes, mime_type=mime_type)
contents.append(file_part)
except Exception as e:
# Si la création de la 'Part' échoue (ex: format non supporté)
error_message = f"Erreur de traitement du fichier: {str(e)}. Le fichier n'a pas été envoyé au modèle."
print(f"Erreur Fichier (user_id: {user_id}): {error_message}", file=sys.stderr)
# On laisse le prompt texte passer, mais on log l'erreur
# Ajouter le prompt texte
contents.append({"role": "user", "parts": [{"text": prompt}]})
# Sécurité: le contenu ne doit pas être vide
if not contents:
yield "Erreur: Le contenu de la requête (prompt ou fichier) est vide."
return
try:
# --- Appel à l'API STREAMING ---
response_stream = client.models.generate_content_stream(
model=GEMINI_MODEL_NAME,
contents=contents, # Contents contient maintenant le fichier et le texte
config=config,
)
# Itérer sur le flux et retourner chaque morceau de texte (token)
for chunk in response_stream:
if chunk.text:
yield chunk.text
except APIError as e:
error_message = f"Erreur de l'API Gemini: {e.message}"
print(f"Erreur API (user_id: {user_id}): {error_message}", file=sys.stderr)
yield f"Erreur: {error_message}"
except Exception as e:
error_message = f"Erreur de streaming inattendue: {str(e)}"
print(f"Erreur Inattendue (user_id: {user_id}): {error_message}", file=sys.stderr)
yield f"Erreur: {error_message}"