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

TE LoRA Extract (Ratio)

Keep the singular values that actually matter

By silveroxides·Created about a year ago·Updated about 24 hours ago· 14
TE LoRA Extract (Ratio)
    • 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

    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 (18)

    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.

    Outputs (1)

    NameTypeDescription
    output_path*