fix(lora): apply te networks before encode and honor lora_apply_te

Network activation ran after prompt encoding, so text encoder lora
weights never affected embeds on the first generation and the stale
result was then served from the embed cache. The trailing unfiltered
activate in network_load also overrode the te exclude filter, so the
lora_apply_te setting was never honored.

- parse and activate networks in process_base before pipeline args are built
- activate_filtered gates text encoder components on per-request or global
  lora_apply_te; used by base, hires, detailer and faceid call sites
- network_load accepts activate=False for callers that run their own
  deactivate/activate sequence with include/exclude
- network_activate walks excluded components in restore-only mode so a
  filtered text encoder reverts to backup instead of keeping stale deltas
- loaded_loras cache is single-entry since per-filter entries go stale when
  the setting toggles
- prompt embed cache key includes the effective lora_apply_te value
This commit is contained in:
CalamitousFelicitousness
2026-07-08 03:06:04 +01:00
parent 917dd3a109
commit 4554b9a277
9 changed files with 42 additions and 20 deletions
+3 -4
View File
@@ -147,6 +147,8 @@ def process_base(p: processing.StableDiffusionProcessing):
desc = 'Base'
if 'detailer' in p.ops:
desc = 'Detail'
p.prompts, p.network_data = extra_networks.parse_prompts(p.prompts, p.network_data)
extra_networks.activate_filtered(p) # networks must patch weights before prompt encode so te loras affect embeds
base_args = set_pipeline_args(
p=p,
model=shared.sd_model,
@@ -176,9 +178,6 @@ def process_base(p: processing.StableDiffusionProcessing):
modelstats.analyze()
try:
t0 = time.time()
p.prompts, p.network_data = extra_networks.parse_prompts(p.prompts, p.network_data)
extra_networks.activate(p, exclude=['text_encoder', 'text_encoder_2', 'text_encoder_3'])
if hasattr(shared.sd_model, 'tgate') and getattr(p, 'gate_step', -1) > 0:
base_args['gate_step'] = p.gate_step
output = shared.sd_model.tgate(**base_args) # pylint: disable=not-callable
@@ -311,7 +310,7 @@ def process_hires(p: processing.StableDiffusionProcessing, output):
prompts, p.network_data = extra_networks.parse_prompts(prompts)
reset_prompts = True
if reset_prompts or ('base' in p.skip):
extra_networks.activate(p)
extra_networks.activate_filtered(p)
hires_args = set_pipeline_args(
p=p,