199 lines
6.9 KiB
Python
199 lines
6.9 KiB
Python
"""
|
||
应用配置管理模块
|
||
|
||
使用 Pydantic Settings 统一管理所有配置项,支持从环境变量和 .env 文件加载配置。
|
||
"""
|
||
from functools import lru_cache
|
||
from pathlib import Path
|
||
from typing import Optional
|
||
|
||
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)"""
|
||
return f"postgresql://{self.db_user}:{self.db_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()
|