# PR #45965 完整报告

- 仓库：`vllm-project/vllm`
- 标题：[Bugfix][Model] Add stability window to DiffusionGemma to match HF stability_threshold semantics
- 合并时间：2026-07-07 03:39
- 原文链接：http://prhub.com.cn/vllm-project/vllm/pull/45965

---

# 执行摘要

- 一句话：修复 DiffusionGemma 稳定性窗口偏移，匹配 HF 语义
- 推荐动作：该 PR 值得快速合并。它是一个明确的 bug 修复，有清晰的动机和来自核心贡献者的确认。虽然改动小，但涉及对 HF 行为对齐的深入理解，值得关注其分析过程。建议精读评论区的讨论以理解 vLLM 与 HF 在状态管理上的差异。

# 功能与动机

DiffusionGemma 的 denoise sampler 在稳定性检查中少考虑了一个步骤，导致像“The capital of France is”这样的短提示返回空字符串而非正确回答。PR body 明确指出：checkpoint 设置的 `stability_threshold=1` 在 HF 中需要 `k+1` 次连续相同 canvas 才停止，但 vLLM 的 `_compiled_sample_step` 将其视为滑动窗口大小，使得 `stability_threshold=1` 时稳定性循环为空，从而过早提交。

# 实现拆解

1. **定位问题**：在 `vllm/model_executor/models/diffusion_gemma.py` 的 `ModelRunner.__init__` 中，构造 `DiffusionGemmaRequestStates` 时直接将 `self.gen_config["stability_threshold"]` 传入，未考虑 vLLM 历史缓冲区包含当前步骤的差异。
2. **单行修复**：将传入的 `stability_threshold` 值加 1，即 `self.gen_config["stability_threshold"] + 1`。这保证了稳定性检查的窗口大小与 HF 一致：HF 的 `stability_threshold` 表示需要匹配的先前步骤数，而 vLLM 的历史缓冲区已包含当前步骤，因此需要增加 1。
3. **添加注释**：在修改处添加了详细注释，解释为何需要加 1，并引用 Transformers 行为对比。
4. **测试调整**：最初包含一个专门的测试文件 `tests/models/test_diffusion_gemma_stability.py`，但后续在评审过程中被删除，因为测试逻辑过于复杂且非必要。最终 PR 仅包含源码修改。

关键文件：
- `vllm/model_executor/models/diffusion_gemma.py`（模块 模型执行器；类别 source；类型 data-contract）: 唯一修改的文件。在 ModelRunner.__init__中修正了 stability_threshold 的传入值，加 1 以匹配 Hugging Face 语义。

关键符号：未识别

## 关键源码片段

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

唯一修改的文件。在 ModelRunner.__init__中修正了 stability_threshold 的传入值，加 1 以匹配 Hugging Face 语义。

```python
# vllm/model_executor/models/diffusion_gemma.py
# 第 803 行修改处
self.diffusion_states = DiffusionGemmaRequestStates(
    max_num_reqs=self.max_num_reqs,
    canvas_length=canvas_length,
    vocab_size=self.model_config.get_vocab_size(),
    max_denoising_steps=max_denoising_steps,
    device=device,
    hidden_size=text_config.hidden_size,
    # 在 Transformers 中，`stability_threshold=1` ( 默认值 ) 表示当前步必须与上一步匹配。
    # 在 vLLM 中，历史缓冲区包含当前步，因此加 1 以匹配相同行为。
    stability_threshold=self.gen_config["stability_threshold"] + 1,
)

```

# 评论区精华

- **AndreasKaratzas**最初提出疑问：“我不知道为什么只会在 Gemma 上发生。这个 PR 可能不正确。你可能需要在 HF 上调查而不是这里。” 这引发了对问题根源的讨论。
- **NathanielMcVicar**回应：“我认为只在这里发生是因为这是 vLLM 中唯一的扩散 LLM，很多通用基础设施都在 DiffusionGemma 模型代码中。HF 语义是正确的，因为没有这个更改，canvas 会立即虚假收敛。”
- **hmellor**确认修复正确，并解释：“关键区别在于 Transformers 中当前步骤不属于历史缓冲区，而 vLLM 中它属于。因此 vLLM 中的历史缓冲区必须比 Transformers 大 1。”
- **gante**提供了权威确认，并指出 bug 实际上可能导致比预期更早的停止（不仅是早一步），因为只要平均 token 熵足够低，模型就会停止，而正确实现应该同时要求熵低且 canvas 稳定超过 `stability_threshold` 步。

- 修复的正确性 (correctness): 修复被接受。hmellor 和 gante 都确认了变更的正确性。
- 测试文件取舍 (testing): 测试文件被删除，最终 PR 不包含新测试。

# 风险与影响

- 风险：该 PR 修改极小（仅一行加一注释），且逻辑已通过 Hugging Face 的参考实现验证。风险极低。潜在风险是：如果其他模型或未来代码也直接使用 `stability_threshold` 而未考虑此偏移，可能引入不一致。但当前仅 DiffusionGemma 使用该参数。
- 影响：
 - **用户影响**：修复了 DiffusionGemma 模型在短提示下生成空字符串的 bug，提高了生成质量。影响范围限于使用 DiffusionGemma 的用户。
 - **系统影响**：无性能影响。变更仅为构造函数中的参数调整，不影响运行时路径。
 - **团队影响**：无。
 - 风险标记：低风险 , 单行改动

# 关联脉络

- PR #45672 [perf]...（PR body 提及的关联 PR，但未在历史数据中完整给出）: PR body 提到 #45672 也修改了同一调用点，如果此 PR 后合并需要调整该 PR 中的 stability_threshold 引用。