# PR #50285 完整报告

- 仓库：`vllm-project/vllm`
- 标题：[Refactor] Remove multiple dead codes
- 合并时间：2026-08-03 22:59
- 原文链接：http://prhub.com.cn/vllm-project/vllm/pull/50285

---

# 执行摘要

- 一句话：跨 22 文件清理 405 行死代码，覆盖模型、量化与编译模块
- 推荐动作：值得快速精读，作为大规模死代码清理的标准参考：重点关注 hmellor 的拦截点（deprecation 工具保留）与作者在两个模型文件间同步清理重复方法的协作方式。如果团队有 agent 或自动审计流程，可以顺带落实「保护废弃兼容工具」的规则，避免未来误删。

# 功能与动机

PR 描述只有一句 `Purpose Remove multiple dead codes`，没有关联 Issue。从 patch 看，被删符号均已在仓库内无任何调用方：ScaledActivation 是 AWQ 时代的激活后缩放组件，SkyworkR1VDummyInputsBuilder 与 InternVL 基类实现逐行一致，CopyNumelCounter 的 copy_ 计数已不再被引用。清理目标是消除历史遗留冗余、降低维护噪音，并精简模块 import 依赖，而非修复具体缺陷。

# 实现拆解

1. **模型层批量清理（约 14 个文件）**：删除 `vllm/model_executor/layers/activation.py` 的 `ScaledActivation` 及其依赖的 Tensor 并行分片导入；`layers/conv.py` 删除 `CausalConv2dLayer` 自定义因果 padding 封装；`layers/quantization/fp8.py` 删除 `CopyNumelCounter`（`TorchDispatchMode` 子类）与相关 import；`models/nemotron_parse.py` 删除 `BartParallelLMHead`；`models/glm_ocr.py` 清理 `GlmOcrVisionPatchEmbed` 残留；`models/skyworkr1v.py` 删除与基类重复的 `SkyworkR1VDummyInputsBuilder`，注册直接复用 `BaseInternVLDummyInputsBuilder`；`models/idefics3.py`、`models/phi4mm.py`、`models/phi4mm_utils.py`、`models/vision.py`、`models/llava_onevision2.py`、`models/minimax_m3/common/mm_preprocess.py` 等同步移除 `_resize_output_size`、`cat_with_pad`、`get_llm_pos_ids_for_vision`、`_get_data_parser` 等工具函数。
2. **基础设施与编译路径清理**：`vllm/v1/core/kv_cache_utils.py` 删除 `need_extra_keys` 与 `is_kv_cache_page_size_uniform`，块哈希与页面统一逻辑收敛到保留函数内部或调用方；`vllm/compilation/passes/fx_utils.py` 删除 `is_auto_func`、`find_getitem`、`get_only_user` 三个 fx 图工具；`vllm/compilation/passes/vllm_inductor_pass.py` 删除调试用途的 `PrinterInductorPass`。
3. **入口与工具函数清理**：`vllm/entrypoints/chat_utils.py` 删除 `get_history_tool_calls_cnt`；`vllm/profiler/utils.py` 删除 `trim_string_front`；`vllm/utils/multi_stream_utils.py` 清理无用枚举 `AuxStreamType`；`vllm/model_executor/models/utils.py` 删除 `isin_list`；`layers/utils.py` 删除 `is_layer_moe_router_gate`。
4. **评审修正**：`vllm/config/utils.py` 的 `handle_deprecated` 首次被列入删除名单，hmellor 指出它对未来 deprecation 仍有用，作者在后续 commit 中恢复；同时按 hmellor 建议追加删除 `minimax_m3/common/mm_preprocess.py` 中与 llava_onevision2 重复的 `_get_data_parser`。
5. **测试与配套**：本次无新增测试文件，也不涉及配置、schema 或部署改动；正确性依赖现有 CI（含模型回归与编译测试）以及删除前对全仓库引用的验证。

关键文件：
- `vllm/model_executor/layers/activation.py`（模块 激活层；类别 source；类型 data-contract；符号 ScaledActivation, __init__, forward, weight_loader）: 删除 ScaledActivation 类及 Tensor 并行相关导入（48 行），是本次最大的单点删除，涉及 AWQ 量化历史引用路径，也是公共符号删除风险最高的文件之一。
- `vllm/model_executor/layers/conv.py`（模块 卷积层；类别 source；类型 data-contract；符号 CausalConv2dLayer, __init__, forward）: 删除 CausalConv2dLayer 及其 52 行自定义因果 padding 逻辑，模型层不再需要该类，同时移除 `F` 相关 padding 分支。
- `vllm/model_executor/models/skyworkr1v.py`（模块 视觉语言模型；类别 source；类型 data-contract；符号 SkyworkR1VDummyInputsBuilder, get_dummy_text, get_dummy_mm_data）: 删除与 InternVL 基类完全重复的 SkyworkR1VDummyInputsBuilder（+1/-31），注册改为直接使用 BaseInternVLDummyInputsBuilder，示例了多模态 dummy 输入构建的统一化。
- `vllm/model_executor/layers/quantization/fp8.py`（模块 量化；类别 source；类型 data-contract；符号 CopyNumelCounter, __init__, __torch_dispatch__）: 删除 CopyNumelCounter（TorchDispatchMode 子类）及其 import，说明 FP8 权重加载的 numel 计数路径已被其它机制替代。
- `vllm/v1/core/kv_cache_utils.py`（模块 KV 缓存；类别 source；类型 core-logic；符号 need_extra_keys, is_kv_cache_page_size_uniform）: 删除 need_extra_keys 与 is_kv_cache_page_size_uniform 两个核心工具函数（34 行），涉及前缀缓存哈希与 KV 页面统一逻辑的收敛。
- `vllm/compilation/passes/fx_utils.py`（模块 编译优化；类别 source；类型 core-logic；符号 is_auto_func, find_getitem, get_only_user）: 删除 is_auto_func、find_getitem、get_only_user 三个 fx 图工具（19 行），表明相关 auto_functionalize 场景已由 find_auto_fn_maybe 等保留函数覆盖。
- `vllm/model_executor/models/idefics3.py`（模块 多模态模型；类别 source；类型 data-contract；符号 _resize_output_size）: 删除 _resize_output_size（35 行）图像尺寸剪裁逻辑，多模态处理中的 resize 策略已统一到基类或处理器。
- `vllm/model_executor/models/vision.py`（模块 视觉编码；类别 source；类型 data-contract；符号 get_llm_pos_ids_for_vision）: 删除 get_llm_pos_ids_for_vision（37 行）动态 RoPE 位置构造，视觉编码的位置生成已内联到调用方。

关键符号：ScaledActivation, CausalConv2dLayer, SkyworkR1VDummyInputsBuilder, CopyNumelCounter, need_extra_keys, is_kv_cache_page_size_uniform, BartParallelLMHead, is_auto_func, find_getitem, get_only_user, _resize_output_size, cat_with_pad, get_llm_pos_ids_for_vision, PrinterInductorPass, isin_list, get_history_tool_calls_cnt, trim_string_front, is_layer_moe_router_gate, _get_data_parser, AuxStreamType

## 关键源码片段

### `vllm/model_executor/layers/activation.py`

删除 ScaledActivation 类及 Tensor 并行相关导入（48 行），是本次最大的单点删除，涉及 AWQ 量化历史引用路径，也是公共符号删除风险最高的文件之一。

```python
# vllm/model_executor/layers/activation.py
# PR #50285 移除了 ScaledActivation 类及其配套的 Tensor 并行导入：
# 它曾经用于 AWQ 等量化方法，在激活后除以 per-partition 的 scales，
# 并依赖 vllm.distributed 的 divide 与 rank/world_size 做切分。
# 全仓库已无任何模块引用它，因此同时清掉了这些导入依赖。
# 下方是保留的激活函数注册表，注册方式不受影响。

_ACTIVATION_REGISTRY = LazyDict(
    {
        "gelu": lambda: GELU(),
        "gelu_fast": lambda: FastGELU(),
        "gelu_new": lambda: NewGELU(),
        "gelu_pytorch_tanh": lambda: _get_gelu_pytorch_tanh(),
        "relu": lambda: nn.ReLU(),
        "relu2": lambda: ReLUSquaredActivation(),
        "silu": lambda: nn.SiLU(),
        "swish": lambda: nn.SiLU(),
        "quick_gelu": lambda: QuickGELU(),
        "tanh": lambda: nn.Tanh(),
        "sigmoid": lambda: nn.Sigmoid(),
        "xielu": lambda: XIELU(),
    }
)

```

### `vllm/model_executor/models/skyworkr1v.py`

删除与 InternVL 基类完全重复的 SkyworkR1VDummyInputsBuilder（+1/-31），注册改为直接使用 BaseInternVLDummyInputsBuilder，示例了多模态 dummy 输入构建的统一化。

```python
# vllm/model_executor/models/skyworkr1v.py
# 原先这里定义了一个局部类 SkyworkR1VDummyInputsBuilder，其
# get_dummy_text 返回 "<image>" * num_images，get_dummy_mm_data 则委托
# self._get_dummy_images(...) 构造占位图；这些实现与 InternVL 的
# BaseInternVLDummyInputsBuilder 完全一致，属于冗余复制。
# PR #50285 删除该类后，注册处理器时直接复用 InternVL 基类实现。

@MULTIMODAL_REGISTRY.register_processor(
    BaseInternVLMultiModalProcessor,
    info=SkyworkR1VProcessingInfo,
    dummy_inputs=BaseInternVLDummyInputsBuilder,
)
class SkyworkR1VChatModel(nn.Module, SupportsMultiModal, SupportsPP):
    """Skywork R1V 聊天模型，处理流程与 InternVL 复用同一套
    处理器与占位输入构造逻辑。"""

```

### `vllm/v1/core/kv_cache_utils.py`

删除 need_extra_keys 与 is_kv_cache_page_size_uniform 两个核心工具函数（34 行），涉及前缀缓存哈希与 KV 页面统一逻辑的收敛。

```python
# vllm/v1/core/kv_cache_utils.py
# PR #50285 删除了两个已无调用方的工具函数：
# - need_extra_keys(request)：判定块是否需要附加 MM / LoRA /
# cache_salt 哈希键，调用方已改为内联等价判断；
# - is_kv_cache_page_size_uniform(spec)：各层页面大小一致性判断，
# 统一逻辑已收敛到下面的 unify_kv_cache_spec_page_size。
# 下方保留函数是页面大小统一的核心入口。

def unify_kv_cache_spec_page_size(
    kv_cache_spec: dict[str, KVCacheSpec],
) -> dict[str, KVCacheSpec]:
    page_sizes = {layer.page_size_bytes for layer in kv_cache_spec.values()}
    if len(page_sizes) <= 1:
        # 所有层页面大小一致，无需统一，直接返回原 spec
        return kv_cache_spec

    max_page_size = max(page_sizes)
    new_kv_cache_spec = {}
    for layer_name, layer_spec in kv_cache_spec.items():
        if layer_spec.page_size_bytes == max_page_size:
            new_kv_cache_spec[layer_name] = layer_spec
        # 其余分支：优先扩大较小页面的 block size；
        # Mamba 状态页与 strided 视图后端则走物理页填充路径

```

# 评论区精华

> hmellor（`vllm/config/utils.py`）：`This one is useful to keep around for future deprecations`——拦截了对 `handle_deprecated` 的误删；作者回复 `OK get it back now` 并在 commit `fc5d7a8` 中恢复。

> hmellor（`llava_onevision2.py`）：`This method also exists in vllm/models/minimax_m3/common/mm_preprocess.py, should it be deleted from there too?`——作者回复 `Done`，同步删除了重复实现。

> hmellor：`I wonder if it's worth adding something to our agents files to protect deprecation utilities during dead code audits?`——提出用 agent 规则保护 deprecation 工具，本次未落地。

最后 hmellor 批准时补充 `maybe one other method that can be deleted`，未展开。关键结论：死代码清理应区分「死代码」与「承担兼容职责的工具」，后者需要保留。

- handle_deprecated 不应被当作死代码删除 (design): 作者接受意见，在 commit fc5d7a8 中恢复 handle_deprecated，删除名单剔除该符号。
- 重复的 _get_data_parser 是否同步清理 (question): 作者回复 `Done`，minimax_m3 的 _get_data_parser 也被移除。
- 用 agent 规则保护 deprecation 工具 (other): 开放建议，本次未落地。

# 风险与影响

- 风险：
 1. 公共符号删除风险：`ScaledActivation`、`CausalConv2dLayer` 位于 `vllm/model_executor/layers` 常用子包，虽非 vLLM 承诺的公开 API，但外部模型插件或定制脚本可能直接 import；删除后这类外部引用会立即 `ImportError`，仓库内已验证无调用，但无法覆盖外部依赖。
 2. 配置分支覆盖不足：`fp8.py` 的 `CopyNumelCounter` 服务于 FP8 checkpoint 权重加载路径，`kv_cache_utils.py` 的 `need_extra_keys` 服务于 MM / LoRA / cache_salt 前缀缓存哈希路径，若相关逻辑只在特定模型与运行时组合下触发，而本次无新增测试，回归只能依赖现有 CI 覆盖。
 3. 编译 pass 工具不可复得：`fx_utils.py` 删除的 `get_only_user`、`is_auto_func` 若未来 Inductor pass 需要重建，只能从 git 历史恢复，删除时没有留下替代实现。
 - 影响：对最终用户无功能影响（纯删除、无行为变化）；对依赖内部类的外部扩展存在兼容性影响。系统层面 import 图更精简，`activation.py` 不再依赖 `vllm.distributed`，`conv.py` 移除一层自定义 padding 封装，轻微改善模块导入开销。团队层面，22 个文件的瘦身降低后续阅读与搜索噪音，并积累了「死代码审计需保护 deprecation 工具」的评审经验。
 - 风险标记：公共符号删除 , 缺少测试配套 , 多模块跨面广

# 关联脉络

- PR #49389 [Misc] Remove deprecated calculate_kv_scales runtime KV scale calculation: 同为清理性质的移除废弃代码 PR，且同样触及量化（KV scale）与 KV 缓存模块，反映仓库持续的死亡代码治理趋势。