Prhub

#41658 [Mistral Tokenizer] allow more leniency in apply_chat_template

原始 PR 作者 juliendenize 合并时间 2026-05-06 10:56 文件变更 10 提交数 7 评论 5 代码增减 +144 / -397

执行摘要

升级 mistral_common 至 1.11.2,将工具适配逻辑移至库内并支持 reasoning 字段

PR body 指出升级 mistral_common 到 1.11.2 允许在 assistant 消息中使用 reasoning 字段,支持用户将思考痕迹发送回模型,提升 Mistral Medium 3.5 等推理模型的性能;同时将工具特殊处理移到 mistral_common 中以减少 vLLM 内的 LOC。

值得精读。该 PR 展示了如何通过升级依赖库将自定义逻辑上移,从而简化 vLLM 代码并获取新功能。关注点包括:add_generation_prompt 传递问题的后续处理、from_openai 方法的接口稳定性、以及测试覆盖是否足够全面。设计决策上,选择信任库原生实现而非手动适配是合理方向。

讨论亮点
  1. add_generation_prompt 缺失传递:gemini-code-assist 在 vllm/tokenizers/mistral.py:409 指出,重构后的调用未将 add_generation_prompt 参数传递到底层 transformers tokenizer,可能导致默认 False 与 vLLM 默认行为不一致,标记为高优先级。作者回应这已是现有行为,且需等待 transformers 新版支持后方可调整。
  2. 增加 Thinking 和 ToolCall 测试:joa-stdn 在测试文件中建议增加对 reasoning(Thinking)和工具调用部分的测试覆盖。作者随后添加了相关测试,如 test_apply_chat_template_reasoning_assistant 等。

实现拆解

  1. 移除手动工具适配函数:删除 vllm/tokenizers/mistral.py 中的 adapt_inplace_to_mistral_tool 函数及相关导入(Function, Tool),该函数负责填充缺失的 parametersdescription 字段并过滤不支持的键。
  2. 重构参数验证:将 _prepare_apply_chat_template_tools_and_messages 重命名为 _validate_apply_chat_template_args,精简为只校验参数互斥和最后消息角色,不再修改消息内容或工具字典。原先移除 reasoning 字段的逻辑被移除,因为 mistral-common 1.11.2 已原生支持。
  3. 替换工具转换为库原生方法:在 vllm/tool_parsers/mistral_tool_parser.py 中,将 MistralTool.model_validate(adapt_inplace_to_mistral_tool(tool.model_dump())) 替换为 MistralTool.from_openai(tool.model_dump()),该新方法内部处理了字段兼容性。
  4. 更新依赖声明:在 requirements/common.txt, requirements/test/cuda.in, requirements/test/rocm.in 等文件中将 mistral_common 版本从 >=1.11.0 / ==1.11.0 提升至 >=1.11.2 / ==1.11.2
  5. 重写测试套件:在 tests/tokenizers_/test_mistral.py 中,将原先面向 _prepare_apply_chat_template_tools_and_messages 的参数化测试替换为针对新验证函数的测试 test_validate_apply_chat_template_args,并新增 TestMistralTokenizer 类,包含对 reasoning 字段、工具可选字段、工具未突变等场景的测试,同时保持对原有特殊 token 和 grammar factory 的覆盖。
文件 模块 状态 重要度
vllm/tokenizers/mistral.py 分词器 modified 7.61
tests/tokenizers_/test_mistral.py 测试 modified 7.24
vllm/tool_parsers/mistral_tool_parser.py 工具解析器 modified 5.31
requirements/test/cuda.in 依赖配置 modified 2.85
requirements/test/rocm.in 依赖配置 modified 2.85
requirements/test/cuda.txt 依赖配置 modified 1.49
requirements/test/rocm.txt 依赖配置 modified 1.49
requirements/test/xpu.txt 依赖配置 modified 1.49
requirements/common.txt 依赖配置 modified 1.32
requirements/test/nightly-torch.txt 依赖配置 modified 1.32

关键符号

adapt_inplace_to_mistral_tool _prepare_apply_chat_template_tools_and_messages _validate_apply_chat_template_args

关键源码片段

vllm/tokenizers/mistral.py core-logic

核心重构文件:移除 adapt_inplace_to_mistral_tool 函数和 _prepare_apply_chat_template_tools_and_messages,新增 _validate_apply_chat_template_args,删除大量手动工具 / 消息修改逻辑。

# vllm/tokenizers/mistral.py (head 版本关键片段 )def _validate_apply_chat_template_args(
    messages: list["ChatCompletionMessageParam"],
    continue_final_message: bool = False,
    add_generation_prompt: bool = False,
) -> None:
    """验证 apply_chat_template 参数合法性,不再修改消息或工具。    mistral-common 1.11.2 已原生支持 tool 转换和 reasoning 字段,
    因此本函数仅负责参数校验,实际的工具转换在 tool_parser 中
    通过 `MistralTool.from_openai` 完成。
    """
    if add_generation_prompt and continue_final_message:
        raise ValueError(
            "Cannot set both `add_generation_prompt` and "
            "`continue_final_message`."
        )
    if add_generation_prompt:
        if messages and messages[-1]["role"] == "assistant":
            raise ValueError(
                "add_generation_prompt requires last message "
                "not from assistant."
            )
    if continue_final_message:
        if messages and messages[-1]["role"] != "assistant":
            raise ValueError(
                "continue_final_message requires last message "
                "from assistant."
            )
    # 注意:不再移除 reasoning 字段,不再修改 tool 字典,
    # 这些已由 mistral-common 的 from_openai 处理。# 在 apply_chat_template 中的调用点(简化):
# 之前 :
# messages, tools = _prepare_apply_chat_template_tools_and_messages(
# messages, tools, continue_final_message, add_generation_prompt)
# 现在 :
_validate_apply_chat_template_args(
    messages, continue_final_message, add_generation_prompt)
# 工具转换移至 adjust_request 中,直接使用 MistralTool.from_openai
vllm/tool_parsers/mistral_tool_parser.py dependency-wiring

工具转换逻辑迁移:将 `adapt_inplace_to_mistral_tool` 调用替换为 `MistralTool.from_openai`,清理导入。

# vllm/tool_parsers/mistral_tool_parser.py (head 版本关键片段 )
from vllm.tokenizers.mistral import MistralTokenizer # 不再导入 adapt_inplace_to_mistral_tool# ... 在 adjust_request 方法中 :
mistral_tools = (
    [MistralTool.from_openai(tool.model_dump()) for tool in request.tools]
    if request.tools is not None
    else None
)
# 原来使用的是 :
# [MistralTool.model_validate(adapt_inplace_to_mistral_tool(tool.model_dump())) ...]

评论区精华

add_generation_prompt 参数未传递到底层 transformers tokenizer 正确性

gemini-code-assist 在 vllm/tokenizers/mistral.py:409 指出,重构后的调用缺少 `add_generation_prompt` 参数,可能导致生成提示不符合用户意图,标记为高优先级问题。

结论:作者回应此问题在重构前已存在,且需等待 transformers 新版发布后方可在 MistralCommonBackend 中支持传递该参数,当前暂不修复。 · 已回应,未解决

建议增加对 Thinking 和 ToolCall 部分的测试 测试

joa-stdn 在 tests/tokenizers_/test_mistral.py:42 中建议为新增的 reasoning 字段和工具调用流程补充测试。

结论:作者随后添加了 `test_apply_chat_template_reasoning_assistant` 等测试用例,覆盖了 reasoning 和 tool optional fields 场景。 · 已解决

风险与影响

  1. add_generation_prompt 行为差异:当前未将该参数传递给底层 tokenizer,可能在高阶用法中导致生成提示不符合用户预期;但该问题 PR 前已存在,属于既有缺陷,未因此 PR 引入新风险。
  2. mistral_common 升级兼容性:从 1.11.0 升级到 1.11.2,依赖库的接口变更(如 from_openai 方法)可能对使用该库的外部代码造成影响,但 vLLM 内部已适配。
  3. 手动适配逻辑移除:原先 adapt_inplace_to_mistral_tool 中通过 _pop_unallowed_keys_and_warn 进行防御性清理,替换为库原生的 from_openai 后,不同版本的 mistral_common 对额外字段的处理可能与原先不一致,需关注工具解析的容错性。

用户:使用 Mistral tokenizer 的用户可以获得更宽松的 chat template 处理,支持在 assistant 消息中传递 reasoning 字段,从而提升推理模型(如 Mistral Medium 3.5)的性能。工具调用行为因对接库原生 API 而更稳定。
系统:vLLM 中 Mistral tokenizer 的代码量大幅减少(-51 行),维护成本降低;依赖升级可能引入细微行为变化,但测试已覆盖关键路径。
团队:后续可直接受益于 mistral-common 库的新特性,无需在 vLLM 侧重复实现。

add_generation_prompt 未显式传递底层 tokenizer mistral_common 升级可能引入接口不兼容 移除手动 tool 适配可能导致边缘 case

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论