deepseek-harness 推理回传修复:dsh-llm-deepseek 适配器在每次推理轮次回放 reasoning_content

发布时间:2026/9/21 3:32:31
deepseek-harness 推理回传修复:dsh-llm-deepseek 适配器在每次推理轮次回放 reasoning_content 人工智能AI AgentAgent 框架DeepSeek【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址https://gitcode.com/gh_mirrors/de/deepseek-harness点击查看免费下载导读本文解读 deepseek-harness 仓库中dsh-llm-deepseekLLM 适配器的一处关键行为变更记录于 Agent Note: DeepSeek reasoning passback on every reasoned turnreasoning_content思维链从仅在携带工具调用的 assistant 轮次回放扩展为所有携带推理的轮次一律回放。读完本文你将理解该变更背后的协议约束、OpenAI 兼容网关下的会话重建风险、实现与测试细节以及它对输入 token 与 KV 缓存复用的实际影响。问题背景为什么此前只在工具调用轮次回放思维链dsh-llm-deepseek是 deepseek-harness 中直连 DeepSeek chat-completions 服务的 LLM 适配器注册deepseek-official路由负责把 harness 的会话历史序列化为 DeepSeek 的线上协议详见 README.md。在本次变更之前适配器只在同时携带工具调用的 assistant 轮次上把reasoning_content回放进后续请求的历史。这样做的依据来自 DeepSeek 思考模式的官方指南thinking mode 文档该字段在带工具调用的轮次上是必需的在其他轮次上则会被忽略。因此在普通轮次上不回传思维链对api.deepseek.com端点而言可以省下输入 token且没有任何可观测的损失。然而问题恰恰出在没有可观测损失这一前提上api.deepseek.com不是这个适配器唯一服务的端点。核心矛盾OpenAI 兼容网关的思考签名恢复适配器的Config.baseURL可以指向任意 OpenAI 兼容端点包括把 DeepSeek chat-completions 对话重新编码并转发给其他厂商的网关。这类网关在协议上没有承载上游思考签名的字段只能通过对回放的思维链文本取哈希来恢复该轮次的思考签名。于是出现如下分叉场景模型未调用工具、直接作答的轮次到达网关时完全不带推理文本网关的签名查找落空重建出的对话与 harness 记录中的对话产生分叉Agent 运行的大多数轮次都会调用工具所以这个损失只在纯作答轮次上出现表现为偶发、难以定位。这正是本次 bug 修复要消除的隐患会话历史是持久化在 session log 中的一旦重建分叉后续所有轮次的上下文都可能不一致。决策serializeAssistant 无条件回放携带推理的轮次修复决策非常明确serializeAssistant对每个内容携带推理的 assistant 轮次都发出reasoning_content与是否伴随工具调用无关没有推理块时仍然不发出该字段因此非思考轮次的行为保持不变。在 serialize.ts 中可以看到这一逻辑的实现其核心是条件展开function serializeAssistant(message: Message): WireMessage { const text flattenText(message.content) const reasoning message.content .filter(block block.type reasoning) .map(block block.text) .join() const toolCalls message.content .filter(block block.type tool-call) .map(block ({ ... })) return { role: assistant, content: text, // CoT passback on every reasoning-carrying turn. // A gateway re-encoding the conversation for another vendor recovers // that turns upstream thinking signature by hashing this exact text, // which a tool-call-free turn carries nowhere else. ...reasoning.length 0 ? { reasoning_content: reasoning } : {}, ...toolCalls.length 0 ? { tool_calls: toolCalls } : {}, } }关键点在于reasoning_content是否出现的唯一判据是reasoning.length 0与toolCalls完全解耦。代码注释明确记录了该决策的动机——网关正是通过对这段逐字文本取哈希来恢复上游思考签名而一个无工具调用的轮次在其他任何地方都不承载这段文本。文本逐字一致哈希可复现的前提回放的推理文本必须与提供方流式下发的内容逐字一致否则哈希仍然对不上。这一前提由 translate.ts 保证该模块把一次响应的整个reasoning_content通道累积进单个推理块reasoningBlock.text reasoning因此serializeAssistant中的.join()实际上只连接一个成员——对回放文本取的哈希与对原始下发文本取的哈希相同。线上类型定义同步更新types.ts 中的WireAssistantMessage类型对两种端点行为做了权威记录/** * CoT passback, present on every turn whose assistant content carried * reasoning. REQUIRED on tool-call turns in thinking mode (see * guides/thinking_mode.mdx § Tool Calls); DeepSeek ignores it elsewhere, * while a gateway re-encoding for another vendor recovers that turns * thinking signature by hashing it. */ reasoning_content?: string内容字段的空字符串纪律值得注意的还有content字段的处理纪律同为 serialize.ts 中注释所强调文本缺失的轮次发送而绝不为 null。纯工具调用轮次按官方示例逐字回放content: 部分网关直接拒绝 null而纯推理轮次模型可以完全在推理通道作答例如 v4-flash 的问候语如果 content 为 null在线 API 会以 400 拒绝content or tool_calls must be set且由于该消息持久化在 session log 中一个 null 就会让该会话此后所有轮次全部失败。这与本次 reasoning passback 变更属于同一轮序列化健壮性治理共同保证历史消息在各类端点上可重建。备选方案评估为什么不做配置开关Agent Note 记录了三个被否决的备选方案每一个都很有启发性方案一用 Config 开关选择回传策略两种端点行为官方 API 忽略、网关依赖哈希都真实存在但该字段在不需要它的地方是惰性的官方 API 忽略它所以开关最多只能换回一个轮次的思维链输入 token。代价却是一旦设置错误会话会静默地无法重建两端都不会报错来归因。一个设错就静默失败的旋钮比那点 token 更糟——这是典型的可观测性优先于微优化决策。方案二根据 baseURL 判断一个端点是否会转发给其他厂商无法从主机名读出内部端点可能直连代理 DeepSeek公网端点也可能转发。适配器只能对自己看不透的部署方式做猜测因此该方案被否决。方案三改为持久化签名如 dsh-llm-pi-ai 的做法孪生适配器dsh-llm-pi-ai会在 replay state 中按块持久化thinkingSignature因为它的提供方把签名放在协议里。而 DeepSeek chat-completions不暴露签名所以这个适配器没有可持久化的东西回放文本是唯一通道。这解释了为什么修复必须落在序列化层而非持久化层。影响与权衡token 成本 vs 前缀稳定性变更的直接代价是每个含推理且不带工具调用的轮次如今都会在后续请求中按其思维链计入输入 token。但这一代价的边际影响被严格控制新增文本位于该轮次所在位置且在此后每次请求中都相同因此组装出的前缀保持稳定只有跨越此次变更的第一个请求会从该位置起失去缓存复用之后的请求前缀与变更前同样可被 DeepSeek 的 KV 缓存复用。这与 README.md 中 Model Experience 小节的描述一致推理回传会把每个推理轮次的思维链带进后续请求Reasoning content from a prior assistant turn is passed back verbatim, whether or not that turn called a tool而未改变的已组装前缀仍可复用缓存前缀失稳的来源是执行世界路径变化、上传刷新替换file_id、Files 到 base64 回退等确定性变更而非回传本身。测试验证三种 assistant 形态的固定变更的测试覆盖在 tests/serialize.spec.ts 中固定了三种必须携带reasoning_content的形态推理与文本并存且无工具调用——这是本次变更新增的关键场景it(passes reasoning_content back on tool-call-free turns, () { const wire serializeMessages([ createMessage({ role: assistant, content: [ { type: reasoning, text: thinking… }, { type: text, text: answer }, ], ... }), ]) expect(wire).toEqual([{ role: assistant, content: answer, reasoning_content: thinking… }]) })推理与工具调用并存——官方回传规则场景且content保持非 nullexpect(wire).toEqual([{ role: assistant, content: , // (not null) on tool-call turns reasoning_content: I should check the weather., tool_calls: [{ id: call-1, type: function, function: { name: get_weather, arguments: {city:Paris} } }], }])内容保持为的纯推理轮次v4-flash 问候语形态expect(wire).toEqual([{ role: assistant, content: , reasoning_content: 你好有什么我可以帮你的吗, }])此外不携带推理的轮次仍不发出该字段由无内容content-less与仅工具调用两种用例覆盖——这保证了非思考模式下的请求体与变更前完全一致不会给官方 API 增加多余字段。小结本次修复体现了适配器层面的一个核心原则在协议边界上做最保守、最可重建的选择。reasoning_content无条件回传虽然在纯作答轮次上增加了输入 token但换来了跨端点官方 API 与各类 OpenAI 兼容网关一致的会话可重建性消除了一个偶发、静默、不可归因的分叉隐患。配合content: 而非 null 的纪律、逐字一致的推理文本累积以及三形态加两反例的测试矩阵这一行为被完整固定下来可放心作为 deepseek-harness 序列化层的既有契约来理解与引用。延伸阅读dsh-llm-deepseek 包说明Wire 格式与 Model Experience 的 token、缓存小节、序列化实现、SSE 翻译实现。赞分享人工智能AI AgentAgent 框架DeepSeek【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址https://gitcode.com/gh_mirrors/de/deepseek-harness点击查看免费下载相关推荐DeepSeek Harness 轮次结束原因通知让 TUI 中每一次 stop 都有用户可见的解释DeepSeek Harness 轮次结束原因通知让 TUI 中每一次 stop 都有用户可见的解释 本篇技术笔记基于仓库中归档的 Agent Note 2人工智能AI AgentAgent 框架DeepSeekdeepseek-harness 轮次封闭不变式让每个会话事件都落在 turn/start 与 turn/end 之间deepseek harness 轮次封闭不变式让每个会话事件都落在 turn/start 与 turn/end 之间 本文基于 deepseek harne人工智能AI AgentAgent 框架DeepSeekDeepSeek Harness 的 TUI 轮次结束原因通知为每种 TurnEndReason 给出用户可见的停止理由DeepSeek Harness 的 TUI 轮次结束原因通知为每种 TurnEndReason 给出用户可见的停止理由 本文围绕 DeepSeek Harn人工智能AI AgentAgent 框架DeepSeek上一篇Ice 菜单栏管理完整指南从杂乱到清爽的三步走下一篇古籍数字化 OCR用 RapidOCR 三档部署把书影变文本创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考