"""Настройки. Нормативы ГОСТ — в миллисекундах и из конфига, не из кода.""" from functools import lru_cache from pydantic import AliasChoices, Field from pydantic_settings import BaseSettings, SettingsConfigDict from app.domain.timers import NORMATIVES, TimerCode class Settings(BaseSettings): model_config = SettingsConfigDict(env_file=".env", extra="ignore") # Данные database_url: str = "postgresql+asyncpg://lct:lct@localhost:5432/lct" # Голосовой контур models_dir: str = "models" stt_model: str = "gigaam-v3-rnnt" endpointing_ms: int = 600 mic_sample_rate: int = 16_000 tts_sample_rate: int = 24_000 offline: bool = False # Голосовой контур: грузит ~5 с моделей при старте. В тестах выключен. voice_enabled: bool = True # LLM. Провайдер меняется значением, не кодом (docs/arch/STACK.md). # Имена COMPAT_MODEL_* принимаются тоже — так их выставляет командный сниппет. llm_provider: str = "openai_compatible" llm_base_url: str = Field( default="", validation_alias=AliasChoices("llm_base_url", "compat_model_url") ) llm_api_key: str = Field( default="", validation_alias=AliasChoices("llm_api_key", "compat_model_api_key"), repr=False, ) llm_model_caller: str = Field( default="", validation_alias=AliasChoices("llm_model_caller", "compat_model_name") ) llm_model_judge: str = Field( default="", validation_alias=AliasChoices("llm_model_judge", "compat_model_name") ) judge_temperature: float = 0.0 # Вход и роли (lct-23). `session_secret` обязателен на рабочем стенде: # значение по умолчанию годится только для разработки, и администратор # видит в состоянии сервисов, что оно не заменено. session_secret: str = "dev-secret-поменять-на-стенде" #: Вход без пароля для `make lesson` и тестов. На стенде выключен. dev_auth_bypass: bool = False # Нормативы: переопределяют значения по умолчанию из domain/timers.py timer_limits_ms: dict[TimerCode, int] = {} def limit_ms(self, code: TimerCode) -> int: return self.timer_limits_ms.get(code, NORMATIVES[code].limit_ms) @lru_cache def get_settings() -> Settings: return Settings()