Nodes/LoRA Optimizer/LoRA Optimizer (Legacy)
ComfyUI Node

LoRA Optimizer (Legacy)

Stop hand-tuning strengths, let it find the conflicts

By ethanfel·Created 5 months ago·Updated 23 days ago· 135
LoRA Optimizer (Legacy)
  • model
  • lora_stack
  • clip
  • tuner_data
  • model
  • clip
  • analysis_report
  • tuner_data
  • lora_data
output_strength1.00
clip_strength_multiplier1.00
auto_strengthenabled
auto_strength_floor-1.00
free_vram_between_passesdisabled
vram_budget0.00
optimization_modeper_prefix
cache_patchesenabled
patch_compressionsmart
svd_devicegpu
normalize_keysenabled
sparsificationdisabled
sparsification_density0.70
dare_dampening0.00
merge_refinementnone
strategy_setfull
architecture_presetauto
merge_strategy_override
settings_sourcemanual
decision_smoothing0.25
smooth_slerp_gatefalse

Stack two or three LoRAs together - a style, a character, maybe a lighting LoRA - and you'll eventually hit the thing everyone hits: oversaturated colors, weird artifacts, or a face that looks subtly wrong in a way no single LoRA does on its own. It's a known, common complaint, not a you-problem. The usual fix is trial-and-error strength tweaking. LoRA Optimizer does something more useful: it actually looks at where your LoRAs disagree, layer by layer, and picks a sensible way to combine them instead of you guessing.

The "(Legacy)" in the display name is worth explaining up front. The pack now ships a newer, modular Optimizer + Settings-node combo, and this node is the older all-in-one version where every parameter - sparsification, merge quality, architecture preset, the works - lives directly on the node instead of behind a separate Settings node. It's not deprecated or broken; it's simply the version that predates the split, and it's still the one the pack's AutoTuner-bridge workflow requires. If you just want to point LoRAs at it and get a good merge without thinking about the settings split, this is the one to use.

How it works

The node runs a two-pass streaming pipeline. Pass 1 aggregates conflict and magnitude statistics per weight group and discards the raw diffs, keeping only lightweight scalars. Pass 2 recomputes each group's diff and decides a strategy for it specifically: a group only one LoRA touches gets weighted_sum at full strength; low-conflict overlapping groups get weighted_average; genuinely conflicting groups get TIES-Merging (trim, elect sign, disjoint merge), which resolves the disagreement instead of averaging it into mush. That per-group granularity is the actual insight - a face LoRA and a style LoRA might only clash in a handful of attention layers, and blanket-averaging the whole model would waste correction on the 90% that never conflicted.

The inputs and outputs that matter

  • model and lora_stack (required) - your base checkpoint and a LoRA Stack node's output. This is the list of LoRAs actually being merged.
  • output_strength (default 1.0) - master volume on the merged result. Set it to -1 for auto, which lets the optimizer pick a strength that compensates for energy naturally lost during merging - the easiest way to stop fiddling with this by hand.
  • clip (optional) - plug in your text encoder so merged LoRAs also affect prompt understanding; leave it disconnected for video models that don't use CLIP.
  • auto_strength (default enabled) - the setting doing the most work behind the scenes. It automatically turns down individual LoRA strengths before merging so 3+ stacked LoRAs at full strength don't blow out into an oversaturated mess. Leave it on unless you have a specific reason not to.
  • optimization_mode (default per_prefix) - how strategies get picked. additive (simple weighted addition, no conflict resolution) is the one to switch to for edit, distillation, or DPO LoRAs - more on why below.
  • Everything else - sparsification, merge_refinement, strategy_set, decision_smoothing - is quality/interference tuning for harder merges; the defaults are sensible, and the companion LoRA Merge Settings node covers the rescue knobs if a merge still comes out wrong.

Outputs: model/clip wire straight into your sampler. analysis_report (a STRING) is genuinely worth connecting to a Show Text node the first time you use this - it prints exactly which strategy each layer got and why. lora_data feeds Save Merged LoRA if you want the result as a portable file. tuner_data and settings_source exist for chaining with the LoRA AutoTuner - run the AutoTuner to find the best config, then switch this node to manual and tweak from its recommendation.

Installing it

ComfyUI Manager: search "LoRA Optimizer," install, restart. Manual:

cd ComfyUI/custom_nodes/
git clone https://github.com/ethanfel/ComfyUI-LoRA-Optimizer.git

Restart ComfyUI - nodes appear under loaders. No models to download and no unusual dependencies; it runs on the tensors your LoRA Stack already loaded.

Common issues & troubleshooting

Don't put distillation, edit, or DPO LoRAs in the stack. This is the pack's own explicit warning: distillation LoRAs like LCM, Lightning, Turbo, and Hyper carry precisely calibrated weights that a conflict-aware merge can quietly break. Apply those through a normal Load LoRA node upstream, and feed only style/character LoRAs into the optimizer. If you must include one, switch optimization_mode to additive and disable sparsification so nothing gets trimmed out from under it.

It only sees LoRAs in its own stack. If your workflow already runs LoRAs through regular Load LoRA nodes upstream, this optimizer has no visibility into them - those patches just stack additively on top of whatever it merges. The pack ships a separate LoRA Optimizer (Inline Chain) node for exactly that situation; it isn't this one.

The merge is still oversaturated after all this. Check auto_strength is actually enabled first - it's the single biggest lever. If it's on and the result is still fried, that's what the tame_layers setting on the LoRA Merge Settings node exists for.

Running out of VRAM on merge_refinement=full. The SVD alignment step (KnOTS) uses more VRAM than the default; drop to refine or none, or set svd_device to cpu.

CategoryLoRA Optimizer

Inputs (25)

NameTypeDefaultDescription
modelMODELYour base model (e.g. SDXL, Flux). The merged LoRAs will be applied to it.
lora_stackLORA_STACKConnect a LoRA Stack node here. This is the list of LoRAs you want to merge together.
output_strengthFLOAT1.00-1–10Master volume for the merged result. 1.0 = full effect, 0.5 = half, 0 = disabled. Set to -1 for auto: uses the suggested max strength (compensates for energy lost during merge).
clipoptCLIPThe text encoder. Connect this so LoRAs can also affect how your prompts are understood. Leave empty for video models that don't use CLIP.
clip_strength_multiplieroptFLOAT1.000–10How strongly LoRAs affect text understanding, relative to output_strength. At 1.0, CLIP uses the same strength as the model. Lower values reduce LoRA influence on prompt interpretation while keeping the visual effect.
auto_strengthoptCOMBOenabledAutomatically turns down individual LoRA strengths when combining many LoRAs to avoid oversaturated or distorted results. Useful when stacking 3+ LoRAs.
auto_strength_flooroptFLOAT-1.00-1–1Floor on how much auto-strength may shrink your LoRA strengths — a uniform down-scale multiplier (never scales UP, never flips signs). 1.0 = don't shrink at all, 0.5 = shrink to at most half, 0 = no floor at all (remove the limit — auto-strength may shrink strengths all the way down), -1 = architecture-aware default (higher for motion-heavy video, lower for image models). Applies to negative LoRAs by magnitude (−1.75 → −1.49 at 0.85, sign kept) and to >1.0 strengths. An explicit value ≥0 applies to EVERY stack, not just orthogonal ones.
free_vram_between_passesoptCOMBOdisabledFrees GPU memory between processing steps. Enable if you're running out of VRAM. Barely affects speed.
vram_budgetoptFLOAT0.000–1Fraction of free VRAM to use for storing merged patches. 0 = all CPU (default), 1.0 = use all free VRAM. Reduces RAM usage on GPU systems.
optimization_modeoptCOMBOper_prefixHow the optimizer decides to combine LoRAs. 'per_prefix' (recommended): automatically picks the best method for each layer. 'global': uses one method everywhere. 'additive': simple weighted addition with no conflict resolution — preserves all weights exactly. Use for edit, distillation, or DPO LoRAs. (Previously: 'additive' was called 'weighted_sum_only'.)
cache_patchesoptCOMBOenabledKeep the merge result in memory so re-running the workflow is instant (no re-merge needed). Disable to save RAM — recommended for large video models like Wan or LTX.
patch_compressionoptCOMBOsmartShrink the merged result to use less memory. 'smart' (recommended): compresses layers where it's lossless, skips layers that already went through rank reduction. 'aggressive': compresses everything including rank-reduced layers — saves the most memory but slightly lossy. 'disabled': no compression, uses more RAM. (Previously: this setting was called 'compress_patches' with values non_ties/all/disabled.)
svd_deviceoptCOMBOgpuWhere to run compression math. GPU is much faster (10-50x). Switch to CPU only if you get out-of-memory errors during the merge.
normalize_keysoptCOMBOenabledRemaps LoRA keys to a canonical format so LoRAs from different training tools (Kohya, AI-Toolkit, PEFT, Musubi Tuner) can be merged correctly. Also splits fused QKV into separate Q/K/V for per-component conflict analysis. Recommended to keep enabled — disable only if it causes issues with unusual LoRA formats.
sparsificationoptCOMBOdisabledReduces interference between LoRAs by sparsifying weights before merging. DARE: random dropout everywhere. DELLA: magnitude-aware dropout everywhere. Conflict variants (recommended): same algorithms but ONLY applied where LoRAs push in opposite directions — unique contributions are preserved untouched.
sparsification_densityoptFLOAT0.700.01–1What percentage of weights to keep (0.7 = keep 70%, drop 30%). Lower values drop more weights — reduces interference but may lose detail. At 1.0, no weights are dropped (equivalent to disabled). Note: in TIES mode, sparsification replaces the trim step — setting density to 1.0 disables both sparsification AND trimming.
dare_dampeningoptFLOAT0.000–1DAREx dampening: reduces the aggressiveness of DARE's rescaling factor. At 0.0 (default): standard DARE rescaling (1/density). At higher values: dampened rescaling that reduces noise amplification at low density values. Only affects DARE/DARE-conflict modes. Based on DAREx (ICLR 2025).
merge_refinementoptCOMBOnoneOptional preprocessing steps applied to weight diffs before merging. none: merge as-is, no extra processing. refine: adds direction orthogonalization + selfish weight protection (TALL-masks) to reduce interference between LoRAs (minimal extra compute). full: adds SVD alignment (KnOTS) on top of refine for maximum interference reduction (uses more VRAM for SVD decomposition). Higher levels help most when LoRAs have high conflict; for low-conflict or orthogonal LoRAs, 'none' is usually fine. (Previously: this setting was called 'merge_quality' with values standard/enhanced/maximum.)
strategy_setoptCOMBOfullWhich merge strategies the auto-selector can choose from. 'full': all strategies available (consensus, SLERP, orthogonal detection). 'no_slerp': same detection logic but SLERP is excluded (weighted_average stays as-is). 'basic': only TIES vs weighted_average, no advanced strategy selection. (Previously: this setting was called 'behavior_profile' with values v1.2/no_slerp/classic.)
architecture_presetoptCOMBOautoArchitecture-aware threshold tuning. 'auto' detects from LoRA keys. 'sd_unet': SD/SDXL UNet defaults. 'dit': DiT models (Flux, WAN, Z-Image, LTX, HunyuanVideo) with higher density floors and wider strength range. 'acestep_dit': ACE-Step music DiT — tuned for voice preservation with wider orthogonal band and conservative TIES threshold. 'llm': LLM-based models (Qwen, LLaMA).
merge_strategy_overrideoptSTRINGConnect the merge_strategy output from a LoRA Conflict Editor to override the optimizer's auto-detected strategy.
settings_sourceoptCOMBOmanualmanual: use widget settings. from_autotuner: passthrough when chained with a live AutoTuner. from_tuner_data: apply the top-ranked config from loaded tuner data (use with Load Tuner Data).
tuner_dataoptTUNER_DATAConnect from the LoRA AutoTuner's tuner_data output. Used when settings_source is 'from_autotuner'.
decision_smoothingoptFLOAT0.250–1Smooth per-group strategy metrics toward each block's average before Pass 2 decisions. 0 disables smoothing; 0.2-0.4 usually removes noisy mode flips without washing out real differences.
smooth_slerp_gateoptBOOLEANfalseWhen enabled, uses smoothed cosine (decision_cosine) for SLERP gate instead of raw avg_cos_sim. Can affect SLERP/weighted_average ratio.

Outputs (5)

NameTypeDescription
modelMODEL
clipCLIP
analysis_reportSTRING
tuner_dataTUNER_DATA
lora_dataLORA_DATA