| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- """
- 配置管理模块
- """
- import os
- from pathlib import Path
- from pydantic_settings import BaseSettings
- from dotenv import load_dotenv
- # 加载环境变量
- load_dotenv()
- class Settings(BaseSettings):
- """应用配置"""
-
- # 应用基础配置
- APP_NAME: str = "Tolan Voice Assistant"
- APP_VERSION: str = "1.0.0"
- DEBUG: bool = False
-
- # 服务器配置
- HOST: str = os.getenv("HOST", "0.0.0.0")
- PORT: int = int(os.getenv("PORT", "8000"))
- host: str = os.getenv("HOST", "0.0.0.0") # 别名,兼容小写
- port: int = int(os.getenv("PORT", "8000")) # 别名,兼容小写
-
- # WebSocket配置
- WS_HEARTBEAT_INTERVAL: int = 30 # 心跳间隔(秒)
- WS_TIMEOUT: int = 60 # 超时时间(秒)
-
- # DashScope API配置(阿里云)
- dashscope_api_key: str = os.getenv("DASHSCOPE_API_KEY", "")
- dashscope_api_key_intl: str = os.getenv("DASHSCOPE_API_KEY_INTL", "") # 国际版单独的key(可选)
- use_dashscope_intl: bool = os.getenv("USE_DASHSCOPE_INTL", "false").lower() == "true" # 是否使用国际版
-
- @property
- def active_dashscope_api_key(self) -> str:
- """获取当前激活的API Key(根据国际版/国内版自动选择)"""
- if self.use_dashscope_intl and self.dashscope_api_key_intl:
- return self.dashscope_api_key_intl
- return self.dashscope_api_key
-
- # LLM配置
- llm_model: str = os.getenv("LLM_MODEL", "qwen-flash")
-
- # STT配置
- # ⚠️ 重要:language参数必须设置!
- # 支持的值:
- # - 'zh' (中文)
- # - 'en' (英文)
- # - 'ja' (日文)
- # - 'ko' (韩文)
- # - 'auto' (自动检测 - 实验性,需要测试)
- # 项目正式使用时应设为'en',测试阶段用'zh'或'auto'
- STT_LANGUAGE: str = os.getenv("STT_LANGUAGE", "zh")
-
- # TTS配置
- tts_model: str = os.getenv("TTS_MODEL", "qwen3-tts-flash")
- tts_voice: str = os.getenv("TTS_VOICE", "Cherry") # 女声(支持:Cherry, Stella)
- tts_speech_rate: float = float(os.getenv("TTS_SPEECH_RATE", "1.1")) # 语速:1.1 = 10%加速(优化延迟)
-
- # TTS重试配置(处理API速率限制)
- TTS_MAX_RETRIES: int = int(os.getenv("TTS_MAX_RETRIES", "3")) # 最大重试次数
- TTS_RETRY_DELAY: float = float(os.getenv("TTS_RETRY_DELAY", "5.0")) # 初始重试延迟(秒)- 增加到5秒
- TTS_RETRY_BACKOFF: float = float(os.getenv("TTS_RETRY_BACKOFF", "2.0")) # 指数退避系数
-
- # TTS速率控制(预防性措施,避免触发API限制)
- TTS_MIN_INTERVAL: float = float(os.getenv("TTS_MIN_INTERVAL", "0.8")) # 两次TTS调用的最小间隔(秒)
-
- # 豆包API超时配置
- DOUBAO_RECV_TIMEOUT: int = 15 # 接收消息超时(秒)
- DOUBAO_CONNECT_TIMEOUT: int = 10 # 连接超时(秒)
- DOUBAO_RESPONSE_TIMEOUT: int = 20 # 响应超时(秒)
-
- # 豆包API配置
- DOUBAO_API_KEY: str = os.getenv("DOUBAO_API_KEY", "")
- DOUBAO_APP_ID: str = os.getenv("DOUBAO_APP_ID", "")
- DOUBAO_API_URL: str = os.getenv("DOUBAO_API_URL", "wss://openspeech.bytedance.com/api/v3/realtime/dialogue")
- DOUBAO_OUTPUT_FORMAT: str = os.getenv("DOUBAO_OUTPUT_FORMAT", "ogg_opus") # ogg_opus 或 pcm
-
- # AI助手提示词配置
- LEARNER_PROFICIENCY: str = os.getenv("LEARNER_PROFICIENCY", "A1-A2")
- AGE_TAG: str = os.getenv("AGE_TAG", "Adult")
- TOPIC_TAG: str = os.getenv("TOPIC_TAG", "Daily Conversation")
- EXPERIMENT_TAG: str = os.getenv("EXPERIMENT_TAG", "control") # control 或 experiment
- USE_SIMPLIFIED_PROMPT: bool = os.getenv("USE_SIMPLIFIED_PROMPT", "false").lower() == "true" # 🔥 使用简化提示词(减少延迟)
-
- # 音频配置
- AUDIO_SAMPLE_RATE: int = 16000
- AUDIO_BIT_RATE: int = 16
- AUDIO_CHANNELS: int = 1
-
- # MySQL配置
- MYSQL_HOST: str = os.getenv("MYSQL_HOST", "47.99.164.66")
- MYSQL_PORT: int = int(os.getenv("MYSQL_PORT", "3306"))
- MYSQL_USER: str = os.getenv("MYSQL_USER", "root")
- MYSQL_PASSWORD: str = os.getenv("MYSQL_PASSWORD", "")
- MYSQL_DATABASE: str = os.getenv("MYSQL_DATABASE", "Lyrria")
- MYSQL_POOL_SIZE: int = int(os.getenv("MYSQL_POOL_SIZE", "10"))
- MYSQL_MAX_OVERFLOW: int = int(os.getenv("MYSQL_MAX_OVERFLOW", "20"))
-
- # Redis配置
- REDIS_HOST: str = os.getenv("REDIS_HOST", "47.99.164.66")
- REDIS_PORT: int = int(os.getenv("REDIS_PORT", "16379"))
- REDIS_DB: int = int(os.getenv("REDIS_DB", "12"))
- REDIS_PASSWORD: str = os.getenv("REDIS_PASSWORD", "")
- REDIS_SSL: bool = os.getenv("REDIS_SSL", "false").lower() == "true"
- REDIS_SESSION_TTL: int = int(os.getenv("REDIS_SESSION_TTL", "86400"))
- REDIS_MAX_CONNECTIONS: int = int(os.getenv("REDIS_MAX_CONNECTIONS", "50"))
-
- # CORS配置
- # 支持localhost和任意IP地址访问(端口3000为Vite默认HTTPS端口)
- CORS_ORIGINS: list = [
- "http://localhost:3000",
- "https://localhost:3000",
- "http://127.0.0.1:3000",
- "https://127.0.0.1:3000",
- "http://localhost:5173",
- "https://localhost:5173",
- "http://127.0.0.1:5173",
- "https://127.0.0.1:5173",
- # 支持局域网IP访问
- "http://192.168.2.112:3000",
- "https://192.168.2.112:3000",
- "http://192.168.2.112:5173",
- "https://192.168.2.112:5173",
- "http://192.168.43.35:3000",
- "https://192.168.43.35:3000",
- "http://192.168.43.35:5173",
- "https://192.168.43.35:5173",
- ]
-
- # 是否允许所有来源(开发环境可设为True,生产环境务必设为False)
- CORS_ALLOW_ALL: bool = os.getenv("CORS_ALLOW_ALL", "true").lower() == "true"
-
- # 日志配置
- LOG_LEVEL: str = "INFO"
- LOG_DIR: str = "logs"
- LOG_ROTATION: str = "500 MB"
- LOG_RETENTION: str = "10 days"
-
- # SSL配置(可选,生产环境建议由nginx统一管理SSL)
- SSL_KEYFILE: str = os.getenv("SSL_KEYFILE", "")
- SSL_CERTFILE: str = os.getenv("SSL_CERTFILE", "")
-
- class Config:
- env_file = ".env"
- case_sensitive = True
- extra = "ignore" # 忽略额外的环境变量(如旧的连接池配置)
- # 创建全局配置实例
- settings = Settings()
- # 确保日志目录存在
- Path(settings.LOG_DIR).mkdir(parents=True, exist_ok=True)
- # DashScope API endpoint 配置
- def get_dashscope_domain() -> str:
- """获取 DashScope API 域名"""
- return "dashscope-intl.aliyuncs.com" if settings.use_dashscope_intl else "dashscope.aliyuncs.com"
- def get_dashscope_ws_url() -> str:
- """获取 DashScope WebSocket URL(用于STT)"""
- domain = get_dashscope_domain()
- return f"wss://{domain}/api-ws/v1/realtime"
- def get_dashscope_http_base_url() -> str:
- """获取 DashScope HTTP base URL(用于LLM)"""
- domain = get_dashscope_domain()
- return f"https://{domain}/compatible-mode/v1"
|