ds2api
读书破万卷,下笔如有神。——唐杜甫
DS2API:把 DeepSeek 的“网页聊天能力”,翻译成 OpenAI / Claude / Gemini 都听得懂的 API 语言
DS2API 有点像一位站在门口的“协议翻译官”。
DeepSeek Web 的对话能力本来习惯用自己的表达方式说话,而你的各种客户端、SDK、框架——OpenAI SDK、Anthropic SDK、Gemini SDK、Vercel AI SDK、LangChain、LlamaIndex、OpenWebUI,甚至 Codex CLI/SDK——又各自有各自的口音。
于是 DS2API 出场了:它一边伸手接住你熟悉的 OpenAI / Claude / Gemini 请求,一边转身去和 DeepSeek API 沟通,最后再把 DeepSeek 的回答,按你期待的协议格式原封不动、流式地送回来。
它不只是“能跑”,它更像一套高并发协议适配的参考实现:用 Go 做核心后端,把复杂的协议适配、并发控制、会话与 PoW、工具调用语义对齐等都安排得明明白白;而在 Vercel 这种对流式输出更挑剔的平台上,它还会请出一位小帮手——少量 Node Runtime 来做流式桥接;至于管理后台,它穿上了 React WebUI 的外衣,安安静静地托管在 /admin,随时等你来指挥。
它是谁(Description 里的自我介绍)
DeepSeek-Compatible Middleware Interface: A technical exploration project in Go, focusing on high-concurrency protocol adaptation. It serves as a reference implementation for converting diverse web protocols into standardized formats.
如果把这段话拟人化一下,DS2API 会这么说:
“我是一个用 Go 写的技术探索项目。我最擅长在高并发场景里做协议适配——把各种不同的 Web 协议,转换成一套标准化、可复用的接口形式。你可以把我当成一份能直接跑起来的参考实现。”
它住在哪儿、由谁组成(架构摘要)
DS2API 不是单一的一段程序,它更像一支分工明确的小队:
- 后端(Go):核心战斗力,主要在
cmd/ds2api/、api/、internal/
它不依赖 Python 运行时,行动迅速,抗压也稳。 - 前端(React WebUI):管理台在
webui/,部署时自动构建到static/admin,最终通过/admin提供一个单页应用(中英文双语、深色模式,还能查看服务器端对话记录)。 - Vercel 流式桥接(Node Runtime):在 Vercel 上为
/v1/chat/completions提供实时 SSE 流式体验,但鉴权、账号选择、会话/PoW 准备仍由 Go 侧完成。
它的工作方式可以想象成一条“接力跑道”:
- 你(客户端 / SDK)把请求交给 DS2API
- DS2API 在内部完成路由、中间件、鉴权、并发队列、Prompt 兼容与工具调用处理
- 然后把请求送去 DeepSeek API
- DeepSeek 把流式结果吐出来
- DS2API 再把它“翻译成你要的协议”,送回给你
核心能力:它能做什么(而且做得很细)
DS2API 的能力表面上像“兼容 OpenAI/Claude/Gemini”,但它真正的性格在细节里。
1) OpenAI 兼容(它对 OpenAI 生态非常友好)
它能用 OpenAI 风格的路径和请求来服务你,包括但不限于:
GET /v1/modelsGET /v1/models/{id}POST /v1/chat/completionsPOST /v1/responsesGET /v1/responses/{response_id}POST /v1/embeddingsPOST /v1/filesGET /v1/files/{file_id}
并且它还贴心地支持很多根路径快捷路由(例如 /models、/chat/completions、/responses、/embeddings、/files…),让你在某些只能填“Base URL + 固定路径”的平台上也能更好配置。
2) Claude 兼容(它懂 Anthropic 的节奏)
它支持:
GET /anthropic/v1/modelsPOST /anthropic/v1/messagesPOST /anthropic/v1/messages/count_tokens
还提供了 Claude 常见的快捷路径:/v1/messages、/messages,让很多旧客户端也能直接接入。
并且 README 里还写了“Claude Code 接入避坑(实测)”——这种感觉就像它拍着胸口说:
“你放心,我不只纸上谈兵,我是踩过坑再把坑填平的人。”
其中要点包括:
ANTHROPIC_BASE_URL推荐指向 DS2API 根地址(例如http://127.0.0.1:5001),因为 Claude Code 会请求/v1/messages?beta=trueANTHROPIC_API_KEY要与config.json中keys一致,并建议保留常规 key 与sk-ant-*形态 key 以兼容不同客户端校验习惯- 若遇到“工具调用输出成文本、未执行”,优先检查模型输出是否为推荐 DSML 工具块结构
3) Gemini 兼容(它也会说 Google 的语言)
Gemini 路由支持:
POST /v1beta/models/{model}:generateContentPOST /v1beta/models/{model}:streamGenerateContent
并兼容 /v1/models/{model}:* 形式的路径。
模型名会通过 model_aliases 或内置规则映射到 DeepSeek 原生模型,还能完整支持 Tool Calling。
4) 统一 CORS 策略(它把门卫规矩定得一致)
/v1/*、/anthropic/*、/v1beta/models/*、/admin/* 都走同一套 CORS 策略;即便在 Vercel 上 /v1/chat/completions 走 Node Runtime,也会对齐相同的放行规则。
它不像那种“这里能跨域、那里不行”的任性系统——它更像一个守纪律的管理员。
5) 多账号轮询 + 并发队列控制(它会安排“排队”和“换班”)
- 支持自动 token 刷新
- 支持邮箱/手机号双登录方式
- 每账号有 in-flight 上限,还有等待队列
- 动态计算建议并发值,避免你一上来把上游挤爆
并发模型在 README 里写得非常直白:
1 | 每账号可用并发 = DS2API_ACCOUNT_MAX_INFLIGHT(默认 2) |
它的态度也很“讲理”:
- 槽位满了先排队,不会立刻 429
- 真超过总承载上限才会
429 Too Many Requests - 并且提供
GET /admin/queue/status给你看实时并发状态
6) DeepSeek PoW(纯 Go,高性能)
DS2API 内置 DeepSeek PoW 纯 Go 实现(DeepSeekHashV1),并强调“毫秒级响应”。
这就像它在关键时刻自己会掏出算盘,迅速把 PoW 算完,不拖你后腿。
7) Tool Calling 适配(它会防泄漏、会对齐语义)
当请求里带 tools 时,它会做一整套“工具调用语义对齐与防泄漏处理”,包括:
- 只在非代码块上下文启用执行型 toolcall 识别(代码块示例默认不触发)
- 推荐可执行调用是 DSML 外壳结构:
<|DSML|tool_calls>→<|DSML|invoke ...>→<|DSML|parameter ...>;同时兼容旧式 canonical XML<tool_calls> responses流式严格遵循官方 item 生命周期事件responses支持并执行tool_choice(auto/none/required/ 强制函数);违规时会返回422或流式response.failed- 客户端请求哪种协议,就按该协议返回工具调用(OpenAI / Claude / Gemini 各自原生结构)
它不像一个“随缘解析器”,更像一个把工具调用当作严肃协议来对待的“口译员”。
8) Admin API + WebUI 管理台(它给你方向盘)
- Admin API:配置管理、运行时设置热更新、代理管理、账号测试/批量测试、会话清理、导入导出、Vercel 同步、版本检查
- WebUI:
/admin单页应用(中英文双语、深色模式,支持查看服务器端对话记录)
9) 运维探针(它会报平安)
GET /healthz:存活GET /readyz:就绪
平台兼容矩阵:它和哪些伙伴配合默契?
它在 README 里给出了兼容矩阵(而且标了优先级):
- 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 兼容接入)✅
如果把它拟人化,它会像一位社交能力很强的协调者:
“你用谁都行,我都能对上暗号。”
模型支持:它如何“点名叫人”?
在 OpenAI 接口 GET /v1/models 下,它把常用模型分得清清楚楚,还额外把 thinking、search 的差异直接写上桌面。
例如(摘取重点):
- default:
deepseek-v4-flash(thinking 默认开启,可由请求参数控制) - default:
deepseek-v4-flash-nothinking(永久关闭) - expert:
deepseek-v4-pro(thinking 默认开启,可由请求参数控制) - expert:
deepseek-v4-pro-nothinking(永久关闭) - search 变体:
*-search/*-search-nothinking - vision:
deepseek-v4-vision/deepseek-v4-vision-nothinking
它也支持常见 alias 输入(如 gpt-4.1、gpt-5、gpt-5-codex、o3、claude-*、gemini-* 等),但 /v1/models 返回会规范化成 DeepSeek 原生模型名。
在 Claude 接口 GET /anthropic/v1/models 下,它还会返回 Claude 4.x snapshots、3.x 历史模型 ID 与常见 alias,照顾旧客户端的情绪。
快速开始:它希望你怎样最快跑起来?
DS2API 很直接:先把 config.json 当作唯一配置源。
通用第一步(所有部署方式)
1 | cp config.example.json config.json |
它还补充了不同场景建议:
- 本地运行:直接读取
config.json - Docker / Vercel:由
config.json生成DS2API_CONFIG_JSON(Base64)注入环境变量,也可以直接写原始 JSON - WebUI 管理台里的“全量配置模板”也复用同一份
config.example.json
它的潜台词是:
“别到处散落配置,集中管理,省得你自己把自己绕晕。”
部署方式优先级建议(它给你排好了最省心的路)
- 下载 Release 构建包运行:最省事
- Docker / GHCR 镜像部署:适合容器化
- Vercel 部署:适合已有 Vercel 环境且接受平台约束
- 本地源码运行 / 自行编译:适合开发调试
方式一:下载 Release 构建包运行(最省事的那条路)
1 | # 下载对应平台的压缩包后 |
它就像把旅行箱都给你收拾好了:打开、放好你的配置、直接出发。
方式二:Docker 运行(它穿上了容器盔甲)
1 | # 1. 准备环境变量和配置文件 |
默认 docker-compose.yml 会把宿主机 6011 映射到容器内的 5001。如果你希望宿主机直接暴露 5001,可以设置 DS2API_HOST_PORT=5001 或调整 ports。
更新镜像也很简单:
1 | docker-compose up -d --build |
Zeabur 一键部署(Dockerfile)
README 里写得很明确:
- 点击 “Deploy on Zeabur” 一键部署
- 部署完成后访问
/admin,用DS2API_ADMIN_KEY登录 - 在管理台导入/编辑配置(会写入并持久化到
/data/config.json)
它就像把“云上落地”的流程也给你铺了红毯。
方式三:Vercel 部署(它也懂 Serverless 的规矩)
流程是:
- Fork 仓库到自己的 GitHub
- 在 Vercel 上导入项目
- 配置环境变量(最少
DS2API_ADMIN_KEY;推荐同时设置DS2API_CONFIG_JSON) - 部署
它还建议你先在仓库目录准备好:
1 | cp config.example.json config.json |
并推荐把 config.json 转 Base64 再粘贴到 DS2API_CONFIG_JSON,避免 JSON 格式错误:
1 | base64 < config.json | tr -d '\n' |
另外它专门解释了流式策略:
- 在 Vercel 上
/v1/chat/completions默认走api/chat-stream.js(Node Runtime)以保证实时 SSE - 但鉴权、账号选择、会话/PoW 准备仍由 Go 内部完成
它就像一个会“因地制宜”的工程师:哪里需要 Node 就用一点 Node,但核心仍由 Go 扛住。
方式四:本地源码运行(适合想和它一起写代码的人)
前置要求(它把门槛说清楚了):
- Go 1.26+
- Node.js
20.19+或22.12+(仅在需要构建 WebUI 时) npm可用,建议npm 10+
启动步骤:
1 | # 1. 克隆仓库 |
默认本地访问地址:
http://127.0.0.1:5001
服务实际绑定是 0.0.0.0:5001,同一局域网设备通常也能通过内网 IP 访问。
它还会在你第一次启动时,若 static/admin 不存在,就自动尝试构建 WebUI(包括 npm ci 与 npm run build ...),像是顺手帮你把屋子打扫干净再迎客。
配置说明:README 只带你到门口,真正的钥匙在模板里
它说得很明确:
- README 只保留快速入口
- 完整字段以
config.example.json为模板 - 并参考部署指南与 API 最佳实践
它列出常用字段(你可以把它当成 DS2API 的“性格面板”):
keys/api_keys:客户端访问密钥(api_keys支持name、remark)accounts:DeepSeek 托管账号(email或mobile),可配代理、名称和备注model_aliases:OpenAI/Claude/Gemini 共用 alias 映射runtime:并发、队列、token 刷新策略(可通过 Admin Settings 热更新)auto_delete.mode:请求结束后的远端会话清理策略(none/single/all)current_input_file:上下文拆分上传策略(默认开启,触发时上传DS2API_HISTORY.txt)thinking_injection:默认开启,在最新 user 消息末尾追加思考增强提示词,提高推理与工具调用前的思考稳定性
鉴权模式:它认识“自己人”,也允许“直通车”
调用业务接口(/v1/*、/anthropic/*、Gemini 路由)时支持两种模式:
托管账号模式
用Bearer或x-api-key传入config.keys中的 key,DS2API 自动轮询选择账号直通 token 模式
如果传入的 token 不在config.keys中,DS2API 直接把它当作 DeepSeek token 使用
它还支持请求头:
X-Ds2-Target-Account:指定使用某个托管账号(email 或 mobile)
以及 Gemini 路由的常见调用方式:
x-goog-api-key- 或在没有认证头时使用
?key=/?api_key=
这感觉就像它在门口同时配了两条通道:
- 一条是“走组织流程、我帮你调度”
- 一条是“你有通行证?那你直走”
本地开发抓包工具:它会把“现场证据”帮你收好
如果你在定位诸如「responses 思考流/工具调用」之类的问题,它提供抓包能力:
启用示例:
1 | DS2API_DEV_PACKET_CAPTURE=true \ |
查询/清空(需 Admin JWT):
GET /admin/dev/capturesDELETE /admin/dev/capturesGET /admin/dev/raw-samples/query?q=关键词&limit=20POST /admin/dev/raw-samples/save
它还支持把抓到的一次真实问题保存为可回放样本,像是把“事故现场”打包成了可复盘的档案袋。
测试:它也有自己的体检清单
README 里给了快速测试命令:
1 | # 本地 PR 门禁 |
它不是那种“只要能跑就行”的项目,它像一个严谨的工程团队:上线前先过门禁,跑完单测,再把 WebUI 构建过一遍,最后还能做真实账号的端到端测试。
Release 自动构建(GitHub Actions):它会自己打包行李
工作流文件:
.github/workflows/release-artifacts.yml
构建产物包括:
- 多平台二进制包(Linux / macOS / Windows,多架构)
- Linux Docker 镜像导出包
- 容器镜像发布到 GHCR:
ghcr.io/cjackhwang/ds2api
每个二进制压缩包包含:
ds2api可执行文件static/adminconfig.example.json.env.exampleREADME.MD、README.en.mdLICENSE
它像是一个每次出发前都把装备打包整齐的旅人:你下载下来,几乎不需要再东拼西凑。
文档入口(它把地图递到你手里)
- 文档导航:
docs/README.md - 架构说明:
docs/ARCHITECTURE.md - 接口文档:
API.md
免责声明(它把边界说得很清楚)
本仓库仅供学习、研究、个人实验和内部验证使用,不提供任何形式的商业授权、适用性保证或结果保证。
作者及仓库维护者不对因使用、修改、分发、部署或依赖本项目而产生的任何直接或间接损失、账号封禁、数据丢失、法律风险或第三方索赔负责。
请勿将本项目用于违反服务条款、协议、法律法规或平台规则的场景。商业使用前请自行确认 LICENSE、相关协议以及你是否获得了作者的书面许可。
结尾:你把请求交给它,它把世界对齐给你
DS2API 最迷人的地方,不只是“把 DeepSeek 变成 OpenAI/Claude/Gemini 兼容 API”。
而是它像一个把“协议差异、并发压力、流式细节、工具调用语义、部署形态、运维可视化”都提前替你消化掉的中间层角色——它站在你和上游之间,像个可靠的翻译官、调度员、守门人、记录员,甚至是一个能在 Vercel 上临时变通的实干派。
你只要把熟悉的请求方式递给它——
它就会把复杂世界的噪音整理好,把你想要的那份标准化输出,清清爽爽地交到你手上。
