DeepSeek 的响应 API 并非 OpenAI Responses。那一个解析器错误就会丢失推理内容。 - DEV Community
DeepSeek 的响应 API 并非 OpenAI Responses。那一个解析器错误就会丢失推理内容。 - DEV Community

我不断看到开发者将"DeepSeek 响应 API"和"OpenAI Responses API"混为一谈,仿佛它们是一回事。
但并非如此。
这个小小的命名错误可能让你的集成看似正常工作,却悄然丢弃了响应中最重要的字段:reasoning_content。
我花时间检查了 DeepSeek V4 文档和实时的 TokenMix 模型目录。实际答案很简单:
DeepSeek 在 Chat Completions 层与 OpenAI 兼容。它并未被记录为兼容 OpenAI 的 /responses 接口。
TL;DR
- 不,DeepSeek 的响应协议并非 OpenAI
/responsesAPI。它是/chat/completions。 - 重要的额外字段是
choices[0].message.reasoning_content。 - 如果你的封装只解析
message.content,你可能会丢失 DeepSeek 的思考输出。 - DeepSeek V4 现在使用
deepseek-v4-flash和deepseek-v4-pro;旧的deepseek-chat和deepseek-reasoner名称计划弃用。 - TokenMix 通过一个与 OpenAI 兼容的基础 URL 支持 DeepSeek V4 Flash 和 Pro,其实时目录中标注了推理、流式、JSON、工具、结构化输出和提示缓存。
实际发生了什么变化
DeepSeek V4 推动了模型命名的演进。
旧的思维模型是:
| 旧模型名称 | 人们的普遍认知 |
|---|---|
deepseek-chat |
普通对话 |
deepseek-reasoner |
推理模型 |
较新的 V4 模型 ID 是:
| 新模型 | 最佳理解 |
|---|---|
deepseek-v4-flash |
更便宜/高吞吐量 V4 |
deepseek-v4-pro |
更强推理/编码 V4 |
DeepSeek 文档称,旧的 deepseek-chat 和 deepseek-reasoner 名称是兼容性别名,将于 2026-07-24 15:59 UTC 起被弃用。
这意味着我不会围绕旧名称构建新的生产代码。
重要的响应对象
如果你习惯 OpenAI Chat Completions,这个结构会看起来很熟悉:
{
"choices": [
{
"message": {
"content": "final answer",
"reasoning_content": "thinking output",
"tool_calls": []
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 123,
"completion_tokens": 456,
"completion_tokens_details": {
"reasoning_tokens": 300
}
}
}
陷阱在于,大多数基本封装只做到这样:
answer = response.choices[0].message.content
这只会获取最终答案。
它不会获取思考输出。
对于某些产品来说,这没问题。但对于调试、评估、智能体追踪和工具工作流来说,这并不好。
我会使用的解析器
我会显式地解析 DeepSeek 响应:
def parse_deepseek_response(response):
choice = response.choices[0]
message = choice.message
return {
"answer": getattr(message, "content", None),
"reasoning": getattr(message, "reasoning_content", None),
"tool_calls": getattr(message, "tool_calls", None),
"finish_reason": choice.finish_reason,
"usage": getattr(response, "usage", None),
}
这并不花哨,是最小安全解析器。
重点不是向用户展示思维链,而是避免静默丢失影响调试、评估和工具调用延续的字段。
工具调用注意事项
这是我不愿忽视的部分。
DeepSeek 的思考模式文档区分了普通多轮对话和工具调用工作流。
对于普通多轮对话,你不需要传回先前的思维链内容。
但是当涉及工具调用时,DeepSeek 表示工具调用后的中间 reasoning_content 必须在后续请求中传回。
这意味着一个通用的 OpenAI 封装可能会以一种非常乏味的方式失败:
- 它接收到
reasoning_content。 - 它只存储
role和content。 - 它调用你的工具。
- 它在没有推理字段的情况下发送下一个请求。
- 模型的工具工作流丢失上下文。
这种类型的错误并不总是导致崩溃,只是会让智能体表现更差。
决策树
以下是我决定如何实现的方法:
def deepseek_integration_plan(app):
if app["uses_old_model_names"]:
return "Migrate from deepseek-chat/deepseek-reasoner to deepseek-v4-flash or deepseek-v4-pro."
if app["uses_tools"] and app["thinking_enabled"]:
return "Preserve reasoning_content across tool-call turns. Do not use a content-only wrapper."
if app["needs_json"]:
return "Use response_format={\"type\":\"json_object\"} and still validate the result."
if app["high_volume"]:
return "Start with deepseek-v4-flash and track cache hit/miss tokens."
if app["hard_reasoning"]:
return "Benchmark deepseek-v4-pro with reasoning enabled."
return "Use Chat Completions compatibility, but parse DeepSeek-specific fields explicitly."
我喜欢这个决策树,因为它避免了最大的错误选择。
问题不在于“DeepSeek 是否与 OpenAI 兼容?”
问题在于“你依赖的是哪个兼容层?”
TokenMix 角度:一个端点,但仍需解析字段
TokenMix 通过一个与 OpenAI 兼容的基础 URL 暴露 DeepSeek:
https://api.tokenmix.ai/v1
当前活跃的目录列出了以下模型:
| 模型 | 推理 | JSON | 工具 | 流式输出 | 提示缓存 |
|---|---|---|---|---|---|
deepseek/deepseek-v4-flash |
是 | 是 | 是 | 是 | 是 |
deepseek/deepseek-v4-pro |
是 | 是 | 是 | 是 | 是 |
这很有用,因为你可以通过一个端点路由 DeepSeek 以及 OpenAI、Claude、Gemini、Qwen、GLM 等其他模型。
但同样的警告依然存在:
OpenAI 兼容路由能让请求通过。
正确的解析仍然属于你。
一分钟理解成本计算
成本问题也容易被误解。
DeepSeek 直接定价区分缓存命中输入、缓存未命中输入和输出 tokens。
TokenMix 发布了通过其端点的路由费率。
例如,使用我查看的实时 TokenMix 目录费率:
| 模型 | 输入/百万 | 输出/百万 |
|---|---|---|
| DeepSeek V4 Flash | $0.132353 | $0.264706 |
| DeepSeek V4 Pro | $0.419118 | $0.838235 |
因此,一个 1000 万输入 / 200 万输出的工作负载大致为:
Flash = 10 * 0.132353 + 2 * 0.264706 = $1.85
Pro = 10 * 0.419118 + 2 * 0.838235 = $5.87
这使得 Flash 成为大批量任务的首选路径。
我只会为 Pro 付费,前提是在你的实际评估中 Flash 不合格。
我在生产环境中的做法
如果我本周要部署 DeepSeek V4,我会:
- 在新代码中停止使用旧模型名称。
- 解析
content、reasoning_content、tool_calls、finish_reason和usage。 - 在思考模式工具中保留
reasoning_content。