# PR #39842 完整报告

- 仓库：`vllm-project/vllm`
- 标题：[Model] Fix Gemma 4 token repetition by dynamic BOS injection for PT models
- 合并时间：2026-04-16 07:13
- 原文链接：http://prhub.com.cn/vllm-project/vllm/pull/39842

---

# 执行摘要

- 一句话：修复 Gemma 4 预训练模型因缺失 BOS 标记导致的重复生成问题。
- 推荐动作：该 PR 值得精读，因为它展示了一个典型的模型特定修复案例：通过动态条件判断来区分模型变体（预训练 vs. 指令调优）的行为差异。关注点在于 `has_chat_template` 的检查逻辑如何优雅地解决双 BOS 与缺失 BOS 的权衡问题，这种模式可能适用于其他具有类似模板依赖的模型。

# 功能与动机

根据 PR 正文和关联 Issue #39827，用户在使用 Gemma 4 预训练模型时观察到输出中出现重复标记（如“is is is is...”）。调查发现，这是因为 `Gemma4ProcessingInfo.get_default_tok_params` 方法为了在指令调优模型中避免双 BOS 序列，强制覆盖了 `add_special_tokens=False`，但这使得预训练模型在加载时缺少聊天模板，导致位置 0 处缺少必需的 `<bos>` 标记，从而引发生成质量下降。

# 实现拆解

1. **入口点修改**：在 `vllm/model_executor/models/gemma4_mm.py` 文件中，修改 `Gemma4ProcessingInfo` 类的 `get_default_tok_params` 方法。
2. **动态条件判断**：新增逻辑获取当前分词器实例，并通过 `getattr(tokenizer, "chat_template", None) is not None` 检查是否存在聊天模板。
3. **条件化参数设置**：如果分词器有聊天模板（即指令调优模型），则保持 `add_special_tokens=False` 以避免双 BOS；否则（即预训练模型），保留从父类继承的默认值 `add_special_tokens=True`，确保为原始提示添加 BOS 标记。
4. **文档更新**：更新方法文档字符串，明确说明此行为现在区分 IT 和 PT 模型。
5. **测试与验证**：PR 正文提供了详细的测试代码和结果对比，展示了修复前后生成输出的差异，但本次变更未包含直接对应的测试文件修改。

关键文件：
- `vllm/model_executor/models/gemma4_mm.py`（模块 模型实现；类别 source；类型 core-logic；符号 Gemma4ProcessingInfo.get_default_tok_params）: 这是唯一被修改的文件，包含了修复 Gemma 4 模型标记重复问题的核心逻辑变更。

关键符号：Gemma4ProcessingInfo.get_default_tok_params


## 关键源码片段

### `vllm/model_executor/models/gemma4_mm.py`

这是唯一被修改的文件，包含了修复 Gemma 4 模型标记重复问题的核心逻辑变更。

```python
class Gemma4ProcessingInfo(BaseProcessingInfo):
    # ... 其他方法 ...

    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 = self.ctx.get_tokenizer()
        # 动态判断：如果分词器有chat_template属性且不为None，则为IT模型
        has_chat_template = getattr(tokenizer, "chat_template", None) is not None

        # 调用父类方法获取默认参数（默认add_special_tokens=True）
        params = super().get_default_tok_params()
        # 仅当有聊天模板时，才覆盖为False以避免双BOS
        if has_chat_template:
            params = params.with_kwargs(add_special_tokens=False)
        return params
```

# 评论区精华

review 中未出现实质性技术讨论。gemini-code-assist[bot] 的评论仅总结了变更内容，指出“没有反馈可提供”。Isotr0py 直接批准了 PR。唯一的相关讨论是作者 lucianommartins 在 Issue 评论中提及一个失败的测试是由于测试代码错误（导入 libcudart.so.12 失败），与本次 PR 的核心变更无关，并请求合并。

- 暂无高价值评论线程

# 风险与影响

- 风险：1. **回归风险**：修改仅针对 Gemma 4 模型的处理信息类，且通过条件判断精确区分 IT 和 PT 模型，降低了影响其他模型或场景的风险。但需确保 `has_chat_template` 的判断逻辑在所有 Gemma 4 模型变体上准确无误。
2. **性能风险**：新增了分词器实例获取和属性检查，但开销极小，不会对推理性能产生可感知的影响。
3. **兼容性风险**：此变更修复了预训练模型的行为，理论上应向后兼容，但需验证是否会影响现有使用 Gemma 4 IT 模型的部署（根据逻辑应保持原行为）。
4. **测试覆盖不足**：PR 未包含自动化测试，仅依赖手动验证示例。虽然变更逻辑简单，但缺乏单元测试可能在未来重构或模型更新时引入潜在错误。
- 影响：1. **用户影响**：直接解决了 Gemma 4 预训练模型用户遇到的重复生成问题，提升了模型输出质量和可用性。对于指令调优模型用户无影响。
2. **系统影响**：仅修改了单个模型的处理逻辑，不影响 vLLM 核心引擎或其他模型执行路径。
3. **团队影响**：为模型加载和分词处理提供了一个细粒度控制 BOS 注入的模式，可作为类似问题（其他模型可能存在的模板依赖差异）的参考解决方案。
- 风险标记：条件判断依赖外部属性 , 缺少自动化测试

# 关联脉络

- PR #30566 Update to transformers v5: 同样涉及 Gemma 4 模型（gemma4_mm.py 文件），但该 PR 是升级 Transformers 依赖以支持新模型架构，而本次 PR 是修复该模型的具体生成问题。