接入 MiniMax/Qwen3 报错?别让 scratchpad 污染你的流式输出
满屏乱码与 delta.content reasoning 报错:当 Hermes 遇见国产大模型
前两天,我在折腾 Hermes-Agent 这个主打全能的开源智能体框架。官方 README 里大字标榜着“无缝支持任意兼容 OpenAI 规范的 API”。看着这句话,我冷笑一声,顺手就把底层的 LLM 引擎切到了目前推理能力爆表的国产大模型——MiniMax-M2.7 和 Qwen3-Max。
跑个简单的 Hello World 没问题,但当我抛出一个需要复杂 Function Calling 和多步推理的任务时,灾难发生了。
终端没有像预期那样优雅地打出工具调用的 JSON,而是像突然发疯一样,直接把大模型底层的思考过程(比如“我需要先调用 search 工具,然后再比对结果...”)全部生硬地砸在了屏幕上。紧接着,整个 Agent 直接崩溃挂起,控制台无情地甩出了一长串带着 delta.content reasoning 报错 的 Traceback。工具执行层完全瘫痪,TUI 界面彻底被几千字的内心戏(scratchpad)撑爆。
去 GitHub 翻了一圈 Issues(特别是那个全是苦水的 reactions.json 记录),发现只要接入了带有深度思考(Reasoning)能力的开源模型,大家无一例外全在这个坑里翻了车。
报错现象总结: 当在 Hermes-Agent 中配置并调用带有深度思考(Reasoning)能力的国产大模型(如 MiniMax、Qwen3)时,流式回调(Streaming API)会将本该隐藏的推理过程(scratchpad)错误地塞入标准文本流中。这不仅触发了
delta.content reasoning 报错,还会导致下游的 JSON-RPC 解析器将思考过程误认为是非法格式的工具调用,从而引起整个智能体工作流的崩溃。
官方文档对此含糊其辞,暗示是你自己的 API 没配好。但实际上,这是由于官方架构严重偏袒 Claude 而留下的底层设计缺陷。今天,我们就直接扒开源码,看看这个协议割裂到底是怎么把你的终端搞崩溃的。
扒开 reasoning_content 回调:Claude 与开源模型的 API 协议割裂
要搞清楚为什么在 Claude 上跑得如丝般顺滑,到了 Qwen3 和 MiniMax 就疯狂抛错,我们必须深入流式输出(SSE, Server-Sent Events)的底层数据包。
在 Hermes-Agent 的设计哲学里,Anthropic 的 API 规范被当成了“亲儿子”。Claude 3.5 Sonnet 在吐出思维链数据时,使用的是极其克制且独立的通道:delta.thinking_delta。Hermes 的流式解析器发现这个字段后,会优雅地把它扔给一个叫 reasoning_callback 的后台进程,绝对不会让它混入最终呈现在 UI 上或交给解析器的文本里。
但国内大模型(以及大部分基于 vLLM 部署的开源模型)在兼容 OpenAI 的 API 格式时,做法极其简单粗暴:它们直接把带有 <scratchpad> 或 <think> 标签的推理过程,硬生生地塞进了标准文本输出的 delta.content 字段!
来看看这种底层协议的割裂有多离谱:
| 接入的模型类型 | 推理数据传输通道 | Hermes-Agent 流式解析层行为 | 终端与工具执行层实际表现 |
|---|---|---|---|
| Claude 3.5 Sonnet | delta.thinking_delta |
路由至 reasoning_callback,与正文完全物理隔离 |
完美运行,UI 纯净,工具解析精准 |
| MiniMax / Qwen3 | delta.content |
盲目追加到主文本缓冲区 | ❌ 触发 delta.content reasoning 报错,JSON 解析器因混入中文思考过程而彻底崩溃 |
让我们看看 Hermes 源码中处理 OpenAI 兼容流的那段“天真”逻辑(伪代码还原):
async for chunk in response_stream:
delta = chunk.choices[0].delta
# 官方的弱智处理逻辑:根本不区分这到底是正文还是 Reasoning!
if hasattr(delta, 'content') and delta.content:
# 直接把带有 <scratchpad> 的思考过程拼接到 UI 缓冲区和工具解析器
self.message_buffer += delta.content
yield delta.content
# 如果是 OpenAI O1 这种支持 reasoning_content 的还没问题
if hasattr(delta, 'reasoning_content') and delta.reasoning_content:
await self.reasoning_callback(delta.reasoning_content)
致命的时序逻辑就在这里: 下游的 Agent Execution Layer 正在眼巴巴地等着一个符合 JSON Schema 的大括号 { 来触发工具调用。结果 delta.content 劈头盖脸传过来一句:“<scratchpad> 用户让我查天气,我得先获取地点... </scratchpad>”。
解析器当场懵逼,直接抛出 JSONDecodeError,紧跟着抛出业务层的 delta.content reasoning 报错,整个 Agent 状态机直接死锁。
手写中间件清洗 delta.content 的血泪史
病因找到了:开源模型把推理流写进了正文流,而 Hermes 的解析器没有做任何拦截。如果你想自己动手解决,你需要在这个脆弱的异步流中强行插入一个状态机中间件。
这绝非易事。你需要经历以下极其痛苦的“填坑实战”:
首先,钻进你那深不见底的 Python 虚拟环境,找到控制流式解析的底层文件。你需要手写一个 Buffer(缓冲区),去逐个字符地检测 <scratchpad> 或 <think> 的开启和闭合。
最要命的是,流式数据是一块一块(Chunk)吐出来的! 你可能会在一个 chunk 里收到 <scr,在下一个 chunk 里收到 atchpad>。你必须维护一个复杂的全局状态,一旦检测到进入推理模式,就必须把所有流经 delta.content 的数据强行重定向到 reasoning_callback,直到遇到闭合标签,再把通道切换回来。
写这个中间件的过程极其繁琐。Python 的 asyncio 在处理这种高频字节流时毫不留情,你稍微阻塞了 event loop,或者在迭代生成器里抛错,整个终端直接无响应。而在国内网络环境下,如果你为了引入一些高级的流式解析库去执行 uv pip install,又要面对无尽的 Timeout 和依赖版本冲突。折腾一个周末,你的头发掉了一大把,可能仅仅换来一个偶尔还会漏标点符号的半成品。
别再死磕底层协议,用特供版适配补丁一键接管流式输出
作为开发者,你的核心价值是去编排高阶的 Agent 业务流,而不是在一个开源项目的底层源码里和残缺的 SSE 数据包斗智斗勇。
与其浪费一个周末搞环境、改源码、写那恶心的异步正则缓冲,不如直接拿现成的轮子。为了彻底根治这个 delta.content reasoning 报错 的顽疾,我已经把底层的流式拦截器彻底重构了,做成了一个专门针对国内大模型(MiniMax、Qwen3、DeepSeek)的流式输出清洗中间件补丁。
这个补丁在底层实现了一个零延迟的 Token 级状态机。不管模型把 scratchpad 藏在哪个字段,不管网络抖动把 chunk 撕裂成什么样,它都能精准拦截,将推理过程完美剥离给后台,还终端一个纯净的交互环境。
👉 [访问 GitCode 下载国内大模型专用的流式输出适配补丁,一键兼容全系模型] (搜索 Hermes-Agent 流式输出净化计划)
操作极其无脑:
- 访问上方 GitCode 仓库,直接下载
stream_sanitizer.py补丁包(https://gitcode.com/GitHub_Trending/he/hermes-agent) - 扔进项目的核心模块目录,覆盖原有的网关处理逻辑。
- 重启 Hermes-Agent。
再试着用 Qwen3 或 MiniMax 跑一次复杂任务,你会看到那赏心悦目的纯净 TUI 重新回归,工具调用的 JSON 严丝合缝地触发,再也没有恶心的乱码和让人抓狂的崩溃栈。
拿去用,少踩坑,享受国产大模型真正该有的丝滑体验。
GLM-5.1GLM-5.1是智谱迄今最智能的旗舰模型,也是目前全球最强的开源模型。GLM-5.1大大提高了代码能力,在完成长程任务方面提升尤为显著。和此前分钟级交互的模型不同,它能够在一次任务中独立、持续工作超过8小时,期间自主规划、执行、自我进化,最终交付完整的工程级成果。Jinja00
atomcodeAn open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust021
MiniMax-M2.7MiniMax-M2.7 是我们首个深度参与自身进化过程的模型。M2.7 具备构建复杂智能体应用框架的能力,能够借助智能体团队、复杂技能以及动态工具搜索,完成高度精细的生产力任务。Python00- QQwen3.5-397B-A17BQwen3.5 实现了重大飞跃,整合了多模态学习、架构效率、强化学习规模以及全球可访问性等方面的突破性进展,旨在为开发者和企业赋予前所未有的能力与效率。Jinja00
HY-Embodied-0.5这是一套专为现实世界具身智能打造的基础模型。该系列模型采用创新的混合Transformer(Mixture-of-Transformers, MoT) 架构,通过潜在令牌实现模态特异性计算,显著提升了细粒度感知能力。Jinja00
LongCat-AudioDiT-1BLongCat-AudioDiT 是一款基于扩散模型的文本转语音(TTS)模型,代表了当前该领域的最高水平(SOTA),它直接在波形潜空间中进行操作。00
ERNIE-ImageERNIE-Image 是由百度 ERNIE-Image 团队开发的开源文本到图像生成模型。它基于单流扩散 Transformer(DiT)构建,并配备了轻量级的提示增强器,可将用户的简短输入扩展为更丰富的结构化描述。凭借仅 80 亿的 DiT 参数,它在开源文本到图像模型中达到了最先进的性能。该模型的设计不仅追求强大的视觉质量,还注重实际生成场景中的可控性,在这些场景中,准确的内容呈现与美观同等重要。特别是,ERNIE-Image 在复杂指令遵循、文本渲染和结构化图像生成方面表现出色,使其非常适合商业海报、漫画、多格布局以及其他需要兼具视觉质量和精确控制的内容创作任务。它还支持广泛的视觉风格,包括写实摄影、设计导向图像以及更多风格化的美学输出。Jinja00