
DeepSeek 把“模型在训练中自己改进自己”这件事从一种模糊的想象变成了一条可以讨论的技术路径。在它公开的 R1-Zero 实验结果里模型不依赖大量人工构造的监督信号而是通过强化学习在生成的推理路径上反复迭代训练过程中甚至出现了主动回溯、重新评估、改变思路的行为。这种能力真正进入工程后给开发者带来的并不是一个魔法接口而是一组必须理解的新字段和新约束。这篇文章不会预测 DeepSeek 后续会发布什么产品也不讨论任何未经证实的内部规划。下面从可复现的开发者视角拆解所谓“自进化”在模型层面到底指什么到 API 调用时会变成哪些字段多轮对话为什么会出现 HTTP 400 和reasoning_content必须回传的错误本地部署如何快速验证以及 Codex、VSCode、自建 Agent 要如何适配这类推理模型。读完你可以自己搭一个最小推理调用也能处理最常见的思维链字段问题。1. 先理解“自进化”它不是模型在服务器上偷偷学习1.1 从 R1-Zero 的“Aha Moment”说起DeepSeek 被反复讨论的 R1-Zero 实验核心并不是“模型突然有了意识”而是训练方式发生了变化。常见的大模型训练流程是先准备大量人工标注或模型生成的数据做监督微调再用 RLHF 对齐人类偏好。R1-Zero 尝试的路线更激进跳过针对复杂推理任务的监督微调直接用强化学习训练模型的推理能力。强化学习的闭环大致是这样模型针对同一个问题生成多个候选回答。规则或程序评估每个回答是否正确给出奖励。奖励信号通过策略梯度反传让模型在下一次更倾向生成能获得更高奖励的路径。这个循环并不需要人工把每一步推理都写出来。模型在探索中发现长一点的思考、显式的回溯、重新评估已经写过的那一步往往能提高最终得分。于是训练日志里出现了社区常说的“Aha Moment”模型开始自己修正推理方向。关键要澄清一点这不是模型在服务器上实时修改自己权重。权重更新仍然发生在训练阶段更新逻辑仍然是强化学习算法在驱动。只是“改进什么、怎么改进”不再完全来自人工步骤而是来自模型生成路径与奖励信号之间的相互作用。1.2 自进化在工程上意味着新输入和输出传统聊天模型输入用户消息输出最终答案过程是一个黑盒。推理模型则把一部分“思考过程”显式化到了接口层。类似 DeepSeek 这类支持推理的 API响应体里可能同时包含content最终答案。reasoning_content模型在生成最终答案前产生的推理内容。对上层应用来说reasoning_content不是附件也不是可丢弃的日志。它在单轮推理中可以帮助你判断模型是“先分析再回答”还是“直接绕过了分析”。在多轮对话或 Agent 循环里这批内容甚至会成为上下文结构的一部分影响后续请求是否合法。1.3 开发者视角下的三层理解可以把“自进化蓝图”拆成三层来看训练层模型通过生成、验证、奖励更新策略持续改进自己的推理分布。推理层改进的结果表现为更长的推理链、更稳定的自我检查以及 API 响应中的reasoning_content。应用层开发者需要在请求参数、消息历史、上下文管理上适配这种新输出否则会看到 400、上下文错位、结果漂移等工程问题。对大多数团队来说训练层没有条件也没有必要重复实现。真正需要下功夫的是推理层和应用层能不能稳定调用推理能力能不能在多轮任务里保留并正确传回推理内容能不能把长链思考转换成用户真正需要的结论。2. 用 API 接住推理能力content 与 reasoning_content 的解耦2.1 环境准备调用 DeepSeek 的推理模型通常不需要额外编译环境只需要一个支持 OpenAI 协议格式的 HTTP 客户端。最省事的方式是使用 OpenAI Python SDK因为 DeepSeek 开放接口兼容 OpenAI 的请求风格。先把必要的库装好pip install --upgrade openai然后在环境变量里放好 API Key。示例中的 base_url 以 DeepSeek 开放平台文档为准常见值是https://api.deepseek.com。不要把密钥直接写死在代码里。export DEEPSEEK_API_KEYsk-你的密钥 export DEEPSEEK_BASE_URLhttps://api.deepseek.com2.2 一次最小推理调用下面代码完成一次最简单的 DeepSeek 推理模型调用。模型 ID 在示例里用deepseek-reasoner实际项目的模型名要结合开放平台最新文档确认不能假设所有版本都用同一个 ID。import os from openai import OpenAI client OpenAI( api_keyos.getenv(DEEPSEEK_API_KEY), base_urlos.getenv(DEEPSEEK_BASE_URL, https://api.deepseek.com), ) resp client.chat.completions.create( modeldeepseek-reasoner, messages[ {role: user, content: 请分析这段日志并给出排查顺序: ...} ], ) msg resp.choices[0].message print(最终答案:, msg.content) print(推理内容:, getattr(msg, reasoning_content, ))这里用getattr(msg, reasoning_content, )而不是msg.reasoning_content是因为不同版本的 SDK 或不同兼容端点对额外字段的处理方式不一致。直接访问不存在的属性会抛异常用getattr更稳。2.3 响应结构里最关键的两个字段一次典型的推理响应在choices[0].message中会包含{ choices: [ { message: { role: assistant, content: 最终答案, reasoning_content: 模型在生成最终答案前产生的推理过程 } } ] }注意几个容易误判的点content是用于最终展示和业务判断的内容。reasoning_content是过程信息通常比content长。两者不一定在同一平台、同一模型版本下都出现。如果调用的是普通聊天模型而不是推理模型往往只有content。推理内容要不要展示给用户取决于产品阶段。调试阶段可以打出来观察模型是否真的在分析生产阶段建议只把最终结论交给用户推理细节放进日志或后台用于评测。2.4 单轮推理和持续推理的分界线单轮推理时只需把当前用户问题发给 API拿到content和reasoning_content后结束。但真实应用很少有真正的单轮请求尤其是 Agent、IDE 助手、客服机器人这些场景几乎都是多轮对话。多轮对话时客户端往往要把历史消息重新组装后再发给 API这时候reasoning_content怎么处理就非常关键。有的处理方式是只保留 assistant 里的content把reasoning_content丢掉。对于普通聊天模型这种处理没有影响。对严格启用 thinking mode 的推理端点丢弃reasoning_content可能导致下一次请求直接返回 HTTP 400。3. thinking mode 下的 HTTP 400reasoning_content 必须回传是怎么发生的3.1 典型报错现场在多轮场景中如果使用工具或代码把 DeepSeek 的请求转到了某个兼容端点并且启用了 thinking mode第二次请求可能遇到类似错误upstream_status: http 400 cause: the reasoning_content in the thinking mode must be passed back to the api.从现象看第一次请求可能成功了第二次请求却在“最终答案之外还少了什么”。客户端把上一轮 assistant 消息改写成只有role和content的普通消息后直接组成了新的请求体结果被上游拒绝。这类错误不一定在所有 DeepSeek 官方接口中必现。更常见的情况是某些兼容网关、切换工具或 OpenAI 协议适配层启用了 thinking mode 会话校验它要求上一个 assistant 轮次的reasoning_content必须随历史一起回传否则无法拼接连续的思考上下文。3.2 根因客户端丢弃了思考上下文要理解为什么接口提出这种要求可以把 thinking mode 想象成一次连续推理会话。当模型开始回答一个复杂问题时推理内容可能分散在多个请求之间。比如用户提出第一个问题。模型生成一段推理给出结论。用户追问“刚刚的思路里哪一步有问题”。客户端希望模型继续基于上一次的推理路径来回答。如果第四步组装 messages 时assistant 消息里只有最终content没有上一次的reasoning_content下游端点就无法还原模型当时“想到哪一步”。在严格的 thinking mode 实现里这会被判定为请求结构不合法。这里还要区分两种不同情况官方模型只要求保存最终 content不要求回传 reasoning_content。兼容端点或某些 thinking mode 实现要求完整回传。排查时不要先把“必须回传”当作所有环境的统一规则。先看你在调哪个 base_url再看官方文档对该模型的 messages 格式要求。3.3 修复思路在 messages 里保留并回传 reasoning_content如果端点要求回传上一轮reasoning_content可以在多轮 messages 组装时保留 assistant 的推理内容。示例代码如下messages [ {role: system, content: 你是一个严谨的排查助手。}, {role: user, content: 服务启动失败请先给出定位方向。}, ] first_resp client.chat.completions.create( modeldeepseek-reasoner, messagesmessages, ) first_msg first_resp.choices[0].message messages.append({ role: assistant, content: first_msg.content, reasoning_content: getattr(first_msg, reasoning_content, ), }) messages.append({ role: user, content: 上一步判断里你认为最可疑的是哪个模块, }) second_resp client.chat.completions.create( modeldeepseek-reasoner, messagesmessages, ) second_msg second_resp.choices[0].message print(第二次最终答案:, second_msg.content)这段代码的核心是把 assistant 消息从普通的两字段消息扩展成带reasoning_content的消息。如果 SDK 或端点不允许在 assistant 消息里塞额外字段还需要结合具体客户端做协议适配比如通过底层 HTTP 请求手动构造 body而不是依赖高层封装。3.4 什么时候可以不用回传不需要回传的场景通常有以下特征调用的是普通对话模型例如deepseek-chat。官方文档明确说明推理内容只在当次响应出现历史请求无需携带。API 对 assistant 消息只校验role和content。工具层已经把上一轮推理压缩成了摘要或最终答案不再需要完整思考路径。按照我的实践建议先按官方最小示例跑通再逐次加入多轮历史。如果官方示例不传 reasoning_content 也正常那就不要画蛇添足不要因为第三方工具报错就把第三方要求强加给官方接口。如果是第三方模型网关再看它的 thinking mode 参数是否开启以及它要求的历史消息结构。4. 本地部署 DeepSeek-R1最小环境下的推理观测台4.1 为什么值得本地部署一次接入远端 API 虽然省事但请求日志、推理字段和失败请求都掌握在平台侧。要真正理解“推理内容如何产生、如何影响多轮上下文”本地部署一个可运行模型会更直观。本地部署还能解决几个问题数据可以留在自己的机器里适合先做原型验证。可以随时修改请求体观察reasoning_content是否随 messages 变化。可以打断、重复、重放请求不受远端限流影响。通过 Ollama 这类工具几分钟就能拉起一个 OpenAI 兼容接口。本地部署不等于生产部署。生产环境如果要处理并发和长上下文还需要考虑显存、吞吐量、模型量化、请求排队和监控。4.2 用 Ollama 拉起 DeepSeek-R1 最小实例Ollama 的用法比较简单。先安装 Ollama再拉取 DeepSeek-R1 的一个较小参数量版本。模型列表会变化落地前先确认你使用的 tag 是否存在。ollama run deepseek-r1:14b第一次执行会先下载模型。下载完成后命令行会进入一个交互式对话界面。可以先问一个需要推理的问题观察模型是否会在最终答案前输出比较长的推导过程。如果不想进入交互模式也可以通过 REST 接口调用。Ollama 默认监听本地 11434 端口并且提供了 OpenAI 兼容路径/v1/chat/completionscurl http://localhost:11434/v1/chat/completions \ -H Content-Type: application/json \ -d { model: deepseek-r1:14b, messages: [ {role: user, content: 解释一下自进化模型和普通模型在训练目标上的区别} ] }在模型没有下载完成时第一次 curl 会返回模型不存在或下载耗时较长。可以用ollama list查看本地模型用ollama pull单独拉取。4.3 参数量怎么选本地部署最实际的约束是硬件尤其是显存。DeepSeek-R1 有多个蒸馏参数量版本运行前要确认量化方式和模型大小。参数量级别适合场景运行前需要确认1.5B / 7B理解接口返回结构、验证消息格式CPU 能否接受速度内存是否足够8B / 14B / 32B日常问答、中等复杂推理量化位数与显存占用长上下文是否触发 OOM70B / 671B高复杂度推理、并发服务多卡并行、量化部署、吞吐优化方案不要只看参数量。不同量化位数会直接影响显存占用和推理效果。实际项目建议先跑一个低于目标规模的版本确认输出质量、首 token 速度和响应长度再决定是否升级。4.4 本地模型和远端 API 的差异本地模型与官方 API 的主要差异不在“能不能返回 reasoning_content”而在于官方 API 的模型版本和参数经过专门优化本地蒸馏模型不能等同替代。本地模型对复杂指令的遵循能力可能更弱需要更多试错。远端 API 对请求格式有严格校验本地 Ollama 通常更宽容这会让兼容性问题更晚暴露。本地接口不一定实现官方 API 的所有扩展字段。如果你在本地能跑通切到远端报错不要怀疑网络先检查 messages 结构是否满足远端要求。5. 把 DeepSeek 接入 Codex、VSCode 和自建 Agent5.1 OpenAI 兼容接口是大多数接入的核心Codex、Continue、Cline、各类自研 Agent 工具通常都支持 OpenAI 兼容的供应商配置。接入 DeepSeek 的关键并不是导入一个特殊插件而是正确配置三样东西base_url请求发到哪个地址。api_key用什么密钥认证。model使用哪个模型 ID。用表格整理如下接入对象核心配置方式注意事项Codex CLI环境变量配置 base_url 和 api_key工具版本可能对模型 ID 有校验VSCode 扩展插件级 OpenAI-compatible Provider不同插件字段名不同Ollama 本地模型base_url 指向本机 11434模型名是本地拉取的 tag自建 Agent请求层维护 model 和 messages按协议要求保留 or 丢弃 reasoning_content5.2 Codex CLI 接入方式Codex CLI 本身优先面向 OpenAI 模型。如果你的目的是测试 DeepSeek 的兼容能力可以先设置环境变量export OPENAI_API_KEYsk-你的DeepSeek密钥 export OPENAI_BASE_URLhttps://api.deepseek.com然后启动 Codex 命令行让它执行一个简单任务codex 用 Python 写一个读取 CSV 并输出统计结果的脚本这里要特别注意Codex 内部可能会发送 OpenAI Responses API 风格的参数而 DeepSeek 兼容端点未必全部支持。如果发现某些复杂任务失败优先看上游返回的 status code 和 cause不要默认所有 OpenAI 客户端参数都能被 DeepSeek 原样接受。5.3 VSCode 扩展接入方式VSCode 里接入 DeepSeek 通常不需要自己写代码而是在 AI 插件中添加一个自定义模型供应商。以 Continue 插件的 YAML 配置为例整体结构类似models: - name: DeepSeek Reasoner provider: openai model: deepseek-reasoner apiBase: https://api.deepseek.com apiKey: sk-你的DeepSeek密钥不同版本字段名可能有差异有的插件使用baseUrl有的使用apiBase有的要求填写/v1后缀。配置时以插件文档为准不要照抄后盲目认为一定生效。配置完成后在对话面板里切换到这个模型先问一个普通问题。然后打开开发者工具或日志面板确认实际请求是否发到了你配置的 base_url。5.4 自建 Agent 的组装准则自建 Agent 比直接接 IDE 更灵活也更容易踩坑。至少要注意下面几条不要把完整历史无限发给模型。Agent 每轮都会产生新的推理内容历史越长token 占用越高。在要求 thinking mode 回传的端点中assistant 的reasoning_content不能被简单丢弃。在不需要回传推理内容的官方 API 中也不要强行加入reasoning_content否则可能破坏消息格式。Agent 的每一步工具调用返回后应把工具结果结构化塞入 messages而不是拼成一段无结构文本。企业微信、飞书、钉钉这类 IM 接入本质上是把用户消息拆出来走同一套消息历史管理逻辑。权限范围、群聊上下文、消息去重要比“调通 API”更早设计。6. 一条面向 reasoning 模型的排查清单6.1 按顺序排查问题遇到 400、空回复、上下文错乱、推理质量差时不要一上来就怀疑模型能力。先按顺序检查检查 API Key 是否正确是否过期。看 401 还是 400。检查 model ID 是否在当前 base_url 下存在。第三方兼容端点尤其容易把模型名映射错。检查 messages 是否是合法历史结构。assistant 消息是否缺少 endpoint 要求的字段。检查上一轮是否返回了reasoning_content。多轮失败先看是否丢了这个字段。检查 messages 里是否放入了系统提示、工具结果、用户隐私信息等不该出现的内容。检查上下文是否超过模型限制。推理模型的 reasoning 内容通常很长容易提前撞到 token 上限。查看响应里的usage判断每轮消耗的 token 是否异常偏高。最后再看是不是网络、限流或平台临时故障。看到 5xx 或连接超时才往这个方向查。6.2 针对 HTTP 400 的速查表现象常见原因检查方式处理方向多轮请求突然 400丢弃了上一轮reasoning_content打印完整请求 body对比消息字段按要求回传 reasoning_content或改用不需要 thinking 的模型单轮请求就 400模型 ID 不匹配或参数不支持查看模型列表和文档换成 endpoint 支持的模型 ID部分工具调用报 400OpenAI 客户端参数与兼容端点不一致打开工具日志定位具体参数删除不兼容参数或升级工具版本请求成功但无推理内容调用的是 chat 模型而不是 reasoner查看响应里字段确认模型 ID 是否为推理模型显存不足或推理很慢本地模型参数量过大查看资源监控换小参数量模型或更低位量化版本6.3 至少避开的三个坑坑一把所有消息都存进历史并原样回传。这样会让上下文无限膨胀长链 Agent 会越来越慢也更早撞到 token 上限。应该只