将 DeepSeek Web 对话能力转换为 OpenAI、Claude 与 Gemini 兼容 API。后端为 Go 全量实现,前端为 React WebUI 管理台(源码在 webui/,部署时自动构建到 static/admin)。
【感谢Linux.do社区及GitHub社区各位开发者对项目的支持与贡献】
重要免责声明
本仓库仅供学习、研究、个人实验和内部验证使用,不提供任何形式的商业授权、适用性保证或结果保证。
作者及仓库维护者不对因使用、修改、分发、部署或依赖本项目而产生的任何直接或间接损失、账号封禁、数据丢失、法律风险或第三方索赔负责。
请勿将本项目用于违反服务条款、协议、法律法规或平台规则的场景。商业使用前请自行确认
LICENSE、相关协议以及你是否获得了作者的书面许可。
flowchart LR
Client["🖥️ 客户端 / SDK\n(OpenAI / Claude / Gemini)"]
Upstream["☁️ DeepSeek API"]
subgraph DS2API["DS2API 4.x(模块化 HTTP surface + PromptCompat 内核)"]
Router["chi Router + 中间件\n(RequestID / RealIP / Logger / Recoverer / CORS)"]
subgraph HTTP["HTTP API surface"]
OA["OpenAI\nchat / responses / files / embeddings"]
CA["Claude\n/anthropic/* + /v1/messages"]
GA["Gemini\n/v1beta/models/* + /v1/models/*"]
Admin["Admin API\n资源子包"]
WebUI["WebUI\n/admin(静态托管)"]
Vercel["Vercel Node Stream\n/v1/chat/completions"]
end
subgraph Runtime["运行时核心能力"]
Compat["PromptCompat\n(API -> 网页纯文本上下文)"]
Chat["Chat / Responses Runtime\n(统一工具调用与流式语义)"]
Auth["Auth Resolver\n(API key / bearer / x-goog-api-key)"]
Pool["Account Pool + Queue\n(并发槽位 + 等待队列)"]
DSClient["DeepSeek Client\n(Session / Auth / Completion / Files)"]
Pow["PoW 实现\n(纯 Go)"]
Tool["Tool Sieve\n(Go/Node 语义对齐)"]
History["History Split\n(长历史文件化)"]
end
end
Client --> Router
Router --> OA & CA & GA
Router --> Admin
Router --> WebUI
Router --> Vercel
OA --> Compat
CA & GA --> Compat
Compat --> Chat
Compat -.长历史.-> History
Vercel -.Go prepare.-> Chat
Vercel -.Node SSE.-> Tool
Chat --> Auth
Chat -.账号轮询.-> Pool
Chat -.工具调用解析.-> Tool
Chat -.PoW 计算.-> Pow
Auth --> DSClient
DSClient --> Upstream
Upstream --> DSClient
Chat --> Client
Vercel --> Client
详细架构拆分与目录职责见 docs/ARCHITECTURE.md。
- 后端:Go(
cmd/ds2api/、api/、internal/),不依赖 Python 运行时 - 前端:React 管理台(
webui/),运行时托管静态构建产物 - 部署:本地运行、Docker、Vercel Serverless、Linux systemd
| 能力 | 说明 |
|---|---|
| OpenAI 兼容 | GET /v1/models、GET /v1/models/{id}、POST /v1/chat/completions、POST /v1/responses、GET /v1/responses/{response_id}、POST /v1/embeddings、POST /v1/files |
| Claude 兼容 | GET /anthropic/v1/models、POST /anthropic/v1/messages、POST /anthropic/v1/messages/count_tokens(及快捷路径 /v1/messages、/messages) |
| Gemini 兼容 | POST /v1beta/models/{model}:generateContent、POST /v1beta/models/{model}:streamGenerateContent(及 /v1/models/{model}:* 路径) |
| 统一 CORS 兼容 | /v1/*、/anthropic/*、/v1beta/models/*、/admin/* 统一走同一套 CORS 策略;Vercel 上 /v1/chat/completions 的 Node Runtime 也对齐相同放行规则,尽量减少第三方预检请求头限制 |
| 多账号轮询 | 自动 token 刷新、邮箱/手机号双登录方式 |
| 并发队列控制 | 每账号 in-flight 上限 + 等待队列,动态计算建议并发值 |
| DeepSeek PoW | 纯 Go 高性能实现(DeepSeekHashV1),毫秒级响应 |
| Tool Calling | 防泄漏处理:非代码块高置信特征识别、delta.tool_calls 早发、结构化增量输出 |
| Admin API | 配置管理、运行时设置热更新、代理管理、账号测试 / 批量测试、会话清理、导入导出、Vercel 同步、版本检查 |
| WebUI 管理台 | /admin 单页应用(中英文双语、深色模式,支持查看服务器端对话记录) |
| 运维探针 | GET /healthz(存活)、GET /readyz(就绪) |
| 级别 | 平台 | 当前状态 |
|---|---|---|
| P0 | Codex CLI/SDK(wire_api=chat / wire_api=responses) |
✅ |
| P0 | OpenAI SDK(JS/Python,chat + responses) | ✅ |
| P0 | Vercel AI SDK(openai-compatible) | ✅ |
| P0 | Anthropic SDK(messages) | ✅ |
| P0 | Google Gemini SDK(generateContent) | ✅ |
| P1 | LangChain / LlamaIndex / OpenWebUI(OpenAI 兼容接入) | ✅ |
| 模型类型 | 模型 ID | thinking | search |
|---|---|---|---|
| default | deepseek-v4-flash |
默认开启,可由请求参数控制 | ❌ |
| expert | deepseek-v4-pro |
默认开启,可由请求参数控制 | ❌ |
| default | deepseek-v4-flash-search |
默认开启,可由请求参数控制 | ✅ |
| expert | deepseek-v4-pro-search |
默认开启,可由请求参数控制 | ✅ |
| vision | deepseek-v4-vision |
默认开启,可由请求参数控制 | ❌ |
| vision | deepseek-v4-vision-search |
默认开启,可由请求参数控制 | ✅ |
除原生模型外,也支持常见 alias 输入(如 gpt-4.1、gpt-5、gpt-5-codex、o3、claude-*、gemini-* 等),但 /v1/models 返回的是规范化后的 DeepSeek 原生模型 ID。完整 alias 行为以 API.md 和 config.example.json 为准。
| 当前常用模型 | 默认映射 |
|---|---|
claude-sonnet-4-6 |
deepseek-v4-flash |
claude-haiku-4-5(兼容 claude-3-5-haiku-latest) |
deepseek-v4-flash |
claude-opus-4-6 |
deepseek-v4-pro |
可通过配置中的 model_aliases 覆盖映射关系。
/anthropic/v1/models 除上述主别名外,还会返回 Claude 4.x snapshots、3.x 历史模型 ID 与常见 alias,便于旧客户端直接兼容。
ANTHROPIC_BASE_URL推荐直接指向 DS2API 根地址(例如http://127.0.0.1:5001),Claude Code 会请求/v1/messages?beta=true。ANTHROPIC_API_KEY需要与config.json中keys一致;建议同时保留常规 key 与sk-ant-*形态 key,兼容不同客户端校验习惯。- 若系统设置了代理,建议对 DS2API 地址配置
NO_PROXY=127.0.0.1,localhost,<你的主机IP>,避免本地回环请求被代理拦截。 - 如遇“工具调用输出成文本、未执行”问题,请优先检查模型输出是否为当前唯一受支持的 XML 工具块:
<tool_calls><invoke name="..."><parameter name="...">...,而不是旧式<tools>/<tool_call>/<tool_name>/<param>、<function_call>、tool_use或纯 JSONtool_calls片段。
Gemini 适配器将模型名通过 model_aliases 或内置规则映射到 DeepSeek 原生模型,支持 generateContent 和 streamGenerateContent 两种调用方式,并完整支持 Tool Calling(functionDeclarations → functionCall 输出)。
推荐按以下顺序选择部署方式:
- 下载 Release 构建包运行:最省事,产物已编译完成,最适合大多数用户。
- Docker / GHCR 镜像部署:适合需要容器化、编排或云环境部署。
- Vercel 部署:适合已有 Vercel 环境且接受其平台约束的场景。
- 本地源码运行 / 自行编译:适合开发、调试或需要自行修改代码的场景。
把 config.json 作为唯一配置源(推荐做法):
cp config.example.json config.json
# 编辑 config.json后续部署建议:
- 本地运行:直接读取
config.json - Docker / Vercel:由
config.json生成DS2API_CONFIG_JSON(Base64)注入环境变量,也可以直接写原始 JSON
WebUI 管理台里的“全量配置模板”也直接复用同一份 config.example.json,所以更新示例文件后,前端模板会自动保持一致。
每次发布 Release 时,GitHub Actions 会自动构建多平台二进制包:
# 下载对应平台的压缩包后
tar -xzf ds2api_<tag>_linux_amd64.tar.gz
cd ds2api_<tag>_linux_amd64
cp config.example.json config.json
# 编辑 config.json
./ds2api# 1. 准备环境变量和配置文件
cp .env.example .env
cp config.example.json config.json
# 2. 编辑 .env(至少设置 DS2API_ADMIN_KEY;如需修改宿主机端口,可额外设置 DS2API_HOST_PORT)
# DS2API_ADMIN_KEY=请替换为强密码
# 3. 启动
docker-compose up -d
# 4. 查看日志
docker-compose logs -f默认 docker-compose.yml 会把宿主机 6011 映射到容器内的 5001。如果你希望直接对外暴露 5001,请设置 DS2API_HOST_PORT=5001(或者手动调整 ports 配置)。
更新镜像:docker-compose up -d --build
- 点击上方 “Deploy on Zeabur” 按钮,一键部署。
- 部署完成后访问
/admin,使用 Zeabur 环境变量/模板指引中的DS2API_ADMIN_KEY登录。 - 在管理台导入/编辑配置(会写入并持久化到
/data/config.json)。
说明:Zeabur 使用仓库内 Dockerfile 直接构建时,不需要额外传入 BUILD_VERSION;镜像会优先读取该构建参数,未提供时自动回退到仓库根目录的 VERSION 文件。
- Fork 仓库到自己的 GitHub
- 在 Vercel 上导入项目
- 配置环境变量(最少设置
DS2API_ADMIN_KEY;推荐同时设置DS2API_CONFIG_JSON) - 部署
建议先在仓库目录复制模板并填写:
cp config.example.json config.json
# 编辑 config.json推荐:先本地把 config.json 转成 Base64,再粘贴到 DS2API_CONFIG_JSON,避免 JSON 格式错误:
base64 < config.json | tr -d '\n'流式说明:
/v1/chat/completions在 Vercel 上默认走api/chat-stream.js(Node Runtime)以保证实时 SSE。鉴权、账号选择、会话/PoW 准备仍由 Go 内部 prepare 接口完成;流式响应(含tools)在 Node 侧执行与 Go 对齐的输出组装与防泄漏处理。虽然这里只有 OpenAI chat 流式走 Node,但 CORS 放行策略仍与 Go 主路由保持一致,统一覆盖第三方客户端预检场景。
详细部署说明请参阅 部署指南。
前置要求:Go 1.26+,Node.js 20.19+ 或 22.12+(仅在需要构建 WebUI 时)
# 1. 克隆仓库
git clone https://github.com/CJackHwang/ds2api.git
cd ds2api
# 2. 配置
cp config.example.json config.json
# 编辑 config.json,填入你的 DeepSeek 账号信息和 API key
# 3. 启动
go run ./cmd/ds2api默认本地访问地址:http://127.0.0.1:5001
服务实际绑定:0.0.0.0:5001,因此同一局域网设备通常也可以通过你的内网 IP 访问。
WebUI 自动构建:本地首次启动时,若
static/admin不存在,会自动尝试执行npm ci(仅在缺少依赖时)和npm run build -- --outDir static/admin --emptyOutDir(需要本机有 Node.js)。你也可以手动构建:./scripts/build-webui.sh
README 只保留快速入口,完整字段请以 config.example.json 为模板,并参考 部署指南 与 API 配置最佳实践。
常用字段:
keys/api_keys:客户端访问密钥,api_keys支持name与remark元信息,keys继续兼容。accounts:DeepSeek 托管账号,支持email或mobile登录,可配置代理、名称和备注。model_aliases:OpenAI / Claude / Gemini 共用的模型 alias 映射。runtime:账号并发、队列与 token 刷新策略,可通过 Admin Settings 热更新。auto_delete.mode:请求结束后的远端会话清理策略,支持none/single/all。history_split:多轮历史拆分策略,已全局强制开启;可调整触发阈值,避免长历史全部内联进 prompt。
环境变量完整列表见 部署指南,接口鉴权规则见 API.md。
调用业务接口(/v1/*、/anthropic/*、Gemini 路由)时支持两种模式:
| 模式 | 说明 |
|---|---|
| 托管账号模式 | Bearer 或 x-api-key 传入 config.keys 中的 key,由服务自动轮询选择账号 |
| 直通 token 模式 | 传入 token 不在 config.keys 中时,直接作为 DeepSeek token 使用 |
可选请求头 X-Ds2-Target-Account:指定使用某个托管账号(值为 email 或 mobile)。
Gemini 路由还可以使用 x-goog-api-key,或在没有认证头时使用 ?key= / ?api_key= 作为调用方凭据。
每账号可用并发 = DS2API_ACCOUNT_MAX_INFLIGHT(默认 2)
建议并发值 = 账号数量 × 每账号并发上限
等待队列上限 = DS2API_ACCOUNT_MAX_QUEUE(默认 = 建议并发值)
429 阈值 = in-flight + 等待队列 ≈ 账号数量 × 4
- 当 in-flight 槽位满时,请求进入等待队列,不会立即 429
- 超出总承载上限后才返回
429 Too Many Requests GET /admin/queue/status返回实时并发状态
当请求中带 tools 时,DS2API 会做防泄漏处理与结构化转译:
- 只在非代码块上下文启用执行型 toolcall 识别(代码块示例默认不触发)
- 解析层当前只把 canonical XML 工具块视为可执行调用:
<tool_calls>→<invoke name="...">→<parameter name="...">;旧式<tools>/<tool_call>/<tool_name>/<param>、<function_call>、tool_use/ antml 变体与纯 JSONtool_calls片段都会按普通文本处理 responses流式严格使用官方 item 生命周期事件(response.output_item.*、response.content_part.*、response.function_call_arguments.*)responses支持并执行tool_choice(auto/none/required/强制函数);required违规时非流式返回422,流式返回response.failed- 客户端请求哪种协议,就按该协议返回工具调用(OpenAI/Claude/Gemini 各自原生结构);模型侧优先约束输出规范 XML,再由兼容层转译
说明:当前版本在 parser 层仍以“尽量解析成功”为优先,未启用基于 allow-list 的工具名硬拒绝。
想评估“把工具调用封装成 XML 再输入模型”的方案,可参考:
docs/toolcall-semantics.md。
用于定位「responses 思考流/工具调用」等问题。开启后会自动记录最近 N 条 DeepSeek 对话上游请求体与响应体(默认 20 条,超出自动淘汰;单条响应体默认最多记录 5 MB)。
启用示例:
DS2API_DEV_PACKET_CAPTURE=true \
DS2API_DEV_PACKET_CAPTURE_LIMIT=20 \
go run ./cmd/ds2api查询/清空(需 Admin JWT):
GET /admin/dev/captures:查看抓包列表(最新在前)DELETE /admin/dev/captures:清空抓包GET /admin/dev/raw-samples/query?q=关键词&limit=20:按问题关键词查询当前内存抓包,并按chat_session_id归并completion + continue链POST /admin/dev/raw-samples/save:把命中的某条抓包链保存为tests/raw_stream_samples/<sample-id>/回放样本
返回字段包含:
request_body:发送给 DeepSeek 的完整请求体response_body:上游返回的原始流式内容拼接文本response_truncated:是否触发单条大小截断
保存接口支持用 query、chain_key 或 capture_id 选中目标。例如:
{"query":"广州天气","sample_id":"gz-weather-from-memory"}| 文档 | 说明 |
|---|---|
| API.md / API.en.md | API 接口文档(含请求/响应示例) |
| DEPLOY.md / DEPLOY.en.md | 部署指南(本地/Docker/Vercel/systemd) |
| CONTRIBUTING.md / CONTRIBUTING.en.md | 贡献指南 |
| TESTING.md | 测试集使用指南 |
详细测试指南请参阅 docs/TESTING.md。
# 本地 PR 门禁
./scripts/lint.sh
./tests/scripts/check-refactor-line-gate.sh
./tests/scripts/run-unit-all.sh
npm run build --prefix webui
# 端到端全链路测试(真实账号,生成完整请求/响应日志)
./tests/scripts/run-live.sh工作流文件:.github/workflows/release-artifacts.yml
- 触发条件:仅在 GitHub Release
published时触发(普通 push 不会触发) - 构建产物:多平台二进制包(
linux/amd64、linux/arm64、darwin/amd64、darwin/arm64、windows/amd64)+sha256sums.txt - 容器镜像发布:仅推送到 GHCR(
ghcr.io/cjackhwang/ds2api) - 每个压缩包包含:
ds2api可执行文件、static/admin、WASM 文件(同时支持内置 fallback)、config.example.json配置示例、README、LICENSE
本项目基于逆向方式实现,仅供学习、研究、个人实验和内部验证使用,不提供任何商业授权、稳定性保证或可用性保证。 作者及仓库维护者不对因使用、修改、分发、部署或依赖本项目而产生的任何直接或间接损失、账号封禁、数据丢失、法律风险或第三方索赔负责。
请勿将本项目用于违反服务条款、协议、法律法规或平台规则的场景。商业使用前请自行确认 LICENSE、相关协议以及你是否获得了作者的书面许可。