Prhub

#35184 fix(diffusion): route quantized VAE component repos safely

原始 PR 作者 mickqian 合并时间 2026-08-19 21:02 文件变更 3 提交数 10 评论 1 代码增减 +181 / -6

执行摘要

量化 VAE 仓库安全路由至 Diffusers,原生侧 fail closed

PR body 明确说明设计目标:detect quantization metadata before the native SGLang VAE raw-state loader,route standard top-level Diffusers quantized component repos through AutoModel.from_pretrained,fail closed for native-only VAEs and metadata layouts Diffusers 0.37 does not auto-restore,同时强调“This is a safe Diffusers passthrough, not a claim that SGLang native VAE quantization is implemented”。背景是 SGLang 原生 VAE loader 通过 raw state dict 恢复权重,无法还原序列化的量化状态(如 bitsandbytes 4bit、compressed-tensors),此前这类仓库会加载失败或静默得到错误权重,因此需要显式检测与安全路由。

值得精读,尤其是 _require_native_loader_for_quantized_vae 的三分支准入逻辑和 ComponentLoader.load()NativeComponentLoaderRequired 的异常驱动 fallback 控制流。对 diffusion 组件加载器、量化 checkpoint 兼容性和 srt 与 multimodal_gen 之间共享工具函数的维护者最为相关。建议在合并前确认 CI Extra 的失败原因是否与量化路由相关。

讨论亮点

该 PR 没有任何 review 评论,仅有一条 issue 评论是作者触发的 /tag-and-rerun-ci。PR body 中 CI 状态显示 Latest PR Test (Base) 通过,Latest PR Test (Extra) 运行失败(Run #32250458913),失败原因未在任何评论中说明。唯一的“讨论”来自 PR body 对设计边界的自我约束:仅做安全的 Diffusers 透传,不宣称 SGLang 原生 VAE 量化已实现。

实现拆解

  1. 新增异常契约:python/sglang/multimodal_gen/runtime/loader/component_loaders/component_loader.py 中定义 NativeComponentLoaderRequired(RuntimeError),并在 ComponentLoader.load() 的兜底 except 分支识别该异常:当 should_raise_customized_load_error 开启时直接 re-raise,禁止静默回退;否则以 logger.info 记录后走 native fallback(即 Diffusers from_pretrained)。
  2. 准入检查函数:python/sglang/multimodal_gen/runtime/loader/component_loaders/vae_loader.py 新增 _require_native_loader_for_quantized_vae(),复用 sglang.srt.model_loader.checkpoint_quantization.resolve_checkpoint_quant_spec() 统一识别量化元数据,分三种情况处理:无量化直接放行;native_only 或元数据来源不是 quantization_config 时抛 ComponentCheckpointUnsupportedError;顶层 quantization_config 时抛 NativeComponentLoaderRequired 请求路由到 Diffusers。
  3. 接线与时序调整:VAELoader.load_customized() 在解析 _class_name 之前调用准入函数,并把 server_args.model_paths[component_name] 的记录提前,native_only 判断上移,确保任何 raw-state 加载尝试之前就能失败。
  4. 测试配套:python/sglang/multimodal_gen/test/unit/test_vae_loader.py 新增 3 个用例,覆盖 plain 配置放行、BnB4 顶层量化配置路由到 diffusers.AutoModel.from_pretrained、native-only 配置 fail closed;同时扩展 _FakeServerArgs 以适配真实 ServerArgs 接口。
文件 模块 状态 重要度
python/sglang/multimodal_gen/runtime/loader/component_loaders/vae_loader.py 加载器 modified 7.09
python/sglang/multimodal_gen/runtime/loader/component_loaders/component_loader.py 加载框架 modified 6.34
python/sglang/multimodal_gen/test/unit/test_vae_loader.py 单元测试 modified 6.94

关键符号

_require_native_loader_for_quantized_vae VAELoader.load_customized ComponentLoader.load NativeComponentLoaderRequired resolve_checkpoint_quant_spec

关键源码片段

python/sglang/multimodal_gen/runtime/loader/component_loaders/vae_loader.py core-logic

核心准入逻辑所在:新增 `_require_native_loader_for_quantized_vae` 并在 `load_customized` 开头接线,决定量化 VAE 仓库走原生 raw-state 还是 Diffusers 路径。

# 准入函数:在原生 raw-state 加载之前检查量化元数据,决定路由方向
# 复用 SRT 侧的共享解析器,统一识别 quantization_config / compression_config 等元数据位置
def _require_native_loader_for_quantized_vae(
    config: dict, component_name: str, *, native_only: bool = False
) -> None:
    quant_spec = resolve_checkpoint_quant_spec(config)
    if quant_spec is None:
        # 普通未量化配置:直接放行,保持原有加载路径不变
        return
​
    method = quant_spec.declared_method or "unspecified"
    if native_only:
        # native-only 组件禁用 Diffusers fallback,必须显式失败而不是静默回退
        raise ComponentCheckpointUnsupportedError(
            f"{component_name} uses a native-only SGLang implementation that "
            f"cannot restore quant_method={method!r}; Diffusers fallback is disabled."
        )
    if quant_spec.source != "quantization_config":
        # 元数据藏在 compression_config / text_config.quantization_config 等嵌套布局,
        # Diffusers 0.37 不会自动恢复该布局,fail closed
        raise ComponentCheckpointUnsupportedError(
            f"{component_name} checkpoint declares quantization metadata in "
            f"{quant_spec.source} (quant_method={method!r}), which the Diffusers "
            "component loader does not restore automatically."
        )
    # 顶层 quantization_config:要求基类 load() 改走 Diffusers from_pretrained 原生加载
    raise NativeComponentLoaderRequired(
        f"{component_name} checkpoint declares quant_method={method!r}; routing "
        "through Diffusers from_pretrained because the SGLang VAE loader cannot "
        "restore serialized quantized state."
    )
    def load_customized(
        self,
        component_model_path: str,
        server_args: ServerArgs,
        component_name: str,
        cpu_offload_flag: bool = False,
    ):
        """加载 VAE:先做量化准入检查,再决定走原生 raw-state 还是 Diffusers 路径。"""
        config = get_diffusers_component_config(component_path=component_model_path)
        server_args.model_paths[component_name] = component_model_path
        # native_only 组件必须提前判定,以便准入函数直接 fail closed
        native_only = component_name in getattr(
            server_args.pipeline_config, "native_only_components", ()
        )
        _require_native_loader_for_quantized_vae(
            config, component_name, native_only=native_only
        )
        class_name = config.pop("_class_name", None)
        # 后续逻辑:普通未量化 VAE 继续走原生 raw-state 加载;
        # 若准入函数抛 NativeComponentLoaderRequired,则由基类 load() 接管为 Diffusers 加载
python/sglang/multimodal_gen/runtime/loader/component_loaders/component_loader.py core-logic

新增 `NativeComponentLoaderRequired` 异常并改写 `ComponentLoader.load()` 的异常处理分支,实现“子类显式请求走 native 加载”的控制流契约。

        except Exception as e:
            # 子类通过 NativeComponentLoaderRequired 显式要求走 native 加载器(Diffusers 路径)
            native_loader_required = isinstance(e, NativeComponentLoaderRequired)
            if self.should_raise_customized_load_error(server_args, component_name):
                if native_loader_required:
                    # native-only 场景禁止回退,直接抛出,让调用方感知
                    raise
                traceback.print_exc()
                raise RuntimeError(
                    f"Failed to load customized {component_name}; native fallback "
                    "is disabled for this component configuration."
                ) from e
            if native_loader_required:
                # 这是预期的路由要求,仅记录 info,不打印堆栈
                logger.info("%s", e)
            elif "Unsupported model architecture" in str(e):
                logger.info(
                    f"Component: {component_name} doesn't have a customized version yet, using native version"
                )
            else:
                traceback.print_exc()
                logger.error(
                    f"Error while loading customized {component_name}, falling back to native version"
                )
            # fallback to native version:这里即 Diffusers AutoModel.from_pretrained
            component = self._load_native_with_context(
                component_model_path,
                server_args,
                component_name,
                transformers_or_diffusers,
                attn_backend,
                component_attn_name,
            )

评论区精华

CI Extra 运行失败与 /tag-and-rerun-ci other

PR 未收到任何 review 讨论;PR body 中 CI 状态显示 Latest PR Test (Extra) 失败(Run #32250458913),作者通过 issue 评论触发 /tag-and-rerun-ci 重跑,但失败原因没有公开说明。

结论:作者已请求重跑,失败原因与最终结果未在评论中讨论。 · unresolved

风险与影响

  • 跨包依赖与耦合:vae_loader.py 新增了对 sglang.srt.model_loader.checkpoint_quantization.resolve_checkpoint_quant_spec 的导入,使 multimodal_gensrt 形成内部依赖,后续 srt 侧该函数签名或语义变化会直接影响 diffusion VAE 加载。
  • 加载行为变更:任何带顶层 quantization_config 的 VAE 仓库都不再走 SGLang 原生 raw-state 路径,而改由 Diffusers from_pretrained,依赖旧行为(无论成败)的自定义流程可能观察到新错误。
  • native-only 显式报错:native_only_components 包含 vae 时,量化 VAE 会直接抛 ComponentCheckpointUnsupportedError,用户需移除 native_only 或改用未量化仓库。
  • CI 覆盖不确定性:Latest PR Test (Extra) 失败且未说明原因,量化路由的端到端回归覆盖存在盲区;测试主要依赖 mock,真实量化仓库的验证仅靠 PR body 声称的“valid serialized BnB4 routing through the real SGLang fallback boundary”。

影响范围集中在 SGLang Diffusion 子系统的 VAE/audio_vae/video_vae 组件加载路径:用户可以安全加载带顶层 quantization_config 的量化 VAE 仓库,native-only 或嵌套量化元数据布局会得到显式错误而非静默回退;普通未量化 VAE 不受影响。对团队而言,这套“组件加载器能力契约 + 异常驱动 fallback + fail closed”模式与 #35183 的门禁思路一脉相承,为后续其他组件(如 encoder、transformer)的量化加载治理提供了可复用范式。

跨包依赖 srt 解析器 量化加载行为变更 CI Extra 失败未说明 native-only 显式报错

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论