Prhub

#41049 [Core] Fix redundant None append in StepPool.forward for chunked prefill

原始 PR 作者 anthonsu 合并时间 2026-04-28 14:42 文件变更 1 提交数 1 评论 2 代码增减 +1 / -1

执行摘要

修复 StepPool 分块预填充时重复追加 None

修复 embedding 模型在 StepPool 处理长序列分块预填充时的输出错位问题。PR body 指出:'This fix is critical for embedding models that utilize StepPool to process long sequences across multiple forward passes. Without this fix, the pooling output becomes misaligned with the batch requests.'

值得精读以理解 StepPool 在 chunked prefill 下的设计。建议后续补充 StepPool 的单元测试覆盖分块预填充场景。

讨论亮点

review 讨论较少,maintainer noooop 快速批准并说明已知 CI 失败无关。无争议。

实现拆解

  1. 定位问题:在 forward 方法的 for 循环中,pooled_data.append(data) 语句位于 if-else 块之外,导致无论 data 是否为 None,都会执行一次 append。
  2. 修正逻辑:将 pooled_data.append(data) 移到 else 分支内部末尾,确保每个请求只追加一次结果。
  3. 影响范围:仅修改 vllm/model_executor/layers/pooler/tokwise/methods.py 文件的一行,将 append 语句缩进调整,无新增测试。
文件 模块 状态 重要度
vllm/model_executor/layers/pooler/tokwise/methods.py 池化层 modified 5.33

关键符号

StepPool.forward

关键源码片段

vllm/model_executor/layers/pooler/tokwise/methods.py core-logic

StepPool 的 forward 方法修复,单行缩进变更解决重复追加 None 问题。

class StepPool(AllPool):
    # ...
    def forward(
        self,
        hidden_states: torch.Tensor,
        pooling_metadata: PoolingMetadata,
    ) -> list[TokenPoolingMethodOutputItem]:
        pooled_data_lst = super().forward(hidden_states, pooling_metadata)
        prompt_token_ids = pooling_metadata.get_prompt_token_ids()
        pooling_params = pooling_metadata.pooling_params
​
        pooled_data = list[torch.Tensor | None]()
        for data, token_id, pooling_param in zip(
            pooled_data_lst, prompt_token_ids, pooling_params
        ):
            # 对于分块预填充中未完成的块,super().forward 返回 None
            # 此时只需追加一次 None 表示该请求尚未完成
            if data is None:
                pooled_data.append(None)
            else:
                step_tag_id = pooling_param.step_tag_id
                returned_token_ids = pooling_param.returned_token_ids
​
                if returned_token_ids is not None and len(returned_token_ids) > 0:
                    data = data[:, returned_token_ids]
​
                if step_tag_id is not None:
                    data = data[token_id == step_tag_id]
                # 将处理后的数据追加到输出列表(修复:原来在 if-else 外部,
                # 导致每个循环迭代都追加一次,对于未完成的块会多追加一个 None)
                pooled_data.append(data)
​
        return pooled_data

评论区精华

CI 失败无关 other

noooop 指出 'Fusion E2E TP2 Quick (H100) is a known main failure. A forced merge will be requested after the CI finishes.'

结论:CI 失败与 PR 无关,将强制合并。 · 已解决

风险与影响

风险极低。单行缩进变更,逻辑正确性明显。但缺少对应单元测试,长期维护可能有回归风险。

直接影响使用 StepPool 的 embedding 模型在长序列分块预填充场景下的正确性;对其他池化类型(如 AllPool)无影响。

缺少测试覆盖

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论