Nodes/BSAI-ComfyUI-MiniMax-H3-PDD-Acc/MiniMax H3 PDD Acc LoRA (Apply)
ComfyUI Node

MiniMax H3 PDD Acc LoRA (Apply)

A Plain LoRA Loader Will Load This File and Quietly Throw Half of It Away

By xm6018924·Created about a month ago·Updated 8 days ago· 4
MiniMax H3 PDD Acc LoRA (Apply)
  • model
  • bypass_sigmas
  • model
  • sigmas
  • info
◄pdd_file▾►
◄nfe8►
◄lora_strength1.00►
◄head_strength1.00►
◄on_off_griderror►
◄partition►
◄enabledtrue►
◄partition_checkerror►

The MiniMax-H3 acceleration LoRAs from alibaba-pai are the reason an H3 clip takes seconds per step instead of a coffee break - 8 sampler steps, no CFG. And they are not normal LoRAs. Load one with LoraLoaderModelOnly and you get a mostly-working, faintly worse video, because the file carries two things and a standard loader only knows what to do with one.

This node is the whole reason the pack exists.

Two things in one file

First, a rank-64 trunk LoRA in diffusers naming. ComfyUI's UNet naming doesn't match any of that, so the node rewrites keys in memory when you hand it an original-format file: q/k/v fuse into one attn.qkv_proj (concatenated A, block-diagonal B, alpha ×3), the FFN projection gets the [value;gate] → [gate;value] half-swap, to_out.0 becomes attn.out_proj. Nothing you have to think about, but it's why the raw HuggingFace files work as-is.

Second - and this is the part a normal loader silently drops - a Parallel Decoding Distillation head bank: 32 per-fine-interval copies of the final-layer video and audio projections. The node fuses those 32 heads down to nfe fp32 heads at load, then swizzles final_layer's forward per sampling step, choosing the right head by sigma. Because it's armed by sigma rather than by a step counter, chunked sampling, resumes and split schedules can't desync it.

That's also the answer to "why 8 steps and not more". Eight is the trained block size. This is the same wall every distilled model hits - as the KB's distillation doc puts it, a model trained to denoise in a specific number of jumps doesn't improve with more jumps, it gets artifacts.

The inputs you'll touch

| What | Set it to | |---|---| | model | your H3 UNET | | pdd_file | the file in ComfyUI/models/pdd_acc/ | | nfe | 8 (trained), 4 (two blocks per step), 6 (the non-uniform 8,8,4,4,4,4) | | lora_strength / head_strength | 1.0 / 1.0 |

nfe is the one that matters. Only block sizes 4 and 8 exist in the training envelope, and the node refuses anything outside it rather than letting it render as noise - community bug reports of "H3 acc LoRA gives heavy noise at 32 steps" are exactly this, not an attention-backend problem. partition lets you spell the blocks out by hand (comma-separated, summing to 32, e.g. 8,8,4,4,4,4 for six steps) and overrides nfe.

Then the safety rails, which are more useful than they sound. on_off_grid defaults to refusing evaluation at sigmas that aren't trained block boundaries - that's your wrong-sampler alarm going off, with a message telling you what to fix; clamp snaps to the nearest block and degrades quietly instead. partition_check catches the nastiest silent failure in this model family: FL2VA and Ref2VA trunks share identical tensor key sets, so pairing an FL2VA file with a ref2va UNET applies cleanly and renders wrong. It fingerprints the loaded model's final_layer.video_out.weight and errors on a confident mismatch; warn continues for deliberate experiments, off disables the check entirely. enabled plus bypass_sigmas is a full A/B switch - set false and you must wire a schedule for the un-distilled model, or the node refuses.

Outputs: model into your guider, sigmas into SamplerCustomAdvanced, and info - a string telling you which format it detected and how many heads fused. Wire it to a PreviewAny once; it's the fastest diagnosis you'll get.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/xm6018924/BSAI-ComfyUI-MiniMax-H3-PDD-Acc

Restart. models/pdd_acc/ is created on first launch - drop either the original alibaba-pai files or the pre-converted ComfyUI ones there; both load. Dependencies are just torch, safetensors, numpy. This is a fork of the original pack (which the README's own install block still links), with a compat layer and renamed enum options; old workflows saved with the old error value map over automatically.

The recipe, and the traps

euler. CFG 1.0 via BasicGuider. SigmaShift 12/3 exactly - the node fails closed otherwise, because the heads are trained on those grids. Remove any other distill LoRA (turbo, lightning) since distills don't stack, and don't put a step-caching pack in the chain; the final-layer patch fails closed and an 8-step render has nothing to cache anyway. Character LoRAs stack fine.

Two traps worth flagging. First, pruned checkpoints: a Comfy-Org *_pruned_* UNET replaces the dense adaln with a curve table, and ordinary loaders spam ~50 adaln_proj errors while dropping that slice of the distill. This pack rebases those modules onto the model's curve basis. Second, lora_strength 0.0 is baked-trunk mode - correct only for a checkpoint pre-merged with bake_pdd_trunk.py. On an unbaked trunk it renders the un-distilled model with PDD heads attached and nothing can detect that, so check the file's metadata before you trust it.

And the room-level caveat: H3's weights are under a community licence that excludes the US, EU, UK and Korea, outputs included. Worth knowing before you build a workflow around it.

Categorymodel/patch/minimax

Inputs (10)

NameTypeDefaultDescription
modelMODEL—
pdd_fileCOMBOPDD Acc file from models/pdd_acc — the original alibaba-pai release or a converted ComfyUI copy, both load. Pair FL2VA with an fl2va UNET, Ref2VA with ref2va.
nfeCOMBO8Model evaluations (sampler steps). 8 = trained block size 4. 4 regroups two blocks per step (faster, official); 6 uses the non-uniform default partition 8,8,4,4,4,4. Higher step counts are OFF the training envelope and render as noise.
lora_strengthFLOAT1.00-2–2Trunk LoRA strength. Trained at 1.0. 0.0 = baked-trunk mode: skip trunk patching entirely for a checkpoint pre-merged with bake_pdd_trunk.py (heads still apply).
head_strengthFLOAT1.000–2PDD head blend: native + s*(pdd - native). 1.0 = trained path (native head not evaluated).
on_off_gridCOMBOerrorWhat to do when the model is evaluated at a sigma that is not a trained block boundary (wrong sampler/scheduler).
partitionoptSTRINGCustom block sizes in fine steps, comma-separated, summing to 32 (e.g. '8,8,4,4,4,4' = 6 steps, or '8,4,4,4,4,4,4' = 7). Overrides nfe. Only sizes 4 and 8 are accepted — the trained envelope; other sizes render as noise and are rejected.
enabledoptBOOLEANtrueFalse = full bypass: the input model and bypass_sigmas pass through untouched (nothing is loaded or patched). Wire bypass_sigmas with the schedule for the un-distilled model.
bypass_sigmasoptSIGMASReturned as the sigmas output when enabled=False (e.g. a BasicScheduler for the base model). Ignored when enabled.
partition_checkoptCOMBOerrorfl2va and ref2va share identical key sets, so an FL2VA file on a ref2va UNET (or vice versa) applies cleanly and renders silently wrong. The loaded model's trunk is identified from its final_layer.video_out fingerprint; a confident mismatch errors. 'warn' continues anyway (deliberate cross-trunk experiments). 'off' = disable the model-type analysis entirely: the fingerprint check never runs, so nothing errors or warns about a mispairing.

Outputs (3)

NameTypeDescription
modelMODEL—
sigmasSIGMAS—
infoSTRING—