读书破万卷,下笔如有神。——唐杜甫  

DS2API icon

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/models
  • GET /v1/models/{id}
  • POST /v1/chat/completions
  • POST /v1/responses
  • GET /v1/responses/{response_id}
  • POST /v1/embeddings
  • POST /v1/files
  • GET /v1/files/{file_id}

并且它还贴心地支持很多根路径快捷路由(例如 /models/chat/completions/responses/embeddings/files…),让你在某些只能填“Base URL + 固定路径”的平台上也能更好配置。

2) Claude 兼容(它懂 Anthropic 的节奏)

它支持:

  • GET /anthropic/v1/models
  • POST /anthropic/v1/messages
  • POST /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=true
  • ANTHROPIC_API_KEY 要与 config.jsonkeys 一致,并建议保留常规 key 与 sk-ant-* 形态 key 以兼容不同客户端校验习惯
  • 若遇到“工具调用输出成文本、未执行”,优先检查模型输出是否为推荐 DSML 工具块结构

3) Gemini 兼容(它也会说 Google 的语言)

Gemini 路由支持:

  • POST /v1beta/models/{model}:generateContent
  • POST /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
2
3
4
每账号可用并发 = DS2API_ACCOUNT_MAX_INFLIGHT(默认 2)
建议并发值 = 账号数量 × 每账号并发上限
等待队列上限 = DS2API_ACCOUNT_MAX_QUEUE(默认 = 建议并发值)
429 阈值 = in-flight + 等待队列 ≈ 账号数量 × 4

它的态度也很“讲理”:

  • 槽位满了先排队,不会立刻 429
  • 真超过总承载上限才会 429 Too Many Requests
  • 并且提供 GET /admin/queue/status 给你看实时并发状态

6) DeepSeek PoW(纯 Go,高性能)

DS2API 内置 DeepSeek PoW 纯 Go 实现(DeepSeekHashV1),并强调“毫秒级响应”。

这就像它在关键时刻自己会掏出算盘,迅速把 PoW 算完,不拖你后腿。

7) Tool Calling 适配(它会防泄漏、会对齐语义)

当请求里带 tools 时,它会做一整套“工具调用语义对齐与防泄漏处理”,包括:

  1. 只在非代码块上下文启用执行型 toolcall 识别(代码块示例默认不触发)
  2. 推荐可执行调用是 DSML 外壳结构:<|DSML|tool_calls><|DSML|invoke ...><|DSML|parameter ...>;同时兼容旧式 canonical XML <tool_calls>
  3. responses 流式严格遵循官方 item 生命周期事件
  4. responses 支持并执行 tool_choiceauto / none / required / 强制函数);违规时会返回 422 或流式 response.failed
  5. 客户端请求哪种协议,就按该协议返回工具调用(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 下,它把常用模型分得清清楚楚,还额外把 thinkingsearch 的差异直接写上桌面。

例如(摘取重点):

  • 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.1gpt-5gpt-5-codexo3claude-*gemini-* 等),但 /v1/models 返回会规范化成 DeepSeek 原生模型名。

在 Claude 接口 GET /anthropic/v1/models 下,它还会返回 Claude 4.x snapshots、3.x 历史模型 ID 与常见 alias,照顾旧客户端的情绪。


快速开始:它希望你怎样最快跑起来?

DS2API 很直接:先把 config.json 当作唯一配置源

通用第一步(所有部署方式)

1
2
cp config.example.json config.json
# 编辑 config.json

它还补充了不同场景建议:

  • 本地运行:直接读取 config.json
  • Docker / Vercel:由 config.json 生成 DS2API_CONFIG_JSON(Base64)注入环境变量,也可以直接写原始 JSON
  • WebUI 管理台里的“全量配置模板”也复用同一份 config.example.json

它的潜台词是:

“别到处散落配置,集中管理,省得你自己把自己绕晕。”


部署方式优先级建议(它给你排好了最省心的路)

  1. 下载 Release 构建包运行:最省事
  2. Docker / GHCR 镜像部署:适合容器化
  3. Vercel 部署:适合已有 Vercel 环境且接受平台约束
  4. 本地源码运行 / 自行编译:适合开发调试

方式一:下载 Release 构建包运行(最省事的那条路)

1
2
3
4
5
6
# 下载对应平台的压缩包后
tar -xzf ds2api_<tag>_linux_amd64.tar.gz
cd ds2api_<tag>_linux_amd64
cp config.example.json config.json
# 编辑 config.json
./ds2api

它就像把旅行箱都给你收拾好了:打开、放好你的配置、直接出发。


方式二:Docker 运行(它穿上了容器盔甲)

1
2
3
4
5
6
7
8
9
10
11
12
# 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

更新镜像也很简单:

1
docker-compose up -d --build

Zeabur 一键部署(Dockerfile)

README 里写得很明确:

  1. 点击 “Deploy on Zeabur” 一键部署
  2. 部署完成后访问 /admin,用 DS2API_ADMIN_KEY 登录
  3. 在管理台导入/编辑配置(会写入并持久化到 /data/config.json

它就像把“云上落地”的流程也给你铺了红毯。


方式三:Vercel 部署(它也懂 Serverless 的规矩)

流程是:

  1. Fork 仓库到自己的 GitHub
  2. 在 Vercel 上导入项目
  3. 配置环境变量(最少 DS2API_ADMIN_KEY;推荐同时设置 DS2API_CONFIG_JSON
  4. 部署

它还建议你先在仓库目录准备好:

1
2
cp config.example.json config.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
2
3
4
5
6
7
8
9
10
# 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 访问。

它还会在你第一次启动时,若 static/admin 不存在,就自动尝试构建 WebUI(包括 npm cinpm run build ...),像是顺手帮你把屋子打扫干净再迎客。


配置说明:README 只带你到门口,真正的钥匙在模板里

它说得很明确:

  • README 只保留快速入口
  • 完整字段以 config.example.json 为模板
  • 并参考部署指南与 API 最佳实践

它列出常用字段(你可以把它当成 DS2API 的“性格面板”):

  • keys / api_keys:客户端访问密钥(api_keys 支持 nameremark
  • accounts:DeepSeek 托管账号(emailmobile),可配代理、名称和备注
  • 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 路由)时支持两种模式:

  1. 托管账号模式
    Bearerx-api-key 传入 config.keys 中的 key,DS2API 自动轮询选择账号

  2. 直通 token 模式
    如果传入的 token 不在 config.keys 中,DS2API 直接把它当作 DeepSeek token 使用

它还支持请求头:

  • X-Ds2-Target-Account:指定使用某个托管账号(email 或 mobile)

以及 Gemini 路由的常见调用方式:

  • x-goog-api-key
  • 或在没有认证头时使用 ?key= / ?api_key=

这感觉就像它在门口同时配了两条通道:

  • 一条是“走组织流程、我帮你调度”
  • 一条是“你有通行证?那你直走”

本地开发抓包工具:它会把“现场证据”帮你收好

如果你在定位诸如「responses 思考流/工具调用」之类的问题,它提供抓包能力:

启用示例:

1
2
3
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
  • POST /admin/dev/raw-samples/save

它还支持把抓到的一次真实问题保存为可回放样本,像是把“事故现场”打包成了可复盘的档案袋。


测试:它也有自己的体检清单

README 里给了快速测试命令:

1
2
3
4
5
6
7
8
# 本地 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

它不是那种“只要能跑就行”的项目,它像一个严谨的工程团队:上线前先过门禁,跑完单测,再把 WebUI 构建过一遍,最后还能做真实账号的端到端测试。


Release 自动构建(GitHub Actions):它会自己打包行李

工作流文件:

  • .github/workflows/release-artifacts.yml

构建产物包括:

  • 多平台二进制包(Linux / macOS / Windows,多架构)
  • Linux Docker 镜像导出包
  • 容器镜像发布到 GHCR:ghcr.io/cjackhwang/ds2api

每个二进制压缩包包含:

  • ds2api 可执行文件
  • static/admin
  • config.example.json
  • .env.example
  • README.MDREADME.en.md
  • LICENSE

它像是一个每次出发前都把装备打包整齐的旅人:你下载下来,几乎不需要再东拼西凑。


文档入口(它把地图递到你手里)

  • 文档导航:docs/README.md
  • 架构说明:docs/ARCHITECTURE.md
  • 接口文档:API.md

免责声明(它把边界说得很清楚)

本仓库仅供学习、研究、个人实验和内部验证使用,不提供任何形式的商业授权、适用性保证或结果保证。
作者及仓库维护者不对因使用、修改、分发、部署或依赖本项目而产生的任何直接或间接损失、账号封禁、数据丢失、法律风险或第三方索赔负责。
请勿将本项目用于违反服务条款、协议、法律法规或平台规则的场景。商业使用前请自行确认 LICENSE、相关协议以及你是否获得了作者的书面许可。


结尾:你把请求交给它,它把世界对齐给你

DS2API 最迷人的地方,不只是“把 DeepSeek 变成 OpenAI/Claude/Gemini 兼容 API”。

而是它像一个把“协议差异、并发压力、流式细节、工具调用语义、部署形态、运维可视化”都提前替你消化掉的中间层角色——它站在你和上游之间,像个可靠的翻译官、调度员、守门人、记录员,甚至是一个能在 Vercel 上临时变通的实干派。

你只要把熟悉的请求方式递给它——
它就会把复杂世界的噪音整理好,把你想要的那份标准化输出,清清爽爽地交到你手上。