统一 voc_llm 密钥解析与默认模型;向量化改为本地 mlx 模型;更新 README、gitignore 与流水线文档。 Co-authored-by: Cursor <cursoragent@cursor.com>
74 lines
2.5 KiB
Python
74 lines
2.5 KiB
Python
"""
|
||
VOC 流水线 Chat 模型配置(DeepSeek OpenAI 兼容 API)。
|
||
|
||
密钥(任选其一)::
|
||
export DEEPSEEK_API_KEY="sk-..."
|
||
export DEEPSEEK_API_KEY_FILE="/path/to/key.txt"
|
||
项目根单行文件 .deepseek_key
|
||
|
||
模型::
|
||
默认 deepseek-v4-pro;可用 DEEPSEEK_MODEL 覆盖。
|
||
流水线默认关闭思考(extra_body thinking disabled);报告等单独开启处见 voc_report。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import os
|
||
from pathlib import Path
|
||
from typing import Any, Dict
|
||
|
||
from openai import OpenAI
|
||
|
||
PROJECT_ROOT = Path(__file__).resolve().parent
|
||
|
||
CHAT_BASE_URL = os.environ.get("DEEPSEEK_BASE_URL", "https://api.deepseek.com").strip()
|
||
CHAT_MODEL = os.environ.get("DEEPSEEK_MODEL", "deepseek-v4-pro").strip()
|
||
|
||
|
||
def resolve_chat_api_key() -> str:
|
||
"""环境变量 > DEEPSEEK_API_KEY_FILE > 项目根 .deepseek_key。"""
|
||
v = os.environ.get("DEEPSEEK_API_KEY", "").strip()
|
||
if v:
|
||
return v
|
||
fp = os.environ.get("DEEPSEEK_API_KEY_FILE", "").strip()
|
||
if fp:
|
||
p = Path(fp).expanduser()
|
||
if p.is_file():
|
||
return p.read_text(encoding="utf-8").strip().strip('"').strip("'")
|
||
local = PROJECT_ROOT / ".deepseek_key"
|
||
if local.is_file():
|
||
return local.read_text(encoding="utf-8").strip().strip('"').strip("'")
|
||
# 兼容:仅有 .dashscope_key 时提示(DashScope 密钥不能用于 api.deepseek.com)
|
||
legacy = PROJECT_ROOT / ".dashscope_key"
|
||
if legacy.is_file():
|
||
raise RuntimeError(
|
||
"检测到 .dashscope_key,但 Chat 已切换为 DeepSeek。"
|
||
"请在项目根创建 .deepseek_key(单行 DEEPSEEK 密钥),"
|
||
"或执行 export DEEPSEEK_API_KEY='sk-...'"
|
||
)
|
||
return ""
|
||
|
||
|
||
def require_chat_api_key() -> str:
|
||
key = resolve_chat_api_key()
|
||
if not key:
|
||
raise RuntimeError(
|
||
"缺少 DeepSeek API Key:设置 DEEPSEEK_API_KEY,"
|
||
"或 DEEPSEEK_API_KEY_FILE,或在项目根创建 .deepseek_key(单行)"
|
||
)
|
||
return key
|
||
|
||
|
||
def create_chat_client(*, api_key: str | None = None, timeout: float | None = None) -> OpenAI:
|
||
kw: Dict[str, Any] = {
|
||
"api_key": api_key or require_chat_api_key(),
|
||
"base_url": CHAT_BASE_URL,
|
||
}
|
||
if timeout is not None:
|
||
kw["timeout"] = timeout
|
||
return OpenAI(**kw)
|
||
|
||
|
||
def chat_extra_body(model: str | None = None) -> Dict[str, Any]:
|
||
"""流水线 Chat 默认关闭思考(Pro 模型 API 默认 otherwise 为 enabled)。"""
|
||
_ = (model or CHAT_MODEL).lower()
|
||
return {"thinking": {"type": "disabled"}}
|