103 lines
3.6 KiB
Python
103 lines
3.6 KiB
Python
import aiohttp
|
|
import base64
|
|
import uuid
|
|
import time
|
|
from typing import Optional, List, Dict, Any
|
|
from app.core.config import settings
|
|
|
|
|
|
class GigaChatService:
|
|
def __init__(self):
|
|
self.access_token: Optional[str] = None
|
|
self.token_expires_at: Optional[float] = None
|
|
|
|
async def _get_token(self) -> str:
|
|
"""Получить OAuth токен"""
|
|
# Проверяем, не истек ли токен (оставляем запас 60 секунд)
|
|
if self.access_token and self.token_expires_at:
|
|
if time.time() < (self.token_expires_at - 60):
|
|
return self.access_token
|
|
|
|
credentials = f"{settings.GIGACHAT_CLIENT_ID}:{settings.GIGACHAT_CLIENT_SECRET}"
|
|
encoded_credentials = base64.b64encode(credentials.encode()).decode()
|
|
|
|
headers = {
|
|
"Authorization": f"Basic {encoded_credentials}",
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
"Accept": "application/json",
|
|
"RqUID": str(uuid.uuid4())
|
|
}
|
|
|
|
data = {"scope": "GIGACHAT_API_PERS"}
|
|
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.post(
|
|
settings.GIGACHAT_AUTH_URL,
|
|
headers=headers,
|
|
data=data
|
|
) as response:
|
|
if response.status != 200:
|
|
raise Exception(f"Failed to get token: {response.status}")
|
|
|
|
result = await response.json()
|
|
self.access_token = result.get("access_token")
|
|
expires_in = result.get("expires_at", 1800)
|
|
# expires_at может быть timestamp или количество секунд
|
|
if expires_in > 1000000000: # Это timestamp
|
|
self.token_expires_at = expires_in
|
|
else: # Это количество секунд
|
|
self.token_expires_at = time.time() + expires_in
|
|
|
|
return self.access_token
|
|
|
|
async def chat(
|
|
self,
|
|
message: str,
|
|
context: Optional[List[Dict[str, Any]]] = None,
|
|
model: str = None
|
|
) -> Dict[str, Any]:
|
|
"""Отправить сообщение в GigaChat"""
|
|
token = await self._get_token()
|
|
model = model or settings.GIGACHAT_MODEL_CHAT
|
|
|
|
messages = context or []
|
|
messages.append({"role": "user", "content": message})
|
|
|
|
headers = {
|
|
"Authorization": f"Bearer {token}",
|
|
"Content-Type": "application/json"
|
|
}
|
|
|
|
payload = {
|
|
"model": model,
|
|
"messages": messages,
|
|
"temperature": 0.7,
|
|
"max_tokens": 2000
|
|
}
|
|
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.post(
|
|
f"{settings.GIGACHAT_BASE_URL}/chat/completions",
|
|
headers=headers,
|
|
json=payload
|
|
) as response:
|
|
if response.status != 200:
|
|
error_text = await response.text()
|
|
raise Exception(f"GigaChat API error: {response.status} - {error_text}")
|
|
|
|
result = await response.json()
|
|
return result
|
|
|
|
async def generate_text(
|
|
self,
|
|
prompt: str,
|
|
model: str = None
|
|
) -> str:
|
|
"""Генерация текста по промпту"""
|
|
result = await self.chat(prompt, model=model)
|
|
return result.get("choices", [{}])[0].get("message", {}).get("content", "")
|
|
|
|
|
|
gigachat_service = GigaChatService()
|
|
|