执行摘要
- 一句话:为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引擎在新模型上的功能性和训练流程的完整性。
实现拆解
- 扩展模型索引映射:在
verl/workers/engine/veomni/utils.py 的 VL_TYPE2INDEX 字典中新增 "qwen3_5" 和 "qwen3_5_moe" 条目,定义其视觉标记的索引值(IMAGE_INPUT_INDEX 和 VIDEO_INPUT_INDEX),使VeOmni引擎能正确识别和处理Qwen3.5模型的视觉输入。
- 完善序列并行数据整理器:在
verl/workers/engine/veomni/transformer_impl.py 中,修改 OmniSequenceShardCollator 类的 padding_features 和 padding_scale 字段,将 "pixel_values_videos" 纳入填充处理,确保视频数据在序列并行下能正确对齐。
- 移除过时注释:在同一文件中,删除
VeOmniEngineWithLMHead.prepare_model_inputs 方法中关于Qwen VL Ulysses的TODO注释,表明该问题已解决。
- 新增训练示例脚本:添加
examples/grpo_trainer/run_qwen3_5-35b-a3b_veomni.sh 脚本,提供从环境配置、模型加载到训练参数设置的完整GRPO训练流程,使用VeOmniEngine并支持序列并行。
- 更新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引擎识别新模型的关键。
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
核心引擎实现文件,修改了序列并行数据整理器以支持视频数据填充,并移除了过时注释。
@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中未直接修复;可能被视为后续任务。
风险与影响
- 风险:
- MoE权重分片风险:如review评论所述,
qwen3_5_moe 缺少 MOE_PARAM_HANDERS 映射,可能导致专家权重同步错误,影响训练稳定性。
- 序列并行兼容性风险:新增的
"pixel_values_videos" 填充逻辑未经充分测试,在复杂视频输入场景下可能引发数据对齐问题。
- 依赖版本风险:CI工作流中VeOmni版本升级到
0.1.9a1(alpha版本),可能存在未预见的API变更或稳定性问题。
- 示例脚本环境依赖风险:新增的示例脚本依赖特定版本的
transformers、sglang 等库,环境配置复杂,可能增加用户使用门槛。
- 影响:
- 对用户的影响:为使用Qwen3.5系列模型的用户提供了VeOmni引擎支持,并提供了可复现的GRPO训练示例,降低了实验门槛。
- 对系统的影响:扩展了VeOmni引擎的模型覆盖范围,增强了序列并行下多模态数据的处理能力,但未修改核心训练逻辑,影响范围有限。
- 对团队的影响:促进了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训练器相关功能,属于同一算法领域的扩展。
参与讨论