This commit is contained in:
kandrusyak
2026-07-25 15:07:53 +03:00
commit 6667e0d253
40 changed files with 3258 additions and 0 deletions

115
assistant_bot/yandex_ai.py Normal file
View File

@@ -0,0 +1,115 @@
from pathlib import Path
from typing import Any
from .ai import AIClientError
from .speech import SpeechRecognitionError
class YandexAIError(AIClientError):
pass
def create_async_sdk(folder_id: str) -> Any:
try:
from yandex_ai_studio_sdk import AsyncAIStudio
except ImportError as exc:
raise RuntimeError(
"Yandex AI Studio SDK is not installed. "
"Run: python -m pip install -r requirements.txt"
) from exc
return AsyncAIStudio(folder_id=folder_id)
def create_sync_sdk(folder_id: str) -> Any:
try:
from yandex_ai_studio_sdk import AIStudio
except ImportError as exc:
raise RuntimeError(
"Yandex AI Studio SDK is not installed. "
"Run: python -m pip install -r requirements.txt"
) from exc
return AIStudio(folder_id=folder_id)
class YandexAIClient:
provider = "yandex"
display_name = "Yandex AI Studio"
def __init__(self, folder_id: str, sdk: Any | None = None) -> None:
self.folder_id = folder_id.strip("/")
self._sdk = sdk if sdk is not None else create_async_sdk(self.folder_id)
def normalize_model(self, model: str) -> str:
normalized = model.strip()
if normalized.startswith("gpt://"):
return normalized
return f"gpt://{self.folder_id}/{normalized.lstrip('/')}"
async def list_models(self) -> list[str]:
try:
models = await self._sdk.chat.completions.list()
except Exception as exc:
raise YandexAIError(f"Не удалось получить список моделей: {exc}") from exc
model_names = {
str(uri)
for model in models
if (uri := getattr(model, "uri", None))
}
return sorted(model_names)
async def chat(
self,
model: str,
messages: list[dict[str, str]],
json_mode: bool = False,
) -> str:
sdk_messages = [
{
"role": message.get("role", "user"),
"text": message.get("content", ""),
}
for message in messages
]
try:
completion = self._sdk.models.completions(self.normalize_model(model))
if json_mode:
completion = completion.configure(response_format="json")
result = await completion.run(sdk_messages, timeout=180)
content = getattr(result[0], "text", None)
except Exception as exc:
raise YandexAIError(f"Запрос к модели завершился ошибкой: {exc}") from exc
if isinstance(content, str) and content.strip():
return content.strip()
raise YandexAIError("Yandex AI Studio вернула пустой ответ.")
class YandexSpeechRecognizer:
def __init__(
self,
folder_id: str,
language: str,
model: str,
sdk: Any | None = None,
) -> None:
self.folder_id = folder_id.strip("/")
self.language = language
self.model = model
self._sdk = sdk if sdk is not None else create_sync_sdk(self.folder_id)
def transcribe(self, audio_path: str | Path) -> str:
try:
audio = Path(audio_path).read_bytes()
recognizer = self._sdk.speechkit.speech_to_text(
audio_format=self._sdk.speechkit.AudioFormat.OGG_OPUS,
language_codes=self.language,
model=self.model,
)
result = recognizer.run(audio, timeout=180)
text = getattr(result, "text", None)
except Exception as exc:
raise SpeechRecognitionError("Yandex SpeechKit transcription failed") from exc
return text.strip() if isinstance(text, str) else ""