Nodes/comfyui_imgtools/Merge LoRAs to File (rholdorf)
ComfyUI Node

Merge LoRAs to File (rholdorf)

Bake two LoRAs into one file — exactly, not approximately

By rholdorf·Created 9 months ago·Updated 13 days ago· 0
Merge LoRAs to File (rholdorf)
    • path
    • retained_energy
    lora_name1
    strength10.50
    lora_name2
    strength20.50
    filename_prefixmerged_lora
    target_rank0

    You've got two LoRAs you reach for together every single time - a character LoRA at 0.7 and a style LoRA at 0.4, say. Loading both works fine, but you're tired of the extra loader, you want one file to share, or you just want to know what the combination looks like with the strengths frozen in. People have been merging LoRAs since 2024 and the ask hasn't gone away.

    Merge LoRAs to File (rholdorf) is the clean answer to that. It bakes two standard LoRAs into a single .safetensors, and here's the part that separates it from the herd: it's an exact merge, not an approximation.

    Why "exact" matters

    Most LoRA merge tools average the weight matrices. That's a blend - it produces a third thing that sort of sits between your two LoRAs, usually mushier than either. This node does the opposite: it reproduces exactly what applying both in sequence does, à la rgthree's Power Lora Loader. Because [Up_A | Up_B] @ [Down_A ; Down_B] == Up_A@Down_A + Up_B@Down_B, concatenating the up matrices along the rank dimension (with each LoRA's strength and alpha/rank scale folded into the up side) and the down matrices along rank gives you the precise weighted sum of both deltas. No SVD, no loss, no guesswork. The ranks don't even have to match - a rank-32 and a rank-64 merge into a rank-96 file.

    The output alpha is set equal to the merged rank, so ComfyUI's load-time alpha/rank scale lands at exactly 1.0. That's the one rule that matters: load the merged file at strength 1.0. If you bake at 0.7 and 0.4 and then load the merged file at 0.5, you get half of both - not your original combination.

    What you set

    • lora_name1 / lora_name2 - dropdowns populated from your loras folder.
    • strength1 / strength2 (default 0.5 each) - the strengths baked in. Read those tooltips: it's the value you'd set in Power Lora Loader.
    • filename_prefix (default merged_lora) - output name relative to the loras folder; .safetensors is appended for you.
    • target_rank (optional, default 0) - 0 keeps the exact merge. A positive value recompresses the merged delta down to that rank via truncated SVD (Eckart–Young optimal), which makes a smaller file at the cost of exactness. Say you merge a 32 and a 64 and don't want a rank-96 file eating space: recompress to 64 and check retained_energy.

    Outputs: path (the relative path of the saved file) and retained_energy. It's an output node, so it saves the file and prints a summary - plus the retained-energy percentage on the node face after a run. Exact merge shows 100% (exact); a recompressed one shows something like 96.4%, which is your quality signal. If that number drops below the high nineties, you've compressed too far for the merge to be worth it.

    What it refuses

    Standard LoRA lora_up / lora_down (+ alpha), plus the other up/down naming schemes ComfyUI recognises and direct .diff / .diff_b deltas - those all work. LoHa, LoKr, OFT, DoRA and LoCon-mid files get a hard error rather than a wrong output, because none of those is a plain up @ down product. It also raises on a shape mismatch between the two LoRAs, which is its way of telling you the LoRAs don't target the same base model. Don't fight it - that's the node being honest.

    Install

    Same pack as the rest of the rholdorf nodes:

    cd ComfyUI/custom_nodes
    git clone https://github.com/rholdorf/comfyui_imgtools
    

    Restart ComfyUI. No dependencies beyond what ComfyUI already ships (torch, numpy, Pillow), no model downloads. The merged file lands in your loras folder, so it shows up in any LoraLoader's dropdown - refresh if it doesn't appear immediately.

    When it's actually worth it

    If your combination is truly fixed - same two LoRAs, same strengths, every generation - baking is a real win: one loader, one file to share, marginally less work per run. If you're constantly nudging strengths between 0.3 and 0.7, keep the two loaders and skip the merge; the whole point is freezing a combination, and a merged file is awkward to re-blend. The niche that makes it shine is sharing and portability - one file instead of "install these two, then set these exact strengths."

    Categoryrholdorf/lora

    Inputs (6)

    NameTypeDefaultDescription
    lora_name1COMBOFirst LoRA to combine.
    strength1FLOAT0.50-100–100Strength baked in for the first LoRA (the value you'd set in Power Lora Loader).
    lora_name2COMBOSecond LoRA to combine.
    strength2FLOAT0.50-100–100Strength baked in for the second LoRA.
    filename_prefixSTRINGmerged_loraOutput name (relative to the loras folder). '.safetensors' is added automatically.
    target_rankoptINT00–40960 = exact rank concatenation (rank = sum of both). A positive value recompresses the merged delta to that rank via truncated SVD (smaller file, approximate). E.g. 64 to match a rank-64 LoRA.

    Outputs (2)

    NameTypeDescription
    pathSTRING
    retained_energySTRING