config.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. from pydantic_settings import BaseSettings
  2. import yaml
  3. from pathlib import Path
  4. class AppConfig(BaseSettings):
  5. name: str = "shudao-chat-py"
  6. host: str = "0.0.0.0"
  7. port: int = 22001
  8. debug: bool = True
  9. class DatabaseConfig(BaseSettings):
  10. user: str
  11. password: str
  12. host: str
  13. port: int
  14. database: str
  15. pool_size: int = 100
  16. max_overflow: int = 10
  17. pool_recycle: int = 3600
  18. class DeepSeekConfig(BaseSettings):
  19. api_key: str
  20. api_url: str
  21. class Qwen3Config(BaseSettings):
  22. api_url: str
  23. model: str
  24. class IntentConfig(BaseSettings):
  25. api_url: str
  26. model: str
  27. class YoloConfig(BaseSettings):
  28. base_url: str
  29. class DifyConfig(BaseSettings):
  30. workflow_url: str
  31. workflow_id: str
  32. auth_token: str
  33. class AuthConfig(BaseSettings):
  34. api_url: str
  35. class OSSConfig(BaseSettings):
  36. access_key_id: str
  37. access_key_secret: str
  38. bucket: str
  39. endpoint: str
  40. parse_encrypt_key: str
  41. class AIChatConfig(BaseSettings):
  42. api_url: str = "http://127.0.0.1:28002/api/v1"
  43. timeout: int = 600
  44. class SpeechProcurementConfig(BaseSettings):
  45. required_cloud_products: list[str] = [
  46. "asr_sentence_recognition",
  47. "asr_flash_file_recognition",
  48. "tts_text_to_voice",
  49. "tts_long_text",
  50. ]
  51. required_credentials: list[str] = [
  52. "app_id",
  53. "secret_id",
  54. "secret_key",
  55. ]
  56. optional_cloud_products: list[str] = [
  57. "cos",
  58. ]
  59. notes: list[str] = [
  60. "sentence_recognition_for_audio_within_60s_and_3mb",
  61. "flash_file_recognition_for_longer_audio_fallback",
  62. "text_to_voice_for_default_tts",
  63. "long_text_tts_for_content_over_150_chinese_chars",
  64. ]
  65. class SpeechTencentConfig(BaseSettings):
  66. app_id: str = ""
  67. secret_id: str = ""
  68. secret_key: str = ""
  69. region: str = "ap-guangzhou"
  70. asr_endpoint: str = "asr.tencentcloudapi.com"
  71. tts_endpoint: str = "tts.tencentcloudapi.com"
  72. class SpeechTranscribeConfig(BaseSettings):
  73. enabled: bool = True
  74. default_api: str = "SentenceRecognition"
  75. fallback_api: str = "CreateRecTask"
  76. engine_model_type: str = "16k_zh"
  77. source_type: int = 1
  78. voice_format: str = "wav"
  79. input_sample_rate: int = 16000
  80. max_audio_seconds: int = 60
  81. max_audio_size_mb: int = 3
  82. word_info: int = 0
  83. filter_dirty: int = 0
  84. filter_modal: int = 0
  85. filter_punc: int = 0
  86. convert_num_mode: int = 1
  87. hotword_list: str = ""
  88. hotword_id: str = ""
  89. customization_id: str = ""
  90. replace_text_id: str = ""
  91. class SpeechSynthesizeConfig(BaseSettings):
  92. enabled: bool = True
  93. default_api: str = "TextToVoice"
  94. fallback_api: str = "CreateTtsTask"
  95. primary_language: int = 1
  96. voice_type: int = 1001
  97. sample_rate: int = 16000
  98. codec: str = "mp3"
  99. speed: float = 0.0
  100. volume: float = 0.0
  101. enable_subtitle: bool = False
  102. segment_rate: int = 0
  103. emotion_category: str = ""
  104. emotion_intensity: int = 100
  105. basic_text_limit_chars: int = 150
  106. long_text_trigger_chars: int = 120
  107. long_text_max_chars: int = 100000
  108. long_text_codec: str = "mp3"
  109. callback_url: str = ""
  110. class SpeechConfig(BaseSettings):
  111. enabled: bool = True
  112. provider: str = "tencent_cloud"
  113. integration_mode: str = "backend_direct"
  114. backend_service: str = "shudao-chat-py"
  115. request_timeout_seconds: int = 60
  116. procurement: SpeechProcurementConfig = SpeechProcurementConfig()
  117. tencent: SpeechTencentConfig = SpeechTencentConfig()
  118. transcribe: SpeechTranscribeConfig = SpeechTranscribeConfig()
  119. synthesize: SpeechSynthesizeConfig = SpeechSynthesizeConfig()
  120. class ThinkingSummaryConfig(BaseSettings):
  121. """思考过程二次总结(方案三)配置"""
  122. enabled: bool = True
  123. max_points: int = 5
  124. max_input_chars: int = 1500
  125. max_output_chars: int = 600
  126. temperature: float = 0.2
  127. class Settings:
  128. def __init__(self, config_path: str = "config.yaml"):
  129. # 获取项目根目录
  130. if not Path(config_path).is_absolute():
  131. # 相对于当前文件的路径
  132. current_dir = Path(__file__).parent.parent
  133. config_file = current_dir / config_path
  134. else:
  135. config_file = Path(config_path)
  136. if config_file.exists():
  137. with open(config_file, 'r', encoding='utf-8') as f:
  138. config_data = yaml.safe_load(f)
  139. else:
  140. raise FileNotFoundError(f"配置文件不存在: {config_file}")
  141. self.app = AppConfig(**config_data.get('app', {}))
  142. self.database = DatabaseConfig(**config_data.get('database', {}))
  143. self.deepseek = DeepSeekConfig(**config_data.get('deepseek', {}))
  144. self.qwen3 = Qwen3Config(**config_data.get('qwen3', {}))
  145. self.intent = IntentConfig(**config_data.get('intent', {}))
  146. self.yolo = YoloConfig(**config_data.get('yolo', {}))
  147. self.dify = DifyConfig(**config_data.get('dify', {}))
  148. self.auth = AuthConfig(**config_data.get('auth', {}))
  149. self.oss = OSSConfig(**config_data.get('oss', {}))
  150. self.aichat = AIChatConfig(**config_data.get('aichat', {}))
  151. self.speech = SpeechConfig(**config_data.get('speech', {}))
  152. self.thinking_summary = ThinkingSummaryConfig(
  153. **config_data.get('thinking_summary', {}))
  154. self.base_url = config_data.get(
  155. 'base_url', 'https://aqai.shudaodsj.com:22001')
  156. settings = Settings()
  157. def get_base_url() -> str:
  158. return settings.base_url
  159. def get_proxy_url(original_url: str) -> str:
  160. """将原始URL转换为代理URL(加密)"""
  161. if not original_url:
  162. return ""
  163. from .crypto import encrypt_url
  164. encrypted = encrypt_url(original_url)
  165. return f"{settings.base_url}/apiv1/oss/parse?url={encrypted}"