2026-03-18 17:18:23 +08:00
|
|
|
|
"""
|
|
|
|
|
|
统一配置:所有环境变量通过此模块的 Settings 单点读取。
|
|
|
|
|
|
业务代码只允许 import settings,禁止散落 os.getenv() / load_dotenv()。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
import secrets
|
|
|
|
|
|
|
|
|
|
|
|
from pydantic import Field
|
|
|
|
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
|
|
|
|
model_config = SettingsConfigDict(
|
|
|
|
|
|
env_file=".env",
|
|
|
|
|
|
env_file_encoding="utf-8",
|
|
|
|
|
|
case_sensitive=False,
|
|
|
|
|
|
extra="ignore",
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# ── Database ──────────────────────────────────────────────
|
|
|
|
|
|
database_url: str = "postgresql://postgres:postgres@localhost:5432/life_echo"
|
|
|
|
|
|
|
|
|
|
|
|
# ── Redis ─────────────────────────────────────────────────
|
|
|
|
|
|
redis_url: str = "redis://localhost:6379/0"
|
|
|
|
|
|
redis_session_ttl: int = 86400
|
|
|
|
|
|
|
|
|
|
|
|
# ── Auth / JWT ────────────────────────────────────────────
|
|
|
|
|
|
secret_key: str = Field(default_factory=lambda: secrets.token_urlsafe(32))
|
|
|
|
|
|
algorithm: str = "HS256"
|
|
|
|
|
|
access_token_expire_minutes: int = 120
|
|
|
|
|
|
refresh_token_expire_days: int = 30
|
|
|
|
|
|
|
|
|
|
|
|
# ── LLM / DeepSeek ───────────────────────────────────────
|
|
|
|
|
|
deepseek_api_key: str = ""
|
|
|
|
|
|
deepseek_base_url: str = "https://api.deepseek.com"
|
|
|
|
|
|
deepseek_model: str = "deepseek-chat"
|
|
|
|
|
|
llm_api_key: str = ""
|
|
|
|
|
|
llm_base_url: str = ""
|
|
|
|
|
|
llm_model: str = ""
|
|
|
|
|
|
llm_temperature: float = 0.7
|
|
|
|
|
|
|
|
|
|
|
|
# ── ASR ───────────────────────────────────────────────────
|
|
|
|
|
|
asr_provider: str = "whisper"
|
|
|
|
|
|
asr_model_size: str = "small"
|
|
|
|
|
|
asr_device: str = "auto"
|
|
|
|
|
|
asr_compute_type: str = "auto"
|
|
|
|
|
|
asr_model_cache_dir: str = ""
|
|
|
|
|
|
|
|
|
|
|
|
# ── Tencent SMS ──────────────────────────────────────────
|
|
|
|
|
|
tencent_sms_secret_id: str = ""
|
|
|
|
|
|
tencent_sms_secret_key: str = ""
|
|
|
|
|
|
tencent_sms_sdk_app_id: str = ""
|
|
|
|
|
|
tencent_sms_sign_name: str = ""
|
|
|
|
|
|
tencent_sms_template_id: str = ""
|
|
|
|
|
|
tencent_sms_template_param_count: int = 2
|
|
|
|
|
|
|
|
|
|
|
|
# ── Tencent ASR ──────────────────────────────────────────
|
|
|
|
|
|
tencent_secret_id: str = ""
|
|
|
|
|
|
tencent_secret_key: str = ""
|
|
|
|
|
|
tencent_asr_app_id: str = ""
|
|
|
|
|
|
|
2026-03-20 15:15:35 +08:00
|
|
|
|
# ── TTS (openai | tencent),与 ASR 独立:仅控制回复侧语音合成 ──
|
|
|
|
|
|
enable_tts: bool = True
|
2026-03-19 09:58:02 +08:00
|
|
|
|
tts_provider: str = "tencent"
|
2026-03-18 17:18:23 +08:00
|
|
|
|
openai_api_key: str = ""
|
2026-03-19 14:14:13 +08:00
|
|
|
|
tts_voice_type: int = 502001 # Tencent 音色 ID,见 https://cloud.tencent.com/document/product/1073/92668
|
2026-03-19 09:11:25 +08:00
|
|
|
|
tts_codec: str = "mp3"
|
2026-03-18 17:18:23 +08:00
|
|
|
|
|
|
|
|
|
|
# ── WeChat Pay ───────────────────────────────────────────
|
|
|
|
|
|
wechat_pay_app_id: str = ""
|
|
|
|
|
|
wechat_pay_mch_id: str = ""
|
|
|
|
|
|
wechat_pay_api_v3_key: str = ""
|
|
|
|
|
|
wechat_pay_private_key_path: str = "certs/apiclient_key.pem"
|
|
|
|
|
|
wechat_pay_private_key: str = "" # PEM 内容,与 private_key_path 二选一
|
|
|
|
|
|
wechat_pay_cert_serial_no: str = ""
|
|
|
|
|
|
wechat_pay_notify_url: str = ""
|
|
|
|
|
|
wechat_pay_platform_public_key: str = ""
|
|
|
|
|
|
wechat_pay_platform_public_key_path: str = ""
|
|
|
|
|
|
wechat_pay_platform_public_key_id: str = ""
|
|
|
|
|
|
|
|
|
|
|
|
# ── Alipay ───────────────────────────────────────────────
|
|
|
|
|
|
alipay_app_id: str = ""
|
|
|
|
|
|
alipay_private_key: str = ""
|
|
|
|
|
|
alipay_public_key: str = ""
|
|
|
|
|
|
alipay_notify_url: str = ""
|
|
|
|
|
|
alipay_sign_type: str = "RSA2"
|
|
|
|
|
|
alipay_under_development: str = "true" # "1"/"true"/"yes" 视为开发中不可用
|
|
|
|
|
|
|
2026-03-22 16:45:57 +08:00
|
|
|
|
# ── Logging ──────────────────────────────────────────────
|
|
|
|
|
|
# 环境变量 LOG_LEVEL;控制 loguru sink 最低级别(TRACE/DEBUG/INFO/…)
|
|
|
|
|
|
log_level: str = "INFO"
|
|
|
|
|
|
|
2026-03-18 17:18:23 +08:00
|
|
|
|
# ── Misc ─────────────────────────────────────────────────
|
|
|
|
|
|
enable_test_subscription: int = 0
|
|
|
|
|
|
enable_test_plan: str = "" # "1" / "true" / "yes" 为 True
|
|
|
|
|
|
enable_docs: bool = True
|
|
|
|
|
|
migration_database_url: str = "" # 脚本迁移用,空则用 database_url
|
|
|
|
|
|
|
|
|
|
|
|
# ── Memoir Image ─────────────────────────────────────────
|
|
|
|
|
|
memoir_image_enabled: bool = False
|
|
|
|
|
|
memoir_image_max_per_chapter: int = 2
|
|
|
|
|
|
memoir_image_poll_interval: int = 3
|
|
|
|
|
|
memoir_image_max_attempts: int = 20
|
|
|
|
|
|
memoir_image_chars_per_extra: int = 1500
|
|
|
|
|
|
memoir_image_max_cap: int = 8
|
|
|
|
|
|
memoir_image_provider: str = "liblib"
|
|
|
|
|
|
memoir_image_style_default: str = "watercolor"
|
|
|
|
|
|
memoir_image_size_default: str = "1280x720"
|
|
|
|
|
|
memoir_image_download_hosts: str = ""
|
|
|
|
|
|
|
|
|
|
|
|
# ── Liblib ───────────────────────────────────────────────
|
|
|
|
|
|
liblib_access_key: str = ""
|
|
|
|
|
|
liblib_secret_key: str = ""
|
|
|
|
|
|
liblib_base_url: str = "https://openapi.liblibai.cloud"
|
|
|
|
|
|
liblib_template_uuid: str = ""
|
|
|
|
|
|
|
|
|
|
|
|
# ── Tencent COS ──────────────────────────────────────────
|
|
|
|
|
|
tencent_cos_secret_id: str = ""
|
|
|
|
|
|
tencent_cos_secret_key: str = ""
|
|
|
|
|
|
tencent_cos_region: str = "ap-shanghai"
|
|
|
|
|
|
tencent_cos_bucket: str = ""
|
|
|
|
|
|
tencent_cos_base_url: str = ""
|
|
|
|
|
|
tencent_cos_token: str = ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
settings = Settings()
|