mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-04-18 01:52:20 +00:00
75 lines
2.5 KiB
Python
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}")
|