执行摘要
- 一句话:修复 Qwen3.5 VL 统一检查点构建 Continuous Token 崩溃
- 推荐动作:值得快速阅读,作为向 _TEXT_TO_VL_FAMILY 扩展新模型家族的参照;测试使用轻量 MockTokenizer / MockProcessor 验证升级路径,思路可复用。但该 PR 改动极小且无深入设计讨论,不建议作为精读案例。
功能与动机
PR body 明确指出:Qwen3.5 VL 的 HF model_type 为 qwen3_5 / qwen3_5_moe(与文本模型相同),wiring 会将其解析到文本家族 QWEN35;由于 QWEN35 未出现在 _TEXT_TO_VL_FAMILY 中,传入多模态 processor 会抛出 ValueError: Model resolved to the text Continuous Token family 'qwen35', but a multimodal processor was provided,使 Qwen3.5 VL 无法用于多模态 RL 训练。gxlvera 的评论进一步确认该问题源于 PR#6804 评论中报告的 bug。
实现拆解
- 修改 wiring 映射:在 verl/utils/tokenizer/continuous_token_wiring.py 的 _TEXT_TO_VL_FAMILY 字典中新增 ContinuousTokenModelFamily.QWEN35 -> ContinuousTokenModelFamily.QWEN3_VL。这是完整升级链路的唯一源码改动,与既有 DEFAULT -> VL_DEFAULT、GEMMA4 -> GEMMA4_VL 模式一致。
- 新增单元测试:在 tests/utils/test_continuous_token_on_cpu.py 的 TestWiringVLFactory 类中新增 test_qwen35_unified_with_processor_upgrades_to_vl 方法,使用带 encode / convert_tokens_to_ids 的 MockTokenizer 与带 image_processor 的 MockProcessor 调用 create_continuous_token_builder,断言返回 QwenVLContinuousTokenBuilder 且 supports_multimodal() 为 True。注意:PR body 声称该测试参数化覆盖 qwen3_5 与 qwen3_5_moe,但当前摘录仅见 qwen3_5_moe 用例,两者存在不一致,合并前应确认。
- 配套与验证:无 API、配置、schema 或部署配套改动;提交历史显示测试用例经历了两次修订后定稿,最终由 wuxibin89 批准合并,CLA 已通过。
关键文件:
verl/utils/tokenizer/continuous_token_wiring.py(模块 构建器路由;类别 source;类型 core-logic;符号 _TEXT_TO_VL_FAMILY, ContinuousTokenModelFamily): 核心入口,通过一行映射修复 QWEN35 文本族到 QWEN3_VL 的升级路径,是多模态 Continuous Token 构建的关键接线点。
tests/utils/test_continuous_token_on_cpu.py(模块 单元测试;类别 test;类型 test-coverage;符号 test_qwen35_unified_with_processor_upgrades_to_vl, MockTokenizer, encode, convert_tokens_to_ids): 新增 CPU 单元测试覆盖 Qwen3.5 统一检查点升级 VL 的路径,防止后续回归,并验证错误提示不再触发。
关键符号:test_qwen35_unified_with_processor_upgrades_to_vl, create_continuous_token_builder
关键源码片段
verl/utils/tokenizer/continuous_token_wiring.py
核心入口,通过一行映射修复 QWEN35 文本族到 QWEN3_VL 的升级路径,是多模态 Continuous Token 构建的关键接线点。
# 统一检查点的文本族 -> 视觉语言族升级映射。
_TEXT_TO_VL_FAMILY: dict[ContinuousTokenModelFamily, ContinuousTokenModelFamily] = {
ContinuousTokenModelFamily.DEFAULT: ContinuousTokenModelFamily.VL_DEFAULT,
ContinuousTokenModelFamily.GEMMA4: ContinuousTokenModelFamily.GEMMA4_VL,
# Qwen3.5 的文本与 VL 版本共用 qwen3_5 / qwen3_5_moe 根类型,
# 因此这里新增 QWEN35 -> QWEN3_VL 升级项,与前面两条规则保持一致。
ContinuousTokenModelFamily.QWEN35: ContinuousTokenModelFamily.QWEN3_VL,
}
tests/utils/test_continuous_token_on_cpu.py
新增 CPU 单元测试覆盖 Qwen3.5 统一检查点升级 VL 的路径,防止后续回归,并验证错误提示不再触发。
def test_qwen35_unified_with_processor_upgrades_to_vl(self):
'''Qwen3.5 统一检查点 + 多模态 processor -> Qwen VL builder。'''
from verl.utils.tokenizer.continuous_token import QwenVLContinuousTokenBuilder
from verl.utils.tokenizer.continuous_token_wiring import create_continuous_token_builder
class MockTokenizer:
name_or_path = 'Qwen/Qwen3.5-35B-A3B'
def encode(self, text, add_special_tokens=False):
# 仅模拟换行符的编码结果,其余文本返回固定 token 序列
return [198] if text == '\n' else [1, 2, 3]
def convert_tokens_to_ids(self, token):
# 覆盖 VL 专用标记的 token id,供 builder 生成视觉填充符
mapping = {
'<|im_end|>': 151645,
'<|vision_start|>': 151652,
'<|vision_end|>': 151653,
'<|image_pad|>': 151655,
}
return mapping.get(token, 0)
class MockProcessor:
# 模拟多模态 processor,触发文本族向 VL 族的升级逻辑
image_processor = type('IP', (), {'merge_size': 2})()
builder = create_continuous_token_builder(
MockTokenizer(),
hf_model_type='qwen3_5_moe',
processor=MockProcessor(),
)
assert isinstance(builder, QwenVLContinuousTokenBuilder)
assert builder.supports_multimodal() is True
评论区精华
全程没有对抗性技术讨论。gxlvera 评论确认:'This PR fixed the bug mentioned here: . I have reviewed.' 这为本 PR 提供了与历史 PR 的直接关联证据;wuxibin89 最终 APPROVED。唯一留意的点是 PR body 与源码摘录在测试参数化上的不一致,未在评论中提及。
- PR#6804 提到的 Qwen3.5 VL bug 修复确认 (other): 确认修复目标并已审阅,无新增疑虑
风险与影响
- 风险:风险较低,核心变更仅一行映射且沿袭既有模式。但 continuous token wiring 位于 agent loop 等训练入口的关键路径,任何映射变化都会影响模型家族解析;若 QWEN35 纯文本模型误传 processor,现在会被升级为 VL 构建器,可能掩盖配置错误。测试方面,摘录仅覆盖 qwen3_5_moe 场景,qwen3_5 文本变体未被直接验证,若参数化描述不实则存在覆盖缺口。
- 影响:受益方为使用 Qwen3.5 VL 统一检查点的多模态 RL 训练用户,builder 创建阶段的崩溃被消除;纯文本 Qwen3.5 用户在不传 processor 时行为不变。改动仅影响连续 token 构建器的家族解析,对其他模块无直接影响,团队可按既有模式接入后续新模型。
- 风险标记:核心路径变更, 测试覆盖存疑
关联脉络
- PR #6804 [BREAKING][rollout] feat: Add Multimodal Continuous Token: 本 PR 直接引用 PR#6804 评论中报告的 bug,且两者都围绕 continuous token 构建器家族解析,本 PR 是其后续修复。
参与讨论