fix(lora): promote per-network multipliers after the removal pass

Cached networks are shared objects, and network_load overwrote their
multipliers before network_deactivate ran, so fuse-mode removal recomputed
the subtraction delta with the new values: a strength edit froze at its
first applied value and a later removal left residue in the model weights.
network_load now stages the values on the net and network_activate promotes
them, so the removal pass always subtracts the delta that was applied.
Backup mode restores from stored tensors and was unaffected.
This commit is contained in:
CalamitousFelicitousness
2026-07-26 21:18:14 +01:00
parent bf0be3da69
commit 76d76be4b7
3 changed files with 12 additions and 3 deletions
+5 -3
View File
@@ -305,9 +305,11 @@ def network_load(names, te_multipliers=None, unet_multipliers=None, dyn_dims=Non
continue
if hasattr(sd_model, 'embedding_db'):
sd_model.embedding_db.load_diffusers_embedding(None, net.bundle_embeddings)
net.te_multiplier = te_multipliers[i] if te_multipliers else shared.opts.extra_networks_default_multiplier
net.unet_multiplier = unet_multipliers[i] if unet_multipliers else shared.opts.extra_networks_default_multiplier
net.dyn_dim = dyn_dims[i] if dyn_dims else None # a multiplier is not a rank; float dyn_dim crashes every consumer that slices with it
net.pending_config = { # staged, not assigned: cached nets are shared objects and network_deactivate must still see the multipliers that were applied
'te': te_multipliers[i] if te_multipliers else shared.opts.extra_networks_default_multiplier,
'unet': unet_multipliers[i] if unet_multipliers else shared.opts.extra_networks_default_multiplier,
'dyn': dyn_dims[i] if dyn_dims else None, # a multiplier is not a rank; float dyn_dim crashes every consumer that slices with it
}
l.loaded_networks.append(net)
while len(lora_cache) > shared.opts.lora_in_memory_limit:
+1
View File
@@ -148,6 +148,7 @@ class Network: # LoraModule
self.te_multiplier = 1.0
self.unet_multiplier = [1.0] * 3
self.dyn_dim = None
self.pending_config = None # staged multipliers; network_activate promotes them after the removal pass so fuse removal subtracts the delta that was applied
self.modules = {}
self.bundle_embeddings = {}
self.mtime = None
+6
View File
@@ -18,6 +18,12 @@ def network_activate(include=None, exclude=None):
exclude = []
if include is None:
include = []
for net in l.loaded_networks: # promote staged multipliers only now: the deactivate pass ran against the previous values, which fuse-mode removal recomputes with
pending = getattr(net, 'pending_config', None)
if pending is not None:
net.te_multiplier = pending['te']
net.unet_multiplier = pending['unet']
net.dyn_dim = pending['dyn']
t0 = time.time()
with limit_errors("network_activate") as elimit:
sd_model = getattr(shared.sd_model, "pipe", shared.sd_model)