ControlLoraSave
Turn any ControlNet into a tiny LoRA — no training, no dataset
- model
- control_net
A 4.7 GB ControlNet, compressed to a fraction of itself - in about a minute
This is the node that makes Control-LoRAs without any training. You feed it a base model and an existing ControlNet, it subtracts the base model's weights from the ControlNet's weights, factorizes the difference with SVD, and saves the result as a .safetensors LoRA. No dataset, no kohya, no rented GPU. If the pair matches, you end up with a file a fraction of the size of the original ControlNet that loads through a normal LoRA loader.
That idea is Stability's own, by the way - this is the official repo. When they shipped SDXL Control-LoRAs back in August 2023, the pitch was exactly that: rank-256 files cut 4.7 GB ControlNets down to ~738 MB, and rank-128 got you ~377 MB. On the modern landscape it still fits: the community's standing advice for "I want control but the full ControlNet is heavy or uncooperative" is a control LoRA, and this node is the fastest route to one from a ControlNet you already have.
How it actually works
The source is short and you can read it in five minutes. It loads your base model onto the GPU, walks every key starting with diffusion_model., finds the matching tensor in the ControlNet's state dict, and computes controlnet_weight - model_weight. That difference gets run through SVD and truncated to your rank (capped at the tensor's actual dimensions), the result is clamped to the ±99th percentile so a few wild values don't wreck the LoRA, and the usual up / down LoRA keys are written out. Weights that don't match anything in the base model - like the ControlNet's own control layers - are stored as-is, plus a lora_controlnet marker tensor so tools know what it is.
The catch, spelled out: this only works on UNet architectures. The diffusion_model. key scheme is SD 1.5 / SDXL territory, so pair your ControlNet with the base it was built for. Feed it an SDXL ControlNet with an SDXL base and you get a working control LoRA. Feed it a mismatch and you get a junk file where most of the "LoRA" is raw ControlNet weights and nothing lines up. Don't blame the node; it's doing exactly what you asked.
The inputs that matter
Four inputs, and you really only touch two of them:
- model - your base checkpoint (the one the ControlNet was trained for).
- control_net - the ControlNet you want to shrink.
- filename_prefix - defaults to
controlnet_loras/ComfyUI_control_lora. Note the subfolder, it matters for the gotcha below. - rank - default 64. Higher rank means better fidelity and a bigger file; 256 is the "official" quality tier, 128 the compact one. The minimum is 0, which is a footgun - a rank-0 LoRA is empty. Keep it at 64 or above.
There are no outputs. This is a dead-end save node; it writes a file and returns nothing. That's the point.
Where the file goes (this is the trap)
It saves into ComfyUI's output folder under output/controlnet_loras/, not into models/loras. Beginners always look in the wrong place, find nothing, and assume it failed. Look in ComfyUI/output/controlnet_loras/ for a file like ComfyUI_control_lora_00001_.safetensors, then copy or move it into ComfyUI/models/loras/. From there it's a plain LoRA: add a LoraLoaderModelOnly node, point it at your file, and start around 0.5–1.0 strength - control LoRAs are lighter than full ControlNets and you generally don't need the full dial.
Installing it
ComfyUI Manager (search "stability-ComfyUI-nodes"), or the manual route:
cd ComfyUI/custom_nodes
git clone https://github.com/Stability-AI/stability-ComfyUI-nodes
then restart ComfyUI and pip install -r requirements.txt. That requirements file is just opencv-python - and it's there for the pack's image nodes, not this one. This node needs nothing beyond stock ComfyUI's torch stack. It'll appear under the stability/controlnet menu.
One more honest caveat: this converts, it doesn't create. The output is only as good as the ControlNet you feed it, and it's a lossy compression of that ControlNet, not a freshly trained condition. If you want a new condition that was never built, this won't invent it - but for shrinking a ControlNet you already like down to something you can ship or stack alongside a dozen other LoRAs, it's the whole job in one node.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| control_net | CONTROL_NET | — | |
| filename_prefix | STRING | controlnet_loras/ComfyUI_control_lora | — |
| rank | INT | 640–1024 | — |
Outputs (0)
No outputs