From 1db6083645176a9b6e18d11425c4e795f44e0f7e Mon Sep 17 00:00:00 2001 From: Jaret Burkett Date: Thu, 17 Sep 2026 09:35:43 -0600 Subject: [PATCH] Show more information about LoRAs when loading loras in generate page --- toolkit/inference_lora.py | 52 +++++++++++++++++++++++++++++++----- ui/src/app/generate/page.tsx | 2 +- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/toolkit/inference_lora.py b/toolkit/inference_lora.py index caf8e90..d88a338 100644 --- a/toolkit/inference_lora.py +++ b/toolkit/inference_lora.py @@ -152,6 +152,9 @@ class InferenceLoRA: self.name = name or os.path.splitext(os.path.basename(path))[0] self.entries: List[LoRAEntry] = [] self.unmatched: List[str] = [] + self.num_keys = 0 # tensors in the file + self.num_skipped_keys = 0 # keys with no recognized lora/diff/lokr suffix + self.convert_error: Optional[str] = None self._hooks: List = [] # ---- loading / key resolution ---- @@ -163,18 +166,23 @@ class InferenceLoRA: # self.path stays as given: it is the spec identity the engine keys its # loaded stack on. self.local_path = resolve_lora_file(self.path, status_fn=status_fn) + if status_fn: + status_fn(f"Loading LoRA {self.name} from {self.local_path}") sd = load_file(self.local_path) + self.num_keys = len(sd) convert = getattr(holder, "convert_lora_weights_before_load", None) if callable(convert): try: sd = convert(sd) - except Exception: - pass + except Exception as e: + self.convert_error = f"{type(e).__name__}: {e}" roots = self._roots(holder) grouped: Dict[Tuple[int, str], dict] = {} + self.num_skipped_keys = 0 for key, tensor in sd.items(): base, part = self._split(key) if part is None: + self.num_skipped_keys += 1 continue grouped.setdefault(base, {})[part] = tensor self.entries = [] @@ -378,6 +386,35 @@ class InferenceLoRA: m_marker = getattr(self, "_marker", None) return merged + def report(self, max_unmatched: Optional[int] = None) -> str: + """Multi-line load report: file, key counts, matched/unmatched modules, unmatched names.""" + n_groups = len(self.entries) + len(self.unmatched) + lines = [ + f"LoRA {self.name}: {self.local_path or self.path}", + f" {self.num_keys} keys in file -> {n_groups} modules: {len(self.entries)} matched, {len(self.unmatched)} unmatched" + + (f", {self.num_skipped_keys} keys ignored (unrecognized suffix)" if self.num_skipped_keys else ""), + ] + if self.convert_error: + lines.append(f" convert_lora_weights_before_load failed, using raw keys: {self.convert_error}") + shown = self.unmatched if max_unmatched is None else self.unmatched[:max_unmatched] + for u in shown: + lines.append(f" unmatched: {u}") + if len(shown) < len(self.unmatched): + lines.append(f" ... {len(self.unmatched) - len(shown)} more unmatched") + return "\n".join(lines) + + def report_line(self, max_unmatched: int = 5) -> str: + """One-line form of report() for status strips.""" + n_groups = len(self.entries) + len(self.unmatched) + line = f"LoRA {self.name}: {len(self.entries)}/{n_groups} modules matched ({self.num_keys} keys)" + if self.unmatched: + shown = ", ".join(self.unmatched[:max_unmatched]) + more = len(self.unmatched) - max_unmatched + line += f"; {len(self.unmatched)} unmatched: {shown}" + (f" +{more} more" if more > 0 else "") + if self.convert_error: + line += f"; convert failed: {self.convert_error}" + return line + def summary(self) -> dict: return { "name": self.name, @@ -404,13 +441,14 @@ class LoRAStack: lora = InferenceLoRA(spec["path"], spec.get("strength", 1.0), spec.get("name")).load( self.holder, status_fn=status_fn ) + print(f"[AITK] {lora.report()}", flush=True) if status_fn: - status_fn( - f"LoRA {lora.name}: {len(lora.entries)} modules" - + (f", {len(lora.unmatched)} unmatched" if lora.unmatched else "") - ) + status_fn(lora.report_line()) if not lora.entries: - raise ValueError(f"LoRA {lora.name} matched no modules of this model (unmatched: {lora.unmatched[:3]})") + raise ValueError( + f"LoRA {lora.name} matched no modules of this model " + f"({lora.num_keys} keys, {len(lora.unmatched)} unmatched; see the engine job log for the list)" + ) self.loras.append(lora) return self diff --git a/ui/src/app/generate/page.tsx b/ui/src/app/generate/page.tsx index e930ace..32e6fd4 100644 --- a/ui/src/app/generate/page.tsx +++ b/ui/src/app/generate/page.tsx @@ -823,7 +823,7 @@ function GeneratePageInner() { {/* status strip over the stage */}
{running && } - + {running ? statusLine : selected