Prhub

#44747 [Cohere] Fix Cohere2MoE weight loading when using Transformers ≥5.10

原始 PR 作者 Terrencezzj 合并时间 2026-06-09 21:27 文件变更 1 提交数 3 评论 2 代码增减 +27 / -9

执行摘要

修复 Cohere2MoE 在 Transformers >=5.10 下的权重加载

PR body 中明确说明:Cohere2MoeDecoderLayer 和 Cohere2MoeAttention 依赖 getattr(config, "first_k_dense_replace", 0) 判断是否使用 dense MLP。Transformers 5.10+ 中 Cohere2MoeConfig 已消费该字段并设置 mlp_layer_types,导致 first_k_dense_replace 为 None,vLLM 默认 0 后错误地将所有层视为 MoE,加载检查点时抛出 KeyError。

值得精读并合入。变更逻辑清晰,影响范围小,修复了对上游库版本变化的关键依赖。建议后续补加单元测试,验证不同 first_k_dense_replace / mlp_layer_types 组合下的行为。

讨论亮点

PR 无 review 评论,仅由 claude[bot] 自动回复(该 PR 来自 fork 且未触发 AI 评审),以及预提交检查失败的自动提醒(由 deepseekv4 相关文件引起,与 PR 无关)。mgoin 直接批准。

实现拆解

  1. 新增 is_prefix_dense_layer() 函数:在文件顶部定义,接受 config 和 layer_idx,基于 config.mlp_layer_types 检查从 layer 0 到当前层是否全为 "dense"。
  2. Cohere2MoeModel.__init__() 中规范化 mlp_layer_types:若 config 无 mlp_layer_types,则从 first_k_dense_replace(若存在)或默认全 "sparse" 推导并赋值。
  3. Cohere2MoeDecoderLayerCohere2MoeAttention 中替换原有判断逻辑:将硬编码的 first_k_dense_replace 获取与比较替换为 is_prefix_dense_layer() 调用,消除对旧属性的直接依赖。
  4. Cohere2MoeDecoderLayer.__init__() 的 MLP 选择处:用 config.mlp_layer_types[self.layer_idx] == "dense" 替代 self.layer_idx < first_k_dense_replace,保持一致性。
  5. 无测试配套改动:仅源码变更,未增删测试文件。
文件 模块 状态 重要度
vllm/model_executor/models/cohere2_moe.py 模型执行器 modified 7.22

关键符号

is_prefix_dense_layer Cohere2MoeModel.__init__ Cohere2MoeDecoderLayer.__init__ Cohere2MoeAttention.__init__

关键源码片段

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

唯一修改文件,包含全部核心变更:新增 `is_prefix_dense_layer()` 函数、在 `Cohere2MoeDecoderLayer` 和 `Cohere2MoeAttention` 中替换旧属性逻辑、在 `Cohere2MoeModel` 中规范化 `mlp_layer_types`。

# vllm/model_executor/models/cohere2_moe.pydef is_prefix_dense_layer(config: CohereConfig, layer_idx: int) -> bool:
    """True when layer_idx lies in the contiguous dense MLP prefix."""
    if layer_idx >= len(config.mlp_layer_types):
        return False
    return all(t == "dense" for t in config.mlp_layer_types[: layer_idx + 1])
​
​
class Cohere2MoeDecoderLayer(nn.Module):
    def __init__(self, *, vllm_config: VllmConfig, prefix: str = "", layer_idx: int):
        ...
        # 使用规范化后的 mlp_layer_types 判断当前层的 MLP 类型
        if config.mlp_layer_types[layer_idx] == "dense":
            self.mlp = Cohere2MoeMLP(...)
        else:
            self.mlp = Cohere2Moe(...)
        ...
​
​
class Cohere2MoeAttention(nn.Module):
    def __init__(self, *, vllm_config: VllmConfig, prefix: str = "", layer_idx: int):
        ...
        self.sliding_window = None
        layer_types = getattr(config, "layer_types", None)
        if (layer_types is not None
            and layer_types[self.layer_idx] == "sliding_attention"):
            self.sliding_window = config.sliding_window
​
        # 用 is_prefix_dense_layer 替代 first_k_dense_replace
        prefix_dense_sliding_window_pattern = getattr(
            config, "prefix_dense_sliding_window_pattern", 1
        )
        self.force_rope = bool(
            is_prefix_dense_layer(config, self.layer_idx)
            and prefix_dense_sliding_window_pattern == 1
        )
        ...
​
​
class Cohere2MoeModel(nn.Module):
    def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
        ...
        # 将旧版 first_k_dense_replace 规范化到 mlp_layer_types
        if getattr(config, "mlp_layer_types", None) is None:
            first_k_dense_replace = getattr(config, "first_k_dense_replace", None)
            n = config.num_hidden_layers
            if first_k_dense_replace is not None:
                config.mlp_layer_types = (
                    ["dense"] * first_k_dense_replace +
                    ["sparse"] * (n - first_k_dense_replace)
                )
            else:
                config.mlp_layer_types = ["sparse"] * n
        ...

评论区精华

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

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

风险与影响

  • 回归风险is_prefix_dense_layer() 假设 mlp_layer_types 列表满足连续 dense 前缀,若未来 Config 出现非连续模式,该逻辑可能错误判断。但当前 Cohere2Moe 的设计保证 dense 层位于前缀。
  • 兼容性风险:需要确保 Transformers 5.10 以下的 first_k_dense_replace 也被正确转换为 mlp_layer_types。规范化逻辑已涵盖此场景。
  • 代码覆盖风险:缺少直接针对此 fix 的回归测试,难以快速验证边界情况(如 first_k_dense_replacemlp_layer_types 为 None/部分缺失)。
  • 用户层面:修复了 Cohere2MoE 模型在 Transformers >=5.10 下的权重加载崩溃,用户可直接升级 Transformers 而无需锁版本。
  • 系统层面:仅影响 Cohere2MoE 模型路径,不影响其他模型。
  • 团队层面:简化了版本兼容逻辑,将 MLP 类型判断集中到辅助函数,方便后续维护。
缺少测试覆盖

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论