Fix: Gemini API modernization, dynamic model selection, and config path corrections

This commit is contained in:
2026-01-03 12:19:51 +00:00
parent 932adb6a99
commit f91f9a2e82
6 changed files with 233 additions and 75 deletions

View File

@@ -56,9 +56,15 @@ try:
import google.genai as genai
HAS_GEMINI = True
except ImportError:
HAS_GEMINI = False
genai = None # Sicherstellen, dass genai definiert ist
logging.warning("google-genai Bibliothek nicht gefunden. KI-Funktionen deaktiviert.")
try:
# Fallback auf die ältere Bibliothek, falls die neue nicht da ist
import google.generativeai as genai
HAS_GEMINI = True
logging.warning("Veraltetes Paket 'google.generativeai' wird verwendet. Bitte auf 'google-genai' aktualisieren.")
except ImportError:
HAS_GEMINI = False
genai = None # Sicherstellen, dass genai definiert ist
logging.warning("Keine Google-KI-Bibliothek (weder google.genai noch google.generativeai) gefunden.")
# OpenAI Imports entfernen wir oder machen sie optional, um Verwirrung zu vermeiden
try:
@@ -320,50 +326,99 @@ def _get_gemini_api_key():
logger.error("CRITICAL: No API Key found in Config.API_KEYS or environment variables.")
raise ValueError("API Key missing.")
# Cache für den ermittelten Modellnamen, um API-Aufrufe zu sparen
_CACHED_MODEL_NAME = None
def _get_best_flash_model(api_key):
"""
Ermittelt dynamisch das beste verfügbare Flash-Modell.
Versucht, 'gemini-1.5-flash' zu finden, oder fällt auf Alternativen zurück.
"""
global _CACHED_MODEL_NAME
if _CACHED_MODEL_NAME:
return _CACHED_MODEL_NAME
logger = logging.getLogger(__name__)
default_model = "gemini-1.5-flash"
try:
if not HAS_GEMINI:
return default_model
genai.configure(api_key=api_key)
# Liste alle Modelle auf
models = list(genai.list_models())
flash_models = [m.name for m in models if 'flash' in m.name.lower() and 'generateContent' in m.supported_generation_methods]
# Bereinige die Namen (entferne 'models/' Präfix für den Vergleich, falls nötig)
clean_flash_models = [m.replace('models/', '') for m in flash_models]
logger.info(f"Gefundene Flash-Modelle: {clean_flash_models}")
# Priorisierung
if "gemini-1.5-flash" in clean_flash_models:
_CACHED_MODEL_NAME = "gemini-1.5-flash"
elif "gemini-1.5-flash-latest" in clean_flash_models:
_CACHED_MODEL_NAME = "gemini-1.5-flash-latest"
elif "gemini-1.5-flash-001" in clean_flash_models:
_CACHED_MODEL_NAME = "gemini-1.5-flash-001"
elif clean_flash_models:
_CACHED_MODEL_NAME = clean_flash_models[0] # Nimm das erste verfügbare
else:
logger.warning("Kein 'Flash'-Modell gefunden. Versuche Fallback auf 'gemini-pro'.")
pro_models = [m.name for m in models if 'pro' in m.name.lower() and 'generateContent' in m.supported_generation_methods]
if pro_models:
_CACHED_MODEL_NAME = pro_models[0].replace('models/', '')
else:
_CACHED_MODEL_NAME = default_model
logger.info(f"Ausgewähltes Gemini-Modell: {_CACHED_MODEL_NAME}")
return _CACHED_MODEL_NAME
except Exception as e:
logger.error(f"Fehler beim Ermitteln des Modells: {e}. Verwende Standard: {default_model}")
return default_model
@retry_on_failure
def call_gemini_flash(prompt, system_instruction=None, temperature=0.3, json_mode=False):
"""
Spezifische Funktion für Gemini 1.5 Flash Aufrufe mit System-Instruction Support.
Aktualisiert für die neue 'google-genai' Bibliothek (v1.0+).
Verwendet die korrekte `GenerativeModel` API.
"""
logger = logging.getLogger(__name__)
if not HAS_GEMINI:
logger.error("Fehler: google-genai Bibliothek fehlt.")
raise ImportError("google-genai not installed.")
logger.error("Fehler: google-generativeai Bibliothek fehlt.")
raise ImportError("google-generativeai not installed.")
api_key = _get_gemini_api_key()
try:
# NEU: Client-basierte Instanziierung für google-genai v1.0+
client = genai.Client(api_key=api_key)
# Konfiguration für den Aufruf
config = {
genai.configure(api_key=api_key)
generation_config = {
"temperature": temperature,
"top_p": 0.95,
"top_k": 40,
"max_output_tokens": 8192,
}
if json_mode:
config["response_mime_type"] = "application/json"
generation_config["response_mime_type"] = "application/json"
# Verwende eine spezifische Version, die oft stabiler ist
model_id = "gemini-1.5-flash-001"
# Dynamische Modell-Ermittlung
model_name = _get_best_flash_model(api_key)
response = client.models.generate_content(
model=model_id,
contents=prompt,
config=genai.types.GenerateContentConfig(
temperature=temperature,
top_p=0.95,
top_k=40,
max_output_tokens=8192,
response_mime_type="application/json" if json_mode else "text/plain",
system_instruction=system_instruction
)
model = genai.GenerativeModel(
model_name=model_name,
generation_config=generation_config,
system_instruction=system_instruction
)
# Der Prompt kann ein String oder eine Liste von Teilen sein
contents = [prompt] if isinstance(prompt, str) else prompt
response = model.generate_content(contents)
return response.text.strip()
@@ -376,42 +431,16 @@ def call_gemini_flash(prompt, system_instruction=None, temperature=0.3, json_mod
@retry_on_failure
def call_openai_chat(prompt, temperature=0.3, model=None, response_format_json=False):
"""
Zentrale Funktion fuer KI API Aufrufe (jetzt Gemini via google-genai Client).
Zentrale Funktion fuer KI API Aufrufe (jetzt Gemini).
Leitet an `call_gemini_flash` weiter, um Code-Duplizierung zu vermeiden.
"""
logger = logging.getLogger(__name__)
# Lade Gemini API Key
api_key = _get_gemini_api_key()
if not HAS_GEMINI:
logger.error("Fehler: google-genai Bibliothek fehlt.")
raise ImportError("google-genai not installed.")
try:
# NEU: Client Instanziierung
client = genai.Client(api_key=api_key)
model_id = "gemini-1.5-flash-001"
response = client.models.generate_content(
model=model_id,
contents=prompt,
config=genai.types.GenerateContentConfig(
temperature=temperature,
top_p=0.95,
top_k=40,
max_output_tokens=8192,
response_mime_type="application/json" if response_format_json else "text/plain"
)
)
return response.text.strip()
except Exception as e:
logger.error(f"Fehler beim Gemini-Aufruf: {e}")
# Wenn der Key falsch ist, werfen wir einen lesbaren Fehler
if "API_KEY_INVALID" in str(e) or "403" in str(e):
raise ValueError(f"Invalid API Key: {str(e)}")
raise e
# Das 'model' Argument wird ignoriert, da wir jetzt fest auf Gemini Flash setzen.
return call_gemini_flash(
prompt=prompt,
temperature=temperature,
json_mode=response_format_json,
system_instruction=None # Alte Signatur hatte keine System-Instruction
)
# ... (Rest der Funktionen wie summarize_website_content bleiben, rufen aber jetzt die neue call_openai_chat auf)
def summarize_website_content(raw_text, company_name): return "k.A." # Placeholder
@@ -477,4 +506,4 @@ def scrape_website_details(url):
logger.error(f"Unerwarteter Fehler beim Parsen der URL {url}: {e}")
return "Fehler: Ein unerwarteter Fehler ist beim Verarbeiten der Website aufgetreten."
def is_valid_wikipedia_article_url(url): return False # Placeholder
def alignment_demo(sheet_handler): pass # Placeholder
def alignment_demo(sheet_handler): pass # Placeholder