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

TE LoRA Extract (Quantile)

Keep enough singular values to reach 90%

By silveroxides·Created 2 years ago·Updated 3 days ago· 17
TE LoRA Extract (Quantile)
  • layer_parameters
  • output_path
◄model_a▾►
◄model_b▾►
◄linear_quantile0.90►
◄conv_quantile0.90►
◄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►

Here's the friendliest way to think about a LoRA rank: "how much of the signal do I keep?" This node turns that sentence into a number. You extract a LoRA from a fine-tuned text encoder minus its base, and instead of picking a rank you tell it to keep enough singular values to reach a target percentage of the total - 90% by default. It's the quantile variant of the ModelUtils TE extractors, and it's the one that reads most naturally if you're new to this.

The mechanism is the pack's standard extraction pipeline: for each .weight tensor, compute A - B, run SVD, and keep singular values until their cumulative sum crosses the target fraction. Layers that are mostly noise stop early and stay cheap; layers with real structure get the rank they earn. The result is written as PEFT-style lora_A/lora_B factors into your loras folder, ready for a normal LoraLoader. If the target fraction demands a rank as big as the layer itself, the node just saves the full difference instead of pretending a decomposition helps.

The inputs that matter

  • model_a / model_b - the fine-tuned and base text encoders from models/text_encoders.
  • linear_quantile / conv_quantile - the cumulative singular-value target for linear/attention vs convolution layers (default 0.9). 0.9 keeps enough rank to cover 90% of the spectrum's mass; bump toward 1.0 for higher fidelity at a bigger file, drop it for compression.
  • linear_max_rank / conv_max_rank - safety caps (default 128) so one outlier layer can't balloon the rank.
  • probe_offset - extra singular values sampled beyond the cap so the "have we hit 90% yet?" decision is made against a spectrum that isn't truncated mid-answer.
  • output_filename / save_dtype / device / lazy_load / force_clear_cache - the usual shared knobs: output name, save precision (fp16 default), compute device (with per-layer CPU fallback on OOM), and streaming vs. eager memory behavior.

Like the other extractors it's an output node: it writes the file and reports output_path. Nothing hangs off it.

Install

Search "Model Utility Toolkit" in ComfyUI Manager, or:

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

Restart, and it lives under ModelUtils/LoRA Extract (TE). The dependency doing the heavy lifting is unifiedefficientloader, which lets the node stream both encoders instead of loading them fully.

Watch out

The silent-skip trap is real here too: default mismatch_mode: skip means mismatched or missing tensors disappear without a peep, so comparing an encoder to the wrong base quietly produces a nearly-empty file. And this is a full SVD per layer, so expect minutes of progress bar, not instant. If 90% of the spectrum sounds arbitrary, it is - the Knee variant's whole job is removing that guess, and Frobenius lets you set the target in terms of energy rather than singular-value mass. Quantile is the middle ground: explicit, interpretable, and usually right at 0.9.

CategoryModelUtils/LoRA Extract (TE)

Inputs (20)

NameTypeDefaultDescription
model_aCOMBOFinetuned Text Encoder model (A - B = LoRA)
model_bCOMBOBase Text Encoder model (A - B = LoRA)
linear_quantileFLOAT0.900–1Target cumulative singular-value fraction for linear layers.
conv_quantileFLOAT0.900–1Target cumulative singular-value fraction for convolution layers.
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_quantile; b=conv_quantile; 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*—