1 line
25 KiB
JSON
1 line
25 KiB
JSON
{"repo": "choco-robot/homebot", "files": {"software/src/configs/secrets.py": {"2b5eb736e6f8ad8fb3402ab778bcdb6229864f38": {"t": 1785674269.117423, "n": 10238, "h": "57bbad16a6dff62e", "c": "# -*- coding: utf-8 -*-\n\"\"\"密钥管理模块 - 安全加载和管理API密钥\n\n支持从环境变量和.env.local文件加载敏感配置\n确保密钥不会意外提交到版本控制\n\"\"\"\nimport os\nimport sys\nfrom pathlib import Path\nfrom typing import Optional\nfrom dataclasses import dataclass, field\n\nfrom common.logging import get_logger\n\nlogger = get_logger(__name__)\n\n\n# 项目根目录(software/)\nPROJECT_ROOT = Path(__file__).parent.parent.parent\n\n\ndef _load_env_file(env_path: Path) -> None:\n \"\"\"加载.env文件到环境变量\n \n Args:\n env_path: .env文件路径\n \"\"\"\n if not env_path.exists():\n return\n \n try:\n with open(env_path, 'r', encoding='utf-8') as f:\n for line in f:\n line = line.strip()\n # 跳过注释和空行\n if not line or line.startswith('#'):\n continue\n # 解析KEY=VALUE\n if '=' in line:\n key, value = line.split('=', 1)\n key = key.strip()\n value = value.strip().strip('\"\\'') # 去除引号\n # 只设置尚未存在的环境变量(允许用户通过系统环境变量覆盖)\n if key not in os.environ:\n os.environ[key] = value\n logger.debug(f\"已加载环境变量文件: {env_path}\")\n except Exception as e:\n logger.warning(f\"加载环境变量文件失败: {e}\")\n\n\ndef _load_all_env_files() -> None:\n \"\"\"按优先级加载所有环境变量文件\"\"\"\n # 优先级:.env.local > .env.development > .env.production > .env\n env_files = [\n PROJECT_ROOT / \".env.local\",\n PROJECT_ROOT / \".env.development\",\n PROJECT_ROOT / \".env.production\",\n PROJECT_ROOT / \".env\",\n ]\n \n for env_file in env_files:\n if env_file.exists():\n _load_env_file(env_file)\n\n\n# 模块加载时自动执行\n_load_all_env_files()\n\n\n@dataclass\nclass TTSSecrets:\n \"\"\"TTS 密钥配置\"\"\"\n appid: str = \"\"\n access_token: str = \"\"\n resource_id: str = \"seed-tts-2.0\"\n voice_type: str = \"zh_female_vv_uranus_bigtts\"\n\n\n@dataclass\nclass LLMSecrets:\n \"\"\"LLM 密钥配置\"\"\"\n api_key: str = \"\"\n api_url: str = \"https://ark.cn-beijing.volces.com/api/v3\" # 默认使用火山Ark\n model: str = \"\" # 火山Ark需要填写模型ID,如 ep-20250324123456-abcdef\n\n\n@dataclass\nclass VisionSecrets:\n \"\"\"图片理解/Vision API 密钥配置\"\"\"\n provider: str = \"deepseek\" # deepseek/qwen/openai\n api_key: str = \"\"\n api_url: str = \"\"\n model: str = \"\"\n\n\n@dataclass\nclass Secrets:\n \"\"\"所有密钥配置\"\"\"\n tts: TTSSecrets = field(default_factory=TTSSecrets)\n llm: LLMSecrets = field(default_factory=LLMSecrets)\n vision: VisionSecrets = field(default_factory=VisionSecrets)\n\n\n# 全局密钥实例\n_secrets_instance: Optional[Secrets] = None\n\n\ndef _get_env(key: str, default: str = \"\") -> str:\n \"\"\"安全获取环境变量\n \n Args:\n key: 环境变量名\n default: 默认值\n \n Returns:\n 环境变量值或默认值\n \"\"\"\n return os.environ.get(key, default)\n\n\ndef _mask_key(key: str, visible_start: int = 4, visible_end: int = 4) -> str:\n \"\"\"脱敏显示API密钥\n \n Args:\n key: 原始密钥\n visible_start: 开头显示的字符数\n visible_end: 结尾显示的字符数\n \n Returns:\n 脱敏后的密钥,如 sk-****1234\n \"\"\"\n if len(key) <= visible_start + visible_end:\n return \"*\" * len(key) if key else \"(未设置)\"\n return f\"{key[:visible_start]}****{key[-visible_end:]}\"\n\n\ndef load_secrets() -> Secrets:\n \"\"\"加载所有密钥配置\n \n 从环境变量加载敏感配置,支持多种命名方式\n \n Returns:\n Secrets: 密钥配置对象\n \"\"\"\n # TTS 配置 - 支持多种环境变量名\n tts = TTSSecrets(\n appid=_get_env(\"VOLCANO_APPID\", _get_env(\"TTS_APPID\", \"\")),\n access_token=_get_env(\"VOLCANO_ACCESS_TOKEN\", _get_env(\"TTS_ACCESS_TOKEN\", \"\")),\n resource_id=_get_env(\"VOLCANO_RESOURCE_ID\", \"seed-tts-2.0\"),\n voice_type=_get_env(\"VOLCANO_VOICE_TYPE\", \"zh_female_vv_uranus_bigtts\"),\n )\n \n # LLM 配置 - 优先使用火山Ark,兼容DeepSeek\n llm = LLMSecrets(\n api_key=_get_env(\"ARK_API_KEY\", _get_env(\"VOLCANO_API_KEY\", _get_env(\"DEEPSEEK_API_KEY\", _get_env(\"LLM_API_KEY\", \"\")))),\n api_url=_get_env(\"ARK_API_URL\", _get_env(\"LLM_API_URL\", \"https://ark.cn-beijing.volces.com/api/v3\")),\n model=_get_env(\"ARK_MODEL_ID\", _get_env(\"VOLCANO_MODEL_ID\", _get_env(\"DEEPSEEK_MODEL\", _get_env(\"LLM_MODEL\", \"\")))),\n )\n \n # Vision 配置\n vision_provider = _get_env(\"VISION_PROVIDER\", \"deepseek\")\n \n # 根据provider获取对应的配置\n vision_api_key = _get_env(\"VISION_API_KEY\", \"\")\n vision_api_url = _get_env(\"VISION_API_URL\", \"\")\n vision_model = _get_env(\"VISION_MODEL\", \"\")\n \n # 如果没有单独设置VISION配置,使用LLM的配置\n if not vision_api_key and vision_provider == \"deepseek\":\n vision_api_key = llm.api_key\n vision_api_url = llm.api_url or \"https://api.deepseek.com/v1\"\n vision_model = vision_model or \"deepseek-chat\"\n \n vision = VisionSecrets(\n provider=vision_provider,\n api_key=vision_api_key,\n api_url=vision_api_url,\n model=vision_model,\n )\n \n return Secrets(tts=tts, llm=llm, vision=vision)\n\n\ndef get_secrets() -> Secrets:\n \"\"\"获取全局密钥实例\n \n Returns:\n Secrets: 全局密钥配置实例\n \"\"\"\n global _secrets_instance\n if _secrets_instance is None:\n _secrets_instance = load_secrets()\n return _secrets_instance\n\n\ndef reload_secrets() -> Secrets:\n \"\"\"重新加载密钥配置\n \n 用于在运行时重新读取环境变量\n \n Returns:\n Secrets: 新的密钥配置实例\n \"\"\"\n global _secrets_instance\n _load_all_env_files()\n _secrets_instance = load_secrets()\n return _secrets_instance\n\n\ndef check_secrets(verbose: bool = True) -> dict:\n \"\"\"检查密钥配置状态\n \n 检查各项密钥是否已配置,并返回状态报告\n \n Args:\n verbose: 是否打印详细信息\n \n Returns:\n dict: 各服务的配置状态\n \"\"\"\n secrets = get_secrets()\n \n status = {\n \"tts\": {\n \"configured\": bool(secrets.tts.appid and secrets.tts.access_token),\n \"appid\": secrets.tts.appid[:6] + \"...\" if secrets.tts.appid else \"(未设置)\",\n \"access_token\": _mask_key(secrets.tts.access_token),\n },\n \"llm\": {\n \"configured\": bool(secrets.llm.api_key),\n \"api_key\": _mask_key(secrets.llm.api_key),\n \"model\": secrets.llm.model,\n },\n \"vision\": {\n \"configured\": bool(secrets.vision.api_key),\n \"provider\": secrets.vision.provider,\n \"api_key\": _mask_key(secrets.vision.api_key),\n },\n }\n \n if verbose:\n print(\"\\n\" + \"=\" * 50)\n print(\"HomeBot API Key Configuration Status\")\n print(\"=\" * 50)\n \n # TTS 状态\n tts_ok = status[\"tts\"][\"configured\"]\n status_icon = \"[OK]\" if tts_ok else \"[MISSING]\"\n print(f\"\\n[TTS] 火山引擎 TTS: {status_icon}\")\n if tts_ok:\n print(f\" AppID: {status['tts']['appid']}\")\n print(f\" Access Token: {status['tts']['access_token']}\")\n else:\n print(\" [提示] 设置 VOLCANO_APPID 和 VOLCANO_ACCESS_TOKEN 环境变量\")\n \n # LLM 状态\n llm_ok = status[\"llm\"][\"configured\"]\n status_icon = \"[OK]\" if llm_ok else \"[MISSING]\"\n print(f\"\\n[LLM] 火山Ark LLM: {status_icon}\")\n if llm_ok:\n print(f\" API Key: {status['llm']['api_key']}\")\n print(f\" Model: {status['llm']['model'] if status['llm']['model'] else '(未设置,必填)'}\")\n else:\n print(\" [提示] 设置 ARK_API_KEY 和 ARK_MODEL_ID 环境变量\")\n print(\" ARK_MODEL_ID 格式: ep-20250324123456-abcdef\")\n \n # Vision 状态\n vision_ok = status[\"vision\"][\"configured\"]\n status_icon = \"[OK]\" if vision_ok else \"[MISSING]\"\n print(f\"\\n[Vision] 图片理解: {status_icon}\")\n print(f\" Provider: {status['vision']['provider']}\")\n if vision_ok:\n print(f\" API Key: {status['vision']['api_key']}\")\n elif status[\"vision\"][\"provider\"] == \"deepseek\" and llm_ok:\n print(\" [提示] 将复用 DeepSeek LLM 的配置\")\n status[\"vision\"][\"configured\"] = True # 复用LLM配置\n else:\n print(\" [提示] 设置 VISION_API_KEY 环境变量\")\n \n # 配置文件路径提示\n local_env = PROJECT_ROOT / \".env.local\"\n print(f\"\\n[文件] 配置文件路径: {local_env}\")\n if not local_env.exists():\n example_env = PROJECT_ROOT / \".env.example\"\n print(f\"[提示] 复制 {example_env.name} 为 {local_env.name} 并填入密钥\")\n \n print(\"=\" * 50 + \"\\n\")\n \n return status\n\n\ndef require_secrets(service: str) -> None:\n \"\"\"检查特定服务的密钥是否已配置\n \n 如果未配置,打印帮助信息并退出程序\n \n Args:\n service: 服务名称 (tts/llm/vision)\n \"\"\"\n secrets = get_secrets()\n \n if service == \"tts\":\n if not (secrets.tts.appid and secrets.tts.access_token):\n logger.error(\"火山引擎 TTS 密钥未配置\")\n print(\"\\n[错误] 火山引擎 TTS 密钥未配置\")\n print(\"\\n请设置以下环境变量之一:\")\n print(\" 1. VOLCANO_APPID and VOLCANO_ACCESS_TOKEN\")\n print(\" 2. TTS_APPID and TTS_ACCESS_TOKEN\")\n print(f\"\\n或创建 {PROJECT_ROOT / '.env.local'} 文件,格式如下:\")\n print(\" VOLCANO_APPID=your_appid\")\n print(\" VOLCANO_ACCESS_TOKEN=your_token\")\n sys.exit(1)\n \n elif service == \"llm\":\n if not secrets.llm.api_key:\n logger.error(\"火山Ark LLM API Key 未配置\")\n print(\"\\n[错误] 火山Ark LLM API Key 未配置\")\n print(\"\\n请设置以下环境变量:\")\n print(\" ARK_API_KEY=your_api_key\")\n print(\" ARK_MODEL_ID=ep-your_model_id\")\n print(f\"\\n或创建 {PROJECT_ROOT / '.env.local'} 文件,格式如下:\")\n print(\" ARK_API_KEY=your_api_key\")\n print(\" ARK_MODEL_ID=ep-20250324123456-abcdef\")\n sys.exit(1)\n if not secrets.llm.model:\n logger.error(\"火山Ark 模型ID未配置\")\n print(\"\\n[错误] 火山Ark 模型ID未配置\")\n print(\"\\n请在 .env.local 文件中设置 ARK_MODEL_ID:\")\n print(\" ARK_MODEL_ID=ep-20250324123456-abcdef\")\n print(\"\\n注意: 需要在火山方舟控制台创建推理接入点并复制模型ID\")\n sys.exit(1)\n \n elif service == \"vision\":\n # Vision 可以复用 DeepSeek 的配置\n if not secrets.vision.api_key:\n if secrets.llm.api_key and secrets.vision.provider == \"deepseek\":\n return # 允许复用LLM配置\n logger.error(\"Vision API Key 未配置\")\n print(\"\\n[错误] Vision API Key 未配置\")\n print(\"\\n请设置以下环境变量:\")\n print(\" VISION_API_KEY\")\n print(f\"\\n或创建 {PROJECT_ROOT / '.env.local'} 文件\")\n sys.exit(1)\n\n\nif __name__ == \"__main__\":\n # 命令行检查密钥配置\n check_secrets(verbose=True)\n"}, "599258e1d553f8f6bd2dde99a005c381928cf9b7": {"t": 1785753286.8075523, "n": 10238, "h": "57bbad16a6dff62e", "c": "# -*- coding: utf-8 -*-\n\"\"\"密钥管理模块 - 安全加载和管理API密钥\n\n支持从环境变量和.env.local文件加载敏感配置\n确保密钥不会意外提交到版本控制\n\"\"\"\nimport os\nimport sys\nfrom pathlib import Path\nfrom typing import Optional\nfrom dataclasses import dataclass, field\n\nfrom common.logging import get_logger\n\nlogger = get_logger(__name__)\n\n\n# 项目根目录(software/)\nPROJECT_ROOT = Path(__file__).parent.parent.parent\n\n\ndef _load_env_file(env_path: Path) -> None:\n \"\"\"加载.env文件到环境变量\n \n Args:\n env_path: .env文件路径\n \"\"\"\n if not env_path.exists():\n return\n \n try:\n with open(env_path, 'r', encoding='utf-8') as f:\n for line in f:\n line = line.strip()\n # 跳过注释和空行\n if not line or line.startswith('#'):\n continue\n # 解析KEY=VALUE\n if '=' in line:\n key, value = line.split('=', 1)\n key = key.strip()\n value = value.strip().strip('\"\\'') # 去除引号\n # 只设置尚未存在的环境变量(允许用户通过系统环境变量覆盖)\n if key not in os.environ:\n os.environ[key] = value\n logger.debug(f\"已加载环境变量文件: {env_path}\")\n except Exception as e:\n logger.warning(f\"加载环境变量文件失败: {e}\")\n\n\ndef _load_all_env_files() -> None:\n \"\"\"按优先级加载所有环境变量文件\"\"\"\n # 优先级:.env.local > .env.development > .env.production > .env\n env_files = [\n PROJECT_ROOT / \".env.local\",\n PROJECT_ROOT / \".env.development\",\n PROJECT_ROOT / \".env.production\",\n PROJECT_ROOT / \".env\",\n ]\n \n for env_file in env_files:\n if env_file.exists():\n _load_env_file(env_file)\n\n\n# 模块加载时自动执行\n_load_all_env_files()\n\n\n@dataclass\nclass TTSSecrets:\n \"\"\"TTS 密钥配置\"\"\"\n appid: str = \"\"\n access_token: str = \"\"\n resource_id: str = \"seed-tts-2.0\"\n voice_type: str = \"zh_female_vv_uranus_bigtts\"\n\n\n@dataclass\nclass LLMSecrets:\n \"\"\"LLM 密钥配置\"\"\"\n api_key: str = \"\"\n api_url: str = \"https://ark.cn-beijing.volces.com/api/v3\" # 默认使用火山Ark\n model: str = \"\" # 火山Ark需要填写模型ID,如 ep-20250324123456-abcdef\n\n\n@dataclass\nclass VisionSecrets:\n \"\"\"图片理解/Vision API 密钥配置\"\"\"\n provider: str = \"deepseek\" # deepseek/qwen/openai\n api_key: str = \"\"\n api_url: str = \"\"\n model: str = \"\"\n\n\n@dataclass\nclass Secrets:\n \"\"\"所有密钥配置\"\"\"\n tts: TTSSecrets = field(default_factory=TTSSecrets)\n llm: LLMSecrets = field(default_factory=LLMSecrets)\n vision: VisionSecrets = field(default_factory=VisionSecrets)\n\n\n# 全局密钥实例\n_secrets_instance: Optional[Secrets] = None\n\n\ndef _get_env(key: str, default: str = \"\") -> str:\n \"\"\"安全获取环境变量\n \n Args:\n key: 环境变量名\n default: 默认值\n \n Returns:\n 环境变量值或默认值\n \"\"\"\n return os.environ.get(key, default)\n\n\ndef _mask_key(key: str, visible_start: int = 4, visible_end: int = 4) -> str:\n \"\"\"脱敏显示API密钥\n \n Args:\n key: 原始密钥\n visible_start: 开头显示的字符数\n visible_end: 结尾显示的字符数\n \n Returns:\n 脱敏后的密钥,如 sk-****1234\n \"\"\"\n if len(key) <= visible_start + visible_end:\n return \"*\" * len(key) if key else \"(未设置)\"\n return f\"{key[:visible_start]}****{key[-visible_end:]}\"\n\n\ndef load_secrets() -> Secrets:\n \"\"\"加载所有密钥配置\n \n 从环境变量加载敏感配置,支持多种命名方式\n \n Returns:\n Secrets: 密钥配置对象\n \"\"\"\n # TTS 配置 - 支持多种环境变量名\n tts = TTSSecrets(\n appid=_get_env(\"VOLCANO_APPID\", _get_env(\"TTS_APPID\", \"\")),\n access_token=_get_env(\"VOLCANO_ACCESS_TOKEN\", _get_env(\"TTS_ACCESS_TOKEN\", \"\")),\n resource_id=_get_env(\"VOLCANO_RESOURCE_ID\", \"seed-tts-2.0\"),\n voice_type=_get_env(\"VOLCANO_VOICE_TYPE\", \"zh_female_vv_uranus_bigtts\"),\n )\n \n # LLM 配置 - 优先使用火山Ark,兼容DeepSeek\n llm = LLMSecrets(\n api_key=_get_env(\"ARK_API_KEY\", _get_env(\"VOLCANO_API_KEY\", _get_env(\"DEEPSEEK_API_KEY\", _get_env(\"LLM_API_KEY\", \"\")))),\n api_url=_get_env(\"ARK_API_URL\", _get_env(\"LLM_API_URL\", \"https://ark.cn-beijing.volces.com/api/v3\")),\n model=_get_env(\"ARK_MODEL_ID\", _get_env(\"VOLCANO_MODEL_ID\", _get_env(\"DEEPSEEK_MODEL\", _get_env(\"LLM_MODEL\", \"\")))),\n )\n \n # Vision 配置\n vision_provider = _get_env(\"VISION_PROVIDER\", \"deepseek\")\n \n # 根据provider获取对应的配置\n vision_api_key = _get_env(\"VISION_API_KEY\", \"\")\n vision_api_url = _get_env(\"VISION_API_URL\", \"\")\n vision_model = _get_env(\"VISION_MODEL\", \"\")\n \n # 如果没有单独设置VISION配置,使用LLM的配置\n if not vision_api_key and vision_provider == \"deepseek\":\n vision_api_key = llm.api_key\n vision_api_url = llm.api_url or \"https://api.deepseek.com/v1\"\n vision_model = vision_model or \"deepseek-chat\"\n \n vision = VisionSecrets(\n provider=vision_provider,\n api_key=vision_api_key,\n api_url=vision_api_url,\n model=vision_model,\n )\n \n return Secrets(tts=tts, llm=llm, vision=vision)\n\n\ndef get_secrets() -> Secrets:\n \"\"\"获取全局密钥实例\n \n Returns:\n Secrets: 全局密钥配置实例\n \"\"\"\n global _secrets_instance\n if _secrets_instance is None:\n _secrets_instance = load_secrets()\n return _secrets_instance\n\n\ndef reload_secrets() -> Secrets:\n \"\"\"重新加载密钥配置\n \n 用于在运行时重新读取环境变量\n \n Returns:\n Secrets: 新的密钥配置实例\n \"\"\"\n global _secrets_instance\n _load_all_env_files()\n _secrets_instance = load_secrets()\n return _secrets_instance\n\n\ndef check_secrets(verbose: bool = True) -> dict:\n \"\"\"检查密钥配置状态\n \n 检查各项密钥是否已配置,并返回状态报告\n \n Args:\n verbose: 是否打印详细信息\n \n Returns:\n dict: 各服务的配置状态\n \"\"\"\n secrets = get_secrets()\n \n status = {\n \"tts\": {\n \"configured\": bool(secrets.tts.appid and secrets.tts.access_token),\n \"appid\": secrets.tts.appid[:6] + \"...\" if secrets.tts.appid else \"(未设置)\",\n \"access_token\": _mask_key(secrets.tts.access_token),\n },\n \"llm\": {\n \"configured\": bool(secrets.llm.api_key),\n \"api_key\": _mask_key(secrets.llm.api_key),\n \"model\": secrets.llm.model,\n },\n \"vision\": {\n \"configured\": bool(secrets.vision.api_key),\n \"provider\": secrets.vision.provider,\n \"api_key\": _mask_key(secrets.vision.api_key),\n },\n }\n \n if verbose:\n print(\"\\n\" + \"=\" * 50)\n print(\"HomeBot API Key Configuration Status\")\n print(\"=\" * 50)\n \n # TTS 状态\n tts_ok = status[\"tts\"][\"configured\"]\n status_icon = \"[OK]\" if tts_ok else \"[MISSING]\"\n print(f\"\\n[TTS] 火山引擎 TTS: {status_icon}\")\n if tts_ok:\n print(f\" AppID: {status['tts']['appid']}\")\n print(f\" Access Token: {status['tts']['access_token']}\")\n else:\n print(\" [提示] 设置 VOLCANO_APPID 和 VOLCANO_ACCESS_TOKEN 环境变量\")\n \n # LLM 状态\n llm_ok = status[\"llm\"][\"configured\"]\n status_icon = \"[OK]\" if llm_ok else \"[MISSING]\"\n print(f\"\\n[LLM] 火山Ark LLM: {status_icon}\")\n if llm_ok:\n print(f\" API Key: {status['llm']['api_key']}\")\n print(f\" Model: {status['llm']['model'] if status['llm']['model'] else '(未设置,必填)'}\")\n else:\n print(\" [提示] 设置 ARK_API_KEY 和 ARK_MODEL_ID 环境变量\")\n print(\" ARK_MODEL_ID 格式: ep-20250324123456-abcdef\")\n \n # Vision 状态\n vision_ok = status[\"vision\"][\"configured\"]\n status_icon = \"[OK]\" if vision_ok else \"[MISSING]\"\n print(f\"\\n[Vision] 图片理解: {status_icon}\")\n print(f\" Provider: {status['vision']['provider']}\")\n if vision_ok:\n print(f\" API Key: {status['vision']['api_key']}\")\n elif status[\"vision\"][\"provider\"] == \"deepseek\" and llm_ok:\n print(\" [提示] 将复用 DeepSeek LLM 的配置\")\n status[\"vision\"][\"configured\"] = True # 复用LLM配置\n else:\n print(\" [提示] 设置 VISION_API_KEY 环境变量\")\n \n # 配置文件路径提示\n local_env = PROJECT_ROOT / \".env.local\"\n print(f\"\\n[文件] 配置文件路径: {local_env}\")\n if not local_env.exists():\n example_env = PROJECT_ROOT / \".env.example\"\n print(f\"[提示] 复制 {example_env.name} 为 {local_env.name} 并填入密钥\")\n \n print(\"=\" * 50 + \"\\n\")\n \n return status\n\n\ndef require_secrets(service: str) -> None:\n \"\"\"检查特定服务的密钥是否已配置\n \n 如果未配置,打印帮助信息并退出程序\n \n Args:\n service: 服务名称 (tts/llm/vision)\n \"\"\"\n secrets = get_secrets()\n \n if service == \"tts\":\n if not (secrets.tts.appid and secrets.tts.access_token):\n logger.error(\"火山引擎 TTS 密钥未配置\")\n print(\"\\n[错误] 火山引擎 TTS 密钥未配置\")\n print(\"\\n请设置以下环境变量之一:\")\n print(\" 1. VOLCANO_APPID and VOLCANO_ACCESS_TOKEN\")\n print(\" 2. TTS_APPID and TTS_ACCESS_TOKEN\")\n print(f\"\\n或创建 {PROJECT_ROOT / '.env.local'} 文件,格式如下:\")\n print(\" VOLCANO_APPID=your_appid\")\n print(\" VOLCANO_ACCESS_TOKEN=your_token\")\n sys.exit(1)\n \n elif service == \"llm\":\n if not secrets.llm.api_key:\n logger.error(\"火山Ark LLM API Key 未配置\")\n print(\"\\n[错误] 火山Ark LLM API Key 未配置\")\n print(\"\\n请设置以下环境变量:\")\n print(\" ARK_API_KEY=your_api_key\")\n print(\" ARK_MODEL_ID=ep-your_model_id\")\n print(f\"\\n或创建 {PROJECT_ROOT / '.env.local'} 文件,格式如下:\")\n print(\" ARK_API_KEY=your_api_key\")\n print(\" ARK_MODEL_ID=ep-20250324123456-abcdef\")\n sys.exit(1)\n if not secrets.llm.model:\n logger.error(\"火山Ark 模型ID未配置\")\n print(\"\\n[错误] 火山Ark 模型ID未配置\")\n print(\"\\n请在 .env.local 文件中设置 ARK_MODEL_ID:\")\n print(\" ARK_MODEL_ID=ep-20250324123456-abcdef\")\n print(\"\\n注意: 需要在火山方舟控制台创建推理接入点并复制模型ID\")\n sys.exit(1)\n \n elif service == \"vision\":\n # Vision 可以复用 DeepSeek 的配置\n if not secrets.vision.api_key:\n if secrets.llm.api_key and secrets.vision.provider == \"deepseek\":\n return # 允许复用LLM配置\n logger.error(\"Vision API Key 未配置\")\n print(\"\\n[错误] Vision API Key 未配置\")\n print(\"\\n请设置以下环境变量:\")\n print(\" VISION_API_KEY\")\n print(f\"\\n或创建 {PROJECT_ROOT / '.env.local'} 文件\")\n sys.exit(1)\n\n\nif __name__ == \"__main__\":\n # 命令行检查密钥配置\n check_secrets(verbose=True)\n"}}}} |