fix(lora): restore first-LoRA state-dict cache and fix v2 IS_CHANGED

Post-merge additional fixes for PR #52 (per md/PR52_MERGE_PLAN.md):

- compose_loras_v2: restore _cached_first_lora_state_dict so the first
  LoRA state dict loaded during section-3 debug inspection is reused in
  the section-4 main loop. Without this the first LoRA is read from disk
  twice whenever the precompiled cache is disabled (default).
- qwenimage_v2.py IS_CHANGED: drop the `model` arg (ComfyUI never passes
  MODEL inputs to IS_CHANGED; the TypeError -> NaN path forced re-compose
  every run) and remove str(model) from the hash (object repr changes
  every run, which also forced constant re-execution).
This commit is contained in:
ussoewwin
2026-07-23 14:25:17 +09:00
parent 2e1539030c
commit b683f8a2bd
2 changed files with 10 additions and 3 deletions
+1 -2
View File
@@ -30,14 +30,13 @@ class NunchakuQwenImageLoraStackV2:
Node for loading and applying multiple LoRAs to a Nunchaku Qwen Image model with dynamic UI.
"""
@classmethod
def IS_CHANGED(cls, model, lora_count, cpu_offload="disable", save_precompiled_lora=False, **kwargs):
def IS_CHANGED(cls, lora_count, cpu_offload="disable", save_precompiled_lora=False, **kwargs):
"""
Detect changes to trigger node re-execution.
Returns a hash of relevant parameters to detect changes.
"""
import hashlib
m = hashlib.sha256()
m.update(str(model).encode())
m.update(str(lora_count).encode())
m.update(cpu_offload.encode())
m.update(str(kwargs.get("apply_awq_mod", False)).encode())
+9 -1
View File
@@ -1315,6 +1315,8 @@ def compose_loras_v2(
# --- 3. Debug Inspection (First LoRA) ---
# Safe unpack: entries may be 2-tuples (path, strength) or 3-tuples
# (path, strength, meta_dict) when the cache meta-dict is attached by the node.
# OPTIMIZATION: Cache first LoRA state dict for reuse in the processing loop
_cached_first_lora_state_dict = None
if lora_configs:
_first_entry = lora_configs[0]
first_lora_path_or_dict = _first_entry[0]
@@ -1336,6 +1338,7 @@ def compose_loras_v2(
_first_detection = {"has_standard": True, "details": "Standard LoRA (Precompiled Cache)"}
else:
first_lora_state_dict = _load_lora_state_dict_robust(first_lora_path_or_dict)
_cached_first_lora_state_dict = first_lora_state_dict # Cache for reuse in main loop
# Simple logging of format detection
_first_detection = _detect_lora_format(first_lora_state_dict)
_log_lora_format_detection(str(first_lora_path_or_dict)[:50], _first_detection)
@@ -1417,7 +1420,12 @@ def compose_loras_v2(
# ------------------------------------------------------------------ #
# NORMAL (FULL) FUSE PATH #
# ------------------------------------------------------------------ #
lora_state_dict = _load_lora_state_dict_robust(lora_path_or_dict)
# Reuse first LoRA state dict cached during debug inspection (avoids double-read)
# Skip reuse when precompiled cache is enabled (matches original flow)
if idx == 0 and _cached_first_lora_state_dict is not None and _cache_path is None:
lora_state_dict = _cached_first_lora_state_dict
else:
lora_state_dict = _load_lora_state_dict_robust(lora_path_or_dict)
if not lora_state_dict:
continue