SGLang 扩散模型 ComfyUI 集成管道测试指南:DiffGenerator 与噪声预测验证实战
【免费下载链接】sglangSGLang is a high-performance serving framework for large language models and multimodal models.项目地址: https://gitcode.com/GitHub_Trending/sg/sglang
本篇文章聚焦于 SGLang 项目中 ComfyUI_SGLDiffusion 插件 的管道测试体系。它通过comfyui_mode=True让 SGLang 的扩散模型运行时(DiffGenerator)直接接收 ComfyUI 风格的前处理输入(latents、timesteps、embeddings),并验证noise_pred能否从OutputBatch中正确取回。读完本文,你将掌握该测试目录的完整运行方式、四个管道测试的输入构造细节、环境变量配置,以及从SamplingParams到Req、再到调度器执行与输出校验的底层调用链。
测试目录概览:每个 ComfyUI 管道一个测试文件
test/目录为 ComfyUI_SGLDiffusion 插件的每种管道集成各提供一个测试文件,整体结构如下:
| 测试文件 | 被测管道类 | 适用模型 / 模式 |
|---|---|---|
| test_zimage_pipeline.py | ComfyUIZImagePipeline | Z-Image(如Z-Image-Turbo) |
| test_flux_pipeline.py | ComfyUIFluxPipeline | FLUX(如FLUX.1-dev) |
| test_qwen_image_pipeline.py | ComfyUIQwenImagePipeline | Qwen-Image(文生图) |
| test_qwen_image_edit_pipeline.py | ComfyUIQwenImageEditPipeline | Qwen-Image-Edit(I2I / 编辑模式) |
此外目录中还有 test_h3_request.py,它不执行扩散推理,而是针对 MiniMax-H3 视频生成节点的请求负载结构做契约测试(详见后文)。
这些测试对应插件 README 中列出的受支持模型:Z-Image(高速图像生成)、FLUX(文生图)、Qwen-Image(多模态图像生成,图像编辑当前为实验性支持)、MiniMax-H3(联合视频与音频生成,仅服务器模式)。管道类名与执行器之间的映射关系,可以在 core/generator.py 的pipeline_class_dict与executor_class_dict中看到。
运行测试:从单文件到全量
测试使用标准的pytest运行,执行命令如下。
运行全部测试
pytest python/sglang/multimodal_gen/apps/ComfyUI_SGLDiffusion/test/ -v -s-v输出每个用例的详细结果,-s允许打印(测试中会用print输出noise_pred的形状、dtype 与设备信息)。
运行单个测试文件
pytest python/sglang/multimodal_gen/apps/ComfyUI_SGLDiffusion/test/test_zimage_pipeline.py -v -s四个管道测试均以if __name__ == "__main__":结尾,因此也可以直接以脚本方式执行单个文件,例如python python/sglang/multimodal_gen/apps/ComfyUI_SGLDiffusion/test/test_zimage_pipeline.py。
运行前置条件
从测试代码看,运行前需要满足以下条件:
- 已安装
sglang[diffusion],否则 core/generator.py 与各 executor 中的try/except ImportError会打印缺少sglang.multimodal_gen的提示; - 有可用的 CUDA GPU(所有 dummy 张量都显式指定了
device="cuda",且断言noise_pred.device.type == "cuda"); - 可以联网下载 HuggingFace 模型,或预先通过环境变量指向本地模型文件。
环境变量:模型路径的两种格式
测试通过环境变量配置模型路径,支持两种格式:
- Safetensors 单文件:指向一个
.safetensors权重文件的路径(例如/path/to/model.safetensors),对应 ComfyUI 插件中“从 checkpoint 文件加载 UNET”的使用方式; - Diffusers 目录格式:HuggingFace 模型 ID 或本地 diffusers 目录(例如
Tongyi-MAI/Z-Image-Turbo)。
四个环境变量及其默认值:
| 环境变量 | 对应模型 | 默认值 |
|---|---|---|
SGLANG_TEST_ZIMAGE_MODEL_PATH | Z-Image | Tongyi-MAI/Z-Image-Turbo |
SGLANG_TEST_FLUX_MODEL_PATH | FLUX | black-forest-labs/FLUX.1-dev |
SGLANG_TEST_QWEN_IMAGE_MODEL_PATH | Qwen-Image | Qwen/Qwen-Image |
SGLANG_TEST_QWEN_IMAGE_EDIT_MODEL_PATH | Qwen-Image-Edit | Qwen/Qwen-Image-Edit-2511 |
在测试代码中,环境变量通过os.environ.get("SGLANG_TEST_XXX_MODEL_PATH", "<默认值>")读取(例如 test_zimage_pipeline.py)。
使用示例
# 使用 HuggingFace 模型 ID(diffusers 格式) export SGLANG_TEST_ZIMAGE_MODEL_PATH="Tongyi-MAI/Z-Image-Turbo" pytest python/sglang/multimodal_gen/apps/ComfyUI_SGLDiffusion/test/test_zimage_pipeline.py -v -s # 使用 safetensors 单文件 export SGLANG_TEST_ZIMAGE_MODEL_PATH="/path/to/z_image_turbo_bf16.safetensors" pytest python/sglang/multimodal_gen/apps/ComfyUI_SGLDiffusion/test/test_zimage_pipeline.py -v -s测试结构:六步走通「透传调度器」全链路
README 中给出了每个测试文件共用的六步结构。结合源码,可以逐一对号入座:
- Setup(初始化生成器):调用
DiffGenerator.from_pretrained()创建生成器,传入pipeline_class_name(如ComfyUIZImagePipeline)、num_gpus、sp_degree等参数,并显式打开comfyui_mode=True。这是所有管道测试的关键开关,用于启用 ComfyUI 特有的行为——输入不再是原始 prompt 文本,而是由 ComfyUI 前端(CLIP、VAE 等节点)预处理好的一整套张量。 - Input Preparation(构造输入):用
torch.ones创建 dummy 的 latents、timesteps 与 embeddings 张量,全部使用bfloat16、放在 CUDA 上。不同管道输入形状差异明显(详见下一节)。 - Request Preparation(构造请求):用
SamplingParams.from_user_sampling_params_args()构建采样参数(prompt、guidance_scale、height/width、num_inference_steps、seed 等),再经prepare_request()转换为调度器可执行的Req对象。 - ComfyUI Inputs(注入 ComfyUI 输入):直接把 ComfyUI 风格的输入写到
Req上,如req.latents、req.timesteps、req.prompt_embeds(必须是List[Tensor])、req.negative_prompt_embeds、req.raw_latent_shape等;随后根据guidance_scale > 1.0且存在负向 embedding 的条件设置req.do_classifier_free_guidance,并根据req.seed构造torch.Generator列表。 - Execution(执行推理):调用
generator._send_to_scheduler_and_wait_for_response([req])将请求送入调度器并同步等待响应,得到OutputBatch。 - Validation(校验输出):断言
output_batch.noise_pred不为None、是torch.Tensor、位于 CUDA、dtype 为bfloat16,并打印其 shape/dtype/device;同时从output_batch.output(回退到req.latents)校验 latents 存在。
这套流程本质上是把插件的 executor 内部逻辑「原样搬进测试」——对比 executors/zimage.py 的forward可以看到完全一致的模式:构造SamplingParams→prepare_request→ 填充req.latents/timesteps/prompt_embeds/raw_latent_shape→ 送入调度器 → 取output_batch.noise_pred返回给 ComfyUI 的 KSampler 继续去噪循环。
四个管道测试的输入差异:形状即模型结构
虽然四个测试骨架相同,但每个管道的输入张量形状直接反映了其模型的 latent 布局与条件编码方式,值得逐一拆解。
Z-Image:五维 latent + 单一 context
在 test_zimage_pipeline.py 中:
- latents 形状为
(1, 16, 1, 90, 160):batch_size=1、num_channels=16、num_frames=1,其中 720×1280 像素经 VAE 8 倍下采样得到 90×160 的 latent 尺寸(height // 8、width // 8); timesteps = torch.tensor([1000]);- context(prompt embeddings)形状为
(19, 2560),序列长度 19、特征维 2560; - 采样参数:
guidance_scale=1.0(无需 CFG,对应do_classifier_free_guidance=False)、num_inference_steps=1、seed=42、save_output=False。
对比 executor 中的实现:zimage.py 会将 ComfyUI 传入的x(四维)unsqueeze(2)扩展出帧维度,并把context.squeeze(0)后包装成req.prompt_embeds列表,timesteps还要乘以 1000 归一化。
FLUX:双流条件(encoder_hidden_states + pooled_projections)
test_flux_pipeline.py 使用num_gpus=2(对应插件 README 中 FLUX 工作流的 Sequence Parallelism 多卡场景),输入包括:
hidden_states:(1, 3600, 64),即 latent 展开后的序列(1280×720 下采样后展平);encoder_hidden_states:(1, 512, 4096),T5 文本编码器输出;pooled_projections:(1, 768),CLIP-L pooled 输出;req.prompt_embeds = [pooled_projections, encoder_hidden_states]——注意 FLUX 的条件是两个张量的列表,顺序为 pooled 在前;req.pooled_embeds = [pooled_projections]、req.neg_pooled_embeds = [];- 若启用 CFG,负向条件为
(1, 77, 768)的 dummy CLIP embedding 加(1, 512, 4096)的负向 encoder hidden states。
FLUX 测试还设置了save_output=True与return_trajectory_latents=True,用于保留输出与去噪轨迹。
Qwen-Image:单一 encoder_hidden_states 条件
test_qwen_image_pipeline.py 使用num_gpus=2且显式关闭dit_layerwise_offload:
hidden_states:(1, 6889, 64)(1328×1328 像素的 latent 展平序列,即 166×166);encoder_hidden_states:(1, 45, 3584),文本条件序列长度仅 45;req.prompt_embeds = [encoder_hidden_states](单元素列表);guidance_scale=3.0,并直接复用同一个 encoder hidden states 张量作为negative_prompt_embeds来开启 CFG。
Qwen-Image-Edit:双 latent(噪声图像 + 条件图像)
test_qwen_image_edit_pipeline.py 是 I2I/编辑模式,输入最复杂:
noisy_image_latents(req.latents):(1, 3600, 64),待去噪的目标图像 latent;condition_image_latents(req.image_latent):(1, 6889, 64),作为编辑条件的参考图像 latent(1328×1328 下采样后展平);req.vae_image_sizes = [(166, 166)]:condition_width_latent与condition_height_latent(1328 ÷ 8);- 使用
num_gpus=1,guidance_scale=1.0(关闭 CFG)。
测试设计要点:为什么用 dummy 张量、为什么校验 noise_pred
README 的 Notes 部分点明了测试设计的四个关键决策,结合源码可进一步理解其目的:
comfyui_mode=True是分水岭:它让 DiffGenerator 走 ComfyUI 专用路径,输入不再是文本 prompt 而是完整的预处理张量。在插件的 core/generator.py 中,init_generator也会强制设置kwargs["comfyui_mode"] = True,测试与插件生产路径保持一致。- 输入是「预处理的」:latents、timesteps、embeddings 本应由 ComfyUI 的 VAE、CLIP 等节点产生,测试直接注入等价张量,从而把关注点锁定在「SGLang 调度器对这批输入的响应是否正确」这一层。
- 校验的核心是
noise_pred:noise_pred(噪声预测)是扩散模型单步去噪的核心输出,ComfyUI 的 KSampler 拿到它才能完成一步采样。所有测试的最终断言都验证它存在、是 CUDA 上的bfloat16张量,这正是「透传调度器」集成成功的标志。 - dummy/ones 张量的取舍:测试使用全 1 张量保持简单可复现,真实场景中这些位置是模型实际输出;因此这类测试验证的是「管道与数据通路」而非「生成图像质量」。
补充:MiniMax-H3 请求契约测试
除四个管道测试外,test_h3_request.py 是另一种风格的测试:它只 mock HTTP 层,用types.ModuleType构造folder_paths、comfy_api、comfy等模块桩,在不安装 ComfyUI、不需要 GPU 的前提下加载真实的nodes.py与core/server_api.py,驱动SGLDiffusionGenerateH3节点捕获 POST 请求负载,并验证:
t2va(文生视频+音频)任务发送target={"short_edge": 768, "aspect_ratio": "16:9", "duration_seconds": 5.0}、flow_shift=12.0、audio_flow_shift=3.0;fl2va任务把首帧/尾帧 keyframe 映射为frame_index0 与 -1;ref2va任务保持图片/视频/音频条件的模态顺序;- 任务类型与条件必须自洽(如
fl2va缺少关键帧会抛ValueError); - 最终负载还能通过
VideoGenerationsRequest(见 openai/protocol.py)的 schema 校验,确保字段名与类型和服务器端解析完全一致。
该测试还验证了extra_fields机制——模型自定义字段优先于通用默认值,印证了插件 README 中「请求 schema 接受未知键,core/server_api.py无需按模型改动」的设计。
结语
ComfyUI_SGLDiffusion 的测试目录以「每个管道一个测试文件」的方式,为 Z-Image、FLUX、Qwen-Image、Qwen-Image-Edit 四条扩散路径提供了统一的回归保障:通过comfyui_mode=True+ 预处理张量 +noise_pred输出校验,把「SGLang 调度器能否正确响应 ComfyUI 风格请求」这一核心契约固定下来;MiniMax-H3 的契约测试则把验证范围扩展到 HTTP 负载与服务器 schema 的一致性。这套测试既可用于插件开发时的快速自检,也是理解 SGLang 扩散运行时与外部前端如何协作的最佳入口。
【免费下载链接】sglangSGLang is a high-performance serving framework for large language models and multimodal models.项目地址: https://gitcode.com/GitHub_Trending/sg/sglang
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考