Prhub

#43579 [Bugfix][Model] Fix GPT2ForSequenceClassification sub-module prefix

原始 PR 作者 QingZhou-YangHY 合并时间 2026-05-26 13:43 文件变更 1 提交数 3 评论 7 代码增减 +7 / -2

执行摘要

修复 GPT2ForSequenceClassification 权重加载前缀错误

GPT2ForSequenceClassification 的 GPT2Model 子模块前缀错误地设置为 "gpt2",但 checkpoint 中该子模块的键命名空间为 "transformer.*",导致权重加载静默失败(部分加载)。此外,_add_transformer_prefix 函数会错误地将 score.weight 加上 "transformer." 前缀,使其无法匹配到正确的模块。本 PR 部分解决了 #15697(Composite model loading using AutoWeightsLoader)中关于 GPT-2 的问题。

该 PR 值得合并,修复明确且符合预期。建议读者关注 _add_transformer_prefix 函数的排除模式,它反映了一种可复用的权重前缀转换模式,未来其他模型若使用 AutoWeightsLoader 并存在类似直接子模块时,可借鉴此模式。

讨论亮点

Review 中,gemini-code-assist[bot] 指出了关键问题:_add_transformer_prefix 函数会将 score.weight 错误地加前缀为 transformer.score.weight,导致加载失败,因为 score 是 GPT2ForSequenceClassification 的直接子模块,不属于 transformer。该评论被标记为高优先级。作者 QingZhou-YangHY 随后提交了修复提交(commit 7ddcced),增加了对 score. 前缀的排除。DarkLight1337 批准了 PR,但要求重命名 PR 标题,因为标题具有误导性(实际没有使用新的 AutoWeightsLoader 代码)。

实现拆解

  1. 修正子模块前缀:在 GPT2ForSequenceClassification.__init__ 中,将 GPT2Model 实例化时的 prefix 参数从 maybe_prefix(prefix, "gpt2") 改为 maybe_prefix(prefix, "transformer"),使得子模块的权重键与 checkpoint 中的 transformer.* 命名空间一致。
  2. 增加权重前缀转换:在 GPT2ForSequenceClassification.load_weights 中添加调用 _add_transformer_prefix(weights) 对输入的权重名称进行转换,将非 transformer.、lm_head.、score. 开头的权重名加上 transformer. 前缀,以便 AutoWeightsLoader 能正确路由至子模块。
  3. 修复 _add_transformer_prefix 逻辑:在 _add_transformer_prefix 的过滤条件中增加 not name.startswith("score.") 的判断,避免 score.weight 等分类头权重被错误添加 transformer. 前缀,从而确保它们能正确加载到 GPT2ForSequenceClassification.score 直接子模块。
文件 模块 状态 重要度
vllm/model_executor/models/gpt2.py 模型执行器 modified 6.09

关键符号

GPT2ForSequenceClassification.__init__ GPT2ForSequenceClassification.load_weights _add_transformer_prefix

关键源码片段

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

修改了 GPT2ForSequenceClassification 的 prefix 和 load_weights,以及 _add_transformer_prefix 函数,是 PR 的唯一变更文件。

# file: vllm/model_executor/models/gpt2.py
# 摘自 GPT2ForSequenceClassification 和 _add_transformer_prefix
​
class GPT2ForSequenceClassification(nn.Module, SupportsCrossEncoding):
    """GPT2 Model for sequence classification."""
​
    def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
        super().__init__()
        config = vllm_config.model_config.hf_config
        # 将 prefix 从 "gpt2" 修正为 "transformer",与 checkpoint 命名空间对齐
        self.transformer = GPT2Model(
            vllm_config=vllm_config, prefix=maybe_prefix(prefix, "transformer")
        )
        self.score = nn.Linear(config.n_embd, config.num_labels, bias=False)
        # ... pooler 初始化 ...
​
    def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]):
        loader = AutoWeightsLoader(self)
        # 应用前缀转换,确保 transformer.* 前缀正确,同时保留 score.* 和 lm_head.*
        weights = _add_transformer_prefix(weights)
        return loader.load_weights(weights)
​
​
def _add_transformer_prefix(
    weights: Iterable[tuple[str, torch.Tensor]],
) -> Iterable[tuple[str, torch.Tensor]]:
    """为权重名称添加 'transformer.' 前缀,但排除特定子模块。"""
    for name, tensor in weights:
        # 如果名称不以 'transformer.', 'lm_head.', 'score.' 开头,则加上前缀
        if (
            not name.startswith("transformer.")
            and not name.startswith("lm_head.")
            and not name.startswith("score.") # score 是直接子模块,不应加前缀
        ):
            name = "transformer." + name
        yield name, tensor

评论区精华

_add_transformer_prefix 错误地为 score.weight 添加前缀 正确性

gemini-code-assist[bot] 指出,`_add_transformer_prefix` 函数将所有非 `transformer.` 或 `lm_head` 开头的权重名都加上了 `transformer.` 前缀,这会导致 `score.weight` 被重命名为 `transformer.score.weight`,从而无法正确加载(因为 `score` 是 `GPT2ForSequenceClassification` 的直接子模块)。该评论被标记为高优先级。

结论:作者在后续提交 (7ddcced) 中增加了 `not name.startswith("score.")` 的排除条件,修复了该问题。 · 已解决

风险与影响

本次修改仅涉及 gpt2.py 单个文件,变更量小(+7/-2),且修复逻辑简单明确。风险极低。主要风险在于:如果未来有新的 GPT-2 变体引入其他直接子模块,_add_transformer_prefix 的排除列表可能需要同步更新。此外,该修复依赖于 _add_transformer_prefix 函数已定义的排除模式,若其他模型复用此函数且存在类似直接子模块,可能引入同样的问题。

直接影响使用 GPT2ForSequenceClassification 进行序列分类推理的用户,修复了权重加载失败或部分加载的问题。对系统无性能影响,因为仅修改了权重加载逻辑(初始化阶段)。代码改动量小,不影响其他模型或模块。

关联 Issue

#15697 [Feature]: Composite model loading using `AutoWeightsLoader` for all models

完整报告

参与讨论