Prhub

#47151 Forward fix nightly errors from #44589

原始 PR 作者 hmellor 合并时间 2026-06-30 22:02 文件变更 3 提交数 4 评论 1 代码增减 +27 / -17

执行摘要

修复 #44589 导致的权重加载回归

PR #44589 移除了多个模型的 load_weights 方法,期望借助 AutoWeightsLoader 自动加载,但实际在 nightly CI 中造成了三个回归失败:MTEB 语言模型测试中 Jina 和 Gemma3 模型报 ValueError(权重未初始化),多模态扩展测试中 CohereForCausalLM 报参数缺失。Issue #47096 曾尝试回滚 #44589,但本 PR 采用更精确的前向修复方案。

建议合并。本 PR 是重要的紧急修复,精确地处理了 #44589 的副作用,避免了全量回滚。对于理解 AutoWeightsLoader 与自定义 load_weights 的交互边界有参考价值。

讨论亮点

无实质性 review 讨论。njhill 直接批准了 PR。Claude bot 因 PR 来自 fork 自动关闭了 review。

实现拆解

  1. Gemma3Model(gemma3.py):将原先定义在 Gemma3ForCausalLM 上的 hf_to_vllm_mapper 移动至 Gemma3Model 类中,并为 Gemma3Model 新增 load_weights 方法,委托 AutoWeightsLoader 加载。Gemma3ForCausalLM 改为引用 Gemma3Model.hf_to_vllm_mapper。原因是 Gemma3Model 被直接注册为 Gemma3TextModel,需要自己拥有 mapper 才能正确加载。
  2. JinaEmbeddingsV5Model(jina.py):为 JinaEmbeddingsV5Model 添加类级 hf_to_vllm_mapper,通过 Qwen3ForCausalLM.hf_to_vllm_mapper | WeightsMapper(orig_to_new_prefix={"": "model."}) 合并父类映射并添加 model. 前缀。同时修改 load_weights 方法,将 AutoWeightsLoader 从加载 self.model 改为加载 self,并使用 self.hf_to_vllm_mapper 而非 self.model.hf_to_vllm_mapper
  3. CohereForCausalLM(commandr.py):合并了两个重复的 hf_to_vllm_mapper 定义:第一个包含 orig_to_new_stacked 映射,第二个包含 orig_to_new_substr 用于过滤 _quantizer. 前缀。现合并为一个 WeightsMapper,同时包含两个参数。
  4. 补充导入:jina.py 新增 WeightsMapper 导入。
文件 模块 状态 重要度
vllm/model_executor/models/gemma3.py 权重加载 modified 6.95
vllm/model_executor/models/jina.py 权重加载 modified 6.09
vllm/model_executor/models/commandr.py 权重加载 modified 5.92

关键符号

load_weights

关键源码片段

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

核心修复:将 hf_to_vllm_mapper 从 Gemma3ForCausalLM 移至 Gemma3Model,并恢复 load_weights 方法。

# vllm/model_executor/models/gemma3.py@support_torch_compile
class Gemma3Model(nn.Module):
    # 将 mapper 从 Gemma3ForCausalLM 移到此处,
    # 因为 Gemma3Model 被直接注册为模型,需要自己持有 mapper
    hf_to_vllm_mapper = WeightsMapper(
        orig_to_new_stacked={
            ".q_proj": (".qkv_proj", "q"),
            ".k_proj": (".qkv_proj", "k"),
            ".v_proj": (".qkv_proj", "v"),
            ".gate_proj": (".gate_up_proj", 0),
            ".up_proj": (".gate_up_proj", 1),
        }
    )
​
    def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
        loader = AutoWeightsLoader(self)
        return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
​
​
class Gemma3ForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
    # 直接引用 Gemma3Model 的 mapper,避免重复定义
    hf_to_vllm_mapper = Gemma3Model.hf_to_vllm_mapper
    packed_modules_mapping = { ... }
vllm/model_executor/models/jina.py data-contract

修复 JinaEmbeddingsV5Model 权重加载:添加缺失的模型前缀映射,并将 loader 加载目标从 self.model 改为 self。

# vllm/model_executor/models/jina.pyclass JinaEmbeddingsV5Model(Qwen3ForCausalLM, VllmModelForPooling):
    is_pooling_model = True
    # 合并父类 Qwen3 的 mapper,并添加 "model." 前缀映射,
    # 使 checkpoint 中的裸键(如 "layers.0")能正确匹配到 self.model
    hf_to_vllm_mapper = Qwen3ForCausalLM.hf_to_vllm_mapper | WeightsMapper(
        orig_to_new_prefix={"": "model."}
    )
​
    def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
        ...
        # 之前是 AutoWeightsLoader(self.model, ...),现在改为 self,
        # 确保顶层 key 前缀正确解析
        loader = AutoWeightsLoader(self, ignore_unexpected_prefixes=["lm_head."])
        weights = _merge_weights(weights)
        return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/commandr.py data-contract

修复 CohereForCausalLM 中 hf_to_vllm_mapper 重复定义导致映射覆盖的问题。

# vllm/model_executor/models/commandr.pyclass CohereForCausalLM(nn.Module, SupportsLoRA, SupportsPP, SupportsQuant):
    # 合并两个独立的 WeightsMapper 为一个,避免第二个覆盖第一个的 stacked 映射
    hf_to_vllm_mapper = WeightsMapper(
        orig_to_new_stacked={
            ".q_proj": (".qkv_proj", "q"),
            ".k_proj": (".qkv_proj", "k"),
            ".v_proj": (".qkv_proj", "v"),
            ".gate_proj": (".gate_up_proj", 0),
            ".up_proj": (".gate_up_proj", 1),
        },
        # ModelOpt NVFP4 checkpoints 会携带量化器状态,
        # 如 "*.weight_quantizer._double_scale",需要过滤掉
        orig_to_new_substr={"_quantizer.": None},
    )
    packed_modules_mapping = { ... }

评论区精华

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

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

风险与影响

风险较低,变更仅针对特定模型的权重加载逻辑,且已在 nightly CI 对应测试上验证通过。但需要注意的是,这类精细的映射修复可能因未来 AutoWeightsLoader 的演化而再次失效。

直接影响使用 Gemma3、Jina Embeddings V5 以及 Cohere(aya_vision)模型的用户,尤其是进行 MTEB 评测或多模态推理的场景。修复后这些模型可正常加载权重,不会回退到回滚 #44589 带来的功能丢失。

核心路径变更 依赖批量重构 缺乏新增测试覆盖

关联 Issue

#44589 Remove unnecessary `load_weights` methods
#47096 Revert "Remove unnecessary `load_weights` methods" (#44589)

完整报告

参与讨论