From e2202bfbdfc8a7b6592287acac9d74792e1a3f0c Mon Sep 17 00:00:00 2001 From: CalamitousFelicitousness Date: Sat, 18 Jul 2026 03:32:53 +0100 Subject: [PATCH] feat(lora): log exact side-channel applies The exact factor path was the only apply route with no log line; its success read as silence. Track layers taking it beside the hosted and fallback lists and report all three as key=value apply lines (apply=exact/hosted/requantize); the stack fallback notices use the same form. The suite pins its stack-mode baseline to sum so a mode left set in user config cannot reroute tests that assume plain summation. --- modules/lora/extra_networks_lora.py | 2 +- modules/lora/lora_sdnq.py | 10 ++++++++-- modules/lora/lora_stack.py | 6 +++--- modules/lora/networks.py | 1 + test/test-sdnq-lora-factors.py | 1 + 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/modules/lora/extra_networks_lora.py b/modules/lora/extra_networks_lora.py index c81b94072..bd44ba7f5 100644 --- a/modules/lora/extra_networks_lora.py +++ b/modules/lora/extra_networks_lora.py @@ -227,7 +227,7 @@ class ExtraNetworkLora(extra_networks.ExtraNetwork): load_method, load_reason = lora_overrides.get_method() from modules.lora import lora_stack if load_method != 'native' and lora_stack.mode() != 'sum': - lora_stack.warn_once(f'method-{load_method}', f'Network stack: mode={lora_stack.mode()} method={load_method} unsupported, using sum') + lora_stack.warn_once(f'method-{load_method}', f'Network stack: mode={lora_stack.mode()} method={load_method} fallback=sum') if debug: import sys fn = f'{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access diff --git a/modules/lora/lora_sdnq.py b/modules/lora/lora_sdnq.py index b1ef10d45..df2e7d2b0 100644 --- a/modules/lora/lora_sdnq.py +++ b/modules/lora/lora_sdnq.py @@ -55,6 +55,7 @@ from modules.logger import log fallback_layers: list[str] = [] hosted_layers: list[tuple[str, float, bool]] = [] hosted_ranks: list[int] = [] +factor_layers: list[str] = [] routed_layers: list[str] = [] REQUANT_RATIO = 0.30 # delta rms over mean grid step above which requantize can retain the delta @@ -211,6 +212,7 @@ def apply_factors(self, network_layer_name, wanted_names): if not ups: return changed append_factors(self, ups, downs) + factor_layers.append(network_layer_name) return True @@ -496,6 +498,7 @@ def apply_select(self, network_layer_name, per_net, wanted_names): del d0, d1 segments, transposed = append_factors(self, [pairs[0][0], pairs[1][0]], [pairs[0][1], pairs[1][1]]) lora_stack.register(network_layer_name, self, 'factor', scores, segments=(segments[0], segments[1], transposed), abs_sums=abs_sums) + factor_layers.append(network_layer_name) return True @@ -509,6 +512,9 @@ def report_fallbacks(): hits, misses = lora_factor_cache.flush() if hits > 0 or misses > 0: log.info(f'Network load: type=LoRA quant=sdnq cache hits={hits} misses={misses}') + if len(factor_layers) > 0: + log.info(f'Network load: type=LoRA quant=sdnq apply=exact layers={len(factor_layers)}') + factor_layers.clear() if len(hosted_layers) > 0: energies = sorted(e for _name, e, _c in hosted_layers) median = energies[len(energies) // 2] @@ -517,7 +523,7 @@ def report_fallbacks(): if len(hosted_ranks) > 0 and min(hosted_ranks) < int(shared.opts.lora_sdnq_host_rank): rs = sorted(hosted_ranks) ranks = f' k={rs[0]}-{rs[len(rs) // 2]}-{rs[-1]}' # realized rank spread; shown only when a spectrum collapsed below the cap - log.info(f'Network load: type=LoRA quant=sdnq hosted={len(hosted_layers)} rank={int(shared.opts.lora_sdnq_host_rank)}{ranks}{f" calib={calibrated}" if calibrated else ""} energy={median:.2f} min={energies[0]:.2f} non-factorable networks hosted on the svd side-channel') + log.info(f'Network load: type=LoRA quant=sdnq apply=hosted layers={len(hosted_layers)} rank={int(shared.opts.lora_sdnq_host_rank)}{ranks}{f" calib={calibrated}" if calibrated else ""} energy={median:.2f} min={energies[0]:.2f}') if l.debug: log.debug(f'Network load: type=LoRA quant=sdnq hosted={[(n, round(e, 3)) for n, e, _c in hosted_layers[:8]]}{"..." if len(hosted_layers) > 8 else ""}') hosted_layers.clear() @@ -529,7 +535,7 @@ def report_fallbacks(): routed_layers.clear() if len(fallback_layers) > 0: if enabled(): - log.warning(f'Network load: type=LoRA quant=sdnq layers={len(fallback_layers)} non-factorable networks requantized in place (reduced fidelity on quantized weights)') + log.warning(f'Network load: type=LoRA quant=sdnq apply=requantize layers={len(fallback_layers)} fidelity=reduced') else: log.info(f'Network load: type=LoRA quant=sdnq apply=requantize layers={len(fallback_layers)} reason=setting') if l.debug: diff --git a/modules/lora/lora_stack.py b/modules/lora/lora_stack.py index 313038b39..b1d889bda 100644 --- a/modules/lora/lora_stack.py +++ b/modules/lora/lora_stack.py @@ -78,10 +78,10 @@ def active_select(n_loaded): if m not in SELECT_MODES: return False if n_loaded != 2: - warn_once('select-count', f'Network stack: mode={m} networks={n_loaded} requires exactly 2, using sum') + warn_once('select-count', f'Network stack: mode={m} networks={n_loaded} required=2 fallback=sum') return False if select_blocked(): - warn_once('select-compile', f'Network stack: mode={m} disabled with model compile, using sum') + warn_once('select-compile', f'Network stack: mode={m} compile=model fallback=sum') return False return True @@ -290,7 +290,7 @@ def weight_selection(module, entry, winner): from modules.lora.lora_apply import network_apply_weights backup = getattr(module, 'network_weights_backup', None) if not isinstance(backup, torch.Tensor): # fuse mode keeps a bool sentinel, not a pristine copy - warn_once('select-nobackup', 'Network stack: select flip skipped, no weight backup') + warn_once('select-nobackup', 'Network stack: flip=skipped backup=none') return net = next((n for n in l.loaded_networks if n.name == entry['nets'][winner]), None) net_module = net.modules.get(entry['layer'], None) if net is not None else None diff --git a/modules/lora/networks.py b/modules/lora/networks.py index 59a66a6e0..be543d2b2 100644 --- a/modules/lora/networks.py +++ b/modules/lora/networks.py @@ -95,6 +95,7 @@ def network_activate(include=None, exclude=None): applied_layers.clear() lora_sdnq.fallback_layers.clear() # a raise mid-pass leaves stale entries behind lora_sdnq.hosted_layers.clear() + lora_sdnq.factor_layers.clear() backup_size = 0 for component in modules.keys(): component_wanted = wanted_names if component in components else () diff --git a/test/test-sdnq-lora-factors.py b/test/test-sdnq-lora-factors.py index b1e1881d4..7259cca26 100644 --- a/test/test-sdnq-lora-factors.py +++ b/test/test-sdnq-lora-factors.py @@ -82,6 +82,7 @@ from sdnq.quantizer import sdnq_quantize_layer, SDNQConfig # pylint: disable=wr DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu') OUT_F, IN_F, RANK = 512, 512, 8 +shared.opts.lora_stack_mode = 'sum' # suite baseline regardless of user config; stack tests set modes via their own context managers results: dict[str, dict] = {}