Prhub

#32402 Switch inkling per-commit test to nvfp4

原始 PR 作者 ispobock 合并时间 2026-08-09 16:49 文件变更 1 提交数 5 评论 9 代码增减 +103 / -0

执行摘要

新增 Inkling-Small-NVFP4 真实 checkpoint 的 CI 精度测试

原 test_inkling.py 启动一个缩小的 checkpoint,只能保证代码路径可运行,无法对答案质量把关;而真实的 NVFP4 checkpoint 才能捕获权重加载或 FP4 内核回归,这类回归会让服务器保持健康但输出错误。PR 标题明确为“Switch inkling per-commit test to nvfp4”,目标是建立针对真实模型和 FP4 数值链路的 per-commit 回归保护。

值得精读。该 PR 展示了如何为真实量化模型设计 CI 精度门控:使用真实 checkpoint 而非缩小版、基于抽样噪声设置合理阈值、选择与部署一致的硬件和后端参数。对于维护量化模型测试或 CI 门控的工程师有参考价值,但需注意其外部依赖和资源成本。

讨论亮点

该 PR 没有 review 评论。评论区主要记录了 CI 重跑过程:作者三次重跑 test/registered/models/test_inkling.py 在 1-gpu-h100 上均失败,随后运行新增的 test_inkling_small_nvfp4.py 在 4-gpu-b200 上通过。这反映出原测试在新环境或真实 checkpoint 下不稳定,新测试更贴合实际部署形态。

实现拆解

  1. 新增测试文件 test/registered/models_e2e/test_inkling_small_nvfp4.py,通过 register_cuda_ci(est_time=600, stage="extra-b", runner_config="4-gpu-b200") 注册到 CI 的 extra-b 阶段,使用 4 卡 B200 运行。
  2. 实现 TestInklingSmallNvfp4 测试类:setUpClass 使用 popen_launch_server 启动真实模型 thinkingmachines/Inkling-Small-NVFP4,配置 --quantization modelopt_fp4、--attention-backend fa4、--fp4-gemm-backend flashinfer_trtllm、--moe-runner-backend flashinfer_trtllm_routed 等关键参数,并设置 Mamba 缓存与显存策略;tearDownClass 通过 kill_process_tree 清理进程。
  3. 核心测试 test_gsm8k 调用 sglang.test.few_shot_gsm8k.run_eval 执行 10-shot、200 题、并行度 128 的 GSM8K 评估,断言准确率不低于 GSM8K_THRESHOLD(0.85)。
  4. 提交历史中有两个临时 debug 提交(打印 w13 load shapes 和 fp4 strategy),最终未保留;并合并 origin/main 解决了 fused_moe_triton/layer.py 的冲突。
  5. CI 验证:原 test_inkling.py 在 1-gpu-h100 上多次失败,新测试在 4-gpu-b200 上通过,确认了切换的合理性。
文件 模块 状态 重要度
test/registered/models_e2e/test_inkling_small_nvfp4.py 回归测试 added 7.38

关键符号

test_gsm8k setUpClass tearDownClass

关键源码片段

test/registered/models_e2e/test_inkling_small_nvfp4.py test-coverage

本 PR 的唯一变更文件,新增了基于真实 NVFP4 checkpoint 的 end-to-end 精度测试,是 FP4 数值回归保护的核心载体。

# test/registered/models_e2e/test_inkling_small_nvfp4.py
"""Per-commit accuracy + logprob-consistency test for Inkling-Small-NVFP4.``test_inkling.py`` boots a shrunken checkpoint, so it can only guard that the
code paths run -- an undertrained model has no answer quality to gate on. This
one serves the real NVFP4 checkpoint, which is what catches a weight-load or
FP4-kernel regression that keeps the server healthy while the outputs go wrong.
"""import os
import unittest
from types import SimpleNamespace
from urllib.parse import urlparsefrom sglang.srt.utils import kill_process_tree
from sglang.test.ci.ci_register import register_cuda_ci
from sglang.test.test_utils import (
    DEFAULT_TIMEOUT_FOR_SERVER_LAUNCH,
    DEFAULT_URL_FOR_TEST,
    CustomTestCase,
    popen_launch_server,
)# 注册到 CI 测试,预计耗时 600 秒,放入 extra-b 阶段,运行在 4 卡 B200 上
register_cuda_ci(est_time=600, stage="extra-b", runner_config="4-gpu-b200")# 默认加载真实 FP4 量化 checkpoint,允许用环境变量覆盖
_MODEL_PATH = os.environ.get(
    "INKLING_SMALL_TEST_MODEL_PATH", "thinkingmachines/Inkling-Small-NVFP4"
)# 实测 10-shot GSM8K 准确率为 0.900,阈值 0.85 约在 2.5 倍抽样标准差以下
# 这样既能捕获真实精度崩塌,又不会被 200 题抽样波动误触发
GSM8K_THRESHOLD = 0.85
​
​
class TestInklingSmallNvfp4(CustomTestCase):
    @classmethod
    def setUpClass(cls):
        cls.model = _MODEL_PATH
        cls.base_url = DEFAULT_URL_FOR_TEST
        # 启动真实服务器的关键参数:modelopt_fp4 量化、FA4 注意力、
        # TRTLLM FP4 GEMM/MoE 后端,确保走的是生产推理路径
        cls.process = popen_launch_server(
            cls.model,
            cls.base_url,
            timeout=DEFAULT_TIMEOUT_FOR_SERVER_LAUNCH,
            other_args=[
                "--tp", "4",
                "--trust-remote-code",
                "--quantization", "modelopt_fp4",
                "--attention-backend", "fa4",
                "--page-size", "128",
                "--fp4-gemm-backend", "flashinfer_trtllm",
                "--moe-runner-backend", "flashinfer_trtllm_routed",
                "--mamba-radix-cache-strategy", "extra_buffer",
                "--swa-full-tokens-ratio", "0.1",
                "--mamba-full-memory-ratio", "0.1",
                "--mem-fraction-static", "0.85",
            ],
            env={**os.environ, "SGLANG_ENABLE_UNIFIED_RADIX_TREE": "1"},
        )
​
    @classmethod
    def tearDownClass(cls):
        # 确保测试结束时清理服务器进程,避免资源泄漏
        if getattr(cls, "process", None) is not None:
            kill_process_tree(cls.process.pid)
​
    def test_gsm8k(self):
        """Answer quality on the real checkpoint: guards the modelopt_fp4 weight
        load and the FP4 GEMM/MoE kernels against changes that keep the server
        healthy but corrupt the numerics."""
        from sglang.test.few_shot_gsm8k import run_eval as run_few_shot_gsm8k
​
        url = urlparse(self.base_url)
        metrics = run_few_shot_gsm8k(
            SimpleNamespace(
                num_shots=10,
                data_path=None,
                num_questions=200,
                max_new_tokens=16000,
                parallel=128,
                host=f"http://{url.hostname}",
                port=int(url.port),
            )
        )
        print(f"[{self.__class__.__name__}] gsm8k: {metrics['accuracy']:.3f}")
        self.assertGreaterEqual(metrics["accuracy"], GSM8K_THRESHOLD)
​
​
if __name__ == "__main__":
    unittest.main()

评论区精华

原 Inkling 测试在 H100 上反复失败 测试

作者三次执行 /rerun-test test/registered/models/test_inkling.py,在 1-gpu-h100 上均失败;随后执行新的 test_inkling_small_nvfp4.py,在 4-gpu-b200 上成功。

结论:新测试采用真实 NVFP4 checkpoint 和 B200 4 卡环境,验证通过,替代原缩水模型测试。 · 已解决

风险与影响

  1. 测试依赖外部 HuggingFace checkpoint(thinkingmachines/Inkling-Small-NVFP4),若网络或仓库不可达会导致 CI 失败。
  2. 新增 CI 阶段占用 4 卡 B200 约 10 分钟(est_time 600 秒),增加 GPU 资源消耗和排队时间。
  3. GSM8K_THRESHOLD 0.85 基于当前模型实测 0.900,若模型版本更新导致分数自然下降可能误报。
  4. 测试仅覆盖 few-shot completion 模式,不经过 thinking 路径,无法捕获推理链相关数值问题。
  5. 服务器启动参数全部硬编码,若默认配置或相关默认值变化,可能导致测试启动失败或不再代表真实路径。

用户:无任何运行时行为影响。
系统:CI 流水线新增一个 4 卡 B200 的端到端测试阶段,预计耗时约 10 分钟,增加 GPU 资源占用和排队延迟。
团队:为 Inkling-Small-NVFP4 提供 per-commit 精度回归保护,可在 FP4 权重加载或内核改动引入静默错误时快速告警,降低线上事故风险。

外部 checkpoint 依赖 新增 CI GPU 资源消耗 阈值可能随模型更新漂移 仅覆盖 completion 不覆盖 thinking 路径

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论