File size: 4,238 Bytes
b94d46c
 
561d3ee
 
 
fe280ca
 
b94d46c
 
561d3ee
b94d46c
 
b706914
b94d46c
561d3ee
 
 
 
b94d46c
 
561d3ee
b94d46c
561d3ee
 
 
 
 
 
 
 
 
 
 
 
 
 
b94d46c
 
fe280ca
b94d46c
fe280ca
 
b94d46c
561d3ee
 
 
b94d46c
561d3ee
 
 
 
 
b94d46c
 
fe280ca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561d3ee
b94d46c
561d3ee
 
 
fe280ca
561d3ee
 
b94d46c
561d3ee
 
 
 
b94d46c
561d3ee
 
 
 
 
b94d46c
561d3ee
 
fe280ca
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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}"