"""Application configuration for imageO_v3.""" from __future__ import annotations import os from typing import Optional from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict # Cache defaults are set only when they are not already configured. os.environ.setdefault("XDG_CACHE_HOME", "/app/.cache") os.environ.setdefault("HF_HOME", "/app/.cache/huggingface") os.environ.setdefault("NUMBA_DISABLE_CACHE", "1") class Settings(BaseSettings): """Typed settings loaded from environment variables.""" model_config = SettingsConfigDict( env_file=".env", env_file_encoding="utf-8", extra="ignore", ) app_env: str = Field(default="development", description="Runtime environment") log_level: str = Field(default="INFO", description="Logger minimum level") model_version: str = Field(default="v3.0.0", description="Service model version") redis_url: str = Field(default="", description="Redis connection URL") hf_token: str = Field(default="", description="Hugging Face token for gated model access") replay_attack_ttl_s: int = Field(default=60, description="HMAC timestamp TTL") prediction_cache_ttl_s: int = Field(default=300, description="Prediction cache TTL") max_image_size_mb: int = Field(default=16, description="Maximum upload size in MB") model_checkpoint_path: str = Field( default="", alias="MODEL_CHECKPOINT_PATH", description="Local path to ABMIL .pt when ABMIL_HF_REPO_ID is unset; ignored when Hub repo id is set", ) abmil_hf_repo_id: Optional[str] = Field( default=None, description="Hugging Face Hub repo id (e.g. org/private-repo). If set, ABMIL checkpoint is fetched via hf_hub_download.", ) abmil_hf_filename: str = Field( default="production_model.pt", description="Checkpoint filename inside the Hub repo (top level or under ABMIL_HF_SUBFOLDER)", ) abmil_hf_revision: Optional[str] = Field( default=None, description="Optional Hub revision: branch, tag, or commit SHA (pin in production)", ) abmil_hf_subfolder: Optional[str] = Field( default=None, description="Optional folder inside the repo containing ABMIL_HF_FILENAME", ) abmil_hf_local_files_only: bool = Field( default=False, description="If true, Hub resolution uses only local HF cache (no network)", ) dinov3_model_id: str = Field( default="facebook/dinov3-vitb16-pretrain-lvd1689m", description="Hugging Face model id for DINOv3 backbone", ) embedding_batch_size: int = Field(default=16, description="Batch size for tile embedding") embedding_device: Optional[str] = Field( default=None, description="Optional device override (cpu/cuda)", ) embedding_dtype: Optional[str] = Field( default=None, description="Optional dtype for DINO model loading (auto/float16/float32/bfloat16)", ) dinov3_local_files_only: bool = Field( default=False, description="If true, do not fetch model files from Hugging Face", ) tile_size: int = Field(default=128, description="Preprocessing tile size") tile_overlap_ratio: float = Field(default=0.25, description="Preprocessing tile overlap ratio") tile_shrink_factor: float = Field(default=0.92, description="ROI shrink factor") abmil_attn_dim: int = Field(default=256, description="Fallback ABMIL attention dimension") abmil_classifier_hidden: int = Field( default=256, description="Fallback ABMIL classifier hidden size", ) abmil_attn_hidden: int = Field(default=128, description="Fallback gated attention hidden size") abmil_dropout: float = Field(default=0.40, description="Fallback ABMIL dropout") abmil_threshold: float = Field(default=0.5, description="Fallback positive class threshold") settings = Settings()