Prhub

#7433 [model] fix: add Qwen3.5 VL to _TEXT_TO_VL_FAMILY for unified checkpoint support

原始 PR 作者 qy0720 合并时间 2026-08-19 09:59 文件变更 2 提交数 4 评论 2 代码增减 +32 / -0

执行摘要

修复 Qwen3.5 VL 统一检查点构建 Continuous Token 崩溃

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。

值得快速阅读,作为向 _TEXT_TO_VL_FAMILY 扩展新模型家族的参照;测试使用轻量 MockTokenizer / MockProcessor 验证升级路径,思路可复用。但该 PR 改动极小且无深入设计讨论,不建议作为精读案例。

讨论亮点

全程没有对抗性技术讨论。gxlvera 评论确认:'This PR fixed the bug mentioned here: . I have reviewed.' 这为本 PR 提供了与历史 PR 的直接关联证据;wuxibin89 最终 APPROVED。唯一留意的点是 PR body 与源码摘录在测试参数化上的不一致,未在评论中提及。

实现拆解

  1. 修改 wiring 映射:在 verl/utils/tokenizer/continuous_token_wiring.py 的 _TEXT_TO_VL_FAMILY 字典中新增 ContinuousTokenModelFamily.QWEN35 -> ContinuousTokenModelFamily.QWEN3_VL。这是完整升级链路的唯一源码改动,与既有 DEFAULT -> VL_DEFAULT、GEMMA4 -> GEMMA4_VL 模式一致。
  2. 新增单元测试:在 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 用例,两者存在不一致,合并前应确认。
  3. 配套与验证:无 API、配置、schema 或部署配套改动;提交历史显示测试用例经历了两次修订后定稿,最终由 wuxibin89 批准合并,CLA 已通过。
文件 模块 状态 重要度
verl/utils/tokenizer/continuous_token_wiring.py 构建器路由 modified 4.75
tests/utils/test_continuous_token_on_cpu.py 单元测试 modified 6.07

关键符号

test_qwen35_unified_with_processor_upgrades_to_vl create_continuous_token_builder

关键源码片段

verl/utils/tokenizer/continuous_token_wiring.py core-logic

核心入口,通过一行映射修复 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 test-coverage

新增 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

评论区精华

PR#6804 提到的 Qwen3.5 VL bug 修复确认 other

gxlvera 评论:This PR fixed the bug mentioned here: <PR#6804 评论链接 >. I have reviewed.

结论:确认修复目标并已审阅,无新增疑虑 · 已解决

风险与影响

风险较低,核心变更仅一行映射且沿袭既有模式。但 continuous token wiring 位于 agent loop 等训练入口的关键路径,任何映射变化都会影响模型家族解析;若 QWEN35 纯文本模型误传 processor,现在会被升级为 VL 构建器,可能掩盖配置错误。测试方面,摘录仅覆盖 qwen3_5_moe 场景,qwen3_5 文本变体未被直接验证,若参数化描述不实则存在覆盖缺口。

受益方为使用 Qwen3.5 VL 统一检查点的多模态 RL 训练用户,builder 创建阶段的崩溃被消除;纯文本 Qwen3.5 用户在不传 processor 时行为不变。改动仅影响连续 token 构建器的家族解析,对其他模块无直接影响,团队可按既有模式接入后续新模型。

核心路径变更 测试覆盖存疑

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论