Prhub

#44805 Added extra_repr() to pooler classes to improve debuggability

原始 PR 作者 taneem-ibrahim 合并时间 2026-06-08 11:19 文件变更 7 提交数 1 评论 0 代码增减 +73 / -0

执行摘要

为 pooler 类添加 extra_repr() 以提升调试性

PR body指出:'Currently most pooler modules print names like SequencePooler() with no visibility into their configuration. This makes debugging pooling pipelines harder.' 因此添加extra_repr()以暴露配置细节。

值得精读,设计模式简单但实用。展示了如何利用 PyTorch 的 extra_repr 钩子以最小成本提升代码可调试性。该模式可推广至其他复杂模块。

讨论亮点

无 reviewer 讨论,合并者 noooop 直接批准并回复 'thanks!'。

实现拆解

实现分以下步骤:

  1. vllm/model_executor/layers/pooler/seqwise/heads.py 中为 EmbeddingPoolerHeadClassifierPoolerHead 添加 extra_repr 方法,选择性输出 head_dtypeprojectoractivationlogit_meanlogit_sigma 等字段。
  2. vllm/model_executor/layers/pooler/tokwise/heads.py 中为 TokenEmbeddingPoolerHeadTokenClassifierPoolerHead 添加相同的逻辑。
  3. vllm/model_executor/layers/pooler/activations.py 中为 PoolerClassifyLambdaPoolerActivation 添加 extra_repr 以显示 num_labelsfn 函数名。
  4. vllm/model_executor/layers/pooler/tokwise/poolers.pyseqwise/poolers.py 中为容器类 TokenPoolerSequencePooler 添加 extra_repr,显示 poolinghead 的类名。
  5. vllm/model_executor/layers/pooler/special.py 中添加 extra_repr 显示 bos_token_ideos_token_id
  6. vllm/model_executor/layers/pooler/tokwise/methods.py 中添加 extra_repr 显示 enable_chunked_prefill 等配置。所有实现均遵循 nn.Moduleextra_repr 约定,仅在配置非空时输出,保持输出简洁。
文件 模块 状态 重要度
vllm/model_executor/layers/pooler/seqwise/heads.py 池化层 modified 7.09
vllm/model_executor/layers/pooler/tokwise/heads.py 池化层 modified 7.09
vllm/model_executor/layers/pooler/activations.py 池化层 modified 6.49
vllm/model_executor/layers/pooler/tokwise/poolers.py 池化层 modified 6.24
vllm/model_executor/layers/pooler/seqwise/poolers.py 池化层 modified 6.02
vllm/model_executor/layers/pooler/special.py 池化层 modified 5.43
vllm/model_executor/layers/pooler/tokwise/methods.py 池化层 modified 5.43

关键符号

EmbeddingPoolerHead ClassifierPoolerHead TokenEmbeddingPoolerHead TokenClassifierPoolerHead TokenPooler SequencePooler PoolerClassify LambdaPoolerActivation SpecialPoolingLayer AllPool

关键源码片段

vllm/model_executor/layers/pooler/seqwise/heads.py debugging

核心文件,为序列池化头(EmbeddingPoolerHead 和 ClassifierPoolerHead)添加了 extra_repr,展示 head_dtype、projector、activation 等关键配置项。

class EmbeddingPoolerHead(SequencePoolerHead):
    def __init__(
        self,
        projector: ProjectorFn | None = None,
        head_dtype: torch.dtype | str | None = None,
        activation: ActivationFn | None = None,
    ) -> None:
        super().__init__()
        self.projector = projector
        self.head_dtype = head_dtype
        self.activation = activation
​
    # 重写 extra_repr 以在 print 时展示配置 (PyTorch 模块标准钩子 )
    def extra_repr(self) -> str:
        attrs = []
        # 仅当字段非 None 时添加,保持输出简洁
        if self.head_dtype is not None:
            attrs.append(f"head_dtype={self.head_dtype}")
        if self.projector is not None:
            attrs.append("projector=True")
        if self.activation is not None:
            # 使用类名而非完整 repr,避免过长
            attrs.append(f"activation={self.activation.__class__.__name__}")
        return ", ".join(attrs)
​
    # 以下方法(get_supported_tasks, forward)保持不变class ClassifierPoolerHead(SequencePoolerHead):
    # 类似实现,增加了 logit_mean / logit_sigma 的输出
    def extra_repr(self) -> str:
        attrs = []
        if self.head_dtype is not None:
            attrs.append(f"head_dtype={self.head_dtype}")
        if self.classifier is not None:
            attrs.append("classifier=True")
        if self.logit_mean is not None:
            attrs.append(f"logit_mean={self.logit_mean}")
        if self.logit_sigma is not None:
            attrs.append(f"logit_sigma={self.logit_sigma}")
        if self.activation is not None:
            attrs.append(f"activation={self.activation.__class__.__name__}")
        return ", ".join(attrs)
vllm/model_executor/layers/pooler/tokwise/heads.py debugging

对应 token 粒度的池化头,为 TokenEmbeddingPoolerHead 和 TokenClassifierPoolerHead 添加 extra_repr,与序列版本保持一致。

class TokenEmbeddingPoolerHead(TokenPoolerHead):
    def __init__(
        self,
        head_dtype: torch.dtype | str | None = None,
        projector: ProjectorFn | None = None,
        activation: ActivationFn | None = None,
    ) -> None:
        super().__init__()
        self.head_dtype = head_dtype
        self.projector = projector
        self.activation = activation
​
    # 与序列版本类似的 extra_repr 实现
    def extra_repr(self) -> str:
        attrs = []
        if self.head_dtype is not None:
            attrs.append(f"head_dtype={self.head_dtype}")
        if self.projector is not None:
            attrs.append("projector=True")
        if self.activation is not None:
            attrs.append(f"activation={self.activation.__class__.__name__}")
        return ", ".join(attrs)
​
    # 以下方法(get_supported_tasks, forward_chunk)保持不变class TokenClassifierPoolerHead(TokenPoolerHead):
    # 类似实现,增加了 logit_mean / logit_sigma 的输出
    def extra_repr(self) -> str:
        attrs = []
        if self.head_dtype is not None:
            attrs.append(f"head_dtype={self.head_dtype}")
        if self.classifier is not None:
            attrs.append("classifier=True")
        if self.logit_mean is not None:
            attrs.append(f"logit_mean={self.logit_mean}")
        if self.logit_sigma is not None:
            attrs.append(f"logit_sigma={self.logit_sigma}")
        if self.activation is not None:
            attrs.append(f"activation={self.activation.__class__.__name__}")
        return ", ".join(attrs)
vllm/model_executor/layers/pooler/activations.py debugging

为激活函数类添加 extra_repr,展示 num_labels(分类任务)或 fn(lambda 包装)等配置。

class PoolerClassify(PoolerActivation):
    def __init__(self, *, num_labels: int | None = None) -> None:
        super().__init__()
        # ... 初始化逻辑(包括异常处理)
        self.num_labels = num_labels
​
    # 输出分类的标签数,有助于区分 softmax / sigmoid 行为
    def extra_repr(self) -> str:
        return f"num_labels={self.num_labels}"
​
    # forward_chunk 保持不变class LambdaPoolerActivation(PoolerActivation):
    def __init__(self, fn: Callable[[torch.Tensor], torch.Tensor]) -> None:
        super().__init__()
        self.fn = fn
​
    # 展示包装的函数名或类名
    def extra_repr(self) -> str:
        name = getattr(self.fn, "__name__", None)
        if name is None:
            name = self.fn.__class__.__name__
        return f"fn={name}"
​
    # forward_chunk 保持不变

评论区精华

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

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

风险与影响

极低风险。仅添加了 repr 相关的 extra_repr 方法,不改变任何前向逻辑或训练结果。若 extra_repr 中有异常会导致打印失败,但 Python 的 extra_repr 调用通常不会阻止程序运行。仍建议在合并前做快速 print 测试以验证输出格式。

正面影响:开发者通过 print(model.pooler) 即可快速了解池化层配置,省略了手动检查配置文件或调试的步骤。对用户无运行时影响,对团队协作调试效率有提升。

仅影响调试输出 低风险

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论