Skip to content

[feat] Route FastWan 5B FullAttn through dense attention - #1888

Open
fusheng-ji wants to merge 5 commits into
hao-ai-lab:mainfrom
fusheng-ji:feat/fastwan-5b-fullattn
Open

fusheng-ji wants to merge 5 commits into
hao-ai-lab:mainfrom
fusheng-ji:feat/fastwan-5b-fullattn

Conversation

@fusheng-ji

@fusheng-ji fusheng-ji commented Sep 25, 2026 •

Copy link
Copy Markdown

Purpose

The FastWan 2.2 5B FullAttn checkpoint needs dense attention and supports
text-to-video only. Its existing shared routing can select VSA or silently
accept image conditioning, while Wan block construction and denoising metadata
can resolve different attention backends for the same component.

Related to #864. This independently addresses the FullAttn runtime guards in
#1563 and overlaps backend-selection work in #1494. The implementation adds
metadata-first detection and per-component backend propagation; I am happy to
coordinate or consolidate if maintainers prefer.

Changes

  • Register the FullAttn ID and legacy alias as a T2V-only Wan variant using
    model_index.json metadata before name-based fallbacks.
  • Reject I2V and VSA requests for that variant before loading weights.
  • Carry the resolved component backend into Wan blocks, attention layers, and
    denoising metadata so construction and execution agree.
  • Keep the existing FullAttn-to-VSA LoRA training recipe usable by selecting
    the existing VSA-capable 5B config only for that training case; the student
    uses VSA while teacher/critic remain dense. FullAttn inference still rejects
    VSA and I2V.
  • Add weight-free API/loader/training regressions, correct the support matrix's
    T2V-only listing, and make the inference guide invoke the real 5B CLI config.

Test Plan

pre-commit run --all-files
pytest fastvideo/tests/api/test_fastwan_fullattn.py \
  fastvideo/tests/api/test_wan_definitions.py \
  fastvideo/tests/api/test_attention_selector_resolution.py \
  fastvideo/tests/stages/test_wan_denoising.py \
  fastvideo/tests/stages/test_wan_dmd_denoising.py \
  fastvideo/tests/stages/test_wan_causal_denoising.py \
  fastvideo/tests/stages/test_wan_pipeline_wiring.py \
  fastvideo/tests/attention/test_sdpa_metadata_mask_contract.py \
  fastvideo/tests/loader/test_wan_family_imports.py \
  fastvideo/tests/train/utils/test_config.py \
  fastvideo/tests/train/utils/test_moduleloader_attention_backend.py -q

GPU validation used the pinned official checkpoint revision
3e187042a324f6f5fb68fd22110a78725253de8f, a private
FlashAttention-2 2.8.1 overlay, and CUDA_VISIBLE_DEVICES resource checks.
The current independent quality comparison ran unchanged official
main@e90be598 and candidate ecd22f5b on the same B200 with the same
prompt, seed 1024, three DMD steps, 704×1280, 24 fps, FlashAttention-2 and
compile enabled. A historical num_frames=104 request on the previous
8760eb7a baseline produced 101 native frames on both sides.

Why the 104-frame deliverable is cropped

The current Wan path compresses time by a factor of four: a request for N
frames prepares floor((N - 1) / 4) + 1 latent frames, and the VAE decodes
those latents to 4 * (latent_frames - 1) + 1 frames. Native decoded lengths
therefore have the form 4k + 1. Requesting 104 gives 26 latent frames
and 101 decoded frames; requesting 105 gives 27 latent frames and
105 decoded frames. There is no native 104-frame output in this unchanged path.

To deliver exactly 104 frames without changing Wan's VAE or the public
inference behavior, we generate the next valid native length (105) and keep
the first 104 decoded frames, dropping only the last frame. We apply this
identical local postprocessing to official main and the candidate, retain
both 105-frame originals, and verify that every retained frame has identical
decoded pixels to its source. This is a validation/output-format step, not a
claim that Wan natively supports 104 frames. The 104-frame and full 105-frame
MS-SSIM comparisons passed both on the historical 8760eb7a baseline and
on the current rebased official main@e90be598 baseline.

Test Results

  • Current rebased branch validated and pushed to the fork. The candidate
    render record binds clean HEAD ecd22f5b against clean official
    main@e90be598; both use the same fixed checkpoint and environment.
  • pre-commit run --all-files: all hooks passed on an underscore-named
    temporary worktree at clean HEAD ecd22f5b, including mypy. The original
    fastwan-fullattn directory name alone trips mypy's invalid package-name
    check.
  • Focused 11-file CPU suite on the rebased branch: 229 passed, 0 failed,
    0 skipped, 14 warnings
    in 539.96s. Optional GPU kernels were
    stubbed under CUDA_VISIBLE_DEVICES='' for parent and fresh child Python
    processes; the stubs fail if actually called. The additional tests cover
    case-insensitive manifest matching and strict rejection of integer 1 as a
    boolean marker. New API and training tests are collected by the existing
    Buildkite unit directories.
  • Current official main@e90be598 and candidate ecd22f5b each generated
    a decodable native 105-frame, 1280×704, 24-fps video on the same B200
    GPU 0
    with identical pinned weights, prompt, seed 1024, three DMD steps,
    FlashAttention-2 and Torch Compile. Both source trees were clean; effective
    backend and checkpoint were confirmed. Sampled own-process peak GPU memory
    was 37,236 MiB for main and 38,962 MiB for candidate, with no
    pressure stop. The two native MP4 files have the same SHA-256.
  • Current same-main comparison: each native video was separately losslessly cropped
    to its first 104 frames using the same libx264 -qp 0 settings. Full
    decode and ffprobe confirmed 105/104 frames, 1280×704, 24 fps on both
    sides; every retained frame's decoded-pixel checksum equals its own native
    source frame. The two cropped MP4 files are byte-identical. Repository
    MS-SSIM over all 104 cropped frames was mean/min/max 1.000000;
    over all 105 native frames it was also mean/min/max 1.000000, including
    frame 105. Both exceed the predeclared 0.93 mean threshold. CPU-hidden
    comparison records retain every per-frame score; no public CI reference was
    uploaded.
  • Earlier focused validation also passed: single-B200 49-frame dense
    TORCH_SDPA and FlashAttention-2 renders; a synthetic FullAttn-to-VSA LoRA
    forward/backward with finite loss and finite, nonzero trainable gate
    gradients; and two-B200 sp_size=2 FlashAttention-2 generation whose
    49-frame output matched the single-B200 render (MS-SSIM 1.000000). These
    focused runs predate the current-main rebase; the full-size independent
    comparison above uses the current clean candidate and official main.

Checklist

  • I ran pre-commit run --all-files and fixed all issues
  • I added or updated tests for my changes
  • I updated documentation, including the support matrix and working 5B CLI example
  • I considered GPU memory impact: existing tensor/kernel paths are
    unchanged; selecting dense FullAttn can use more memory than VSA

For model/pipeline changes:

  • I verified local MS-SSIM parity against unchanged official
    main@e90be598: mean 1.000000 ≥ 0.93 for both the 104 cropped frames
    and all 105 native frames, including the final frame.
  • I corrected the FullAttn support matrix and linked the runnable
    5B CLI guide.

Register the FullAttn checkpoint as a T2V-only Wan variant and reject incompatible sparse attention or image-conditioning requests at load time.

Carry the resolved per-component attention backend through Wan block construction and denoising metadata. Add API regressions and inference documentation.
…config

When a FullAttn checkpoint is trained with VSA sparsity, select the
VSA-capable FastWan 5B pipeline config for the student while keeping
dense FullAttn inference guards unchanged.
Replace the 1.3B basic_dmd example with the existing 5B DMD YAML and
document the FullAttn-to-VSA LoRA training exception.
Explain metadata-first routing, dense attention propagation, and the FullAttn-to-VSA training exception. Keep manifest matching semantics while making the checks and regressions easier to read.
@mergify mergify Bot added type: feat New feature or capability scope: training Training pipeline, methods, configs scope: inference Inference pipeline, serving, CLI scope: attention Attention backends (VSA, STA, Flash, etc.) scope: infra CI, tests, Docker, build scope: docs Documentation scope: model Model architecture (DiTs, encoders, VAEs) labels Sep 25, 2026
@mergify

mergify Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Merge Protections

🔴 1 of 1 protections blocking · waiting on 👀 reviews and 🤖 CI

Protection Waiting on
🔴 PR merge requirements 👀 reviews and 🤖 CI

🔴 PR merge requirements

Waiting for

  • #approved-reviews-by>=1
  • check-success=fastcheck-passed
  • check-success=full-suite-passed
  • check-success~=pre-commit
This rule is failing.
  • #approved-reviews-by>=1
  • check-success=fastcheck-passed
  • check-success=full-suite-passed
  • check-success~=pre-commit
  • title~=(?i)^\[(feat|feature|bugfix|fix|refactor|perf|ci|doc|docs|misc|chore|kernel|new.?model|skill|skills|infra)\]

@fusheng-ji
fusheng-ji marked this pull request as ready for review September 25, 2026 16:52
@greptile-apps

greptile-apps Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 3/5

[Medium risk] Adds dense attention routing for a video model variant.

The PR is not ready to merge because the FullAttn T2V-only guard can silently discard an image or allow an override that fails during denoising.

Findings

  1. P1 Image input is silently ignored ▶
  2. P1 Override re-enables unsupported conditioning ▶
Fix with agent prompt
### Issue 1
fastvideo/models/wan/pipeline_config.py:306-308
A T2V request can still include `image_path`, but this guard checks only the workload label. Input validation loads the image, while `WanDMDPipeline` has no first-frame encoding stage and this config disables TI2V conditioning. The request therefore returns a text-only video without warning the caller that its image was ignored.

### Issue 2
fastvideo/models/wan/pipeline_config.py:306-309
`FastVideoArgs.from_kwargs(model_path=FULL, workload_type="t2v", ti2v_task=True)` applies `ti2v_task` after this config’s `__post_init__`, but the guard does not check the resulting value. If that request includes an image, Wan denoising expects a first-frame latent that `WanDMDPipeline` never prepared and fails instead of rejecting the unsupported configuration up front.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

The PR registers the FastWan 5B FullAttn checkpoint as a dense, T2V-only variant, propagates per-component attention decisions into Wan construction and denoising metadata, preserves a separate VSA training configuration, and updates tests and inference documentation.

  • The FullAttn workload guard still permits an image supplied with a T2V request and permits a direct ti2v_task argument override.
  • Greptile automatically discovered a related ticket that helped explain the purpose of this PR: Wan attention layers can select inconsistent backends when support is declared differently across layers.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Model ID or manifest] --> B[FullAttn pipeline config]
  B --> C[FastVideoArgs overrides and runtime validation]
  C --> D[Transformer loader]
  D --> E[Wan attention blocks]
  E --> F[Denoising metadata]
  C --> G[WanDMDPipeline request stages]
Loading

Reviews (1) · Last reviewed commit: "[docs] Correct FastWan FullAttn guide an..."

Comment on lines +306 to +308
if workload != "t2v":
raise ValueError(f"FastWan2.2-TI2V-5B-FullAttn does not support workload type {workload!r}; "
"supported workload: 't2v'.")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Image input is silently ignored A T2V request can still include image_path, but this guard checks only the workload label. Input validation loads the image, while WanDMDPipeline has no first-frame encoding stage and this config disables TI2V conditioning. The request therefore returns a text-only video without warning the caller that its image was ignored.

Prompt To Fix With AI
This is a comment left during a code review.
Path: fastvideo/models/wan/pipeline_config.py
Line: 306-308

Comment:
**Image input is silently ignored** A T2V request can still include `image_path`, but this guard checks only the workload label. Input validation loads the image, while `WanDMDPipeline` has no first-frame encoding stage and this config disables TI2V conditioning. The request therefore returns a text-only video without warning the caller that its image was ignored.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +306 to +309
if workload != "t2v":
raise ValueError(f"FastWan2.2-TI2V-5B-FullAttn does not support workload type {workload!r}; "
"supported workload: 't2v'.")
if coerce_attn_backend(attention_backend) is AttentionBackendEnum.VIDEO_SPARSE_ATTN:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Override re-enables unsupported conditioning FastVideoArgs.from_kwargs(model_path=FULL, workload_type="t2v", ti2v_task=True) applies ti2v_task after this config’s __post_init__, but the guard does not check the resulting value. If that request includes an image, Wan denoising expects a first-frame latent that WanDMDPipeline never prepared and fails instead of rejecting the unsupported configuration up front.

Prompt To Fix With AI
This is a comment left during a code review.
Path: fastvideo/models/wan/pipeline_config.py
Line: 306-309

Comment:
**Override re-enables unsupported conditioning** `FastVideoArgs.from_kwargs(model_path=FULL, workload_type="t2v", ti2v_task=True)` applies `ti2v_task` after this config’s `__post_init__`, but the guard does not check the resulting value. If that request includes an image, Wan denoising expects a first-frame latent that `WanDMDPipeline` never prepared and fails instead of rejecting the unsupported configuration up front.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: attention Attention backends (VSA, STA, Flash, etc.) scope: docs Documentation scope: inference Inference pipeline, serving, CLI scope: infra CI, tests, Docker, build scope: model Model architecture (DiTs, encoders, VAEs) scope: training Training pipeline, methods, configs type: feat New feature or capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant