PM LoRA Stack Decompose
The node that gets LoRAs ready to merge — PM LoRA Stack Decompose
- key_dicts
- block_selection
- LoRATensors
Merge algorithms don't care about "LoRAs" - they care about numbers: the low-rank up and down matrices that make up each layer. This node is the translator. It takes the LoRAStack from any stacker, pulls each LoRA into its (up, down, alpha) components per layer, and hands the merger something it can actually do math on. In the pack's pipeline it's the step between stack and merge, and the step most people skip to their regret.
It also solves the problem that makes LoRA merging fail in practice: LoRAs of different ranks. Try to add a rank-16 LoRA and a rank-64 LoRA element-wise and you get a shape error. The decompose node reconciles ranks automatically via SVD, which is what lets you merge a mixed-rank collection at all.
How it works
It decomposes each layer into its tensor components. When ranks differ, it uses the chosen decomposition_method to reconcile them to a common rank. There's hash-based caching - rerun with unchanged inputs and it skips the expensive decomposition. It auto-detects the architecture (SD vs DiT, and the rest of the six supported) so the key handling is right without you telling it.
The inputs that matter
key_dicts- theLoRAStackfrom a stacker.decomposition_method-rSVD(randomized SVD, the recommended default),energy_rSVD(prunes low-energy components first; best for DiT/large LoRAs),SVD(full, slow but exact), ornone(fastest, but hard-fails if ranks don't match).svd_rank- the target rank after decomposition. Default −1 keeps the first LoRA's rank; set a value to force all of them to it. Lower rank = smaller, weaker merge.device- where to run the decomposition. It always uses float32 internally for stability, then converts back.
Output is LoRATensors - the decomposed components the merger consumes, along with the strengths it carries.
Installing
Part of the LoRA Power-Merger pack. ComfyUI Manager (search "LoRA Power-Merger") or:
cd ComfyUI/custom_nodes
git clone https://github.com/larsupb/LoRA-Merger-ComfyUI
cd LoRA-Merger-ComfyUI
pip install -r requirements.txt
Restart ComfyUI. Dependencies: PyTorch, lxml, mergekit.
Common issues
The none method is the trap. It's the fastest path, but it throws the moment your stack has mismatched ranks, and most real collections do. If you're getting rank errors at the merger, switch to rSVD here rather than fighting it. For big DiT or Flux LoRAs, energy_rSVD is the smooth path - the full SVD on giant layers is slow and memory hungry. And the output isn't a LoRA you can load or apply - it's intermediate data. If you tried to feed it into a LoraLoader, that's the wrong wire; apply or save only after the merger rebuilds a bundle.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| key_dicts | LoRAStack | — | |
| decomposition_method | COMBO | rSVD | Method used to reconcile LoRA ranks when they differ. 'none' will raise an error if ranks do not match. 'SVD' uses full singular value decomposition (slow but optimal). 'rSVD' uses randomized SVD (much faster, near-optimal). 'energy_rSVD' first prunes low-energy LoRA components and then applies randomized SVD for fast, stable rank reduction (recommended for DiT and large LoRAs). |
| svd_rank | INT | -1-1–128 | Target LoRA rank after decomposition. -1 = auto (keep the rank of the first LoRA in the stack). Set a positive value to force a rank; lower values reduce model size and strength. |
| device | COMBO | Decomposition device. Note: All decomposition uses float32 internally for numerical stability, then converts back to the original dtype. | |
| block_selectionopt | BlockSelection | Per-block, per-LoRA weights from PM Block Selector. Scales each LoRA's contribution per block; weight 0 drops the block. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| LoRATensors | LoRATensors | — |