Prhub

#51998 chore: Upstream Cohere parser fixes + tests

原始 PR 作者 jasonozuzu-cohere 合并时间 2026-08-13 20:05 文件变更 10 提交数 2 评论 4 代码增减 +533 / -54

执行摘要

上游化 Cohere 解析器修复并补 510 行测试

PR body 仅说明 “Adding some local fixes for Cohere parsers alongside corresponding tests”,没有关联 issue。从变更内容可以还原动机:vLLM 中 Cohere Command 3/4 的 reasoning parser 在流式模式下未启用 no_tools(),导致工具调用提取职责与 tool parser 重叠;tool parser 未启用 start_in_answer(),可能把推理文本中的 JSON 片段误判为工具调用。这些都是 Cohere 内部已修复的问题,本 PR 将其合入主线并补齐回归测试,使 vLLM 解析行为与 Cohere 平台一致。

值得精读。重点看两处设计:一是 no_tools()start_in_answer() 如何界定 reasoning parser 与 tool parser 的职责边界,二是测试中 _token_deltas 用 U+FFFD 缓冲不完整多字节字符、以字节粒度模拟流式输入的手法,可作为其他 streaming parser 测试的范本。建议维护者关注 melody 0.11.1 的版本约束是否需要在运行时文档和镜像构建中显式声明。

讨论亮点

review 评论为空,自动化 review 因 fork 被禁用:claude[bot] 提示维护者可评论 @claude review 手动触发。维护者 DarkLight1337 在 issue 评论区两次运行 /ci run(Buildkite #83560、#83711),分别验证首个 commit 与合并 main 后的版本,随后直接 approve。核心设计权衡(no_tools()start_in_answer() 的职责划分)没有在评论区展开讨论,但从 diff 中可以明确推断。

实现拆解

  1. 依赖与提示升级requirements/test/cuda.inrequirements/test/rocm.incohere_melody>=0.9.0 提升到 >=0.11.1,锁文件 cpu.txtcuda.txtrocm.txt 同步为 0.11.1;vllm/reasoning/cohere_command_reasoning_parser.pyvllm/tool_parsers/cohere_command_tool_parser.pyvllm/renderers/cohere.py 的 ImportError 安装提示统一改为 pip install 'cohere-melody>=0.11.1',因为 no_tools()start_in_answer() 等 filter 选项依赖新版本。
  2. 推理解析器行为修复CohereCommand3ReasoningParserCohereCommand4ReasoningParserstreaming_optsstream_non_grounded_answer() 改为 no_tools().stream_non_grounded_answer(),与既有 unary_opts 对齐,明确 reasoning parser 不负责工具调用提取,流式输出中 <|START_ACTION|> 块原样作为 content 交给下游;同时 collect_tool_schema 生成的 EBNF 中 tools 规则由 ws "," ws 调整为 (ws "," ws) 语义,允许逗号前出现空白,匹配模型实际输出格式。
  3. 工具解析器行为修复CohereCommand3ToolParserCohereCommand4ToolParser 的 streaming/unary 配置均增加 .start_in_answer(),约束工具调用只能从 <|START_ACTION|> 锚点之后开始,避免把推理文本中的 JSON 误判为工具调用。
  4. 测试配套:新增 tests/tool_parsers/test_cohere_command_tool_parser.py(510 行),用 MockCohereTokenizer 按 UTF-8 字节模拟逐 token 流,覆盖单/多工具调用、仅推理、引用与 emoji 场景,并校验 streaming 与 non-streaming 结果一致;tests/reasoning/test_cohere_command_reasoning_parser.py 删除 ExpectedToolCall 及工具调用断言,改为断言 content 原样输出且 tool_call_deltas == []
  5. 影响面:所有依赖 Cohere Command 3/4 parser 的推理与 tool-calling 路径行为更新,解析结果与 Cohere 平台对齐;测试与依赖变更同时落地,CI 在 CPU/NVIDIA 平台验证。
文件 模块 状态 重要度
vllm/reasoning/cohere_command_reasoning_parser.py 推理解析器 modified 6.14
vllm/tool_parsers/cohere_command_tool_parser.py 工具解析器 modified 5.74
tests/tool_parsers/test_cohere_command_tool_parser.py 工具解析器 added 7.48
tests/reasoning/test_cohere_command_reasoning_parser.py 推理解析器 modified 5.13
vllm/renderers/cohere.py 渲染器 modified 3.92
requirements/test/cuda.in 测试依赖 modified 3.25

关键符号

CohereCommand3ReasoningParser.__init__ CohereCommand4ReasoningParser.__init__ CohereCommand3ToolParser.__init__ CohereCommand4ToolParser.__init__ collect_tool_schema _try_import_melody _token_deltas _run_streaming_over_deltas

关键源码片段

vllm/reasoning/cohere_command_reasoning_parser.py core-logic

核心行为修复:streaming_opts 增加 no_tools(),统一流式与非流式的工具调用职责;同时修正 collect_tool_schema 生成的 EBNF 语法。

# vllm/reasoning/cohere_command_reasoning_parser.py
# ``no_tools()`` 让 reasoning parser 在流式路径下也不解析工具调用,
# 工具调用统一交给 tool parser 处理,避免两个解析器重复提取。
# ``stream_non_grounded_answer`` 保持 melody 对不完整引用标记的缓冲。
class CohereCommand3ReasoningParser(BaseCohereCommandReasoningParser):
    def __init__(self, tokenizer: TokenizerLike, *args, **kwargs):
        super().__init__(
            tokenizer,
            *args,
            streaming_opts=(
                PyFilterOptions().cmd3().no_tools().stream_non_grounded_answer()
            ),
            unary_opts=PyFilterOptions().cmd3().no_tools(),
            **kwargs,
        )
​
​
class CohereCommand4ReasoningParser(BaseCohereCommandReasoningParser):
    def __init__(self, tokenizer: TokenizerLike, *args, **kwargs):
        super().__init__(
            tokenizer,
            *args,
            streaming_opts=(
                PyFilterOptions().cmd4().no_tools().stream_non_grounded_answer()
            ),
            unary_opts=PyFilterOptions().cmd4().no_tools(),
            **kwargs,
        )

评论区精华

fork PR 自动 review 状态 other

claude[bot] 评论指出该 PR 来自 fork,自动化 review 被禁用,可由维护者通过 @claude review 手动触发一次性 review。

结论:未触发额外自动 review,由维护者 DarkLight1337 直接 approve。 · 已解决

CI 验证触发 测试

DarkLight1337 在 issue 评论区两次运行 /ci run,分别针对首个 commit 126b7e29cb10(Buildkite #83560)与合并 main 后的 3ec6b34e47a3(Buildkite #83711)。

结论:两次 CI 均已触发,PR 最终合并。 · 已解决

风险与影响

依赖版本下限提升到 cohere_melody>=0.11.1,低于该版本的环境会直接触发 ImportError,安装提示虽已更新,但用户若使用缓存安装或旧 Docker 镜像可能出现版本不一致;reasoning parser 流式路径启用 no_tools() 后不再输出 tool_calls,依赖该行为的上游调用方需要改用 tool parser;collect_tool_schema 的 EBNF 语法放宽了逗号前空白,存在结构化输出解析歧义的微小可能,需回归验证;新增测试基于字节级 mock tokenizer,未覆盖真实 Cohere tokenizer 的分词边界(如特殊 token 被拆成多个子 token 的情况),真实环境仍有回归风险。

用户侧:使用 Cohere Command 3/4 的 tool calling 与 reasoning 输出在升级后获得更准确的解析结果,但必须安装 cohere-melody>=0.11.1。系统侧:通过 no_tools()start_in_answer() 明确了 reasoning parser 与 tool parser 的职责边界,降低两类 parser 的耦合,长期利于维护。团队侧:510 行新增测试显著提高 Cohere 解析功能的回归防护,字节级 mock tokenizer 的设计可复用到其他厂商 parser 的流式测试。CI 影响:新增测试在 CPU/NVIDIA 平台运行,依赖锁文件同步更新。

依赖版本下限提升 (cohere_melody>=0.11.1) streaming 输出行为变更 reasoning/tool 解析职责分离 测试基于 mock tokenizer

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论