hugging-apps/minimax-h3-flashgen-4step

Space

30

stars

17

commits

1

linked in READMEs

Aug 26, 2026

updated

gradio

README

MiniMax-H3 4-Step FlashGen LoRA

A demo of the FlashGen 4-step distillation LoRA applied to MiniMax-H3, MiniMax's 33B omni-modal model that generates video with native stereo audio.

The FlashGen LoRA uses distribution-matching distillation (DMD2 / VSD, data-free) to reduce inference from ~20 steps to just 4 steps — approximately a 5x speedup. The distilled base_schedule [1.0, 0.7, 0.4, 0.15, 0.0] replaces the uniform linspace(1, 0, num_inference_steps) grid MiniMaxH3Scheduler.set_timesteps would otherwise build, and H3's per-modality exponential sigma shift still applies on top of it — a single base schedule can serve both modalities precisely because it is pre-shift. So the video scheduler runs σ 1 → 0.9655 → 0.8889 → 0.6792 → 0 (shift = 12.0) and the audio scheduler σ 1 → 0.875 → 0.6667 → 0.3462 → 0 (shift = 3.0). Each shifted grid is injected through MiniMaxH3Scheduler.set_timesteps(sigmas=...), which takes it verbatim, and pinned onto its scheduler, because the pipeline's own denoise step calls set_timesteps(num_inference_steps, ...) again — and for this scheduler num_inference_steps counts sigma grid points (terminal 0.0 included), so it runs len(sigmas) - 1 model evaluations. Pinning is the runtime equivalent of merge_lora_ckpt.py writing _minimax_h3.base_schedule into model_index.json. Each generation reports the number of Euler steps the scheduler actually took, read back off scheduler.step_index, rather than a hardcoded 4.

How it works

PieceWhat runs here
TransformerMiniMaxH3Transformer3DModel — the 33B / 50-block H3 DiT, bf16, with the FlashGen LoRA folded in
VAEsAutoencoderKLMiniMaxH3 (video) + AutoencoderKLMiniMaxH3Audio (audio), float32
SchedulersMiniMaxH3Scheduler with the 4-step distilled base_schedule [1.0, 0.7, 0.4, 0.15, 0.0] under each modality's own shift (video 12.0, audio 3.0)
ConditioningDelegated to multimodalart/qwen3vl-conditioner over the gradio API (the 62 GB Qwen3-VL text encoder does not fit alongside the transformer on a single ZeroGPU worker)

How the LoRA is applied

The LoRA repo ships its own merge script, merge_lora_ckpt.py, and this Space follows it rather than a default diffusers LoRA load. The adapter is merged into the base weights at startup — W' = W + scale * (lora_B @ lora_A), accumulated in fp32, at scale = lora_alpha / rank = 1.0 (FlashGen's alpha equals its rank of 64) — instead of being attached as a runtime PEFT adapter, and all 259 LoRA targets are required to resolve or startup fails, exactly as the reference script does.

The reference script merges into the original MiniMax-H3 partition, whose keys are the LoRA's own (blocks.N.attn.qkv_proj.weight, mlp.fc1/fc2, attn.out_proj, adaln_proj.linear). Merging into the diffusers port instead requires replaying the same layout transforms convert_minimax_h3_to_diffusers.py applied to the base weights, because a delta is only valid in the layout of the weight it is added to:

Original LoRA targetdiffusers parameterTransform
blocks.N.… / token_refiner.blocks.N.…transformer_blocks.N.… / token_refiner.refiner_blocks.N.…rename
attn.out_projattn.to_out.0rename
mlp.fc2ff.net.2rename
final_layer.adaln_proj.linearnorm_out.linearrename
adaln_proj.linearadaln_proj.linearidentity
mlp.fc1ff.net.0.projfused halves swapped, [gate; value][value; gate] for diffusers' SwiGLU
attn.qkv_projattn.to_q / to_k / to_vde-interleave the per-head rows ([head0: q k v, head1: q k v, …][q_all; k_all; v_all]), then split thirds

That last row is the one that is easy to get wrong: the checkpoint's fused QKV rows are per-head interleaved, so splitting them into contiguous thirds — the naive reading — scatters every head's q/k/v across all three projections and turns the adapter into noise on all 52 attention blocks. With the de-interleave in place, the merged weights reproduce merge_lora_ckpt.py-then-convert to within bf16 rounding.

License

MiniMax-H3 is covered by the MiniMax H3 Community License Agreement. The FlashGen LoRA is Apache-2.0. Read both before using any output of this Space.

Contributors

multimodalart

17 commits

hugging-apps/minimax-h3-flashgen-4step

Space

30

stars

17

commits

1

linked in READMEs

Aug 26, 2026

updated

gradio

README

MiniMax-H3 4-Step FlashGen LoRA

A demo of the FlashGen 4-step distillation LoRA applied to MiniMax-H3, MiniMax's 33B omni-modal model that generates video with native stereo audio.

The FlashGen LoRA uses distribution-matching distillation (DMD2 / VSD, data-free) to reduce inference from ~20 steps to just 4 steps — approximately a 5x speedup. The distilled base_schedule [1.0, 0.7, 0.4, 0.15, 0.0] replaces the uniform linspace(1, 0, num_inference_steps) grid MiniMaxH3Scheduler.set_timesteps would otherwise build, and H3's per-modality exponential sigma shift still applies on top of it — a single base schedule can serve both modalities precisely because it is pre-shift. So the video scheduler runs σ 1 → 0.9655 → 0.8889 → 0.6792 → 0 (shift = 12.0) and the audio scheduler σ 1 → 0.875 → 0.6667 → 0.3462 → 0 (shift = 3.0). Each shifted grid is injected through MiniMaxH3Scheduler.set_timesteps(sigmas=...), which takes it verbatim, and pinned onto its scheduler, because the pipeline's own denoise step calls set_timesteps(num_inference_steps, ...) again — and for this scheduler num_inference_steps counts sigma grid points (terminal 0.0 included), so it runs len(sigmas) - 1 model evaluations. Pinning is the runtime equivalent of merge_lora_ckpt.py writing _minimax_h3.base_schedule into model_index.json. Each generation reports the number of Euler steps the scheduler actually took, read back off scheduler.step_index, rather than a hardcoded 4.

How it works

PieceWhat runs here
TransformerMiniMaxH3Transformer3DModel — the 33B / 50-block H3 DiT, bf16, with the FlashGen LoRA folded in
VAEsAutoencoderKLMiniMaxH3 (video) + AutoencoderKLMiniMaxH3Audio (audio), float32
SchedulersMiniMaxH3Scheduler with the 4-step distilled base_schedule [1.0, 0.7, 0.4, 0.15, 0.0] under each modality's own shift (video 12.0, audio 3.0)
ConditioningDelegated to multimodalart/qwen3vl-conditioner over the gradio API (the 62 GB Qwen3-VL text encoder does not fit alongside the transformer on a single ZeroGPU worker)

How the LoRA is applied

The LoRA repo ships its own merge script, merge_lora_ckpt.py, and this Space follows it rather than a default diffusers LoRA load. The adapter is merged into the base weights at startup — W' = W + scale * (lora_B @ lora_A), accumulated in fp32, at scale = lora_alpha / rank = 1.0 (FlashGen's alpha equals its rank of 64) — instead of being attached as a runtime PEFT adapter, and all 259 LoRA targets are required to resolve or startup fails, exactly as the reference script does.

The reference script merges into the original MiniMax-H3 partition, whose keys are the LoRA's own (blocks.N.attn.qkv_proj.weight, mlp.fc1/fc2, attn.out_proj, adaln_proj.linear). Merging into the diffusers port instead requires replaying the same layout transforms convert_minimax_h3_to_diffusers.py applied to the base weights, because a delta is only valid in the layout of the weight it is added to:

Original LoRA targetdiffusers parameterTransform
blocks.N.… / token_refiner.blocks.N.…transformer_blocks.N.… / token_refiner.refiner_blocks.N.…rename
attn.out_projattn.to_out.0rename
mlp.fc2ff.net.2rename
final_layer.adaln_proj.linearnorm_out.linearrename
adaln_proj.linearadaln_proj.linearidentity
mlp.fc1ff.net.0.projfused halves swapped, [gate; value][value; gate] for diffusers' SwiGLU
attn.qkv_projattn.to_q / to_k / to_vde-interleave the per-head rows ([head0: q k v, head1: q k v, …][q_all; k_all; v_all]), then split thirds

That last row is the one that is easy to get wrong: the checkpoint's fused QKV rows are per-head interleaved, so splitting them into contiguous thirds — the naive reading — scatters every head's q/k/v across all three projections and turns the adapter into noise on all 52 attention blocks. With the de-interleave in place, the merged weights reproduce merge_lora_ckpt.py-then-convert to within bf16 rounding.

License

MiniMax-H3 is covered by the MiniMax H3 Community License Agreement. The FlashGen LoRA is Apache-2.0. Read both before using any output of this Space.

Contributors

multimodalart

17 commits