LoRA Extract from Model
Pull a LoRA back out of a baked-in finetune
- base_model
- finetuned_model
- base_clip
- finetuned_clip
- lora_stack
- lora_stack
- lora_data
Sometimes a LoRA doesn't exist as a file - it's already baked into a merged checkpoint, and there's no separate .safetensors you can point at. That happens a lot: someone releases a finetuned checkpoint but not the LoRA it was built from, or you have an old full finetune you want to make portable again. LoRA Extraction is exactly the technique for this - take the difference between a base model and a finetune, decompose it, and get a LoRA back out. It's a known move in the wider ecosystem (extraction is how a lot of people turn a full finetune into something they can apply to other checkpoints at a fraction of the file size), and this node is this pack's implementation of it, wired directly into the rest of the optimizer suite.
How it works
You give it the clean base model and the finetuned model that started from it. It diffs the two, layer by layer, and SVD-decomposes each layer's delta into a low-rank approximation - the same math a LoRA is, just derived backward from two full checkpoints instead of trained forward from a dataset. rank_mode=auto (the default) picks how much rank each layer needs to retain a target fraction of the delta's "energy" (its signal, essentially); fixed forces every layer to the same rank regardless of how much detail that layer's delta actually contains.
The inputs and outputs that matter
base_model/finetuned_model(required) - the clean starting checkpoint and the finetune you're extracting from. These need to be from the same lineage; diffing unrelated models won't produce something meaningful.rank(default32) - used directly infixedmode, or as an upper bound inautomode.rank_mode(defaultauto) -autoretains a quality target per layer (recommended);fixedforces uniform rank everywhere.energy_threshold(default0.99) - only matters inautomode. Fraction of the delta's signal to keep; higher retains more accuracy at the cost of a larger effective rank.strength(default1.0) - the strength this extracted LoRA gets assigned in the output stack.base_clip/finetuned_clip(optional, connect both together) - provide these if you also want to extract text-encoder changes, not just the UNet/diffusion side. Leave both disconnected to extract UNet components only.lora_stack(optional) - connect another stack (or another extractor) here to append the extracted LoRA to it, rather than getting it on its own.
Outputs: lora_stack - feed this straight into LoRA Optimizer or LoRA AutoTuner to merge the extracted LoRA with others. lora_data - feed this into Save Merged LoRA to write the extracted LoRA out as a standalone .safetensors file.
How to install it
ComfyUI Manager: search "LoRA Optimizer", install, restart. Manually:
cd ComfyUI/custom_nodes/
git clone https://github.com/ethanfel/ComfyUI-LoRA-Optimizer.git
Restart - nodes appear under loaders. No extra downloads; you need the two checkpoints (base and finetuned) loaded already, which is the real prerequisite here.
Common issues & troubleshooting
You need the actual base model, not a guess. Extraction only works cleanly if base_model is genuinely the checkpoint the finetune started from - not a similar-looking model, not a different version of the same architecture family. A mismatched base will diff against noise instead of the real training delta, and the resulting "LoRA" won't reproduce the finetune's effect.
Output looks weaker or blurrier than the original finetune. That's the energy_threshold/rank tradeoff showing up. Raise energy_threshold toward 1.0 (or bump rank in fixed mode) to retain more of the original signal - the cost is a larger, heavier LoRA file.
Fully-baked checkpoints you didn't finetune yourself. The README is upfront about the ceiling here: this only works when you actually have both a base and a finetuned model to diff. A .safetensors checkpoint you downloaded with no separate base reference is indistinguishable from a model that was never a LoRA at all - there's nothing to extract from a single file with no comparison point.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| base_model | MODEL | The original clean base model (e.g. the Flux or SDXL base checkpoint that was used as the starting point for finetuning). | |
| finetuned_model | MODEL | The finetuned model with a LoRA already baked into its weights. | |
| rank | INT | 321–512 | Maximum rank for SVD decomposition. Used directly in 'fixed' mode; acts as an upper bound in 'auto' mode. |
| rank_mode | COMBO | auto | 'auto': choose rank to retain the given energy fraction (recommended). 'fixed': always use exactly the specified rank. |
| energy_threshold | FLOAT | 0.990.5–1 | Fraction of delta energy to retain when rank_mode='auto'. 0.99 = retain 99% of the signal. Higher = more accurate, higher rank. |
| strength | FLOAT | 1.00-10–10 | Strength to assign this extracted LoRA in the output stack. |
| base_clipopt | CLIP | The CLIP encoder for the base model. Required to extract CLIP/text-encoder LoRA components (e.g. for SDXL). Leave disconnected to extract UNet components only. | |
| finetuned_clipopt | CLIP | The CLIP encoder for the finetuned model. Must be connected together with base_clip. | |
| lora_stackopt | LORA_STACK | Optional. Connect a LoRA Stack (or another extractor) here to merge the extracted LoRA TOGETHER with those LoRAs. The extracted LoRA is appended to the incoming stack. Leave disconnected to output the extracted LoRA on its own. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| lora_stack | LORA_STACK | — |
| lora_data | LORA_DATA | — |