From 978a290d6e26da93ac035624ce7d7ee7f3e8b132 Mon Sep 17 00:00:00 2001 From: Samit <285365963@qq.com> Date: Mon, 26 Jan 2026 13:09:03 +0800 Subject: [PATCH] [Bugfix] Fix diffusion pipeline CFG (guidance_scale parsing failure bug) (#922) Signed-off-by: samithuang <285365963@qq.com> Signed-off-by: Hongsheng Liu Co-authored-by: Hongsheng Liu --- .../text_to_video/text_to_video.md | 7 ++++--- .../models/qwen_image/pipeline_qwen_image.py | 2 ++ .../qwen_image/pipeline_qwen_image_edit.py | 2 ++ .../pipeline_qwen_image_edit_plus.py | 2 ++ .../qwen_image/pipeline_qwen_image_layered.py | 2 ++ .../models/wan2_2/pipeline_wan2_2.py | 20 +++++++++++-------- .../models/wan2_2/pipeline_wan2_2_i2v.py | 20 +++++++++++-------- .../models/wan2_2/pipeline_wan2_2_ti2v.py | 20 +++++++++++-------- vllm_omni/entrypoints/async_omni_diffusion.py | 3 +++ 9 files changed, 51 insertions(+), 27 deletions(-) diff --git a/examples/offline_inference/text_to_video/text_to_video.md b/examples/offline_inference/text_to_video/text_to_video.md index f0ce5495a..7204ec58a 100644 --- a/examples/offline_inference/text_to_video/text_to_video.md +++ b/examples/offline_inference/text_to_video/text_to_video.md @@ -9,10 +9,11 @@ python text_to_video.py \ --prompt "Two anthropomorphic cats in comfy boxing gear and bright gloves fight intensely on a spotlighted stage." \ --negative_prompt "" \ --height 480 \ - --width 640 \ + --width 832 \ --num_frames 33 \ --guidance_scale 4.0 \ --guidance_scale_high 3.0 \ + --flow_shift 12.0 \ --num_inference_steps 40 \ --fps 16 \ --output t2v_out.mp4 @@ -21,9 +22,9 @@ python text_to_video.py \ Key arguments: - `--prompt`: text description (string). -- `--height/--width`: output resolution (defaults 720x1280). Dimensions should align with Wan VAE downsampling (multiples of 8). +- `--height/--width`: output resolution (defaults 480x832, i.e. 480P). Dimensions should align with Wan VAE downsampling (multiples of 8). - `--num_frames`: Number of frames (Wan default is 81). -- `--guidance_scale` and `--guidance_scale_high`: CFG scale (applied to low/high).. +- `--guidance_scale` and `--guidance_scale_high`: CFG scale (applied to low/high). - `--negative_prompt`: optional list of artifacts to suppress (the PR demo used a long Chinese string). - `--boundary_ratio`: Boundary split ratio for low/high DiT. - `--fps`: frames per second for the saved MP4 (requires `diffusers` export_to_video). diff --git a/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image.py b/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image.py index 5ae8228a0..2b9d906d3 100644 --- a/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image.py +++ b/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image.py @@ -672,6 +672,8 @@ class QwenImagePipeline( num_inference_steps = req.num_inference_steps or num_inference_steps generator = req.generator or generator true_cfg_scale = req.true_cfg_scale or true_cfg_scale + if req.guidance_scale_provided: + guidance_scale = req.guidance_scale req_num_outputs = getattr(req, "num_outputs_per_prompt", None) if req_num_outputs and req_num_outputs > 0: num_images_per_prompt = req_num_outputs diff --git a/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image_edit.py b/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image_edit.py index 4927ca3ac..ac74507c7 100644 --- a/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image_edit.py +++ b/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image_edit.py @@ -748,6 +748,8 @@ class QwenImageEditPipeline( num_inference_steps = req.num_inference_steps or num_inference_steps generator = req.generator or generator true_cfg_scale = req.true_cfg_scale or true_cfg_scale + if req.guidance_scale_provided: + guidance_scale = req.guidance_scale req_num_outputs = getattr(req, "num_outputs_per_prompt", None) if req_num_outputs and req_num_outputs > 0: num_images_per_prompt = req_num_outputs diff --git a/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image_edit_plus.py b/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image_edit_plus.py index 9eeaed5f9..4e2fe35f1 100644 --- a/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image_edit_plus.py +++ b/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image_edit_plus.py @@ -704,6 +704,8 @@ class QwenImageEditPlusPipeline(nn.Module, SupportImageInput): num_inference_steps = req.num_inference_steps or num_inference_steps generator = req.generator or generator true_cfg_scale = req.true_cfg_scale or true_cfg_scale + if req.guidance_scale_provided: + guidance_scale = req.guidance_scale req_num_outputs = getattr(req, "num_outputs_per_prompt", None) if req_num_outputs and req_num_outputs > 0: num_images_per_prompt = req_num_outputs diff --git a/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image_layered.py b/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image_layered.py index 4642b3eb4..ae2d039e3 100644 --- a/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image_layered.py +++ b/vllm_omni/diffusion/models/qwen_image/pipeline_qwen_image_layered.py @@ -722,6 +722,8 @@ the image\n<|vision_start|><|image_pad|><|vision_end|><|im_end|>\n<|im_start|>as num_inference_steps = req.num_inference_steps or num_inference_steps generator = req.generator or generator true_cfg_scale = req.true_cfg_scale or true_cfg_scale + if req.guidance_scale_provided: + guidance_scale = req.guidance_scale req_num_outputs = getattr(req, "num_outputs_per_prompt", None) if req_num_outputs and req_num_outputs > 0: num_images_per_prompt = req_num_outputs diff --git a/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2.py b/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2.py index 3b04e2a5a..8ff6271a0 100644 --- a/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2.py +++ b/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2.py @@ -284,11 +284,11 @@ class Wan22Pipeline(nn.Module): req: OmniDiffusionRequest, prompt: str | None = None, negative_prompt: str | None = None, - height: int | None = None, - width: int | None = None, - num_inference_steps: int | None = None, + height: int = 480, + width: int = 832, + num_inference_steps: int = 40, guidance_scale: float | tuple[float, float] = 4.0, - frame_num: int | None = None, + frame_num: int = 81, output_type: str | None = "np", generator: torch.Generator | None = None, prompt_embeds: torch.Tensor | None = None, @@ -301,9 +301,9 @@ class Wan22Pipeline(nn.Module): if prompt is None and prompt_embeds is None: raise ValueError("Prompt or prompt_embeds is required for Wan2.2 generation.") - height = req.height or height or 720 - width = req.width or width or 1280 - num_frames = req.num_frames if req.num_frames else frame_num or 81 + height = req.height or height + width = req.width or width + num_frames = req.num_frames if req.num_frames else frame_num # Ensure dimensions are compatible with VAE and patch size # For expand_timesteps mode, we need latent dims to be even (divisible by patch_size) @@ -311,7 +311,11 @@ class Wan22Pipeline(nn.Module): mod_value = self.vae_scale_factor_spatial * patch_size[1] # 16*2=32 for TI2V, 8*2=16 for I2V height = (height // mod_value) * mod_value width = (width // mod_value) * mod_value - num_steps = req.num_inference_steps or num_inference_steps or 40 + num_steps = req.num_inference_steps or num_inference_steps + + # Respect per-request guidance_scale when explicitly provided. + if req.guidance_scale_provided: + guidance_scale = req.guidance_scale guidance_low = guidance_scale if isinstance(guidance_scale, (int, float)) else guidance_scale[0] guidance_high = ( diff --git a/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2_i2v.py b/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2_i2v.py index ed0d6e4c6..635da11e6 100644 --- a/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2_i2v.py +++ b/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2_i2v.py @@ -261,11 +261,11 @@ class Wan22I2VPipeline(nn.Module, SupportImageInput): prompt: str | None = None, negative_prompt: str | None = None, image: PIL.Image.Image | torch.Tensor | None = None, - height: int | None = None, - width: int | None = None, - num_inference_steps: int | None = None, + height: int = 480, + width: int = 832, + num_inference_steps: int = 40, guidance_scale: float | tuple[float, float] = 5.0, - frame_num: int | None = None, + frame_num: int = 81, output_type: str | None = "np", generator: torch.Generator | None = None, prompt_embeds: torch.Tensor | None = None, @@ -287,10 +287,14 @@ class Wan22I2VPipeline(nn.Module, SupportImageInput): if image is None: raise ValueError("Image is required for I2V generation.") - height = req.height or height or 480 - width = req.width or width or 832 - num_frames = req.num_frames if req.num_frames else frame_num or 81 - num_steps = req.num_inference_steps or num_inference_steps or 50 + height = req.height or height + width = req.width or width + num_frames = req.num_frames if req.num_frames else frame_num + num_steps = req.num_inference_steps or num_inference_steps + + # Respect per-request guidance_scale when explicitly provided. + if req.guidance_scale_provided: + guidance_scale = req.guidance_scale # Handle guidance scales guidance_low = guidance_scale if isinstance(guidance_scale, (int, float)) else guidance_scale[0] diff --git a/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2_ti2v.py b/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2_ti2v.py index 6a9a6a6a0..6c1e39242 100644 --- a/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2_ti2v.py +++ b/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2_ti2v.py @@ -200,11 +200,11 @@ class Wan22TI2VPipeline(nn.Module, SupportImageInput): prompt: str | None = None, negative_prompt: str | None = None, image: PIL.Image.Image | torch.Tensor | None = None, - height: int | None = None, - width: int | None = None, - num_inference_steps: int | None = None, + height: int = 704, + width: int = 1280, + num_inference_steps: int = 40, guidance_scale: float = 5.0, - frame_num: int | None = None, + frame_num: int = 81, output_type: str | None = "np", generator: torch.Generator | None = None, prompt_embeds: torch.Tensor | None = None, @@ -223,10 +223,14 @@ class Wan22TI2VPipeline(nn.Module, SupportImageInput): image = req.pil_image # Default dimensions for TI2V-5B (720P) - height = req.height or height or 704 - width = req.width or width or 1280 - num_frames = req.num_frames if req.num_frames else frame_num or 121 - num_steps = req.num_inference_steps or num_inference_steps or 50 + height = req.height or height + width = req.width or width + num_frames = req.num_frames if req.num_frames else frame_num + num_steps = req.num_inference_steps or num_inference_steps + + # Respect per-request guidance_scale when explicitly provided. + if req.guidance_scale_provided: + guidance_scale = req.guidance_scale self._guidance_scale = guidance_scale diff --git a/vllm_omni/entrypoints/async_omni_diffusion.py b/vllm_omni/entrypoints/async_omni_diffusion.py index 1d47205f1..bfaf7aaae 100644 --- a/vllm_omni/entrypoints/async_omni_diffusion.py +++ b/vllm_omni/entrypoints/async_omni_diffusion.py @@ -138,6 +138,9 @@ class AsyncOmniDiffusion: if key in field_names: init_kwargs[key] = value + if "guidance_scale" in kwargs: + init_kwargs["guidance_scale_provided"] = True + return OmniDiffusionRequest(**init_kwargs) async def generate(