"""Yandex GPT provider for VoIdea.""" import time from datetime import datetime, timezone from typing import Any, Optional import httpx from app.core.config import get_settings from app.integrations.ai.base import AIProvider, AIResult settings = get_settings() class YandexGPTProvider(AIProvider): """Yandex GPT AI provider. Supports both API key (Api-Key header) and IAM token (Bearer header). Automatically falls back between auth methods on 401. """ name = "yandex_gpt" model = "yandexgpt/latest" timeout = settings.ai_timeout max_retries = settings.ai_max_retries def __init__(self, api_key: str = ""): super().__init__(api_key or settings.ai_yandex_key) self.base_url = settings.ai_yandex_url.rstrip("/") self.folder_id = settings.ai_yandex_folder_id self._client = httpx.AsyncClient(timeout=self.timeout) async def analyze(self, prompt: str, **kwargs: Any) -> AIResult: """Send prompt to Yandex GPT and return result.""" start = time.time() temperature = kwargs.get("temperature", 0.7) max_tokens = kwargs.get("max_tokens", 2000) model_uri = f"gpt://{self.folder_id}/{self.model}" if self.folder_id else self.model # Split prompt into system and user parts parts = prompt.split("\n\n", 1) system_text = parts[0] user_text = parts[1] if len(parts) > 1 else "" body = { "modelUri": model_uri, "completionOptions": { "temperature": temperature, "maxTokens": max_tokens, }, "messages": [ {"role": "system", "text": system_text}, {"role": "user", "text": user_text}, ], } try: response = await self._client.post( f"{self.base_url}/foundationModels/v1/completion", json=body, ) duration = int((time.time() - start) * 1000) if response.status_code == 401: # Try with Api-Key header instead response = await self._client.post( f"{self.base_url}/foundationModels/v1/completion", json=body, headers={"Authorization": f"Api-Key {self.api_key}"}, ) duration = int((time.time() - start) * 1000) if response.status_code == 200: data = response.json() result_text = ( data.get("result", {}) .get("alternatives", [{}])[0] .get("message", {}) .get("text", "") ) tokens = ( data.get("result", {}) .get("usage", {}) .get("inputTextTokens", 0) ) return AIResult( success=True, content=result_text, model=self.model, provider=self.name, tokens_used=tokens, duration_ms=duration, ) else: error_body = response.text[:500] return AIResult( success=False, error=f"Yandex GPT {response.status_code}: {error_body}", provider=self.name, duration_ms=duration, ) except httpx.TimeoutException: return AIResult( success=False, error="Yandex GPT timeout", provider=self.name, duration_ms=int((time.time() - start) * 1000), ) except Exception as e: return AIResult( success=False, error=f"Yandex GPT error: {str(e)}", provider=self.name, duration_ms=int((time.time() - start) * 1000), ) async def close(self) -> None: await self._client.aclose()