Skip to content

[BugFix] Fix Wan2.2-VACE-Fun cache and serving lifecycle - #4667

Merged
david6666666 merged 14 commits into
vllm-project:mainfrom
david6666666:codex/wan22-vace-issues
Jun 25, 2026
Merged

david6666666 merged 14 commits into
vllm-project:mainfrom
david6666666:codex/wan22-vace-issues

Conversation

@david6666666

@david6666666 david6666666 commented Jun 24, 2026 •

Copy link
Copy Markdown
Collaborator

Purpose

This PR builds on #4249 after rebasing it onto current upstream/main and fixes the Wan2.2-VACE issues found while reproducing the supplied performance script with:

  • MODEL_PATH=Pyros13/Wan2.2-VACE-Fun-A14B-Diffusers
  • INPUT_VIDEO=mkt_part_000.mp4 (61 frames)

I also validated Pyros13/Wan2.2-VACE-Fun-A14B-Diffusers against the original alibaba-pai/Wan2.2-VACE-Fun-A14B checkpoint. Under the same vLLM-Omni pipeline, prompt, input video, seed, size, frame count, and 30 inference steps, both produced a byte-identical MP4. This lets the PR use the standard diffusers model layout and avoid adding original-format key remapping / .pth component loading code.

What changed

  1. Register Wan22VACEPipeline in the Cache-DiT custom enabler registry so it uses the Wan2.2 block-level path instead of the generic transformer-level path.
  2. Pass TaylorSeer calibrator_config through enable_cache_for_wan22() for both single-transformer and dual-transformer Wan2.2 paths.
  3. Keep the API server's AsyncOmni engine context alive until the HTTP shutdown task completes. Previously omni_run_server_worker() exited build_async_omni immediately after serve_http() returned its shutdown task, which could close the engine while the server was still accepting requests.
  4. Support dual-transformer Wan2.2 VACE denoising by switching between transformer and transformer_2 at the configured boundary timestep.
  5. Include VACE conditioning blocks in layerwise offload discovery by declaring WanVACETransformer3DModel._layerwise_offload_blocks_attrs = ["vace_blocks", "blocks"].
  6. Add a recipe and supported-model docs for Pyros13/Wan2.2-VACE-Fun-A14B-Diffusers.

Issue reproduction notes

Issue Local result Fix
#4632 Cache-DiT not working for Wan22VACEPipeline Reproduced in code: #4249 had no Wan22VACEPipeline entry in CUSTOM_DIT_ENABLERS, so CacheDiTBackend.enable() would fall back to the generic path. Added Wan22VACEPipeline -> enable_cache_for_wan22 and a registry regression test.
#4633 TaylorSeer silently disabled Reproduced in code: enable_cache_for_wan22() did not resolve or pass calibrator_config, unlike the generic path and S2V custom path. Added _resolve_calibrator_config() usage and passed the same calibrator into both ParamsModifier and cache_dit.enable_cache().
#4634 subsequent V2V requests return 504 Reproduced in code: the server worker awaited shutdown_task after exiting build_async_omni, so the engine context could shut down while HTTP serving continued. Moved await shutdown_task inside the engine context and added a lifecycle regression test.
#4635 HSDP OOM on 64GB NPU Could not reproduce the NPU allocator behavior on local NVIDIA B300. Code inspection found VACE-specific memory pressure: vace_blocks were not included in layerwise offload discovery. Added VACE vace_blocks to layerwise offload discovery. The NPU allocator limit itself is outside this repo.

Validation

Unit / CPU tests

pytest tests/diffusion/cache/test_cache_dit.py tests/diffusion/models/wan2_2/test_wan22_vace_pipeline.py tests/diffusion/offloader/test_layerwise_backend.py tests/entrypoints/openai_api/test_video_server.py::test_server_worker_keeps_engine_alive_until_http_shutdown -q
# 27 passed

pre-commit run --files docs/models/supported_models.md recipes/Pyros13/Wan2.2-VACE-Fun-A14B-Diffusers.md tests/diffusion/cache/test_cache_dit.py tests/diffusion/models/wan2_2/test_wan22_vace_pipeline.py tests/entrypoints/openai_api/test_video_server.py vllm_omni/diffusion/cache/cache_dit_backend.py vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2_vace.py vllm_omni/diffusion/models/wan2_2/wan2_2_vace_transformer.py vllm_omni/entrypoints/openai/api_server.py
# passed

Local GPU validation

Platform: single NVIDIA B300 for offline runs and vllm serve.

30-step V2V equivalence test, 736x1280, 61 frames, seed=1, boundary_ratio=0.875:

original alibaba-pai/Wan2.2-VACE-Fun-A14B: 248.7s total, 8.3s/step
Pyros13/Wan2.2-VACE-Fun-A14B-Diffusers: 248.6s total, 8.3s/step
SHA256(original mp4) == SHA256(Pyros13 mp4)
MAE=0, RMSE=0, max pixel diff=0, PSNR=inf, mean SSIM=1.0

Pyros13 smoke test after removing original-format loader code:

BASELINE: 28.2s total, 14.1s/step  # 2 steps

Cache-DiT evidence after the fix:

Using custom cache-dit enabler for model: Wan22VACEPipeline
Calibrator Config: TaylorSeer_O(1)

Online serving validation for #4634:

POST /v1/videos/sync request 1: HTTP 200
POST /v1/videos/sync request 2: HTTP 200
GET /health after both requests: HTTP 200

Validation videos are attached in the PR discussion.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@david6666666

david6666666 commented Jun 24, 2026 •

Copy link
Copy Markdown
Collaborator Author

Validation update for Wan2.2-VACE using the supplied mkt_part_000.mp4 and alibaba-pai/Wan2.2-VACE-Fun-A14B.

Environment note: local validation was on NVIDIA B300 GPUs, so the Ascend/NPU allocator behavior from #4635 cannot be reproduced exactly here. I validated the vLLM-Omni code paths that are relevant to the fix.

30-step videos for each issue scenario:

Key local validation from the 30-step rerun:

Unit/regression checks already run:

  • pytest tests/diffusion/cache/test_cache_dit.py tests/diffusion/offloader/test_layerwise_backend.py tests/diffusion/models/wan2_2/test_wan22_vace_pipeline.py tests/entrypoints/openai_api/test_video_server.py::test_server_worker_keeps_engine_alive_until_http_shutdown -q
  • pytest tests/entrypoints/openai_api/test_video_server.py -q
  • pre-commit run --files ...

@david6666666
david6666666 marked this pull request as draft June 24, 2026 02:07
@david6666666 david6666666 changed the title [BugFix] Fix Wan2.2-VACE cache and serving lifecycle [BugFix] Fix alibaba-pai/Wan2.2-VACE-Fun-A14B cache and serving lifecycle Jun 24, 2026
@david6666666
david6666666 marked this pull request as ready for review June 24, 2026 06:24
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

david6666666 commented Jun 24, 2026 •

Copy link
Copy Markdown
Collaborator Author

Follow-up from review/testing addressed through f8f8410:

  • Switched the PR to use Pyros13/Wan2.2-VACE-Fun-A14B-Diffusers instead of adding support for the original alibaba-pai/Wan2.2-VACE-Fun-A14B layout.
  • Removed the original-format detection/key-remapping/.pth component loading code and the corresponding original-format unit tests.
  • Updated docs and recipe to point at the diffusers checkpoint.
  • Kept the actual issue fixes: VACE Cache-DiT registration, TaylorSeer calibrator passthrough, server lifecycle fix, dual-transformer VACE boundary switching, and VACE vace_blocks layerwise offload discovery.
  • Dropped the optional None block-group fallback in layerwise_backend.py; supported VACE configs include vace_layers, so vace_blocks is initialized as a real ModuleList.

Why this replacement is safe from the local validation:

Input: mkt_part_000.mp4
Resolution: 736x1280
Frames: 61
Steps: 30
Seed: 1
boundary_ratio: 0.875

alibaba-pai/Wan2.2-VACE-Fun-A14B:          248.7s total, 8.3s/step
Pyros13/Wan2.2-VACE-Fun-A14B-Diffusers:   248.6s total, 8.3s/step

SHA256(original mp4) == SHA256(Pyros13 mp4)
MAE=0, RMSE=0, max pixel diff=0, PSNR=inf, mean SSIM=1.0

Validation after cleanup:

pytest tests/diffusion/cache/test_cache_dit.py tests/diffusion/models/wan2_2/test_wan22_vace_pipeline.py tests/diffusion/offloader/test_layerwise_backend.py tests/entrypoints/openai_api/test_video_server.py::test_server_worker_keeps_engine_alive_until_http_shutdown -q
# 27 passed

pre-commit run --files docs/models/supported_models.md examples/offline_inference/vace/vace_video_generation.md recipes/Pyros13/Wan2.2-VACE-Fun-A14B-Diffusers.md tests/diffusion/cache/test_cache_dit.py tests/diffusion/models/wan2_2/test_wan22_vace_pipeline.py tests/entrypoints/openai_api/test_video_server.py vllm_omni/diffusion/cache/cache_dit_backend.py vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2_vace.py vllm_omni/diffusion/models/wan2_2/wan2_2_vace_transformer.py vllm_omni/entrypoints/openai/api_server.py
# passed

Pyros13 2-step smoke after removing original loader:
# BASELINE: 28.2s total, 14.1s/step

@lishunyang12
lishunyang12 force-pushed the codex/wan22-vace-issues branch from f9eff96 to da8cb89 Compare June 24, 2026 06:46
@david6666666 david6666666 changed the title [BugFix] Fix alibaba-pai/Wan2.2-VACE-Fun-A14B cache and serving lifecycle [BugFix] Fix Wan2.2-VACE-Fun cache and serving lifecycle Jun 24, 2026
@david6666666 david6666666 added ready label to trigger buildkite CI and removed ready label to trigger buildkite CI labels Jun 24, 2026
@Gaohan123 Gaohan123 added this to the v0.24.0 milestone Jun 24, 2026

@hsliuustc0106 hsliuustc0106 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wan2.2-VACE-Fun bugfix looks correct. All gate checks pass, regression tests cover Cache-DiT, TaylorSeer calibrator, dual-transformer switching, layerwise offload, and server lifecycle issues documented in PR description.

Ianniu123 and others added 14 commits June 25, 2026 01:47
  convert_original_to_diffusers_key rewrites original key names
  (self_attn->attn1, q->to_q, ffn.0->ffn.net.0, modulation->scale_shift_table,
  VACE before_proj/after_proj) into diffusers form at the top of
  WanTransformer3DModel.load_weights, so the existing QKV-fusion/remapping
  handles them. No-op on already-diffusers keys.

Signed-off-by: Ianniu <985683179yzy@gmail.com>
  The original release has no top-level config.json/model_index.json; its DiT
  config lives in high_noise_model/config.json (model_type=vace). Add a shared
  _looks_like_wan2_2_vace_original detector (hf_utils) and route it through both
  gates: resolve_model_config_path returns None (same default diffusion path as
  diffusers VACE), enrich_config sets WanVACEPipeline.

Signed-off-by: Ianniu <985683179yzy@gmail.com>
…eline

  For the original two-expert layout (high_noise_model/low_noise_model + .pth
  text-encoder/VAE), build via _init_original_format (S2V-style): both experts as transformer/transformer_2, the umt5-xxl tokenizer,
  and the .pth T5/VAE. convert_original_vace_config translates the VaceWanModel
  config field names to diffusers keys.

Signed-off-by: Ianniu <985683179yzy@gmail.com>
  Wan22VACEPipeline.diffuse() was written for single-transformer Wan2.1 and never
  selected an expert, so every step ran the high-noise transformer and the loaded
  low-noise transformer_2 was unused. Compute
  boundary_timestep in forward() and pick current_model per step, mirroring the
  Wan2.2 T2V/I2V pipelines.

Signed-off-by: Ianniu <985683179yzy@gmail.com>
Signed-off-by: Ianniu <985683179yzy@gmail.com>
  Add the original (non-diffusers) checkpoint to the supported-models table
  (NVIDIA-validated) and the VACE example's model list.

Signed-off-by: Ianniu <985683179yzy@gmail.com>
Signed-off-by: Ianniu <985683179yzy@gmail.com>
  Split __init__ into _init_runtime / _load_components / _finalize as a pure,
  behavior-preserving extraction. Wan22VACEPipeline's original-format path now
  reuses _init_runtime + _finalize and overrides only the component-loading
  middle (_load_components_original), removing the super(Wan22Pipeline, self)
  bypass and the duplicated init tail. T2V / T2V-DMD2 / diffusers-VACE behavior
  is unchanged.

Signed-off-by: Ianniu <985683179yzy@gmail.com>
    Narrow the original-checkpoint detector to except (OSError, ValueError);
    get_hf_file_to_dict returns None for missing configs, so only a corrupt
    config / bad repo-id or a local read error can reach the handler, while
    unexpected errors (OOM, ImportError) now propagate.

Signed-off-by: Ianniu <985683179yzy@gmail.com>
Signed-off-by: Ianniu <985683179yzy@gmail.com>
Signed-off-by: david6666666 <530634352@qq.com>
Signed-off-by: david6666666 <530634352@qq.com>
Signed-off-by: david6666666 <530634352@qq.com>
Signed-off-by: david6666666 <530634352@qq.com>
@lishunyang12
lishunyang12 force-pushed the codex/wan22-vace-issues branch from f8f8410 to 5804d89 Compare June 25, 2026 01:49
@david6666666 david6666666 added ready label to trigger buildkite CI and removed ready label to trigger buildkite CI labels Jun 25, 2026
@david6666666
david6666666 merged commit d941086 into vllm-project:main Jun 25, 2026
9 checks passed
khairulkabir1661 pushed a commit to khairulkabir1661/vllm-omni that referenced this pull request Sep 25, 2026
…t#4667)

Signed-off-by: Ianniu <985683179yzy@gmail.com>
Signed-off-by: david6666666 <530634352@qq.com>
Co-authored-by: Ianniu <985683179yzy@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready label to trigger buildkite CI

Projects

None yet

5 participants