""" Google Gemini Provider for LLM requests """ import httpx import json from typing import Dict, Any, List from .base import BaseLLMProvider, LLMRequest, LLMResponse class GeminiProvider(BaseLLMProvider): """Google Gemini API provider""" def __init__(self, config: Dict[str, Any]): super().__init__(config) self.api_key = config.get('api_key') self.base_url = config.get('base_url', 'https://generativelanguage.googleapis.com/v1beta') self.model = config.get('model', 'gemini-1.5-flash') self.timeout = config.get('timeout', 300) @property def requires_api_key(self) -> bool: return True def get_supported_models(self) -> List[str]: return [ 'gemini-1.5-flash', 'gemini-1.5-pro', 'gemini-1.0-pro' ] async def generate_response(self, request: LLMRequest) -> LLMResponse: """Generate response using Gemini API""" try: # Gemini uses a different API format payload = { 'contents': [ { 'parts': [ { 'text': request.prompt } ] } ], 'generationConfig': { 'temperature': request.temperature or self.config.get('temperature', 0.8), 'maxOutputTokens': request.max_tokens or self.config.get('max_tokens', 2000), 'candidateCount': 1 } } url = f"{self.base_url}/models/{self.model}:generateContent" params = {'key': self.api_key} async with httpx.AsyncClient() as client: response = await client.post( url, params=params, json=payload, timeout=self.timeout ) if response.status_code == 200: data = response.json() # Extract content from Gemini response format if 'candidates' in data and len(data['candidates']) > 0: candidate = data['candidates'][0] if 'content' in candidate and 'parts' in candidate['content']: content = candidate['content']['parts'][0]['text'] # Extract token usage if available tokens_used = None if 'usageMetadata' in data: tokens_used = data['usageMetadata'].get('totalTokenCount') return LLMResponse( content=content, success=True, provider='gemini', model=self.model, tokens_used=tokens_used ) return LLMResponse( content="", success=False, error="Gemini API returned unexpected response format", provider='gemini' ) else: error_text = response.text return LLMResponse( content="", success=False, error=f"Gemini API error: {response.status_code} - {error_text}", provider='gemini' ) except Exception as e: return LLMResponse( content="", success=False, error=f"Gemini provider error: {str(e)}", provider='gemini' ) async def health_check(self) -> bool: """Check Gemini API health""" try: url = f"{self.base_url}/models" params = {'key': self.api_key} async with httpx.AsyncClient() as client: response = await client.get( url, params=params, timeout=10 ) return response.status_code == 200 except Exception: return False