Fix: Gemini API modernization, dynamic model selection, and config path corrections
This commit is contained in:
157
helpers.py
157
helpers.py
@@ -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
|
||||
Reference in New Issue
Block a user