From 16293375dcaae6e3d365f1d99b205534c665a242 Mon Sep 17 00:00:00 2001 From: vladmandic Date: Sun, 18 Jan 2026 10:06:03 +0100 Subject: [PATCH] lora native stack improvements Signed-off-by: vladmandic --- CHANGELOG.md | 4 ++++ modules/extra_networks.py | 1 - modules/lora/extra_networks_lora.py | 18 ++++++++++++------ modules/lora/networks.py | 5 +++-- modules/processing_args.py | 3 ++- modules/shared.py | 2 ++ wiki | 2 +- 7 files changed, 24 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77a6b5bdb..437a68055 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,8 @@ For full list of changes, see full changelog. - persistent panel minimize/maximize state - gallery improve sorting behavior - **Internal** + - **lora** native support by default will now skip text-encoder + can be enabled in *settings -> networks* - update js linting to `eslint9`, thanks @awsr - update strong typing checks, thanks @awsr - update reference models previews, thanks @liutyi @@ -97,6 +99,8 @@ For full list of changes, see full changelog. - improve qwen i2i handling - networks filter by model type - netoworks icon/list view type switch, thanks @awsr + - lora skip with strength zero + - lora force unapply on change ## Update for 2025-12-26 diff --git a/modules/extra_networks.py b/modules/extra_networks.py index 8e4019ac4..054bc5c2b 100644 --- a/modules/extra_networks.py +++ b/modules/extra_networks.py @@ -108,7 +108,6 @@ def activate(p, extra_network_data=None, step=0, include=[], exclude=[]): if args is not None: continue try: - # extra_network.activate(p, []) signature = list(inspect.signature(extra_network.activate).parameters) if 'include' in signature and 'exclude' in signature: extra_network.activate(p, [], include=include, exclude=exclude) diff --git a/modules/lora/extra_networks_lora.py b/modules/lora/extra_networks_lora.py index 1c73712cd..882c0d91b 100644 --- a/modules/lora/extra_networks_lora.py +++ b/modules/lora/extra_networks_lora.py @@ -97,7 +97,7 @@ def parse(p, params_list, step=0): dyn_dims = [] lora_modules = [] for params in params_list: - names.append(params.positional[0]) + name = params.positional[0] default_multiplier = params.positional[1] if len(params.positional) > 1 else shared.opts.extra_networks_default_multiplier default_multiplier = to_float(default_multiplier) @@ -121,6 +121,11 @@ def parse(p, params_list, step=0): unet_multiplier[i] = to_float(unet_multiplier[i]) dyn_dim = int(params.named["dyn"]) if "dyn" in params.named else None + + if (te_multiplier == 0) and all(u == 0 for u in unet_multiplier): # skip lora with strength zero + continue + + names.append(name) te_multipliers.append(te_multiplier) unet_multipliers.append(unet_multiplier) dyn_dims.append(dyn_dim) @@ -180,7 +185,7 @@ class ExtraNetworkLora(extra_networks.ExtraNetwork): exclude = ['none'] key = f'include={",".join(include)}:exclude={",".join(exclude)}' loaded = sd_model.loaded_loras.get(key, []) - debug_log(f'Network load: type=LoRA key="{key}" requested={requested} loaded={loaded}') + debug_log(f'Network check: type=LoRA key="{key}" requested={requested} loaded={loaded}') if len(requested) != len(loaded): sd_model.loaded_loras[key] = requested return True @@ -223,18 +228,19 @@ class ExtraNetworkLora(extra_networks.ExtraNetwork): if has_changed: jobid = shared.state.begin('LoRA') if len(l.previously_loaded_networks) > 0: - shared.log.info(f'Network unload: type=LoRA apply={[n.name for n in l.previously_loaded_networks]} mode={"fuse" if shared.opts.lora_fuse_diffusers else "backup"}') + shared.log.info(f'Network unload: type=LoRA networks={[n.name for n in l.previously_loaded_networks]} mode={"fuse" if shared.opts.lora_fuse_native else "backup"}') networks.network_deactivate(include, exclude) networks.network_activate(include, exclude) - l.previously_loaded_networks = l.loaded_networks.copy() - debug_log(f'Network load: type=LoRA previous={[n.name for n in l.previously_loaded_networks]} current={[n.name for n in l.loaded_networks]} changed') + debug_log(f'Network change: type=LoRA previous={[n.name for n in l.previously_loaded_networks]} current={[n.name for n in l.loaded_networks]}') + if len(include) == 0: + l.previously_loaded_networks = l.loaded_networks.copy() shared.state.end(jobid) if len(l.loaded_networks) > 0 and (len(networks.applied_layers) > 0 or load_method=='diffusers' or load_method=='nunchaku') and step == 0: infotext(p) prompt(p) if has_changed and len(include) == 0: # print only once - shared.log.info(f'Network load: type=LoRA apply={[n.name for n in l.loaded_networks]} method={load_method} mode={"fuse" if shared.opts.lora_fuse_native else "backup"} te={te_multipliers} unet={unet_multipliers} time={l.timer.summary}') + shared.log.info(f'Network load: type=LoRA networks={[n.name for n in l.loaded_networks]} method={load_method} mode={"fuse" if shared.opts.lora_fuse_native else "backup"} te={te_multipliers} unet={unet_multipliers} time={l.timer.summary}') def deactivate(self, p, force=False): if len(lora_diffusers.diffuser_loaded) > 0: diff --git a/modules/lora/networks.py b/modules/lora/networks.py index 4294615c9..6d37fd656 100644 --- a/modules/lora/networks.py +++ b/modules/lora/networks.py @@ -7,6 +7,7 @@ from modules import shared, devices, sd_models applied_layers: list[str] = [] +default_components = ['text_encoder', 'text_encoder_2', 'text_encoder_3', 'text_encoder_4', 'unet', 'transformer', 'transformer_2'] def network_activate(include=[], exclude=[]): @@ -17,7 +18,7 @@ def network_activate(include=[], exclude=[]): sd_models.move_model(sd_model, device=devices.cpu) device = None modules = {} - components = include if len(include) > 0 else ['text_encoder', 'text_encoder_2', 'text_encoder_3', 'unet', 'transformer'] + components = include if len(include) > 0 else default_components components = [x for x in components if x not in exclude] active_components = [] for name in components: @@ -43,7 +44,7 @@ def network_activate(include=[], exclude=[]): for _, module in modules[component]: network_layer_name = getattr(module, 'network_layer_name', None) current_names = getattr(module, "network_current_names", ()) - if getattr(module, 'weight', None) is None or shared.state.interrupted or network_layer_name is None or current_names == wanted_names: + if getattr(module, 'weight', None) is None or shared.state.interrupted or (network_layer_name is None) or (current_names == wanted_names): if task is not None: pbar.update(task, advance=1) continue diff --git a/modules/processing_args.py b/modules/processing_args.py index 7f207eb5e..db64aa449 100644 --- a/modules/processing_args.py +++ b/modules/processing_args.py @@ -208,7 +208,8 @@ def set_pipeline_args(p, model, prompts:list, negative_prompts:list, prompts_2:t steps = kwargs.get("num_inference_steps", None) or len(getattr(p, 'timesteps', ['1'])) clip_skip = kwargs.pop("clip_skip", 1) - extra_networks.activate(p, include=['text_encoder', 'text_encoder_2', 'text_encoder_3']) + if shared.opts.lora_apply_te: + extra_networks.activate(p, include=['text_encoder', 'text_encoder_2', 'text_encoder_3']) parser = 'fixed' prompt_attention = prompt_attention or shared.opts.prompt_attention diff --git a/modules/shared.py b/modules/shared.py index 3f9d9a072..5deb96825 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -743,6 +743,8 @@ options_templates.update(options_section(('extra_networks', "Networks"), { "extra_networks_default_multiplier": OptionInfo(1.0, "Default strength", gr.Slider, {"minimum": 0.0, "maximum": 2.0, "step": 0.01}), "lora_force_reload": OptionInfo(False, "LoRA force reload always"), "lora_force_diffusers": OptionInfo(False if not cmd_opts.use_openvino else True, "LoRA load using Diffusers method"), + + "lora_apply_te": OptionInfo(False, "LoRA native apply to text encoder"), "lora_fuse_native": OptionInfo(True, "LoRA native fuse with model"), "lora_fuse_diffusers": OptionInfo(False, "LoRA diffusers fuse with model"), "lora_apply_tags": OptionInfo(0, "LoRA auto-apply tags", gr.Slider, {"minimum": -1, "maximum": 32, "step": 1}), diff --git a/wiki b/wiki index 47de6fa7c..e18041f2b 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 47de6fa7c0327cd221537498e3536d385c94534b +Subproject commit e18041f2bab7709706fe9205a8f27695e0a5af8f