Prhub

#39842 [Model] Fix Gemma 4 token repetition by dynamic BOS injection for PT models

原始 PR 作者 lucianommartins 合并时间 2026-04-16 07:13 文件变更 1 提交数 1 评论 3 代码增减 +7 / -2

执行摘要

动态 BOS 注入修复 Gemma 4 PT 模型重复 token

修复 Issue #39827 报告的 Gemma 4 模型在 completion 场景下输出无限重复 token 的问题。根本原因是 Gemma4ProcessingInfo.get_default_tok_params 对所有加载的 Gemma 4 模型均强制设置 add_special_tokens=False,但 PT 模型(不含 chat template)的 raw prompt 本身不带 BOS,导致模型始终以无 BOS 状态生成,引起 token 循环。

该 PR 值得精读,尤其是它展示了一个轻量级的条件分支设计:通过检查 tokenizer 的 chat_template 属性来适配两种不同模型类型(IT vs PT),避免硬编码假设。建议团队为类似场景(同一个模型架构存在 IT/PT 变体)建立统一的处理模式。

讨论亮点

PR 无 review 讨论(0 条 review 评论),仅有一个 gemini-code-assist[bot] 的自动化 comment 和 Isotr0py 的 approve。后经测试 CI 中有一不相关的 ImportError 被作者指出并请求合并。合并后,Issue 评论区 @alexcardo 报告问题依旧存在,但作者回复其现象为句子级重复而非 token 级重复,推测为不同 bug,建议另提 Issue。

实现拆解

  1. 获取 tokenizer 实例:通过 self.ctx.get_tokenizer() 获取当前 tokenizer。
  2. 检测 chat template:使用 getattr(tokenizer, "chat_template", None) is not None 判断 tokenizer 是否注册了 chat_template
  3. 条件设置 add_special_tokens:仅在 has_chat_template 为 True 时(即 IT 模型)调用 params.with_kwargs(add_special_tokens=False);对于 PT 模型(无 chat_template),保留基类默认的 add_special_tokens=True,确保 BOS 被正确注入。
  4. 仅修改函数 get_default_tok_params:位于文件 vllm/model_executor/models/gemma4_mm.py 的第 162-179 行,变更量仅 +7/-2 行。
文件 模块 状态 重要度
vllm/model_executor/models/gemma4_mm.py 模型执行器 modified 6.09

关键符号

Gemma4ProcessingInfo.get_default_tok_params

关键源码片段

vllm/model_executor/models/gemma4_mm.py data-contract

核心修改文件:改变了 `Gemma4ProcessingInfo.get_default_tok_params` 的逻辑,根据 tokenizer 是否具有 `chat_template` 动态决定 `add_special_tokens` 参数,从而区分 IT/PT 模型行为。

# vllm/model_executor/models/gemma4_mm.py
# Gemma4ProcessingInfo.get_default_tok_params 方法(第 162-179 行)def get_default_tok_params(self):
    """Gemma4's chat template already embeds a literal ``<bos>`` token in
    the rendered text.  If ``add_special_tokens=True`` (the base-class
    default), the tokenizer prepends *another* BOS, producing a
    ``[2, 2, ...]`` double-BOS sequence that the model was not trained on.    Setting ``add_special_tokens=False`` here prevents the duplicate and
    ensures both ``llm.generate()`` and the chat/completions API behave
    correctly for IT models. For PT models (without chat template), we
    keep the default (True) to ensure BOS is added for raw prompts.
    """
    # 获取 tokenizer 实例并检查是否注册了 chat_template
    tokenizer = self.ctx.get_tokenizer()
    # 若 chat_template 不为 None,说明是 Instruction-Tuned 模型
    has_chat_template = getattr(tokenizer, "chat_template", None) is not None
​
    params = super().get_default_tok_params()
    # 只在 IT 模型中禁用 add_special_tokens,避免重复 BOS
    # PT 模型(无 chat_template)将使用基类默认的 add_special_tokens=True
    if has_chat_template:
        params = params.with_kwargs(add_special_tokens=False)
    return params

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

  • 低风险:变更仅 7 行,通过检查 chat_template 属性区分 IT/PT 模型,不改变其他模型行为。
  • 潜在风险:若某个非 Gemma 4 模型也使用了相同的条件分支或子类覆盖,可能受影响,但该方法是 Gemma 4 专属。
  • 无性能风险:增加一次 getattr 调用,开销可忽略。
  • 无测试覆盖:本次改动未附带单元测试,若未来 tokenizer 的 chat_template 行为变化可能引入回归。
  • 用户影响:修复了 Gemma 4 PT 模型在 completion 模式(如 llm.generate())下的 token 重复 bug,使生成恢复正常。
  • 系统影响:不影响其他模型,不影响 IT 模型(保持原有行为)。
  • 团队影响:小型、聚焦的 bugfix,易于审查和合并。
缺少测试覆盖 仅影响 Gemma 4 PT 模型

关联 Issue

#39827 [Bug]: VLLM Gemma4 output repeated token

完整报告

参与讨论