first commit
This commit is contained in:
94
backend/app/config.py
Normal file
94
backend/app/config.py
Normal file
@@ -0,0 +1,94 @@
|
||||
"""Application configuration from environment + runtime overrides."""
|
||||
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
"""App settings loaded from env."""
|
||||
|
||||
app_name: str = "Fund Tracer API"
|
||||
debug: bool = False
|
||||
|
||||
# Database
|
||||
database_url: str = "sqlite+aiosqlite:///./fund_tracer.db"
|
||||
|
||||
# Uploads
|
||||
upload_dir: Path = Path("./uploads")
|
||||
max_upload_size_mb: int = 20
|
||||
allowed_extensions: set[str] = {"png", "jpg", "jpeg", "webp"}
|
||||
|
||||
# LLM
|
||||
llm_provider: str = "openai" # openai | anthropic | deepseek | custom_openai
|
||||
openai_api_key: str | None = None
|
||||
anthropic_api_key: str | None = None
|
||||
deepseek_api_key: str | None = None
|
||||
custom_openai_api_key: str | None = None
|
||||
custom_openai_base_url: str | None = None
|
||||
openai_model: str = "gpt-4o"
|
||||
anthropic_model: str = "claude-3-5-sonnet-20241022"
|
||||
deepseek_model: str = "deepseek-chat"
|
||||
custom_openai_model: str = "gpt-4o-mini"
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
env_file_encoding = "utf-8"
|
||||
extra = "ignore"
|
||||
|
||||
|
||||
_runtime_overrides: dict[str, str | None] = {}
|
||||
|
||||
|
||||
def _apply_overrides(settings: Settings) -> Settings:
|
||||
for key, value in _runtime_overrides.items():
|
||||
if hasattr(settings, key):
|
||||
setattr(settings, key, value)
|
||||
return settings
|
||||
|
||||
|
||||
@lru_cache
|
||||
def get_settings() -> Settings:
|
||||
return _apply_overrides(Settings())
|
||||
|
||||
|
||||
def update_runtime_settings(payload: dict[str, str | None]) -> Settings:
|
||||
"""Update runtime settings and refresh cached Settings object."""
|
||||
allowed = {
|
||||
"llm_provider",
|
||||
"openai_api_key",
|
||||
"anthropic_api_key",
|
||||
"deepseek_api_key",
|
||||
"custom_openai_api_key",
|
||||
"custom_openai_base_url",
|
||||
"custom_openai_model",
|
||||
}
|
||||
for key, value in payload.items():
|
||||
if key in allowed:
|
||||
_runtime_overrides[key] = value
|
||||
get_settings.cache_clear()
|
||||
return get_settings()
|
||||
|
||||
|
||||
def public_settings() -> dict:
|
||||
s = get_settings()
|
||||
return {
|
||||
"llm_provider": s.llm_provider,
|
||||
"providers": ["openai", "anthropic", "deepseek", "custom_openai"],
|
||||
"models": {
|
||||
"openai": s.openai_model,
|
||||
"anthropic": s.anthropic_model,
|
||||
"deepseek": s.deepseek_model,
|
||||
"custom_openai": s.custom_openai_model,
|
||||
},
|
||||
"base_urls": {
|
||||
"custom_openai": s.custom_openai_base_url or "",
|
||||
},
|
||||
"has_keys": {
|
||||
"openai": bool(s.openai_api_key),
|
||||
"anthropic": bool(s.anthropic_api_key),
|
||||
"deepseek": bool(s.deepseek_api_key),
|
||||
"custom_openai": bool(s.custom_openai_api_key),
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user