SPB Git forge

spb/ai-atlas

Public
41commits 1branches 0releases
4.6 MBsize
maindefault branch
12 days agolast push
HTML 77.2% TypeScript 10.5% Python 9.6% JavaScript 2.5%
3.7 KB · 95 lines python
Raw Blame History
1"""Runtime settings (environment variables, `AIA_` prefix). Never log `settings.model_dump()` — it contains secrets."""2from __future__ import annotations34from functools import lru_cache5from pathlib import Path67from pydantic import Field8from pydantic_settings import BaseSettings, SettingsConfigDict91011class Settings(BaseSettings):12    model_config = SettingsConfigDict(env_file=(".env",), env_file_encoding="utf-8", extra="ignore")1314    app_env: str = Field("development", alias="APP_ENV")15    site_url: str = Field("https://www.ai-atlas.co", alias="AIA_SITE_URL")1617    database_url: str = Field("postgresql+asyncpg://aiatlas:aiatlas@127.0.0.1:5432/aiatlas", alias="DATABASE_URL")18    redis_url: str = Field("redis://127.0.0.1:6379/5", alias="REDIS_URL")1920    data_dir: Path = Field(Path("./data"), alias="AIA_DATA_DIR")21    api_host: str = Field("127.0.0.1", alias="AIA_API_HOST")22    api_port: int = Field(8321, alias="AIA_API_PORT")23    admin_token: str = Field("", alias="AIA_ADMIN_TOKEN")24    log_json: bool = Field(True, alias="AIA_LOG_JSON")25    tz: str = Field("America/Toronto", alias="AIA_TZ")2627    # Crawler28    user_agent: str = Field("AIAtlasBot/0.1 (+https://www.ai-atlas.co/bot; contact@spboucher.ai)", alias="AIA_USER_AGENT")29    http_timeout_s: float = Field(45.0, alias="AIA_HTTP_TIMEOUT")30    max_body_bytes: int = Field(25 * 1024 * 1024, alias="AIA_MAX_BODY_BYTES")31    default_rate_per_min: int = Field(30, alias="AIA_DEFAULT_RATE_PER_MIN")32    respect_robots: bool = Field(True, alias="AIA_RESPECT_ROBOTS")33    fetch_concurrency: int = Field(8, alias="AIA_FETCH_CONCURRENCY")3435    # Escalation transports (optional; never required)36    scrapfly_api_key: str = Field("", alias="SCRAPFLY_API_KEY")37    firecrawl_api_key: str = Field("", alias="FIRECRAWL_API_KEY")38    browser_enabled: bool = Field(False, alias="AIA_BROWSER_ENABLED")3940    # Local LLM factory (OpenAI-compatible endpoint, e.g. MacLustr llm-api.io). Optional.41    llm_base_url: str = Field("", alias="AIA_LLM_BASE_URL")42    llm_api_key: str = Field("", alias="AIA_LLM_API_KEY")43    llm_small_model: str = Field("qwen3-4b-instruct-2507-4bit", alias="AIA_LLM_SMALL_MODEL")44    llm_medium_model: str = Field("qwen3.6-35b-a3b-4bit", alias="AIA_LLM_MEDIUM_MODEL")45    llm_large_model: str = Field("qwen3.8-27b-4bit", alias="AIA_LLM_LARGE_MODEL")46    llm_timeout_s: float = Field(600.0, alias="AIA_LLM_TIMEOUT")47    llm_enabled: bool = Field(True, alias="AIA_LLM_ENABLED")48    embedding_model: str = Field("qwen3-embedding-0.6b-8bit", alias="AIA_EMBEDDING_MODEL")49    embedding_dim: int = Field(1024, alias="AIA_EMBEDDING_DIM")5051    # Scheduler52    scheduler_tick_s: int = Field(30, alias="AIA_SCHEDULER_TICK_S")53    worker_concurrency: int = Field(4, alias="AIA_WORKER_CONCURRENCY")54    backup_cron: str = Field("40 4 * * *", alias="AIA_BACKUP_CRON")5556    @property57    def raw_dir(self) -> Path:58        return self.data_dir / "raw"5960    @property61    def text_dir(self) -> Path:62        return self.data_dir / "text"6364    @property65    def logs_dir(self) -> Path:66        return self.data_dir / "logs"6768    @property69    def backups_dir(self) -> Path:70        return self.data_dir / "backups"7172    @property73    def cache_dir(self) -> Path:74        return self.data_dir / "cache"7576    @property77    def sync_database_url(self) -> str:78        return self.database_url.replace("+asyncpg", "")7980    @property81    def llm_available(self) -> bool:82        return bool(self.llm_enabled and self.llm_base_url and self.llm_api_key)8384    def ensure_dirs(self) -> None:85        for d in (self.raw_dir, self.text_dir, self.logs_dir, self.backups_dir, self.cache_dir, self.data_dir / "seed"):86            d.mkdir(parents=True, exist_ok=True)878889@lru_cache90def get_settings() -> Settings:91    return Settings()929394settings = get_settings()95