""" Configuration management for ShopAgent Loads environment variables and provides configuration objects """ from pathlib import Path from typing import Optional from pydantic_settings import BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict # config.py sits at app/config.py → parent.parent = project root PROJECT_ROOT = Path(__file__).resolve().parent.parent class Settings(BaseSettings): """Application settings loaded from environment variables All settings can be configured via .env file or environment variables. Priority (high → low): init kwargs > .env file > env vars > defaults """ model_config = SettingsConfigDict( env_file=str(PROJECT_ROOT / ".env"), env_file_encoding="utf-8", case_sensitive=False, extra="ignore", ) # OpenAI Configuration openai_api_key: str openai_model: str = "gpt-4o-mini" # 图片理解 / 多模态模型(例如 Qwen3-Omni-Flash) openai_vision_model: str = "qwen3-omni-flash" openai_temperature: float = 0.7 openai_max_tokens: int = 1000 # Base URL for OpenAI-compatible APIs (e.g. Qwen/DashScope) # Qwen 北京: https://dashscope.aliyuncs.com/compatible-mode/v1 openai_api_base_url: Optional[str] = None # Search Configuration top_k_results: int = 10 similarity_threshold: float = 0.6 # Search API (see docs/搜索API对接指南.md) search_api_base_url: str = "http://120.76.41.98:6002" search_api_tenant_id: str = "170" # Application Configuration app_host: str = "0.0.0.0" app_port: int = 8000 debug: bool = True log_level: str = "INFO" # Data Paths raw_data_path: str = "./data/raw" processed_data_path: str = "./data/processed" image_data_path: str = "./data/images" @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: """Make .env file take priority over system environment variables. Default order: init > env > dotenv > secrets Our order: init > dotenv > env > secrets """ return init_settings, dotenv_settings, env_settings, file_secret_settings # Global settings instance settings = Settings() def get_absolute_path(relative_path: str) -> str: """Convert relative path to absolute path based on project root""" return str(PROJECT_ROOT / relative_path)