Nodes/Model Utility Toolkit/TE LoRA Extract (Ratio)
ComfyUI Node

TE LoRA Extract (Ratio)

Keep the singular values that actually matter

By silveroxides·Created 2 years ago·Updated 3 days ago· 17
TE LoRA Extract (Ratio)
  • layer_parameters
  • output_path
◄model_a▾►
◄model_b▾►
◄linear_ratio2.0►
◄conv_ratio2.0►
◄probe_offset32►
◄linear_max_rank128►
◄conv_max_rank128►
◄lazy_loadtrue►
◄force_clear_cachefalse►
◄chunk_large_layersfalse►
◄clamp_quantile0.99►
◄min_diff0.000►
◄mismatch_modeskip►
◄output_filenameextracted_te_lora►
◄save_dtypefp16►
◄devicecuda►
◄skip_patterns►
◄glob_skip_patternsfalse►
◄include_modefalse►

Picking a LoRA rank is usually a guess: 16, 32, 64, whatever fits. This node replaces the guess with a rule. Extract a LoRA from a fine-tuned text encoder minus its base, but instead of forcing a fixed rank, keep every singular value that's at least max(S) / ratio - the ratio variant of silveroxides/ComfyUI-ModelUtils' TE extractors.

It's the same family as the pack's other extract nodes: A - B per weight tensor, SVD, write lora_A/lora_B factors to your loras folder. The only real difference is how the rank is decided per layer. Where the Fixed node sets one rank for everything, Ratio lets the singular value spectrum of each layer speak - a layer whose signal decays fast gets a low rank automatically, a layer with lots of meaningful structure keeps more. That per-layer adaptation is the entire selling point, and it's why you'd reach for this over Fixed if you want efficiency without hand-tuning ranks.

The inputs that matter

  • model_a / model_b - fine-tuned encoder and base encoder, both from models/text_encoders. A minus B is the delta.
  • linear_ratio / conv_ratio - the threshold for linear/attention vs convolution layers, default 2. Higher values retain more singular values: a ratio of 4 keeps everything above max/4, which is a lower cutoff than max/2, so more of the spectrum survives. Lower it to force a tighter rank. This is the kohya convention, so if you've used "extract LoRA" in sd-scripts, you've met this knob before.
  • linear_max_rank / conv_max_rank - hard caps (default 128) so a single noisy layer can't blow the rank up.
  • probe_offset - extra singular values sampled past the max rank so the rank decision is made against a full-enough spectrum rather than a truncated one.
  • output_filename / save_dtype / device / lazy_load - shared across the whole extractor family: where it's written, what dtype it's saved in (fp16 default), where the arithmetic runs, and whether tensors stream from disk.

One output, output_path - the path of the written file. It's an output node; nothing needs to follow it.

Install

From ComfyUI Manager, search "Model Utility Toolkit". Or:

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

Restart, and the node appears under ModelUtils/LoRA Extract (TE). The key runtime dependency is unifiedefficientloader, which streams the two safetensors so you don't need to hold both encoders in RAM.

Where it bites

The silent-skip trap applies here as much as anywhere in this pack: with mismatch_mode: skip (the default), missing or shape-incompatible tensors just vanish. Compare an encoder against the wrong base and you'll get a small, useless file with no error. And remember this is SVD over a whole encoder - it runs for minutes with a progress bar, not seconds. If you'd rather the spectrum pick the rank for you in one shot, the Knee variant automates exactly that; use Ratio when you want the explicit, tunable threshold.

CategoryModelUtils/LoRA Extract (TE)

Inputs (20)

NameTypeDefaultDescription
model_aCOMBOFinetuned Text Encoder model (A - B = LoRA)
model_bCOMBOBase Text Encoder model (A - B = LoRA)
linear_ratioFLOAT2.01–100Ratio threshold for linear layers; higher values retain more singular values.
conv_ratioFLOAT2.01–100Ratio threshold for convolution layers; higher values retain more singular values.
probe_offsetINT321–4096Extra singular values sampled beyond Max Rank for a reliable bounded rank decision.
linear_max_rankINT1281–16384Maximum extracted rank for linear layers.
conv_max_rankINT1281–16384Maximum extracted rank for convolution layers.
lazy_loadBOOLEANtrueLow memory mode: load tensors from disk on demand
force_clear_cacheBOOLEANfalseClear CUDA cache after each layer; slower but useful under severe VRAM pressure.
chunk_large_layersBOOLEANfalseSplit large fused layers (QKV, MLP) into chunks
clamp_quantileFLOAT0.990.5–1Clamp outlier singular values
min_diffFLOAT0.0000–1Skip layers with max difference below this
mismatch_modeCOMBOskipHandle missing or incompatible text-encoder tensors by skipping them, substituting zeros where supported, or aborting.
output_filenameSTRINGextracted_te_loraOutput filename without extension, written under the ComfyUI LoRA directory.
save_dtypeCOMBOfp16Data type used to save extracted text-encoder LoRA factors.
deviceCOMBOcudaDevice used for per-layer extraction arithmetic; CUDA out-of-memory retries the affected layer on CPU where supported.
skip_patternsSTRINGPatterns for layers to skip (regex or glob depending on glob_skip_patterns)
glob_skip_patternsBOOLEANfalseWhen True, skip_patterns use glob syntax (* = any sequence, ? = any char, dots are literal). When False (default), patterns are Python regex matched as substrings.
include_modeBOOLEANfalseUse Skip Patterns as a whitelist instead. Only matching layers are extracted; an empty whitelist extracts nothing.
layer_parametersoptMODELUTILS_LAYER_PARAMETERSOptional Layer Parameter Configuration. a=linear_ratio; b=conv_ratio; c=clamp_quantile; d=min_diff; e=linear_max_rank; f=conv_max_rank Full names are also accepted. Unassigned values use this node's settings; existing filters still apply.

Outputs (1)

NameTypeDescription
output_path*—