6.6 KiB
Causal-Forcing in FastVideo: Clean-History Teacher Forcing + Causal Consistency Distillation
Adds two of the critical Wan-parity gaps identified vs thu-ml/Causal-Forcing:
Stage-1 clean-history Teacher Forcing (TF) and Stage-2b Causal Consistency
Distillation (CD / Causal-Forcing++). Implemented in the modular fastvideo/train/
stack, reusing existing abstractions; the legacy fastvideo/training/ stack is
untouched.
What was added
1. DiT: clean-history teacher-forcing path
fastvideo/models/dits/causal_wanvideo.py
_prepare_teacher_forcing_mask(...)— ported from Causal-Forcingwan/modules/causal_model.py:569. Builds a FlexAttention mask over the concatenated[clean | noisy]sequence (length2 * num_frames * frame_seqlen): a noisy block attends to its own noisy tokens plus the clean context of all strictly previous blocks (+ diagonal)._forward_train(..., clean_x=None, aug_t=None)— whenclean_xis provided: patch-embeds the clean latents, prepends them to the noisy tokens, tiles RoPE and the per-frame timestep modulation so clean frame i and noisy frame i share the same position / embedding (clean frames are time-embedded ataug_t, default 0), runs the blocks under the TF mask, then drops the clean half beforenorm_out(loss is denoise-only on the current/noisy tokens). The diffusion-forcing path is unchanged. A separateteacher_forcing_block_maskis cached so the two masks never collide.
2. Wrapper plumbing
fastvideo/train/models/wan/wan.py
predict_noise(..., clean_x=None, aug_t=None)and_build_distill_input_kwargs(...)forwardclean_x/aug_tto the transformer (permutingclean_xto[B,C,F,H,W]). The streaming/KV-cache path is untouched.
3. Teacher-Forcing SFT method (Stage 1)
fastvideo/train/methods/fine_tuning/tfsft.py — TeacherForcingSFTMethod, a thin
subclass of DiffusionForcingSFTMethod. Identical objective (inhomogeneous per-chunk
timesteps, flow MSE, bsmntw weighting) except it passes clean_x=clean_latents. The
only change to dfsft.py is extracting the predict call into an overridable
_predict_noise(...) hook (behavior-preserving for DFSFT).
4. Causal Consistency Distillation method (Stage 2b)
fastvideo/train/methods/consistency_model/causal_cd.py —
CausalConsistencyDistillationMethod, ported from Causal-Forcing
model/naive_consistency.py. Per step:
- Sample a discrete index over a
discrete_cd_N-step flow-match schedule →(t, t_next). - Teacher (frozen, teacher-forced) does a single CFG Euler step
latent_t → latent_t_next = latent_t - dt·[v_uncond + g·(v_cond - v_uncond)],dt = (t - t_next)/num_train_timesteps. - Student (trainable, teacher-forced) predicts
x0att. - EMA student (frozen, teacher-forced) predicts
x0att_next. - Loss
= MSE(x0_t, x0_t_next); EMA is lerp-updated after each optimizer step.
Roles: student (trainable), teacher and ema (frozen) — all initialized from the
same checkpoint, matching the reference's three-network setup.
5. Configs, tests, registration
- Smoke tests (mirror
test_wan_causal_dfsft.py, real Wan-1.3B + tiny synthetic data):fastvideo/tests/train/methods/test_wan_causal_tfsft.py,.../test_wan_causal_cd.py, with fixturesfastvideo/tests/train/fixtures/wan_causal_t2v_{tfsft,causal_cd}_min.yaml. - Example run configs:
examples/train/configs/fine_tuning/wan/tfsft_causal_t2v.yaml,examples/train/configs/consistency_model/wan/causal_cd_t2v.yaml. - Registered in
fastvideo/train/methods/__init__.py,.../fine_tuning/__init__.py,.../consistency_model/__init__.py.
Running the smoke tests
conda activate FastVideo_kaiqin
export PYTHONPATH=$PWD # from the FastVideo_cf clone
pytest fastvideo/tests/train/methods/test_wan_causal_tfsft.py -q
pytest fastvideo/tests/train/methods/test_wan_causal_cd.py -q
Both require CUDA and the cached Wan-AI/Wan2.1-T2V-1.3B-Diffusers weights. Each runs
one real train step and asserts finite loss + nonzero student gradients reaching the
first transformer block (CD additionally asserts a frozen teacher and a working EMA
update). Status: both pass on GB200.
For W&B logging on a real run, set WANDB_API_KEY in the environment (do not commit
keys) and add a training.tracker block (see the example configs).
Assumptions & deviations from the reference
- Discrete CD schedule. The reference builds its own
FlowMatchScheduler(shift=5, extra_one_step=True).set_timesteps(discrete_cd_N). Here we sub-samplediscrete_cd_Npoints from the student'sFlowMatchEulerDiscreteScheduler.timestepsand reuse the reference's Euler conventiondt = (t - t_next)/num_train_timesteps. The shift-vs-linear sigma parameterization is therefore approximate in exactly the same way the reference's/1000Euler step is — internally consistent, but not a bit-exact reproduction of the reference scheduler. Tunediscrete_cd_N/flow_shiftfor a real run. - EMA as an explicit role, not a deepcopy. The reference keeps
generator_emaand updates it via an external EMA tracker (ema_model.copy_to). FSDPfully_shardforbidsdeepcopy, so the EMA is a third role model loaded from the same checkpoint and lerp-updated in place (optimizers_schedulers_step). This is FSDP-safe and the EMA shards align with the student's. It does cost a third full model copy (as the reference also effectively does). It is not integrated with FastVideo'sEMACallback(which is export/inference-only); a production setup may want to unify these. aug_tnoise augmentation of the clean context (referencenoise_augmentation_max_timestep) is plumbed through the DiT (aug_t) but the TF method passesaug_t=None(clean context at timestep 0), matching the reference's default. CD also uses clean (un-augmented) context.- Chunk vs frame granularity is the existing
num_frame_per_blockknob (1 = frame, 3 = chunk); both TF and CD honor it. There is still no shipped Wan framewise checkpoint/recipe (orthogonal to this change). - CFG uncond text for the teacher comes from the student's negative-prompt
conditioning (
unconditional_dict), as in the reference.
Not implemented (out of scope for this change)
- Stage-2a Causal ODE init /
blockwise_kvdata curation (the CD branch is the ODE-data-free alternative). - Stage 3 asymmetric DMD changes, 1/2-step few-step (ASD first-chunk), SiD/GAN.
- Native frame-wise I2V architecture, Rolling-Forcing long video, TAEHV/TRT decode.
--use_emaselection at standalone inference. See../CAUSAL_FORCING_PARITY_GAP_ANALYSIS.mdfor the full gap list and priorities.