[Bug]: Minimax m3 reasoning parser sending in content field in streaming

用户使用 vLLM(标签 minimax-m3 )部署 MiniMax M3 模型,并同时启用 --tool-call-parser minimax_m3 和 --reasoning-parser minimax_m3 。在非流式模式下,推理解析器正常工作;但在 streaming 模式下, <mm

[Bug]: Minimax m3 reasoning parser sending in content field in streaming

[Bug]: Minimax m3 reasoning parser sending in content field in streaming

快速结论:该报错发生在 vLLM 部署 MiniMax M3 模型并使用 --reasoning-parser minimax_m3 启用流式输出时。优先检查 streaming 模式下,<mm:think> 标签和推理内容是否被错误地放入 content 字段而非 reasoning 字段,原因是流式推理解析器依赖 token ID 匹配,而真实 tokenizer 中标签可能被编码为多个子 token。

问题场景

用户使用 vLLM(标签 minimax-m3)部署 MiniMax M3 模型,并同时启用 --tool-call-parser minimax_m3--reasoning-parser minimax_m3。在非流式模式下,推理解析器正常工作;但在 streaming 模式下,<mm:think> 标签和推理内容被当作普通文本放入 content 字段,reasoning 字段始终为空。

报错原文

data: {"choices":[{"delta":{"content":""}}]}
data: {"choices":[{"delta":{"content":"Reasoning"}}]}
data: {"choices":[{"delta":{"content":" content"}}]}
data: {"choices":[{"delta":{"content":""}}]}
data: {"choices":[{"delta":{"content":"content"}}]}

Expected output:
data: {"choices":[{"delta":{"reasoning":"Reasoning"}}]}
data: {"choices":[{"delta":{"content":"content"}}]}

原因分析

核心原因在于 vllm/reasoning/minimax_m3_reasoning_parser.py 中的 extract_reasoning_streaming() 方法依赖 token ID 来识别 <mm:think></mm:think> 标记。然而,实际部署中该标签可能被 tokenizer 编码为多个子 token,导致 self.start_token_idself.end_token_id 无法在 delta_token_ids 中匹配,从而使所有内容落入文本分支,标签和推理内容全部泄漏到 content 字段。

非流式路径 extract_reasoning() 直接操作原始字符串(使用 partition 等字符串方法),不受 tokenize 方式影响,因此工作正常。单元测试 tests/reasoning/test_minimax_m3_reasoning_parser.py 使用 mock tokenizer,其中标签被当作单一原子 token,导致测试未能捕获此问题。

环境排查

  • 模型:MiniMaxAI/MiniMax-M3-MXFP8
  • vLLM 版本/分支:minimax-m3 或 0.1.dev17492+g454b47db8(基于 vllm/vllm-openai:minimax-m3 镜像)
  • 启动参数:需确认是否同时设置了 --reasoning-parser minimax_m3
  • API 调用:使用 stream: true 调用 /v1/chat/completions
  • tokenizer 行为:检查 <mm:think> 经 tokenizer 编码后的 token ID 数量和值:tok.encode("<mm:think>", add_special_tokens=False)

解决步骤

  1. 临时方案 1:修改 chat template(不推荐)
    修改 chat_template.jinja 中的标记定义:
    {%- set think_begin_token = '<think>' -%}
    {%- set think_end_token = '</think>' -%}
    警告:此方法会改变模型的标记习惯,可能影响工具调用等其他功能。

  2. 临时方案 2:设置默认 chat template kwargs(可优先尝试)
    在 vLLM 启动参数中添加:
    --default-chat-template-kwargs '{"thinking_mode":"enabled"}'
    验证效果后,streaming 模式下推理内容会出现在 delta.reasoning,最终回答出现在 delta.content,且 <mm:think> 不再泄漏。
    注意:此方法强制对每个请求启用推理模式,会增加延迟和 token 消耗,且请求级的 chat_template_kwargs 可能覆盖服务器端默认值。

  3. 长期修复:等待官方 PR 合入
    参考 PR #45713(后自动关闭,请追踪 PR #45718 进展)。该修复将让流式推理解析器也能基于文本标记(而非仅依赖 token ID)检测 <mm:think>,从而与 extract_reasoning() 保持一致。如果读者有能力,可前往 PR 进行 review 或验证。

验证方法

执行一次带 stream: true 的聊天请求,检查 streaming 响应中:reasoning 字段是否包含推理内容,content 字段中是否不再出现 <mm:think></mm:think> 标签。对于非流式请求,确保 reasoning 字段仍然正确分离。

参考来源

vllm-project/vllm #45687

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

celebrityanime
celebrityanime
文章: 9639

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注