""" 应用配置管理模块 使用 Pydantic Settings 统一管理所有配置项,支持从环境变量和 .env 文件加载配置。 """ from functools import lru_cache from pathlib import Path from typing import Optional from urllib.parse import quote_plus from pydantic import AliasChoices, Field, model_validator from pydantic_settings import BaseSettings, SettingsConfigDict # backend/ 目录(与 uvicorn CWD 无关,始终读取该目录下的 .env) _BACKEND_DIR = Path(__file__).resolve().parent.parent class Settings(BaseSettings): """应用配置类""" # 应用配置 app_name: str = "星云 API Server" app_description: str = "星云 API 服务器" debug: bool = False # 未关联企业或库中未配置时的 AI 助手展示名(可被 enterprise.ai_display_name 覆盖) ai_display_name_default: str = "智能助手 AI" # API 服务器配置(同时兼容 .env 里的 API.HOST / API.PORT 与常规 API_HOST / API_PORT) api_host: str = Field( default="0.0.0.0", validation_alias=AliasChoices("API_HOST", "api_host", "API.HOST"), ) api_port: int = Field( default=7861, validation_alias=AliasChoices("API_PORT", "api_port", "API.PORT"), ) # 数据库配置 db_host: str = "localhost" db_port: int = 5432 db_name: str = "huoyan" db_user: str = "postgres" db_password: str = "root1234" # 数据库连接池配置 db_pool_min_size: int = 10 db_pool_max_size: int = 50 # 增加连接池大小,避免连接耗尽 db_command_timeout: int = 120 # 增加超时时间(从60秒到120秒) # Checkpointer 连接池配置(psycopg) checkpointer_pool_max_size: int = 50 # 增加 checkpointer 连接池大小 # JWT 配置 jwt_secret_key: str = "your-secret-key-change-in-production" jwt_algorithm: str = "HS256" jwt_expire_minutes: int = 60 * 24 * 7 # 7 天 # AI 模型配置 # True:通义聊天走 LangChain ``ChatTongyi``(DashScope 原生协议);False:走 ``ChatOpenAI`` + 兼容 base_url use_origin_model: bool = Field( default=False, validation_alias=AliasChoices("USE_ORIGIN_MODEL", "use_origin_model"), ) dashscope_api_key: Optional[str] = None dashscope_api_base: Optional[str] = None deepseek_api_key: Optional[str] = None deepseek_api_base: Optional[str] = None openai_api_key: Optional[str] = None tavily_api_key: Optional[str] = None # LLM 的 OpenAI 兼容 base_url 见 ``core.llm_env``(从 ``backend/.env`` 读取);此处只保留与密钥相关的项 # OSS 配置 oss_access_key_id: Optional[str] = None oss_access_key_secret: Optional[str] = None oss_endpoint: Optional[str] = None oss_bucket_name: Optional[str] = None # MCP 配置(第三方 MCP 完整端点地址;传输协议见 mcp_transport) mcp_url: Optional[str] = None mcp_transport: str = "sse" # HTTPX 配置 httpx_default_timeout: float = 300.0 # Redis 配置 redis_host: str = "127.0.0.1" redis_port: int = 6379 redis_password: Optional[str] = None redis_db: int = 0 # 阿里云短信配置 sms_access_key_id: Optional[str] = None sms_access_key_secret: Optional[str] = None sms_sign_name: Optional[str] = None sms_template_code: Optional[str] = None # 阿里云 OCR 配置 ocr_access_key_id: Optional[str] = None ocr_access_key_secret: Optional[str] = None ocr_endpoint: str = "ocr-api.cn-hangzhou.aliyuncs.com" # OCR 服务端点 # 微信小程序配置 wechat_app_id: Optional[str] = None wechat_app_secret: Optional[str] = None # 阿里云内容审核配置 aliyun_access_key_id: Optional[str] = None aliyun_access_key_secret: Optional[str] = None aliyun_moderation_region: str = "cn-shanghai" moderation_timeout_seconds: float = 3.0 moderation_review_action: str = "allow" # "allow" 或 "block" moderation_enabled: bool = True # 功能开关 moderation_service_type: str = "comment_detection_pro" # 文本审核增强版服务类型 image_moderation_service_type: str = "baselineCheck" # 图片审核服务类型 # 企业版:关闭后禁止自助注册(仅管理员在后台创建用户) enable_public_register: bool = True # 日志配置 logging_level: str = "INFO" logging_dir: str = "logs" logging_max_file_size: str = "30 MB" logging_retention_days: int = 30 logging_enable_console: bool = True # 向量数据库配置 (ChromaDB) chroma_host: str = "localhost" chroma_port: int = 8000 chroma_persist_directory: Optional[str] = None # 如果为空则使用内存模式 # RAG 配置 rag_chunk_size: int = 512 # 文本分块大小 rag_chunk_overlap: int = 50 # 分块重叠大小 rag_top_k: int = 5 # 检索返回的文档数量 rag_score_threshold: float = 0.5 # 相关性分数阈值 # Embedding 模型配置 embedding_model: str = "text-embedding-v4" # 通义千问 Embedding 模型 embedding_dimension: int = 1536 # Embedding 维度 # Neo4j 图数据库配置 neo4j_uri: str = "bolt://127.0.0.1:7687" neo4j_user: str = "neo4j" neo4j_password: str = "neo4j" @property def db_uri(self) -> str: """获取数据库连接 URI(asyncpg 格式)""" return f"postgresql://{self.db_user}:{self.db_password}@{self.db_host}:{self.db_port}/{self.db_name}" @property def db_uri_psycopg(self) -> str: """获取数据库连接 URI(psycopg 格式,用于 checkpointer)""" encoded_password = quote_plus(self.db_password) return f"postgresql://{self.db_user}:{encoded_password}@{self.db_host}:{self.db_port}/{self.db_name}?sslmode=disable" @property def api_address(self) -> str: """获取 API 服务器地址""" host = self.api_host if self.api_host != "0.0.0.0" else "127.0.0.1" return f"http://{host}:{self.api_port}" @model_validator(mode='after') def validate_moderation_credentials(self): """验证内容审核凭证配置""" if self.moderation_enabled: if not self.aliyun_access_key_id: raise ValueError( "ALIYUN_ACCESS_KEY_ID is required when MODERATION_ENABLED is True" ) if not self.aliyun_access_key_secret: raise ValueError( "ALIYUN_ACCESS_KEY_SECRET is required when MODERATION_ENABLED is True" ) return self model_config = SettingsConfigDict( env_file=str(_BACKEND_DIR / ".env"), env_file_encoding="utf-8", case_sensitive=False, extra="ignore", # 忽略未定义的环境变量 populate_by_name=True, # 支持旧的环境变量名格式(带点号的) env_prefix="", ) @lru_cache() def get_settings() -> Settings: """ 获取配置实例(单例模式) 使用 lru_cache 确保只创建一个配置实例。 """ return Settings() # 导出全局配置实例 settings = get_settings()