Merge LoRAs (2 Models)
Blend two LoRA files with the same engine as the checkpoint mergers
- output_filename
- documentation
Worth clearing up before anything else: this pack ships two different ways to combine LoRA files, and they're not the same tool. LoRATwoMerger (this one) runs LoRA files through the exact same generic weighted-merge engine as CheckpointTwoMerger and ModelTwoMerger - it treats the LoRA's tensors like any other set of weights and blends them. LoRAMultiMerge, elsewhere in this pack, is LoRA-aware: it understands ranks and reconciles naming conventions across up to eight files, and gives you an explicit choice between concatenating (safe, grows the rank) or a weighted sum (fixed rank, more like what Kohya-style tools do). If you're stacking several trained LoRAs cleanly, you probably want LoRAMultiMerge. If you specifically want two LoRA files blended with the same generic merge math you'd use on checkpoints - same calc_mode, same weight knobs, same everything - this is that node.
How it works
model_a and model_b pick the two source LoRAs. calc_mode selects the merge algorithm from a dropdown whose option list isn't documented in the node metadata - check what's on your install. The six weight knobs (alpha 0.5, beta 0.5, gamma 0.99, delta 2, epsilon 0.01, zeta 0) carry the identical defaults every two-input merger in this pack ships with; alpha is the one most people touch for a straight blend, the rest are undocumented per-field and presumably feed more specific algorithm choices.
mismatch_mode (default skip) and alignment_mode (default pad/crop) matter more here than you might expect - two LoRAs trained at different ranks, or with different naming conventions from different trainers, genuinely produce shape mismatches at the tensor level, and this node lets you skip or pad/crop around them rather than erroring out. exclude_patterns/discard_patterns (regex, or glob with glob_patterns) scope specific layers out of the merge. lazy_load and force_clear_cache manage memory; save_dtype/override_dtype set output precision; process_device picks CPU or GPU; seed covers whatever randomness a given calc_mode might use. Output is output_filename (default merged_2_lora) and a documentation string.
Installing it
ComfyUI Manager: search Model Utility Toolkit, install, restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/silveroxides/ComfyUI-ModelUtils
Restart ComfyUI. No downloads needed beyond the LoRA files you already have.
Where people get burned
The recurring gotcha with generic-engine LoRA merging is that it's blending two low-rank decompositions as if they were arbitrary weight tensors, without the rank-aware math that a purpose-built LoRA merger uses. Two LoRAs at genuinely different ranks, or trained on different base architectures, are exactly the case mismatch_mode/alignment_mode exist to survive mechanically - but surviving isn't the same as producing something that behaves well at inference. If the merged LoRA looks muddy or barely does anything compared to either source at full strength, that's the generic-blend tradeoff showing up, and it's worth trying LoRAMultiMerge's weighted_sum mode instead, which is built specifically for reconciling rank differences rather than averaging around them.
Architecture mismatch is the other one, and it's absolute, not a matter of degree - a LoRA trained for one base model does nothing useful merged with a LoRA trained for a different one; you don't get a hybrid, you get noise on both ends.
Inputs (22)
| Name | Type | Default | Description |
|---|---|---|---|
| execution_mode | COMBO | 2 options: MERGE, DOCUMENTATION ONLY | |
| model_a | COMBO | 1 options: None | |
| model_b | COMBO | 1 options: None | |
| calc_mode | COMBO | 10 options: Weight-Sum, Comparative-Interpolation, Power-Up (DARE), Power-Up (DARE+TIES), SVD LoRA Extraction, Enhanced Man Interp, +4 | |
| mismatch_mode | COMBO | skip | 3 options: skip, zeros, error |
| alignment_mode | COMBO | pad/crop | 2 options: pad/crop, interpolate |
| alpha | FLOAT | 0.50-10–10 | — |
| beta | FLOAT | 0.50-10–10 | — |
| gamma | FLOAT | 0.990-10–10 | — |
| delta | FLOAT | 2.00-10–10 | — |
| epsilon | FLOAT | 0.01-10–10 | — |
| zeta | FLOAT | 0.00-10–10 | — |
| seed | INT | 00–18446744073709550000 | — |
| output_filename | STRING | merged_2_lora | — |
| save_dtype | COMBO | 3 options: fp32, fp16, bf16 | |
| process_device | COMBO | 2 options: cuda, cpu | |
| exclude_patterns | STRING | — | |
| discard_patterns | STRING | — | |
| glob_patterns | BOOLEAN | false | When True, exclude/discard patterns use glob syntax (* = any sequence, dots are literal). When False (default), patterns are Python regex matched as substrings. |
| lazy_load | BOOLEAN | true | Low memory mode: load tensors from disk on demand |
| force_clear_cache | BOOLEAN | true | Clear CUDA cache after each layer |
| override_dtype | BOOLEAN | false | Force the entire model to be saved as the selected save_dtype. If False (default), higher precision dtypes are preserved. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| output_filename | STRING | — |
| documentation | STRING | — |