Prhub

#36044 [Diffusion] Load Comfy NVFP4 MiniMax H3 checkpoints

原始 PR 作者 mickqian 合并时间 2026-08-24 22:57 文件变更 9 提交数 17 评论 2 代码增减 +123 / -6

执行摘要

支持原生加载 Comfy NVFP4 量化 MiniMax H3 检查点

PR body 明确这是 Comfy 生态检查点的原生加载诉求:需要从 tensor 或全局逐层元数据直接推断 Comfy NVFP4 H3 检查点布局,复用现有 ModelOpt NVFP4 后端(包括 packed group size、scale 布局与 nibble 顺序),同时保留 H3 原生 QKV 检查点布局并拒绝不支持的 FSDP 加载。关键约束在于:序列化检查点省略 --quantization 参数,显式组件量化仅留给在线量化场景,因此加载端必须能自动识别布局并保障文档中描述的 --transformer-weights-path 自动检测流程。

值得快速阅读,核心看点是"从 safetensors 元数据自描述推断量化布局"与"配置合并时对 Comfy 专属开关做 OR 合并"两个模式,对后续扩展其他模型/后端的 Comfy 序列化检查点支持有直接借鉴价值;对不涉及量化加载的读者可以只看实现拆解与风险部分。

讨论亮点

该 PR 没有任何 code review 评论线程;Issue 评论只有 /tag-and-rerun-ci 触发指令与 Mintlify 文档预览 bot 通知。设计取舍更多体现在提交历史中:Preserve standard ModelOpt NVFP4 layout 说明作者特意保护标准 ModelOpt NVFP4(linear scale 布局)不被 Comfy 推断逻辑污染;一系列 merge ... CI fix 提交表明验证主要依靠 NVIDIA CI 反复运行,而非人工 review 讨论。

实现拆解

  1. 加载入口调整python/sglang/multimodal_gen/runtime/loader/component_loaders/transformer_loader.py::load_customized 在解析 MiniMax H3 检查点时,把 safetensors_listdit_config.arch_config.param_names_mappingreverse_param_names_mapping 下传给 resolve_minimax_h3_checkpoint_quantization,使量化格式推断能接触原始文件与参数名映射。

  2. NVFP4 布局自发现python/sglang/multimodal_gen/runtime/loader/minimax_h3_weights.py 中该函数先聚合各层 marker 的 format;当全部层都为 nvfp4 时调用 build_nvfp4_config_from_safetensors_list 推断 group size、exclude_modules、scale 布局与 nibble 顺序,随后强制 checkpoint_uses_comfy_quantization=Truecheckpoint_uses_native_qkv_layout=Truecheckpoint_weight_scale_layout="swizzled"swap_weight_nibbles=True;safetensors_list 缺失时抛 ValueError。

  3. 数据契约扩展python/sglang/multimodal_gen/runtime/layers/quantization/modelopt_quant.py::ModelOptFp4Config 新增 checkpoint_uses_comfy_quantization 字段并在 from_config 中支持从 config.json 读取;base_config.py 的基础 QuantizationConfig 补充布局开关默认字段(1 行),保证后续合并逻辑可以安全读取 checkpoint_uses_native_qkv_layout 等属性。

  4. 配置合并与分派python/sglang/multimodal_gen/runtime/loader/transformer_load_utils.py::_merge_modelopt_fp4_configs 对两个 Comfy 专属开关做 OR 合并(推断来源与 config.json 声明来源互不覆盖);TransformerQuantLoadSpec.uses_comfy_layer_markers 属性把 checkpoint_uses_comfy_quantization 纳入判定,使 NVFP4 Comfy 检查点正确进入 Comfy 层 marker 处理路径。

  5. 测试与文档python/sglang/multimodal_gen/test/unit/test_transformer_quant.py 新增 test_minimax_h3_comfy_nvfp4_resolves_modelopt_backend(构造带 _quantization_metadata 的 NVFP4 分片 + fallback 分片,断言后端为 ModelOptFp4Config、group_size=16、exclude_modules、native QKV 与 swizzled 布局),并给既有两个 NVFP4 推断测试补充元数据与断言;MiniMax-H3.mdxquantization.mdx 同步补充自动检测流程说明。

文件 模块 状态 重要度
python/sglang/multimodal_gen/runtime/loader/minimax_h3_weights.py 模型加载 modified 6.59
python/sglang/multimodal_gen/test/unit/test_transformer_quant.py 量化 modified 6.11
python/sglang/multimodal_gen/runtime/loader/transformer_load_utils.py 加载工具 modified 5.8
python/sglang/multimodal_gen/runtime/layers/quantization/modelopt_quant.py 量化后端 modified 5.74
python/sglang/multimodal_gen/runtime/utils/quantization_utils.py 量化工具 modified 5.19
python/sglang/multimodal_gen/runtime/loader/component_loaders/transformer_loader.py 组件加载 modified 4.96
python/sglang/multimodal_gen/runtime/layers/quantization/configs/base_config.py 量化配置 modified 4.35
docs/cookbook/diffusion/MiniMax/MiniMax-H3.mdx 文档 modified 2.44
docs/docs/sglang-diffusion/quantization.mdx 文档 modified 2.44

关键符号

resolve_minimax_h3_checkpoint_quantization build_nvfp4_config_from_safetensors_list _merge_modelopt_fp4_configs TransformerQuantLoadSpec.uses_comfy_layer_markers ModelOptFp4Config.from_config _build_nvfp4_config_from_safetensors_files TransformerLoader.load_customized inspect_minimax_h3_safetensors

关键源码片段

python/sglang/multimodal_gen/runtime/loader/minimax_h3_weights.py core-logic

PR 核心:resolve_minimax_h3_checkpoint_quantization 新增 NVFP4 分支,负责从 safetensors 推断并强制 Comfy/H3 布局开关。

def resolve_minimax_h3_checkpoint_quantization(
    layer_markers: dict[str, dict[str, Any]],
    safetensors_list: list[str] | None = None,
    param_names_mapping: dict | None = None,
    reverse_param_names_mapping: dict | None = None,
) -> QuantizationConfig | None:
    # 先把各层 marker 声明的 format 收拢成集合,只有整份检查点全为 nvfp4 时才进入 NVFP4 推断分支,
    # 避免与 FP8 / INT8 等 Comfy 格式混用路径。
    formats = {str(marker.get("format")) for marker in layer_markers.values()}
    if formats == {"nvfp4"}:
        # Comfy 序列化的 NVFP4 检查点不带 --quantization 参数,必须依赖检查点文件本身推断布局。
        if safetensors_list is None:
            raise ValueError("MiniMax-H3 NVFP4 metadata requires checkpoint files")
        # 复用现有 ModelOpt NVFP4 后端,group size、exclude_modules、scale 布局、nibble 顺序
        # 全部由 build_nvfp4_config_from_safetensors_list 从张量形状与元数据推断。
        config = build_nvfp4_config_from_safetensors_list(
            safetensors_list,
            param_names_mapping,
            reverse_param_names_mapping,
        )
        if config is None:
            raise ValueError("Could not resolve MiniMax-H3 NVFP4 checkpoint layout")
        # 强制 Comfy 布局约定:swizzled scale 布局 + 交换 nibble,并保留 H3 原生 QKV 打包布局,
        # 后续加载与反量化逻辑依赖这些开关做正确的张量解析。
        config.checkpoint_uses_comfy_quantization = True
        config.checkpoint_uses_native_qkv_layout = True
        config.checkpoint_weight_scale_layout = "swizzled"
        config.swap_weight_nibbles = True
        return config
    # 其他 Comfy 量化格式(如 FP8、INT8)继续走通用的层 marker 解析路径。
    return resolve_comfy_checkpoint_quantization(layer_markers)
python/sglang/multimodal_gen/runtime/loader/transformer_load_utils.py core-logic

配置合并与分派:_merge_modelopt_fp4_configs 对 Comfy 专属开关做 OR 合并,uses_comfy_layer_markers 纳入 NVFP4 判断。

def _merge_modelopt_fp4_configs(existing_config, inferred_config):
    # 合并 safetensors 推断出的配置与 config.json 中声明的配置。前面的逻辑已处理
    # exclude_modules、packed_modules_mapping、swap_weight_nibbles、scale 布局与 group_size,
    # 这里补充两个 Comfy 专属开关的 OR 合并,防止分支来源(推断 vs 声明)互相覆盖丢失信息。
    inferred_config.checkpoint_uses_comfy_quantization = (
        inferred_config.checkpoint_uses_comfy_quantization
        or existing_config.checkpoint_uses_comfy_quantization
    )
    inferred_config.checkpoint_uses_native_qkv_layout = (
        inferred_config.checkpoint_uses_native_qkv_layout
        or existing_config.checkpoint_uses_native_qkv_layout
    )
    return inferred_config

评论区精华

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

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

风险与影响

  • 混合格式检查点回退风险resolve_minimax_h3_checkpoint_quantizationformats == {"nvfp4"} 全量匹配判断;若检查点同时含 NVFP4 与其他格式(如 FP8)的层,会回退到 resolve_comfy_checkpoint_quantization,该路径不会设置 swizzled scale 与 nibble swap,NVFP4 层可能被错误解析。
  • 加载函数契约变更:该函数新增参数并要求 NVFP4 场景必须传入 safetensors_list(否则直接 raise),从原来可返回 None 变为抛异常;当前仓库内仅 transformer_loader.py 一处调用并已同步,但属于行为契约变化。
  • 布局强制覆盖:H3 路径无条件覆盖 checkpoint_weight_scale_layout="swizzled"swap_weight_nibbles=True,若未来出现标准 ModelOpt(linear 布局)的 H3 检查点,会被错误强制转换;目前仅依赖全量 format 判断来区分。
  • 实验性格式与兼容性:NVFP4 本身是实验性格式(ModelOptFp4Config 构造时打印警告),且 get_min_capability 要求算力 100(Blackwell);CI Extra run 显示失败(:x:),存在测试环境层面的不确定性。
  • 测试覆盖局限:以单元测试为主,缺少真实 Comfy 导出检查点的端到端加载验证。
  • 用户侧:MiniMax H3 用户可直接加载 Comfy 导出的 NVFP4 序列化检查点,无需手动指定 --quantization,只需提供 --transformer-weights-path;文档同步更新了自动检测流程。
  • 系统侧:改动集中在 multimodal_gen 量化加载管线;ModelOptFp4Config 数据契约扩展影响所有 NVFP4 检查点加载路径(新字段默认 False,向后兼容),uses_comfy_layer_markers 的判定变化会影响分派行为。
  • 团队侧:这是序列化量化检查点支持系列(FP8、INT8、W4A4、NVFP4)的一环,与 #36040、#36039、#36052 形成功能族,为后续其他模型/后端的 Comfy 检查点支持奠定模式基础。
NVFP4 为实验性格式 加载函数契约变更 混合量化格式回退风险 缺少端到端加载测试

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论