LC LoRA Bake π
Bake Your LoRA Stack Into the Model and Stop Stacking Loaders
- path
- info
You know the shape of it: base model, then three LoRA loaders chained in a row, each carrying a strength you tuned by feel over a week - and one careless delete later the whole look is gone. LC LoRA Bake folds that chain into the model file: pick up to four LoRAs, set strengths, queue, and you get a new .safetensors that behaves like a plain checkpoint. One loader, one library entry, no archaeology about which value it was.
What baking actually is
A LoRA is a small correction. Baking means evaluating W + strength Γ ΞW once at full precision and writing the answer to disk, instead of re-doing that math on every sample. The result loads anywhere a diffusion model loads - including in front of LC Model Quantize, when you want a small fp8 or GGUF copy of a model with its LoRAs already inside.
Until now that meant A1111-with-SuperMerger - still a named reason people keep a legacy install around.
How the bake works
It doesn't need the model in VRAM. It reads the safetensors header, builds a skeleton on the meta device so there's no memory cost, and asks ComfyUI's own machinery for that model's key table - comfy.lora.model_lora_keys_unet. Each LoRA goes through comfy.lora.load_lora, so every format ComfyUI reads works: PEFT, kohya with alpha, split Q/K/V on a fused qkv, the lot. The file is then walked one tensor at a time with comfy.lora.calculate_weight, and tensors no LoRA touches pass straight through. The recipe - base file, LoRA names, strengths, curve - is stamped into the metadata under the key lc_merge.
The inputs you'll actually touch
model_name picks the source, and it's the field that will argue with you: the list comes from models/diffusion_models, and it wants the bf16 or fp16 original. Point it at an fp8 or GGUF file and it refuses outright, telling you to bake from full precision and quantize afterwards. That order matters - quantize first and every LoRA correction inherits the rounding.
Then lora_1 through lora_4, each with its own strength_1β¦strength_4 (default 1.0, range -4 to 4, so negative is legal and occasionally useful). Slots left at None are skipped; you need at least one.
blocks_curve is the interesting one: an optional comma list, one multiplier per numbered block, applied on top of each LoRA's strength. 0 in a slot leaves that block completely alone. outside_blocks is the same idea for everything else - embedders, text side, final layer - and defaults to 1.0. Same list format as the pack's LoRA Editor and Block Scan, so a curve you found by scanning carries over.
filename defaults to baked/my_model_baked, lands next to the source model inside models/diffusion_models (subfolders fine), .safetensors appended for you. device is cpu - about a minute, zero VRAM - or gpu, which is faster and wants a little VRAM. Leave it on cpu and go make coffee.
What comes out
Two strings: path and info. This is an output node, not a pipe; there's nothing to wire into a sampler. It writes a file, and info tells you how many layers changed, in how many seconds, and how many of each LoRA's modules matched. A LoRA reporting "0 of 68 modules matched" isn't broken, it's for another architecture - LoRAs are architecture-bound, and this node says so instead of silently baking nothing.
Reload the result with Load Diffusion Model. Trigger words still matter; you baked the weights in, not the prompt.
Install
ComfyUI Manager, search ComfyUI_LC_ModelBuilder_nodes, or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/lonecatone23/ComfyUI_LC_ModelBuilder_nodes
Restart. There's no requirements.txt - this node needs nothing past core, since it rides comfy.lora, comfy.model_detection and safetensors, all shipped with ComfyUI. (The pack's Face Variety Scorer needs onnxruntime; its install.py handles that - irrelevant here.) Make sure __init__.py sits directly inside ComfyUI_LC_ModelBuilder_nodes/, not one folder deeper: the pack warns if it's nested, and unzipped archives are where that happens. Hard-refresh (Ctrl+Shift+R) after updates.
Where it goes wrong
Disk, first. Baking shrinks nothing - the output is a full copy of a full-precision model, and a 12B bf16 base is around 25 GB. If you're here to get a smaller file, the bake is step one, LC Model Quantize is step two.
The curve doesn't interpolate. Give blocks_curve a short list on a 28-block model and every block past the end of your list runs at 1.0 - full strength - not a smooth continuation. The merge nodes in this pack stretch short curves; this one doesn't. Paste all 28 numbers or leave it empty.
Baked is committed. No dial afterwards. If 0.65 was right for one batch and 0.8 for another, bake two variants. And "bake the LoRA only partly" is a real request, usually because one bad LoRA wrecks every face - that's what blocks_curve and outside_blocks are for: aim them at the block range you care about.
Your graph can ride along. The recipe is in the metadata by design: great for your own library, mildly annoying when you share a model. Run the pack's LC Strip Metadata in necessary only mode first.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| model_name | COMBO | The bf16 / fp16 model to bake into. Quantize the result afterwards with LC Model Quantize. | |
| lora_1 | COMBO | None | A LoRA made for this model family. |
| strength_1 | FLOAT | 1.00-4β4 | β |
| lora_2 | COMBO | None | A LoRA made for this model family. |
| strength_2 | FLOAT | 1.00-4β4 | β |
| lora_3 | COMBO | None | A LoRA made for this model family. |
| strength_3 | FLOAT | 1.00-4β4 | β |
| lora_4 | COMBO | None | A LoRA made for this model family. |
| strength_4 | FLOAT | 1.00-4β4 | β |
| blocks_curve | STRING | Optional: one number per block (comma list), multiplies the strengths in that block. 0 leaves the block alone. Empty = 1 everywhere. Same lists as the LoRA Editor and Block Scan. | |
| outside_blocks | FLOAT | 1.000β4 | Multiplier for the layers outside the numbered blocks (embedders, text side, final layer). |
| filename | STRING | baked/my_model_baked | Saved next to the source model, .safetensors added. |
| device | COMBO | cpu | cpu: no VRAM used, about a minute. gpu: faster, needs a little VRAM. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| path | STRING | β |
| info | STRING | β |