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 (23)
| Name | Type | Default | Description |
|---|---|---|---|
| execution_mode | COMBO | MERGE writes the selected result; DOCUMENTATION ONLY returns the operation reference without loading model files. | |
| model_a | COMBO | Primary LoRA; anchors metadata, tensor shapes, and values preserved by exclusions or skip handling. | |
| model_b | COMBO | Second LoRA contributing to the selected calculation mode. | |
| calc_mode | COMBO | Two-model operation to apply per comparable tensor; DOCUMENTATION ONLY shows its formula and coefficient meanings. | |
| mismatch_mode | COMBO | skip | Handle missing or incompatible tensors: preserve Model A, substitute zeros where supported, or abort with an error. |
| alignment_mode | COMBO | pad/crop | Resolve compatible shape differences by zero-padding/cropping or by interpolating Model B and Model C to Model A shape. |
| alpha | FLOAT | 0.50-10–10 | Mode-specific coefficient; use DOCUMENTATION ONLY for its exact role in the selected calculation mode. |
| beta | FLOAT | 0.50-10–10 | Mode-specific coefficient; some calculation modes ignore it. See DOCUMENTATION ONLY for the selected formula. |
| gamma | FLOAT | 0.990-10–10 | Mode-specific coefficient; some calculation modes ignore it. See DOCUMENTATION ONLY for the selected formula. |
| delta | FLOAT | 2.00-10–10 | Mode-specific coefficient; some calculation modes ignore it. See DOCUMENTATION ONLY for the selected formula. |
| epsilon | FLOAT | 0.01-10–10 | Mode-specific coefficient; some calculation modes ignore it. See DOCUMENTATION ONLY for the selected formula. |
| zeta | FLOAT | 0.00-10–10 | Mode-specific coefficient; some calculation modes ignore it. See DOCUMENTATION ONLY for the selected formula. |
| seed | INT | 00–18446744073709550000 | Random seed used only by calculation modes with stochastic behavior. |
| output_filename | STRING | merged_2_lora | Output filename without extension, written under the matching ComfyUI model directory. |
| save_dtype | COMBO | Output tensor dtype; when Override Dtype is disabled, source tensors with higher precision remain at that precision. | |
| process_device | COMBO | Device used for per-tensor merge arithmetic; CUDA out-of-memory retries the affected tensor on CPU. | |
| exclude_patterns | STRING | Newline-separated regex or glob patterns for tensors excluded from merging and preserved from Model A. | |
| discard_patterns | STRING | Newline-separated regex or glob patterns for tensors omitted entirely from the output. | |
| 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 merged non-1D tensors to save_dtype. Enabled 1D direct diffs remain FP32. |
| include_1d_diffs | BOOLEAN | false | Merge 1D tensors. When disabled, preserve Model A's 1D tensors unchanged. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| output_filename | * | — |
| documentation | STRING | — |