执行摘要
- 一句话:quality 门控 VAE 快速路径,打通 OpenAI 图像与视频 API
- 推荐动作:值得精读。核心看点:①用 WeakKeyDictionary 做 nn.Module 级注册表,兼顾对象身份匹配与 GC 友好;②contextmanager 的 previous_enabled 恢复模式让门控可嵌套、异常安全,是请求级开关的干净范式;③_runtime_sampling_quality 把 OpenAI 的 auto 默认值隔离在采样契约之外,是 API 兼容性处理的范例。对要在 diffusion 运行时新增请求级行为开关或维护 OpenAI 兼容入口的开发者有直接参考价值。建议结合 #33818 一起阅读以理解快速路径本体。
功能与动机
PR body 明确说明:“Fast VAE paths must be gated by the explicit output-quality mode so incompatible requests retain the correct decode path.” 快速 VAE 路径必须由显式输出质量档位门控,不兼容的请求应保留正确解码路径。此前 #33818 已在内部实现按 quality=“high” 启用的 FLUX.2 / AutoencoderKL 快速路径,但 quality 未暴露到 OpenAI 图像与视频 API,用户无法显式选择;同时门控类 VaeFastPathGate 定义在 flux2_vae_cuda_opt.py 中,由 wan_vae_cuda_opt.py 反向 import,解码阶段用手写 getattr + try/finally 管理开关。本 PR 解决两个问题:统一门控实现与生命周期管理;把 quality 变成公共 API 参数。
实现拆解
- 新增共享门控模块
python/sglang/multimodal_gen/runtime/models/vaes/fast_path_gate.py:定义 VaeFastPathGate(每 VAE 一份的可变开关)、register_vae_fast_path_gate(以 WeakKeyDictionary 按 VAE 模块对象登记,弱引用保证 VAE 释放后条目自动消失)、use_vae_fast_path(contextmanager,先保存 previous_enabled 再覆盖并在 finally 恢复,异常安全且支持嵌套)。
- VAE 优化模块去重:
flux2_vae_cuda_opt.py 与 wan_vae_cuda_opt.py 删除本地门控类与 GATE_ATTR,改为从共享模块导入并调用 register_vae_fast_path_gate(vae, gate) 登记;wan_vae_cuda_opt.py 因此不再反向依赖 flux2_vae_cuda_opt.py;_decoder_layout_forward 的布局切换日志由 info 降为 debug,避免每请求刷屏。
- 解码流水线接入:
decoding.py 的 DecodingStage.forward 将手写 getattr + try/finally 替换为 with use_vae_fast_path(vae, batch.sampling_params.quality == "high"),主解码与 trajectory 批量解码同处一个上下文内;注意这里由 getattr(..., None) 兜底改成了直接属性访问。
- OpenAI API 透传:
image_api.py 的 generations 与 edits 新增 _runtime_sampling_quality 过滤(None 与 "auto" 映射为 None,避免 OpenAI 默认值进入 SGLang 采样契约),edits 端点新增 quality: Optional[str] = Form(None) 表单参数;video_api.py 把 quality 加入额外字段白名单并在 _build_video_sampling_params 中转发。quality 与 output_quality 语义分离:后者只控制输出文件压缩。
- 测试、文档与 CI:新增
test_vae_fast_path_gate.py(验证 decode 作用域、嵌套复位与未登记透传),test_openai_image_api.py 覆盖 _runtime_sampling_quality 的默认值保持,test_video_api_profiling.py 验证 quality 转发;openai_api.mdx 补充 quality 参数说明。CI 通过 /tag-and-rerun-ci 触发,未在本地运行 SGLang-Diffusion 测试。
关键文件:
python/sglang/multimodal_gen/runtime/models/vaes/fast_path_gate.py(模块 门控模块;类别 source;类型 data-contract;符号 VaeFastPathGate, register_vae_fast_path_gate, use_vae_fast_path): 新增的统一门控模块,集中定义 VaeFastPathGate、WeakKeyDictionary 注册表与 use_vae_fast_path 上下文管理器,是本次重构的核心。
python/sglang/multimodal_gen/runtime/models/vaes/flux2_vae_cuda_opt.py(模块 VAE 解码;类别 source;类型 core-logic;符号 _install_decoder_fast_paths, _decoder_layout_forward, maybe_optimize_flux2_vae, maybe_optimize_autoencoder_kl): 删除本地 VaeFastPathGate 类与 GATE_ATTR,改用共享注册表;FLUX.2 / AutoencoderKL 快速路径安装入口所在。
python/sglang/multimodal_gen/runtime/entrypoints/openai/image_api.py(模块 图像入口;类别 source;类型 entrypoint;符号 _runtime_sampling_quality, generations, edits): generations 与 edits 入口透传 quality,新增 _runtime_sampling_quality 过滤 OpenAI 的 auto 默认值。
python/sglang/multimodal_gen/runtime/pipelines_core/stages/decoding.py(模块 解码流水线;类别 source;类型 core-logic;符号 DecodingStage.forward): DecodingStage.forward 由手写开关改为 use_vae_fast_path 上下文管理器,是门控语义落地的关键接线点。
python/sglang/multimodal_gen/runtime/models/vaes/wan_vae_cuda_opt.py(模块 VAE 解码;类别 source;类型 refactor;符号 maybe_optimize_wan_vae): Wan VAE 快速路径同步迁移到共享门控,消除对 flux2_vae_cuda_opt 的反向依赖。
python/sglang/multimodal_gen/runtime/entrypoints/openai/video_api.py(模块 视频入口;类别 source;类型 entrypoint;符号 _build_video_sampling_params): 视频请求支持 quality 透传:加入额外字段白名单并在采样参数构造中转发。
python/sglang/multimodal_gen/test/unit/test_vae_fast_path_gate.py(模块 单元测试;类别 test;类型 test-coverage;符号 test_vae_fast_path_gate_is_decode_scoped_and_nestable): 验证门控的 decode 作用域、嵌套复位与未登记透传行为。
python/sglang/multimodal_gen/test/unit/test_openai_image_api.py(模块 单元测试;类别 test;类型 test-coverage;符号 test_runtime_sampling_quality_preserves_the_openai_default): 覆盖 _runtime_sampling_quality 对 None / auto 的默认值保持。
python/sglang/multimodal_gen/test/unit/test_video_api_profiling.py(模块 单元测试;类别 test;类型 test-coverage): 验证视频 API 将 quality 转发到采样参数构造。
docs/docs/sglang-diffusion/api/openai_api.mdx(模块 公开文档;类别 docs;类型 documentation): 公开文档补充 quality 参数语义及其与 output_quality 的区别。
关键符号:use_vae_fast_path, register_vae_fast_path_gate, VaeFastPathGate, _runtime_sampling_quality, DecodingStage.forward, _install_decoder_fast_paths, maybe_optimize_flux2_vae, maybe_optimize_autoencoder_kl, maybe_optimize_wan_vae, _build_video_sampling_params
关键源码片段
python/sglang/multimodal_gen/runtime/entrypoints/openai/image_api.py
generations 与 edits 入口透传 quality,新增 _runtime_sampling_quality 过滤 OpenAI 的 auto 默认值。
# python/sglang/multimodal_gen/runtime/entrypoints/openai/image_api.py
def _runtime_sampling_quality(quality: str | None) -> str | None:
"""把 OpenAI 的自动默认值挡在 SGLang 采样契约之外。
OpenAI 客户端常默认携带 quality=auto,原样透传会让服务端误以为
用户显式选择档位并可能改变解码路径;这里统一映射为 None(不指定),
由运行时保持默认(lossless 原始路径),只有显式的 high / lossless 等
才进入采样契约。
"""
return None if quality in (None, "auto") else quality
# 在 generations / edits 两个入口的 build_sampling_params( ... ) 调用中:
# quality 经 _runtime_sampling_quality 过滤后透传,edits 端点在表单上
# 新增了 quality: Optional[str] = Form(None) 参数。
# 注意与 output_quality(仅控制输出文件压缩)语义不同、互不覆盖。
python/sglang/multimodal_gen/runtime/pipelines_core/stages/decoding.py
DecodingStage.forward 由手写开关改为 use_vae_fast_path 上下文管理器,是门控语义落地的关键接线点。
# python/sglang/multimodal_gen/runtime/pipelines_core/stages/decoding.py
# DecodingStage.forward 中的核心解码段(节选)
with self.use_declared_component(
component_name=self.component_name,
module=self.vae,
) as vae:
assert vae is not None
self.vae = vae
# 统一的 decode 作用域门控:quality == "high" 才走 CUDA 融合快速路径,
# 其余取值(None / "lossless" 等)保持原始模块路径逐比特一致。
# use_vae_fast_path 内部用 try/finally 保证 decode 抛异常时也会复位开关。
with use_vae_fast_path(vae, batch.sampling_params.quality == "high"):
frames = self.decode(batch.latents, server_args, vae_dtype=vae_dtype)
# 需要时批量解码 trajectory latents 以提高 GPU 利用率:
# 先展平成 [B*T, C, F, H, W] 一次调核,再按时间步切回列表
if batch.return_trajectory_decoded:
assert (
batch.trajectory_latents is not None
), "batch should have trajectory latents"
B, T, C, F, H, W = batch.trajectory_latents.shape
flat_latents = batch.trajectory_latents.view(B * T, C, F, H, W)
all_decoded = self.decode(
flat_latents, server_args, vae_dtype=vae_dtype
)
decoded_tensor = all_decoded.view(B, T, *all_decoded.shape[1:])
trajectory_decoded = [decoded_tensor[:, i] for i in range(T)]
else:
trajectory_decoded = None
评论区精华
本 PR 没有任何 review 评论,3 条 issue 评论均为作者 mickqian 触发的 CI 重跑指令(/tag-and-rerun-ci 两次、/tag-and-rerun-ci extra 一次),随后作者自审自合。门控设计(按 quality 显式门控、安装 fail-closed、lossless 走逐比特一致路径)的主要权衡在前置 PR #33818 中已经讨论并定型,本 PR 属于收尾与 API 打通,无遗留争议。
- 无实质 review 讨论,仅有 CI 重跑指令 (other): 作者自审自合,无遗留待解决项。
风险与影响
- 风险:
- 属性访问回归风险:
decoding.py 由 getattr(batch.sampling_params, "quality", None) 改为直接 batch.sampling_params.quality,若存在未设置 quality 字段的 sampling_params 构造路径,会抛 AttributeError 使 VAE decode 直接失败,需确认 build_sampling_params 全路径均带默认值。
- 对象身份匹配风险:注册表按 nn.Module 对象身份查找,
DecodingStage.forward 传入的 vae 若与安装时注册的不是同一实例(如组件管理器按需加载或包装返回新对象),快速路径会静默关闭——fail-closed 保证正确性,但可能静默损失性能。
- 全局门控并发语义:gate 是每 VAE 一份的全局可变状态,
use_vae_fast_path 只保证同线程内嵌套正确;若多个请求并发 decode 同一 VAE 且 quality 不同,存在状态互相覆盖的竞态(运行时若串行化 decode 则无碍)。
- 取值校验缺失:
video_api.py 对 quality 无白名单校验,未知取值原样透传,最终仅在等于 "high" 时生效从而被静默忽略;OpenAI 标准的 quality="low" 也会被透传,行为未定义。
- 回归防线未变:快速路径安装仍 fail-closed(Triton 缺失、attention 块不兼容、spatial-parallel decode 时跳过),本 PR 未削弱该防线。
- 影响:用户侧:图像 generations/edits 与视频请求现在可显式传 quality="high" 获得加速 VAE 解码(#33818 报告 AutoencoderKL 解码约 2.4x 提速);不传或传 "auto" 时行为与之前完全一致。系统侧:门控实现从两处复制收敛为单一模块,wan_vae_cuda_opt 不再反向依赖 flux2_vae_cuda_opt,依赖方向更清晰;decode 开关由上下文管理器接管,异常路径更安全。团队侧:新增 3 处单测覆盖与 1 处文档说明,后续新增 VAE 快速路径只需注册 gate 即可复用同一套门控语义。影响范围限定在 multimodal_gen diffusion 运行时,不触及 SRT 核心调度。
- 风险标记:直接属性访问无 getattr 兜底, 门控注册按对象身份匹配, 全局门控状态依赖串行 decode, quality 取值无服务端校验
关联脉络
- PR #33818 [diffusion] Generalize the FLUX.2 VAE decoder fast path to AutoencoderKL (Z-Image / FLUX.1) behind quality=high: 直接前置:引入 quality=“high” 门控概念与 CUDA 快速路径本体;本 PR 将其收敛为共享模块并打通 API。
- PR #33823 [diffusion] FLUX.2 bit-exact residual-gate fast path (H200 klein-4B 50-step denoise -1.2%): 同属 diffusion 快速路径优化线,与 flux2_vae_cuda_opt 的改造背景一致。
- PR #33850 [diffusion] retire released warmup and decoder flags: 同属 diffusion 运行时参数面规范化(统一为 warmup_mode),与本 PR 的 API 参数收口方向一致。
- PR #33845 [diffusion] centralize entrypoint API hygiene: 同模块入口层重构,集中 OpenAI 入口的 API 卫生与共享游标分页,与本 PR 的入口透传改动同域。
参与讨论