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

Dev.to AI 2026-06-27T03:16:03.024437

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

Cover image for DeepSeek's Response API Isn't OpenAI Responses. That One Parser Mistake Drops the Reasoning.

我不断看到开发者将"DeepSeek 响应 API"和"OpenAI Responses API"混为一谈,仿佛它们是一回事。

但并非如此。

这个小小的命名错误可能让你的集成看似正常工作,却悄然丢弃了响应中最重要的字段:reasoning_content

我花时间检查了 DeepSeek V4 文档和实时的 TokenMix 模型目录。实际答案很简单:

DeepSeek 在 Chat Completions 层与 OpenAI 兼容。它并未被记录为兼容 OpenAI 的 /responses 接口。

TL;DR

实际发生了什么变化

DeepSeek V4 推动了模型命名的演进。

旧的思维模型是:

旧模型名称 人们的普遍认知
deepseek-chat 普通对话
deepseek-reasoner 推理模型

较新的 V4 模型 ID 是:

新模型 最佳理解
deepseek-v4-flash 更便宜/高吞吐量 V4
deepseek-v4-pro 更强推理/编码 V4

DeepSeek 文档称,旧的 deepseek-chatdeepseek-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 封装可能会以一种非常乏味的方式失败:

  1. 它接收到 reasoning_content
  2. 它只存储 rolecontent
  3. 它调用你的工具。
  4. 它在没有推理字段的情况下发送下一个请求。
  5. 模型的工具工作流丢失上下文。

这种类型的错误并不总是导致崩溃,只是会让智能体表现更差。

决策树

以下是我决定如何实现的方法:

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,我会:

查看原文