Files
ProxMenux/AppImage/scripts/ai_providers/gemini_provider.py
2026-03-17 14:07:47 +01:00

75 lines
2.5 KiB
Python

"""Google Gemini provider implementation.
Google's Gemini models offer a free tier and excellent quality/price ratio.
Gemini 1.5 Flash is particularly fast and cost-effective.
"""
from typing import Optional
from .base import AIProvider, AIProviderError
class GeminiProvider(AIProvider):
"""Google Gemini provider using the Generative Language API."""
NAME = "gemini"
DEFAULT_MODEL = "gemini-1.5-flash"
REQUIRES_API_KEY = True
API_BASE = "https://generativelanguage.googleapis.com/v1beta/models"
def generate(self, system_prompt: str, user_message: str,
max_tokens: int = 200) -> Optional[str]:
"""Generate a response using Google's Gemini API.
Note: Gemini uses a different API format. System instructions
go in a separate systemInstruction field.
Args:
system_prompt: System instructions
user_message: User message to process
max_tokens: Maximum response length
Returns:
Generated text or None if failed
Raises:
AIProviderError: If API key is missing or request fails
"""
if not self.api_key:
raise AIProviderError("API key required for Gemini")
url = f"{self.API_BASE}/{self.model}:generateContent?key={self.api_key}"
# Gemini uses a specific format with contents array
payload = {
'systemInstruction': {
'parts': [{'text': system_prompt}]
},
'contents': [
{
'role': 'user',
'parts': [{'text': user_message}]
}
],
'generationConfig': {
'maxOutputTokens': max_tokens,
'temperature': 0.3,
}
}
headers = {
'Content-Type': 'application/json',
}
result = self._make_request(url, payload, headers)
try:
# Gemini returns candidates array with content parts
candidates = result.get('candidates', [])
if candidates:
content = candidates[0].get('content', {})
parts = content.get('parts', [])
if parts:
return parts[0].get('text', '').strip()
raise AIProviderError("No content in response")
except (KeyError, IndexError) as e:
raise AIProviderError(f"Unexpected response format: {e}")