# PR #6061 完整报告

- 仓库：`verl-project/verl`
- 标题：[veomni] feat: support Qwen3.5 SP and add GRPO trainer demo using VeOmniEngine
- 合并时间：2026-04-20 11:32
- 原文链接：http://prhub.com.cn/verl-project/verl/pull/6061

---

# 执行摘要

- 一句话：为 VeOmni 引擎新增 Qwen3.5 系列模型支持，并提供基于 VeOmniEngine 和 Sglang 的 GRPO 训练示例。
- 推荐动作：该 PR 值得精读，特别是 `OmniSequenceShardCollator` 类的修改展示了序列并行下多模态数据处理的通用设计模式。但需注意 review 中提到的 `MOE_PARAM_HANDERS` 缺失问题，建议在合并后优先修复以避免潜在训练故障。

# 功能与动机

根据 PR 描述，主要目标是支持 Qwen 3.5 系列模型（特别是 Qwen3.5-35B-A3B MoE 模型）的序列并行（Ulysses）训练，并提供一个使用 VeOmniEngine 和 Sglang 进行 GRPO 训练的示例。这有助于验证 VeOmni 引擎在新模型上的功能性和训练流程的完整性。

# 实现拆解

1. **扩展模型索引映射**：在 `verl/workers/engine/veomni/utils.py` 的 `VL_TYPE2INDEX` 字典中新增 `"qwen3_5"` 和 `"qwen3_5_moe"` 条目，定义其视觉标记的索引值（`IMAGE_INPUT_INDEX` 和 `VIDEO_INPUT_INDEX`），使 VeOmni 引擎能正确识别和处理 Qwen3.5 模型的视觉输入。
2. **完善序列并行数据整理器**：在 `verl/workers/engine/veomni/transformer_impl.py` 中，修改 `OmniSequenceShardCollator` 类的 `padding_features` 和 `padding_scale` 字段，将 `"pixel_values_videos"` 纳入填充处理，确保视频数据在序列并行下能正确对齐。
3. **移除过时注释**：在同一文件中，删除 `VeOmniEngineWithLMHead.prepare_model_inputs` 方法中关于 Qwen VL Ulysses 的 TODO 注释，表明该问题已解决。
4. **新增训练示例脚本**：添加 `examples/grpo_trainer/run_qwen3_5-35b-a3b_veomni.sh` 脚本，提供从环境配置、模型加载到训练参数设置的完整 GRPO 训练流程，使用 VeOmniEngine 并支持序列并行。
5. **更新 CI 依赖版本**：在多个 `.github/workflows` YAML 文件中，将 VeOmni 依赖从 Git 引用升级到固定版本 `veomni==0.1.9a1`，确保 CI 环境的一致性。

关键文件：
- `verl/workers/engine/veomni/utils.py`（模块 VeOmni 引擎；类别 source；类型 configuration；符号 VL_TYPE2INDEX）: 核心配置文件，新增 Qwen3.5 系列模型的视觉标记索引映射，是 VeOmni 引擎识别新模型的关键。
- `verl/workers/engine/veomni/transformer_impl.py`（模块 VeOmni 引擎；类别 source；类型 core-logic；符号 OmniSequenceShardCollator, VeOmniEngineWithLMHead.prepare_model_inputs）: 核心引擎实现文件，修改了序列并行数据整理器以支持视频数据填充，并移除了过时注释。
- `examples/grpo_trainer/run_qwen3_5-35b-a3b_veomni.sh`（模块 示例脚本；类别 other；类型 entrypoint）: 新增的示例脚本，提供了完整的 GRPO 训练流程，是用户使用新功能的入口。
- `.github/workflows/e2e_ppo_trainer_veomni_vllm.yml`（模块 CI 配置；类别 infra；类型 infrastructure）: CI 配置文件，更新了 VeOmni 依赖版本，确保测试环境一致性。

关键符号：VL_TYPE2INDEX, OmniSequenceShardCollator.__post_init__, VeOmniEngineWithLMHead.prepare_model_inputs

## 关键源码片段

### `verl/workers/engine/veomni/utils.py`

核心配置文件，新增 Qwen3.5 系列模型的视觉标记索引映射，是 VeOmni 引擎识别新模型的关键。

```python
VL_TYPE2INDEX = {
    "qwen2_5_vl": {
        "IMAGE_INPUT_INDEX": 151655,
        "VIDEO_INPUT_INDEX": 151656,
    },
    "qwen3_vl": {
        "IMAGE_INPUT_INDEX": 151655,
        "VIDEO_INPUT_INDEX": 151656,
    },
    "qwen3_vl_moe": {
        "IMAGE_INPUT_INDEX": 151655,
        "VIDEO_INPUT_INDEX": 151656,
    },
    "qwen3_5": {  # 新增 Qwen3.5 标准模型的视觉标记索引
        "IMAGE_INPUT_INDEX": 248056,
        "VIDEO_INPUT_INDEX": 248057,
    },
    "qwen3_5_moe": {  # 新增 Qwen3.5 MoE 变体的视觉标记索引，但缺少对应的 MOE_PARAM_HANDERS 映射
        "IMAGE_INPUT_INDEX": 248056,
        "VIDEO_INPUT_INDEX": 248057,
    },
}

```

### `verl/workers/engine/veomni/transformer_impl.py`

核心引擎实现文件，修改了序列并行数据整理器以支持视频数据填充，并移除了过时注释。

```python
@dataclass
class OmniSequenceShardCollator:
    """
    数据整理器，用于沿序列维度分块输入数据，支持序列并行。
    """
    # 需要填充序列维度的特征
    padding_features: dict[str, int] = field(
        default_factory=lambda: {
            "pixel_values": 0,        # 图像数据
            "pixel_values_videos": 0, # 新增：视频数据，确保在序列并行下能正确对齐
        },
        metadata={"help": "features to padding sequence dimension."},
    )
    # 填充特征的缩放因子
    padding_scale: dict[str, int] = field(
        default_factory=lambda: {
            "pixel_values": 4,
            "pixel_values_videos": 4,  # 新增：视频数据使用相同的缩放因子
        },
        metadata={"help": "padding scale for padding features."},
    )

```

# 评论区精华

reviewer `gemini-code-assist[bot]` 指出一个关键问题：在 `verl/workers/engine/veomni/utils.py` 中，虽然为 `qwen3_5_moe` 添加了 `VL_TYPE2INDEX` 映射，但未将其添加到 `MOE_PARAM_HANDERS` 字典中，这可能导致 MoE 专家权重分片失败，影响与 Sglang 等 rollout 引擎的权重同步。该问题被标记为高风险，但 PR 作者未在本次提交中直接回应或修复；reviewer `wuxibin89` 批准了 PR，可能意味着该问题被视为后续待处理事项。

- MoE 参数处理器缺失 (correctness): 问题被标记为高风险，但 PR 中未直接修复；可能被视为后续任务。

# 风险与影响

- 风险：
 1. **MoE 权重分片风险**：如 review 评论所述，`qwen3_5_moe` 缺少 `MOE_PARAM_HANDERS` 映射，可能导致专家权重同步错误，影响训练稳定性。
 2. **序列并行兼容性风险**：新增的 `"pixel_values_videos"` 填充逻辑未经充分测试，在复杂视频输入场景下可能引发数据对齐问题。
 3. **依赖版本风险**：CI 工作流中 VeOmni 版本升级到 `0.1.9a1`（alpha 版本），可能存在未预见的 API 变更或稳定性问题。
 4. **示例脚本环境依赖风险**：新增的示例脚本依赖特定版本的 `transformers`、`sglang` 等库，环境配置复杂，可能增加用户使用门槛。
- 影响：
 1. **对用户的影响**：为使用 Qwen3.5 系列模型的用户提供了 VeOmni 引擎支持，并提供了可复现的 GRPO 训练示例，降低了实验门槛。
 2. **对系统的影响**：扩展了 VeOmni 引擎的模型覆盖范围，增强了序列并行下多模态数据的处理能力，但未修改核心训练逻辑，影响范围有限。
 3. **对团队的影响**：促进了 VeOmni 引擎的生态完善，为后续模型集成提供了参考模板；但遗留的 MoE 参数处理问题需要团队后续关注。
 - 风险标记：MoE 参数映射缺失 , 序列并行数据填充 , 依赖版本升级

# 关联脉络

- PR #6034 [veomni] fix: use local paths for VeOmni model loading: 同样涉及 VeOmni 引擎的修复，关注模型加载路径问题。
- PR #5996 [veomni] feat: add DeepSeek-V3 to MOE_PARAM_HANDERS: 类似地，为另一个 MoE 模型添加了 MOE_PARAM_HANDERS 映射，可作为修复本 PR 缺失问题的参考。
- PR #5951 [5/n][trainer] feat: flowgrpo trainer: 同样新增了 GRPO 训练器相关功能，属于同一算法领域的扩展。