from __future__ import annotations from dataclasses import dataclass from decouple import config def _to_bool(value: str) -> bool: return value.strip().lower() in {"1", "true", "yes", "on"} @dataclass(frozen=True) class Settings: app_host: str = config("API_HOST", default="0.0.0.0") app_port: int = config("API_PORT", cast=int, default=8080) openai_base_url: str = config( "OPENAI_BASE_URL", default="https://openrouter.ai/api/v1" ) openai_api_key: str = config("OPENAI_API_KEY", default="") llm_model: str = config("LLM_MODEL", default="openai/gpt-4.1-mini") embedding_model: str = config( "EMBEDDING_MODEL", default="deepvk/USER2-small" ) embedding_device: str = config("EMBEDDING_DEVICE", default="cpu") chroma_host: str = config("CHROMA_HOST", default="chromadb") chroma_port: int = config("CHROMA_PORT", cast=int, default=8000) chroma_collection: str = config("CHROMA_COLLECTION", default="law_chunks") chroma_ssl: bool = _to_bool(config("CHROMA_SSL", default="false")) rag_top_k: int = config("RAG_TOP_K", cast=int, default=5) fts_top_k: int = config("FTS_TOP_K", cast=int, default=20) vector_top_k: int = config("VECTOR_TOP_K", cast=int, default=20) index_batch_size: int = config("INDEX_BATCH_SIZE", cast=int, default=32) llm_timeout_seconds: int = config("LLM_TIMEOUT_SECONDS", cast=int, default=90) log_level: str = config("LOG_LEVEL", default="INFO") auto_index_on_startup: bool = _to_bool(config("AUTO_INDEX_ON_STARTUP", default="true")) auto_index_only_if_empty: bool = _to_bool( config("AUTO_INDEX_ONLY_IF_EMPTY", default="true") ) auto_index_reset_collection: bool = _to_bool( config("AUTO_INDEX_RESET_COLLECTION", default="false") ) auto_index_retry_delay_seconds: int = config( "AUTO_INDEX_RETRY_DELAY_SECONDS", cast=int, default=15 ) auto_index_max_attempts: int = config( "AUTO_INDEX_MAX_ATTEMPTS", cast=int, default=20 ) settings = Settings()