Prhub

#45217 [Bugfix] Initialize missing attributes in mistral eagle

原始 PR 作者 jjppp 合并时间 2026-06-12 08:21 文件变更 2 提交数 4 评论 2 代码增减 +156 / -0

执行摘要

补全 EagleMistralLarge3Model 缺失的 use_mha 与 num_redundant_experts

Issue #44846 报告 Mistral Small 4 的 EAGLE draft 头初始化时崩溃,因为 EagleMistralLarge3Model 继承了 DeepseekV2Model.forward 但未设置必要属性 use_mha,同时 num_redundant_experts 也缺失。

建议阅读,因为此 PR 展示了如何安全修复子类因跳过父类 __init__ 导致的属性缺失问题,同时配套的回归测试设计(monkeypatch 打桩 + 参数化 + forward 验证)是高质量的实践参考。

讨论亮点

无人工审查评论,仅自动化机器人提示 pre-commit 检查通过。

实现拆解

  1. EagleMistralLarge3Model.__init__ 中,self.normself.aux_hidden_state_layers 之后补充了 self.use_mha 的计算逻辑:从 config.qk_nope_head_dimconfig.qk_rope_head_dim 获取,若两者均为 0 或模型类型为 'deepseek' 则启用 MHA。
  2. 同时添加 self.num_redundant_expertsvllm_config.parallel_config.eplb_config.num_redundant_experts 读取,与父类 DeepseekV2Model.__init__ 保持一致。
  3. 新增测试文件 tests/model_executor/test_mistral_large_3_eagle.py,通过 monkeypatch 打桩替换 get_pp_groupVocabParallelEmbeddingRowParallelLinearRMSNormDeepseekV2DecoderLayer 为无重量 Dummy 实现,使测试可在 CPU 上运行。提供参数化测试验证三种配置下 use_mha 的预期值(MLA 时为 False,无 MLA dims 时为 True,deepseek 类型时为 True),以及一个端到端 forward 测试确保整个前向路径不报错。
文件 模块 状态 重要度
vllm/model_executor/models/mistral_large_3_eagle.py Eagle 模型 modified 6.24
tests/model_executor/test_mistral_large_3_eagle.py Eagle 测试 added 7.8

关键符号

EagleMistralLarge3Model.__init__ EagleMistralLarge3Model.forward test_eagle_mistral_large3_initializes_deepseek_runtime_attrs test_eagle_mistral_large3_forward_reuses_deepseek_parent_forward

关键源码片段

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

修复的核心文件,在 EagleMistralLarge3Model.__init__ 中添加了 use_mha 和 num_redundant_experts 的初始化,确保与父类 DeepseekV2Model 的行为一致。

# 在 EagleMistralLarge3Model.__init__ 中,设置基础模块后补充父类必要属性
self.norm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
self.aux_hidden_state_layers: tuple[int, ...] = ()# 以下属性是 DeepseekV2Model.__init__ 中原有的,用于 forward 和 load_weights
# 从 config 中读取 qk_nope_head_dim 和 qk_rope_head_dim,若不存在则默认 0
qk_nope_head_dim = getattr(config, "qk_nope_head_dim", 0)
qk_rope_head_dim = getattr(config, "qk_rope_head_dim", 0)# 计算 use_mha:模型类型为 deepseek 或 MLA 维度均为 0 时启用 MHA
self.use_mha = config.model_type == "deepseek" or all(
    dim == 0 for dim in (qk_nope_head_dim, qk_rope_head_dim)
)# 读取冗余专家数,与父类逻辑一致
self.num_redundant_experts = (
    vllm_config.parallel_config.eplb_config.num_redundant_experts
)# 继续原有初始化
self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
    ["hidden_states", "residual"], config.hidden_size
)
tests/model_executor/test_mistral_large_3_eagle.py test-coverage

新增回归测试文件,通过 monkeypatch 打桩避免 GPU 依赖,参数化验证 use_mha 三种场景的正确性,并测试 forward 调用不崩溃。

# 测试 EagleMistralLarge3Model 是否正确继承了 DeepseekV2Model 的运行时属性
@pytest.mark.cpu_test
@pytest.mark.parametrize(
    ("model_type", "qk_nope_head_dim", "qk_rope_head_dim", "expected_use_mha"),
    [
        # MLA 样式配置:不应使用 MHA
        ("mistral3", 128, 64, False),
        # 无 MLA 维度:应使用 MHA,符合父类逻辑
        ("mistral3", 0, 0, True),
        # DeepSeek 模型类型始终使用 MHA
        ("deepseek", 128, 64, True),
    ],
)
def test_eagle_mistral_large3_initializes_deepseek_runtime_attrs(
    model_type, qk_nope_head_dim, qk_rope_head_dim, expected_use_mha
):
    vllm_config = make_vllm_config(
        model_type=model_type,
        qk_nope_head_dim=qk_nope_head_dim,
        qk_rope_head_dim=qk_rope_head_dim,
    )
    model = eagle_mod.EagleMistralLarge3Model(vllm_config=vllm_config)
    # 验证 aux_hidden_state_layers 为空元组
    assert model.aux_hidden_state_layers == ()
    # 验证 use_mha 与预期一致
    assert model.use_mha is expected_use_mha
    # 验证冗余专家数为 0(测试配置中设定)
    assert model.num_redundant_experts == 0

评论区精华

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

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

风险与影响

风险较低。属性初始化逻辑与 DeepseekV2Model.__init__ 完全相同,仅在子类中显式设置,不会影响其他模型。但需注意 config.qk_nope_head_dimconfig.qk_rope_head_dim 缺失时使用默认值 0 的行为(此时 use_mhaTrue),测试已覆盖该边界。无性能影响。

直接影响使用 mistralai/Mistral-Small-4-119B-2603-NVFP4 搭配 EAGLE draft 头的 speculative decoding 用户:drafter 初始化不再崩溃,可正常启动服务。不影响其他模型或功能,无破坏性变更。

属性初始化与父类同步风险 配置项缺失默认值依赖

关联 Issue

#44846 [Bug]: Mistral Small 4 EAGLE drafter crashes at init — EagleMistralLarge3Model missing use_mha (skips DeepseekV2Model.__init__)

完整报告

参与讨论