From a4d1bae9f0dbd1b4cc3ecfac1be88c55faa610df Mon Sep 17 00:00:00 2001 From: el Date: Thu, 26 Jun 2025 20:28:59 +0200 Subject: [PATCH] Transition google-generativeai pour google-genai --- backend/services/ai_service.py | 77 ++++++++++++++-------------------- 1 file changed, 31 insertions(+), 46 deletions(-) diff --git a/backend/services/ai_service.py b/backend/services/ai_service.py index 9f854dd..8d9e8b7 100644 --- a/backend/services/ai_service.py +++ b/backend/services/ai_service.py @@ -3,8 +3,9 @@ import logging import sys from typing import Optional, Dict, Any -# MODIFIÉ ICI: Supprime 'from google.genai import types' car types.GenerateContentConfig n'est plus utilisé de cette manière -import google.generativeai as genai +# MODIFIÉ ICI: Importations pour google-genai +from google import genai +from google.genai import types # Nécessaire pour configurer les types comme GenerateContentConfig import mistralai from mistralai.client import MistralClient @@ -28,53 +29,38 @@ try: except Exception as e: logger.error(f"Error during mistralai debug info collection: {e}") -# --- Configuration globale du client Gemini (Ce bloc est maintenant supprimé car la configuration est faite via GenerativeModel) --- -# Vous pouvez retirer ce bloc si vous l'aviez : -# if settings.LLM_PROVIDER == "gemini" and settings.GEMINI_API_KEY: -# try: -# genai.configure( -# api_key=settings.GEMINI_API_KEY, -# client_options={"api_endpoint": "generativelanguage.googleapis.com"} -# ) -# logger.info("GenAI client globally configured with API endpoint.") -# except Exception as e: -# logger.error(f"Erreur lors de la configuration globale de GenAI: {e}") - class AIService: def __init__(self): self.provider = settings.LLM_PROVIDER self.model_name = settings.GEMINI_MODEL_NAME if self.provider == "gemini" else settings.MISTRAL_MODEL_NAME - self.raw_safety_settings = [ - {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"}, - {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"}, - {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"}, - {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"}, - ] - - self.raw_generation_config = { - "temperature": 0.7, - "top_p": 1, - "top_k": 1, - } - if self.provider == "gemini": try: - # MODIFICATION CRUCIALE ICI : On initialise directement le GenerativeModel - # genai.Client() et types.GenerateContentConfig ne sont plus utilisés directement ici - self.model = genai.GenerativeModel( - model_name=self.model_name, - safety_settings=self.raw_safety_settings, # Passez safety_settings ici - generation_config=self.raw_generation_config # Passez generation_config ici - # La clé API est lue automatiquement depuis GEMINI_API_KEY si elle est configurée. - # Ou vous pouvez la passer explicitement: api_key=settings.GEMINI_API_KEY + # Initialisation du client genai.Client() + self.client = genai.Client( + api_key=settings.GEMINI_API_KEY ) - logger.info(f"Modèle Gemini GenerativeModel initialisé avec modèle : {self.model_name}") + logger.info(f"Client Gemini genai.Client() initialisé.") + + # Configuration de la génération avec types.GenerateContentConfig + self.gemini_config = types.GenerateContentConfig( + temperature=0.7, + top_p=1.0, + top_k=1, + safety_settings=[ + types.SafetySetting(category="HARM_CATEGORY_HARASSMENT", threshold="BLOCK_NONE"), + types.SafetySetting(category="HARM_CATEGORY_HATE_SPEECH", threshold="BLOCK_NONE"), + types.SafetySetting(category="HARM_CATEGORY_SEXUALLY_EXPLICIT", threshold="BLOCK_NONE"), + types.SafetySetting(category="HARM_CATEGORY_DANGEROUS_CONTENT", threshold="BLOCK_NONE"), + ] + ) + logger.info(f"Configuration Gemini types.GenerateContentConfig créée.") + except Exception as e: - logger.error(f"Erreur d'initialisation du modèle Gemini: {e}") - raise ValueError(f"Impossible d'initialiser le modèle Gemini. Vérifiez votre GEMINI_API_KEY et le nom du modèle. Erreur: {e}") + logger.error(f"Erreur d'initialisation du client Gemini: {e}") + raise ValueError(f"Impossible d'initialiser le client Gemini. Vérifiez votre GEMINI_API_KEY. Erreur: {e}") elif self.provider == "mistral": if not settings.MISTRAL_API_KEY: @@ -117,15 +103,14 @@ class AIService: response_content = "" if self.provider == "gemini": try: - contents = [ - {"role": "user", "parts": [{"text": prompt}]} - ] - - # MODIFIÉ ICI : 'contents' est maintenant passé comme argument positionnel direct à generate_content + # MODIFIÉ ICI: Utilisation d'une lambda pour envelopper l'appel à generate_content + # avec tous ses arguments, pour que run_sync reçoive une fonction sans arguments supplémentaires response = await anyio.to_thread.run_sync( - self.model.generate_content, - contents, # <-- Correction pour l'erreur "unexpected keyword argument 'contents'" - # Les configurations (température, safety_settings) sont déjà définies lors de l'initialisation de self.model + lambda: self.client.models.generate_content( + model=self.model_name, + contents=[{"role": "user", "parts": [{"text": prompt}]}], + config=self.gemini_config, + ) ) response_content = response.text