import os import logging import random import time from functools import wraps # --- KI UMSCHALTUNG: Google Generative AI (Dual Support) --- # This is a simplified, self-contained version for the transcription tool. HAS_NEW_GENAI = False HAS_OLD_GENAI = False # 1. New library (google-genai) try: from google import genai from google.genai import types HAS_NEW_GENAI = True logging.info("Library 'google.genai' (v1.0+) loaded.") except ImportError: logging.warning("Library 'google.genai' not found. Trying fallback.") # 2. Old library (google-generativeai) try: import google.generativeai as old_genai HAS_OLD_GENAI = True logging.info("Library 'google.generativeai' (Legacy) loaded.") except ImportError: logging.warning("Library 'google.generativeai' not found.") HAS_GEMINI = HAS_NEW_GENAI or HAS_OLD_GENAI # A simple retry decorator, as the global one is not available def retry_on_failure(func): @wraps(func) def wrapper(*args, **kwargs): max_retries = 3 base_delay = 5 for attempt in range(max_retries): try: if attempt > 0: logging.warning(f"Retrying attempt {attempt + 1}/{max_retries} for '{func.__name__}'...") return func(*args, **kwargs) except Exception as e: if attempt < max_retries - 1: wait_time = base_delay * (2 ** attempt) + random.uniform(0, 1) time.sleep(wait_time) else: raise e return wrapper def _get_gemini_api_key(): """Gets the Gemini API key from environment variables.""" api_key = os.environ.get("GEMINI_API_KEY") or os.environ.get("OPENAI_API_KEY") if not api_key: raise ValueError("GEMINI_API_KEY or OPENAI_API_KEY environment variable not set.") return api_key @retry_on_failure def call_gemini_flash(prompt: str, system_instruction: str = None, temperature: float = 0.3, json_mode: bool = False): """ Calls the Gemini Flash model to generate text content. This is a focused, local version of the function. """ logger = logging.getLogger(__name__) api_key = _get_gemini_api_key() if not HAS_GEMINI: raise ImportError("No Google Generative AI library is available (google-genai or google-generativeai).") # The legacy library was noted as preferred in the original helpers.py if HAS_OLD_GENAI: try: old_genai.configure(api_key=api_key) generation_config = { "temperature": temperature, "top_p": 0.95, "top_k": 40, "max_output_tokens": 8192, } if json_mode: generation_config["response_mime_type"] = "application/json" model = old_genai.GenerativeModel( model_name="gemini-1.5-flash", # Using 1.5 as it's the modern standard generation_config=generation_config, system_instruction=system_instruction ) response = model.generate_content([prompt]) return response.text.strip() except Exception as e: logger.error(f"Error with legacy GenAI Lib: {e}") if not HAS_NEW_GENAI: raise e # Fallthrough to new lib if legacy fails # Fallback to the new library if HAS_NEW_GENAI: try: # CORRECT: Use the Client-based API for the new library client = genai.Client(api_key=api_key) config = { "temperature": temperature, "top_p": 0.95, "top_k": 40, "max_output_tokens": 8192, } if json_mode: config["response_mime_type"] = "application/json" # Construct the contents list, including the system instruction if provided contents = [] if system_instruction: # Note: The new API doesn't have a direct 'system_instruction' parameter # in generate_content. It's typically passed as the first message. # This is an adaptation. For a more robust solution, one would # structure prompts with roles. contents.append({'role': 'system', 'parts': [{'text': system_instruction}]}) contents.append({'role': 'user', 'parts': [{'text': prompt}]}) # Use the client to generate content response = client.models.generate_content( model="models/gemini-2.0-flash-001", # CORRECTED: Using the project's standard model contents=contents, config=config ) return response.text.strip() except Exception as e: logger.error(f"Error with new GenAI Lib: {e}") raise e raise RuntimeError("Both Gemini libraries failed or are unavailable.")