Prhub

#33087 [Fix] Repair verify mask test fixture

原始 PR 作者 JustinTong0323 合并时间 2026-08-01 05:48 文件变更 2 提交数 1 评论 5 代码增减 +3 / -6

执行摘要

修复 verify-mask 测试夹具,补齐缺失的 context_len

PR body 明确指出这是修复当前 main 的确定性 Base CPU CI 失败。根因是 #32690 引入的 HybridAttnBackend 无条件下读 model_runner.model_config.context_len,但 #32920 引入的 test_verify_mask.py 轻量夹具没有提供 model_config,导致 registered Base CPU 测试在后端构造阶段就抛 AttributeError,未走到任何断言。

值得快速浏览,不建议精读。这是一个典型的“跨 PR 契约漂移”案例:一个 PR 引入新构造依赖,另一个 PR 的 fixture 未同步,导致确定性 CI 失败。值得关注的实践是 PR body 中的回归时间线定位方法(通过 CI 运行时间与合并时间交叉比对锁定触发 PR),以及用 /rerun-test 单独验证目标测试的流程。

讨论亮点

该 PR 没有 review comments,评论主要是 bot 与 CI 操作记录。核心讨论价值在 PR body 的回归时间线分析:作者精确锁定了 #32920(引入夹具)与 #32690(引入 model_config.context_len 读取但漏改该夹具)两处合并之间的窗口,并指出 #33074 只是受影响方而非触发方。另外通过 /rerun-test 命令单独重跑目标测试文件,确认修复有效。

实现拆解

该 PR 的修复分两层:

  1. 测试夹具补契约:在 test/registered/unit/layers/attention/test_verify_mask.py_make_hybrid_backend 中,向 model_runnerSimpleNamespace 增加 model_config=SimpleNamespace(context_len=_MAX_CONTEXT_LEN),对齐 HybridAttnBackend.__init__ 新增的无条件读取 model_runner.model_config.context_len 的构造契约。这是让测试能走到断言的关键修复。

  2. 源码注释同步:在 python/sglang/srt/layers/attention/verify_mask.pyVerifyMask.fits() 文档字符串中,删除关于“composite backends do not carry max_context_len”的过时描述,改为更准确的“FULL_MASK keeps unconditional reuse because its runtime bound depends on sequence lengths not passed to fits()”。原因是 #32690 之后 composite backend 实际已经携带 context_len,旧注释已失真。

  3. 测试描述清理:移除 test_capacity_check_needs_nothing_from_the_backend 中“fits() reaching back through the backend would raise AttributeError here”的过时 docstring,因为夹具现在提供 model_config 后该描述不再成立。

验证方式:py_compile、pre-commit、git diff --check、局部冒烟测试;完整测试文件因本机解释器无 torch 未运行,交由 registered CI 执行,并通过 /rerun-test 确认了 ubuntu-latesttest_verify_mask.py 通过。

文件 模块 状态 重要度
test/registered/unit/layers/attention/test_verify_mask.py 测试夹具 modified 4.48
python/sglang/srt/layers/attention/verify_mask.py 注意力层 modified 4.62

关键符号

_make_hybrid_backend VerifyMask.fits

关键源码片段

test/registered/unit/layers/attention/test_verify_mask.py test-coverage

修复的核心所在:为 _make_hybrid_backend 夹具补齐 model_config.context_len,对齐 HybridAttnBackend 构造契约,使 registered CPU 测试不再在构造阶段抛 AttributeError。

def _make_hybrid_backend(speculative_attention_mode, prefill_mask, decode_mask):
    # 轻量夹具需要对齐 HybridAttnBackend.__init__ 的构造契约:
    # #32690 之后构造函数会无条件读取 model_runner.model_config.context_len,
    # 缺少该字段会在后端构造阶段直接抛 AttributeError,测试根本走不到断言。
    model_runner = SimpleNamespace(
        kv_cache_dtype=None,
        token_to_kv_pool=object(),
        req_to_token_pool=object(),
        server_args=SimpleNamespace(
            speculative_attention_mode=speculative_attention_mode
        ),
        model_config=SimpleNamespace(context_len=_MAX_CONTEXT_LEN), # 修复点
    )
    return HybridAttnBackend(
        model_runner,
        prefill_backend=_FakeAttnBackend(prefill_mask),
        decode_backend=_FakeAttnBackend(decode_mask),
    )

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

风险极低:

  • 源码侧仅修改 docstring(verify_mask.py 的 fits() 注释),无任何逻辑行为变化,不引入回归面。
  • 测试侧只给 fixture 增加 model_config 属性、删除两条过时 docstring,不影响断言逻辑。
  • 唯一潜在问题是若未来 HybridAttnBackend 构造契约再次变化(例如 context_len 变为可选),该 fixture 的硬编码 _MAX_CONTEXT_LEN 可能再次产生偏差,但这是夹具类测试的常态维护成本。

影响面限定在 CI 与测试链路:修复 registered Base CPU 测试 test_verify_mask.py 的确定性失败,恢复对 verify-mask 混合后端子掩码分发逻辑的回归保护;同时消除该失败对无关 PR 检查的级联干扰(如 #33074 因 merge main 后无辜失败)。对生产运行时无影响,因为源码改动仅为注释。

测试夹具契约漂移 仅影响 CI 测试链路

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论