Nodes/ComfyUI_StarNodes/⭐ Star LoRA Extractor
ComfyUI Node

⭐ Star LoRA Extractor

Pull the LoRA back out of a merged checkpoint

By Starnodes2024·Created 2 years ago·Updated a day ago· 111
⭐ Star LoRA Extractor
    • info
    ◄base_model▾►
    ◄merge_model▾►
    ◄lora_namestar_extracted_lora►
    ◄dim16►
    ◄conv_dim8►
    ◄precisionfp16►
    ◄devicecpu►
    ◄extract_convstrue►
    ◄include_text_encodertrue►
    ◄overwritefalse►

    What it's actually for

    You know the situation. Someone uploaded a merge - a base model with three LoRAs baked in - and it does exactly the thing you wanted. But it's 6 GB, it's got someone else's aesthetic welded on, and you can't turn the effect down or point it at a different base. What you want is the difference: a small file that says "whatever was added here," loadable at 0.6 onto a model of your choosing.

    That's what ⭐ Star LoRA Extractor does. It's the same technique kohya's extract_lora_from_models.py uses, wrapped as a node that runs inside your graph instead of a separate Python environment. Extraction only ever recovers an approximation, and it lives or dies on picking the correct base model - get that wrong and you're diffing two unrelated things.

    How it works

    For every weight both files have in common:

    diff = merged_weight − base_weight
    diff ≈ lora_up @ lora_down     (per-matrix SVD, truncated to your chosen rank)
    

    Diff in fp32, one matrix at a time, SVD, truncate to dim (Linear layers) or conv_dim (Conv2d), store the pair plus an alpha equal to the rank. Keys get rewritten into ComfyUI's LoRA naming (lora_unet_…, lora_te1_…) and the whole thing saves as one .safetensors into your top-level models/loras.

    The memory story is why this runs on a normal machine: both files are opened as memory-mapped safetensors and read key by key, so neither 6 GB model is ever resident in full. The catch is printed at runtime - .ckpt/.pt files have no lazy path and load whole, which puts you right back over the RAM limit. Convert to safetensors first.

    Quantized files work too: it dequantizes int8 / int8-convrot (Hadamard un-rotation included) and fp8_e4m3/e5m2 with scalar or per-row scales before diffing. Packed 4- and 6-bit formats (nvfp4, convrot_w4a4, asym_w4a8_int8, w6a8_int8) can't be diffed at all; the node raises instead of writing garbage.

    The inputs that matter

    • base_model and merge_model - dropdowns filled from models/diffusion_models. Same architecture required (SD 1.5 with SD 1.5, Flux with Flux); mismatched shapes are skipped rather than crashing. Picking the same file twice is a hard error.
    • lora_name - the output filename in models/loras. .safetensors is appended for you, and subfolders work: style/my_extract gives you models/loras/style/my_extract.safetensors. Refuses to overwrite unless you set overwrite to true.
    • dim / conv_dim - rank. Defaults of 16 and 8 are the pack's "balanced" pair, about 60–150 MB on SDXL. Go 8/4 for something small, or 32–64 / 16–32 when the merge bundled many strong LoRAs, since those diffs don't compress as cleanly.
    • precision (fp16/bf16/fp32) and device (cpu/cuda). cpu is the default and the safe one; cuda is much faster if the whole thing fits in VRAM.
    • Optional: extract_convs (leave true), include_text_encoder (leave true unless the merge only touched the UNet), overwrite.

    Output is a single info string with the save path, file size, and a layer breakdown - extracted vs. unchanged vs. skipped. Read it. If almost everything comes back "unchanged," your two files are basically the same model and the LoRA is empty.

    Install

    Manager → search Starnodes → Install → restart, or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/Starnodes2024/ComfyUI_StarNodes
    cd ComfyUI_StarNodes
    pip install -r requirements.txt
    

    Ignore the heavy entries in that requirements file - psd-tools, opencv-python, imageio-ffmpeg, ollama and friends belong to other nodes in the pack. This one is pure torch + safetensors, and the pack is built so a missing package knocks out only its own node, not the whole install.

    You'll find it by double-clicking the canvas and searching star.

    Where people get burned

    The dropdown is empty. base_model and merge_model list models/diffusion_models, not models/checkpoints. A merged full checkpoint sitting in checkpoints/ simply won't show up. Move or symlink the file first.

    "No differences found." Either the files are genuinely near-identical (diffs under 1e-7 are skipped as unchanged) or you're diffing against the wrong base. If you don't know which base the merger used, that's the whole problem: find the closest match by similarity and accept the noise.

    It's slow, and it looks frozen. This runs an SVD per matrix across thousands of matrices. The progress bar crawls, especially on cpu. device: cuda on an SD 1.5/SDXL-sized model is a big difference; on a 20B model it may not fit and you're back to cpu. Let it run.

    Quality is a dial, not a switch. Two independently quantized models carry quantization noise in the diff, and SVD truncation removes most of it - but if the merge was re-quantized after baking, that smoothing is in your file now. Diffing a bf16/fp16 pair gives the cleanest result.

    VAEs are always skipped, on purpose - LoRAs don't target the VAE. If the merge's look came largely from a VAE swap, none of that is in your file, and it'll read as a bad extraction when really it was never there.

    Last thing: it's a terminal node, so it only runs when you queue a prompt with it in the graph. Refresh the node list if the new LoRA doesn't show up in Load LoRA's dropdown straight away.

    Category⭐StarNodes/Helpers And Tools

    Inputs (10)

    NameTypeDefaultDescription
    base_modelCOMBOThe clean base diffusion model (from models/diffusion_models).
    merge_modelCOMBOThe diffusion model with LoRAs already baked in (from models/diffusion_models).
    lora_nameSTRINGstar_extracted_loraFile name for the extracted LoRA (saved into models/loras). May contain subfolders.
    dimINT161–1024Rank/size of the LoRA for Linear layers. Higher = more detail, bigger file.
    conv_dimINT81–512Rank for Conv2d layers (UNet resnet blocks). Lower than dim is usually fine.
    precisionCOMBOfp16Save precision/quality of the extracted LoRA weights.
    deviceCOMBOcpuWhere the SVD math runs. cpu = lowest RAM/VRAM usage, cuda = much faster if it fits.
    extract_convsoptBOOLEANtrueAlso extract Conv2d layer differences (recommended for full fidelity).
    include_text_encoderoptBOOLEANtrueAlso extract text encoder (CLIP) differences.
    overwriteoptBOOLEANfalseAllow overwriting an existing LoRA file with the same name.

    Outputs (1)

    NameTypeDescription
    infoSTRING—