from pydantic import Field, model_validator from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): """应用全局配置""" model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8") # 应用基础配置 app_name: str = "DreamWeaver" debug: bool = False secret_key: str = Field(..., description="JWT 签名密钥") base_url: str = Field("http://localhost:8000", description="后端对外回调地址") # 数据库 database_url: str = Field(..., description="SQLAlchemy async URL") # OAuth - GitHub github_client_id: str = "" github_client_secret: str = "" # OAuth - Google google_client_id: str = "" google_client_secret: str = "" # AI Capability Keys text_api_key: str = "" tts_api_base: str = "" tts_api_key: str = "" image_api_key: str = "" # Additional Provider API Keys openai_api_key: str = "" elevenlabs_api_key: str = "" cqtai_api_key: str = "" minimax_api_key: str = "" minimax_group_id: str = "" antigravity_api_key: str = "" antigravity_api_base: str = "" # AI Model Configuration text_model: str = "gemini-2.0-flash" tts_model: str = "" image_model: str = "" # Provider routing (ordered lists) text_providers: list[str] = Field(default_factory=lambda: ["gemini"]) image_providers: list[str] = Field(default_factory=lambda: ["cqtai"]) tts_providers: list[str] = Field(default_factory=lambda: ["minimax", "elevenlabs", "edge_tts"]) # Celery (Redis) celery_broker_url: str = Field("redis://localhost:6379/0") celery_result_backend: str = Field("redis://localhost:6379/0") # Generic Redis redis_url: str = Field("redis://localhost:6379/0", description="Redis connection URL") # Admin console enable_admin_console: bool = False admin_username: str = "admin" admin_password: str = "admin123" # 建议通过环境变量覆盖 # CORS cors_origins: list[str] = Field(default_factory=lambda: ["http://localhost:5173"]) @model_validator(mode="after") def _require_core_settings(self) -> "Settings": # type: ignore[override] missing = [] if not self.secret_key or self.secret_key == "change-me-in-production": missing.append("SECRET_KEY") if not self.database_url: missing.append("DATABASE_URL") if missing: raise ValueError(f"Missing required settings: {', '.join(missing)}") return self settings = Settings()