From c6865feac66437ec6fef68994c0981adefc62ea5 Mon Sep 17 00:00:00 2001 From: IAMCCS Date: Wed, 19 Nov 2025 12:59:39 +0100 Subject: [PATCH] Updated IAMCCS-nodes to version 1.3.0 --- CHANGELOG.md | 16 ++ README.md | 99 ++++++++++++- __init__.py | 26 +++- assets/LORAQWEN.png | Bin 0 -> 50616 bytes assets/lora_stack_model_I_O.png | Bin 0 -> 38131 bytes iamccs_qwen_lora_loader.py | 254 ++++++++++++++++++++++++++++++++ iamccs_qwen_monkeypatch.py | 56 +++++++ iamccs_wan_lora_stack_simple.py | 112 ++++++++++++++ pyproject.toml | 4 +- version.json | 4 +- 10 files changed, 560 insertions(+), 11 deletions(-) create mode 100644 assets/LORAQWEN.png create mode 100644 assets/lora_stack_model_I_O.png create mode 100644 iamccs_qwen_lora_loader.py create mode 100644 iamccs_qwen_monkeypatch.py create mode 100644 iamccs_wan_lora_stack_simple.py diff --git a/CHANGELOG.md b/CHANGELOG.md index f66df22..baa3be6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## 🆕 Version 1.3.0 — MODEL In→Out LoRA Stack & Qwen Loader Docs + +Date: 2025-11-19 + +Changes: +- Added new node `IAMCCS_WanLoRAStackModelIO` ("LoRA Stack (Model In→Out) WAN") for direct multi-LoRA application to an incoming MODEL (WAN 2.2 / Flow / Standard). +- Preserves WAN key remap + optional chaining via existing `IAMCCS_WanLoRAStack` (use optional `lora` input to extend beyond 4 slots). +- Updated `README.md` with explicit low VRAM instructions for Qwen Image LoRA loader and dependency checklist (`ComfyUI-nunchaku`, `ComfyUI-QwenImageLoraLoader`). +- Bumped versions (`version.json`, `pyproject.toml`) to 1.3.0. +- Neutralized deprecated Save&Load DragCrop code (frontend/backend) — removed from active registration. + +Notes: +- Existing workflows using the older two-node stack + apply pattern continue to work unchanged. +- Use `IAMCCS_WanLoRAStackModelIO` to simplify WAN 2.2 graphs or reduce node count before samplers. + +--- ## 🆕 Version 1.2.3 — Stackable LoRA Input - Added optional `lora` input to IAMCCS_WanLoRAStack node diff --git a/README.md b/README.md index 1d3ee88..cb9a7d3 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,47 @@ ### Category: ComfyUI Custom Nodes ### Main Feature: Fix for LoRA loading in native WANAnimate workflows -Version: 1.2.3 +Version: 1.3.0 -# UPDATE VERSION 1-2-3 +# UPDATE VERSION 1-3-0 -## 🆕 Version 1.2.3 — New input lora - add another StackLoraModel (concatenate) + Extended Wan 2.1 Compatibility +## 🆕 Version 1.3.0 — New MODEL IO LoRA Stack + Qwen Loader Instructions -Version: 1.2.1 +Highlights: +- Added `LoRA Stack (Model In→Out) WAN` node: directly applies up to 4 WAN / Flow / Standard LoRAs to an incoming MODEL and outputs a patched MODEL (ideal for WAN 2.2 workflows where a single node step is preferred). +- Qwen Image LoRA (IAMCCS QwenImgLoadFix) – Updated for 1.3.0: a fixed Qwen Image LoRA loader with improved offload controls and UX. +- Extended internal WAN key remapping for seamless WAN 2.2 (Flow) + WAN 2.1 cross-compatibility. +- Documentation updated with explicit Qwen Image LoRA loader prerequisites for low VRAM users (nunchaku based). +- Version bump across project files. + +### New Node: LoRA Stack (Model In→Out) WAN + +![Node piece no_7](assets/lora_stack_model_I_O.png)lora_stack_model_I_O.png + +Use this node when you already have a base MODEL loaded (WAN 2.2, Flow, SDXL, etc.) and want a single pass application of multiple LoRAs without an intermediate stack/output hand-off. It mirrors the behavior of the classic stack + apply pair but merges them for simpler graphs (especially animation or chained sampler pipelines). + +Inputs: +- `model`: base diffusion MODEL. +- `lora1..lora4` + `strength1..strength4` (skips if "no" or strength == 0.0) +- `model_type`: choose `flow`, `wan2x`, or `standard` to control remapping logic. +- Optional `lora` (LORA) input: allows concatenating a previously built stack from `IAMCCS_WanLoRAStack` for more than 4 total LoRAs. + +Output: +- Patched `MODEL` ready for samplers / video pipelines. + +Recommended Use (WAN 2.2 workflows): +1. Load base WAN 2.2 / LightX2V model. +2. Add `LoRA Stack (Model In→Out) WAN` and select up to 4 LoRAs. +3. (Optional) Chain a classic `IAMCCS_WanLoRAStack` into the optional `lora` input if you need >4. +4. Connect output to KSampler / Animate nodes. + +Why this node: Eliminates one extra node hop, reduces graph complexity and clarifies model lineage in large animation workflows. + +## Previous Versions + +### Version 1.2.3 — New input lora - add another StackLoraModel (concatenate) + Extended Wan 2.1 Compatibility + +### Version 1.2.1 # UPDATE VERSION 1-2-1 @@ -71,7 +105,7 @@ Ideal for WANAnimate, WANVideo, or any Flow-based cinematic model. ![Node piece no_3](assets/ensemble.png) -# New version 1.2.3!! Lora concatenate!! You can add another Lora stack to the node! +# LoRA Concatenation (1.2.3) ![Node piece no_4](assets/lora_concatenatel.png)lora_concatenatel.png @@ -128,3 +162,58 @@ This modular architecture makes LoRA management in WANAnimate flexible, transpar Buy Me A Coffee + +--- + +## Qwen Image LoRA (IAMCCS QwenImgLoadFix) – Updated for 1.3.0 + +This repo ships a fixed Qwen Image LoRA loader with improved offload controls and UX. + +![Node piece no_5](assets/LORAQWEN.png)LORAQWEN.png + +### Prerequisites (Low VRAM Friendly) +Required: +- ComfyUI (≥ 0.3.0) +- `ComfyUI-nunchaku` (Qwen Image / Sana transformer implementation) +- `ComfyUI-QwenImageLoraLoader` (wrappers.qwenimage module with `ComfyQwenImageWrapper`) +- Qwen Image model weights placed as per nunchaku loader instructions +- LoRA files (`.safetensors`) in `ComfyUI/models/loras` + +Recommended for low VRAM systems: +- Enable `offload_auto_tune` (auto scales transformer block residency) +- Set `offload_policy=disable` only if you experience instability during composition (keeps everything on GPU while LoRAs active) +- Keep `offload_num_blocks_on_gpu` low (1–2) if VRAM < 12 GB + +### Node Overview +`IAMCCS QwenImgLoadFix` +- Wraps a `NunchakuQwenImageTransformer2DModel` / `NunchakuSanaTransformer2DModel` if not already wrapped. +- Adds LoRA via internal wrapper (`model_wrapper.loras.append(...)`) with strength preset. +- Supports composition modes: + - `append`: legacy shape-changing approach + - `merge_v2`: in-place delta merge (preferred; no rank expansion) +- Offload Controls: dynamic, rebuild or disable strategies; pin-memory toggle; auto-tune; VRAM margin. +- Device Safety: ensures params & buffers migrate to correct CUDA device before forward. + + + +### Dependency Checklist +| Component | Purpose | +|-----------|---------| +| ComfyUI-nunchaku | Provides transformer class loaded by base model node | +| ComfyUI-QwenImageLoraLoader | Supplies `wrappers/qwenimage.py` used for wrapping | +| IAMCCS-nodes | Adds fixed loader + WAN LoRA stack system | +| LoRA safetensors | User-provided style/character adapters | + +If `wrappers/qwenimage.py` is not found the node will raise an import error. Ensure `ComfyUI-QwenImageLoraLoader` repository resides in `custom_nodes/`. + +### Quick Start (Low VRAM Scenario) +1. Load Qwen Image model (nunchaku loader node). +2. Place `IAMCCS QwenImgLoadFix` directly after it. +3. Select `lora_name` & preset (start with 0.76–1.00 for natural balance). +4. Set `composition_mode=merge_v2` unless you need legacy behavior. +5. Keep `offload_auto_tune=ON`; reduce `offload_num_blocks_on_gpu` if memory errors occur. +6. Run sampler; adjust preset or switch to a higher strength if effect too weak. + +### External Requirements Recap +This loader will not function standalone — both `ComfyUI-nunchaku` and `ComfyUI-QwenImageLoraLoader` must be installed, and the Qwen Image weights must be correctly placed. The IAMCCS node auto-wraps only if it detects a supported transformer class. If wrapping fails, verify repository folder names match expected conventions. + diff --git a/__init__.py b/__init__.py index 6f2372a..ebe3f39 100644 --- a/__init__.py +++ b/__init__.py @@ -1,19 +1,41 @@ # ========================================================== -# __init__.py — Registro nodi IAMCCS LoRA -# Versione pulita: mantiene solo i nodi principali +# __init__.py — Registro nodi IAMCCS +# Versione estesa: include LoRA + Qwen Bridge Conditioning # ========================================================== +# Apply safety monkeypatches on import (no-op if target not present) +from . import iamccs_qwen_monkeypatch # noqa: F401 + from .iamccs_wan_lora_stack import ( IAMCCS_WanLoRAStack, IAMCCS_ModelWithLoRA, ) +from .iamccs_wan_lora_stack_simple import ( + IAMCCS_WanLoRAStackModelIO, +) + +# Qwen Image LoRA loader (fixed copy) +from .iamccs_qwen_lora_loader import ( + IAMCCS_QwenImageLoraLoader, +) + +# Nodi principali NODE_CLASS_MAPPINGS = { "IAMCCS_WanLoRAStack": IAMCCS_WanLoRAStack, "IAMCCS_ModelWithLoRA": IAMCCS_ModelWithLoRA, + "IAMCCS_WanLoRAStackModelIO": IAMCCS_WanLoRAStackModelIO, + "IAMCCS_qwenloraloader": IAMCCS_QwenImageLoraLoader, } NODE_DISPLAY_NAME_MAPPINGS = { "IAMCCS_WanLoRAStack": "LoRA Stack (WAN-style remap)", "IAMCCS_ModelWithLoRA": "Apply LoRA to MODEL (Native)", + "IAMCCS_WanLoRAStackModelIO": "LoRA Stack (Model In→Out) WAN", + "IAMCCS_qwenloraloader": "IAMCCS QwenImgLoraLoaderFix", } + +# Web directory for JavaScript extensions +WEB_DIRECTORY = "./web" + +__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"] diff --git a/assets/LORAQWEN.png b/assets/LORAQWEN.png new file mode 100644 index 0000000000000000000000000000000000000000..541848150cd667a01fb1be36ffc12781adec733c GIT binary patch literal 50616 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 R84vt-McY`bLBj#_e*ozQdT9Uv literal 0 HcmV?d00001 diff --git a/assets/lora_stack_model_I_O.png b/assets/lora_stack_model_I_O.png new file mode 100644 index 0000000000000000000000000000000000000000..94c1f4bec65bfd27af6cb736ca48dcb125dbdfaf GIT binary patch literal 38131 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 literal 0 HcmV?d00001 diff --git a/iamccs_qwen_lora_loader.py b/iamccs_qwen_lora_loader.py new file mode 100644 index 0000000..f2546cb --- /dev/null +++ b/iamccs_qwen_lora_loader.py @@ -0,0 +1,254 @@ +""" +IAMCCS Qwen Image LoRA Loader/Stack +A Nunchaku Qwen Image LoRA loader node +compatible with current `nunchaku` where Qwen image transformer is aliased +as `NunchakuSanaTransformer2DModel`. +""" + +import copy +import logging +import os +import sys + +# Support both old/new nunchaku class names (alias to a common name) +try: + from nunchaku import NunchakuQwenImageTransformer2DModel +except Exception: + from nunchaku import NunchakuSanaTransformer2DModel as NunchakuQwenImageTransformer2DModel + +import folder_paths + +# Logging +log_level = os.getenv("LOG_LEVEL", "INFO").upper() +logging.basicConfig(level=getattr(logging, log_level, logging.INFO), format="%(asctime)s - %(levelname)s - %(message)s") +logger = logging.getLogger(__name__) + + +def _get_wrappers_module(): + """Dynamically load wrappers.qwenimage from ComfyUI-QwenImageLoraLoader.""" + import importlib.util + # Try to locate the sibling custom node folder + # typical structure: .../custom_nodes/ComfyUI-QwenImageLoraLoader + base_custom_nodes = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + qwen_node_dir = os.path.join(base_custom_nodes, "ComfyUI-QwenImageLoraLoader") + + # Fallback: if running outside expected layout, try current sys.path entries + candidate_dirs = [qwen_node_dir] + [p for p in sys.path if isinstance(p, str) and p.endswith("ComfyUI-QwenImageLoraLoader")] + + wrappers_path = None + for d in candidate_dirs: + wp = os.path.join(d, "wrappers", "qwenimage.py") + if os.path.exists(wp): + wrappers_path = wp + break + + if not wrappers_path: + raise ImportError("Cannot locate ComfyUI-QwenImageLoraLoader/wrappers/qwenimage.py") + + spec = importlib.util.spec_from_file_location("wrappers.qwenimage", wrappers_path) + if spec is None or spec.loader is None: + raise ImportError(f"Failed to load module spec for {wrappers_path}") + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) # type: ignore[attr-defined] + return mod + + +class IAMCCS_QwenImageLoraLoader: + """ + Load and apply a single LoRA to a Nunchaku Qwen Image model. + """ + @classmethod + def IS_CHANGED(cls, **kwargs): + """ComfyUI calls IS_CHANGED with widget values only; avoid positional args warnings. + Build a hash from model reference (stringified) and LoRA parameters. + """ + import hashlib + m = hashlib.sha256() + model = kwargs.get("model") + if model is not None: + m.update(str(model).encode()) + lora_name = kwargs.get("lora_name", "") + m.update(lora_name.encode()) + preset = str(kwargs.get("lora_strength_preset", "1.00")) + m.update(preset.encode()) + return m.hexdigest() + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "model": ( + "MODEL", + { + "tooltip": "The diffusion model the LoRA will be applied to. Make sure the model is loaded by a Nunchaku Qwen Image loader.", + }, + ), + "lora_name": ( + folder_paths.get_filename_list("loras"), + {"tooltip": "The file name of the LoRA."}, + ), + "lora_strength_preset": ( + ["0.25", "0.50", "0.76", "1.00", "1.25", "1.50"], + { + "default": "1.00", + "tooltip": "Preset strength values.", + }, + ), + "composition_mode": ( + ["append", "merge_v2"], + { + "default": "merge_v2", + "tooltip": "How to apply LoRAs: 'append' (original behavior, may change shapes) or 'merge_v2' (in-place delta, no rank expansion).", + }, + ), + "offload_policy": ( + ["rebuild", "disable"], + { + "default": "rebuild", + "tooltip": "CPU offload with LoRAs: 'rebuild' re-enables offload after composing; 'disable' keeps it off while LoRAs are active.", + }, + ), + "offload_num_blocks_on_gpu": ( + "INT", + { + "default": 1, + "min": 1, + "max": 64, + "step": 1, + "tooltip": "How many transformer blocks stay on GPU when offload is enabled (higher = more VRAM, more speed).", + }, + ), + "offload_use_pin_memory": ( + "BOOLEAN", + { + "default": False, + "tooltip": "Use pinned host memory for offload transfers (can improve bandwidth, uses more system RAM).", + }, + ), + "offload_auto_tune": ( + "BOOLEAN", + { + "default": True, + "tooltip": "Automatically choose offload settings based on free VRAM (overrides saved settings).", + }, + ), + "vram_margin_gb": ( + "FLOAT", + { + "default": 4.0, + "min": 0.0, + "max": 16.0, + "step": 0.25, + "tooltip": "VRAM margin used when cpu_offload_setting='auto' to decide enabling offload for composition.", + }, + ), + } + } + + RETURN_TYPES = ("MODEL",) + OUTPUT_TOOLTIPS = ("The modified diffusion model.",) + FUNCTION = "load_lora" + TITLE = "IAMCCS QwenImgLoraLoaderFix" + CATEGORY = "IAMCCS/Nunchaku" + DESCRIPTION = "Apply a single LoRA to a Nunchaku Qwen Image model." + + def load_lora(self, model, lora_name: str, lora_strength_preset: str = "1.00", composition_mode: str = "merge_v2", offload_policy: str = "rebuild", offload_num_blocks_on_gpu: int = 1, offload_use_pin_memory: bool = False, offload_auto_tune: bool = True, vram_margin_gb: float = 4.0): + # Resolve effective strength from preset or default + import math + strength_val: float = 1.0 + try: + strength_val = float(lora_strength_preset) + except Exception: + strength_val = 1.0 + if not math.isfinite(strength_val): + strength_val = 1.0 + if abs(strength_val) < 1e-5: + return (model,) + + # Coerce offload_num_blocks_on_gpu to a sane integer (avoid NaN/None/inf) + import math as _math + try: + _tmp_val = float(offload_num_blocks_on_gpu) + if not _math.isfinite(_tmp_val): + _tmp_val = 1.0 + if _tmp_val < 1: + _tmp_val = 1.0 + if _tmp_val > 64: + _tmp_val = 64.0 + offload_num_blocks_on_gpu = int(_tmp_val) + except Exception: + offload_num_blocks_on_gpu = 1 + + # Advanced toggle removed: always respect user-provided widget values + + model_wrapper = model.model.diffusion_model + + wrappers_module = _get_wrappers_module() + ComfyQwenImageWrapper = wrappers_module.ComfyQwenImageWrapper + + # Debug logging + model_wrapper_type_name = type(model_wrapper).__name__ + model_wrapper_module = type(model_wrapper).__module__ + logger.info(f"🔍 Model wrapper type: '{model_wrapper_type_name}'") + logger.info(f"🔍 Model wrapper module: {model_wrapper_module}") + + if hasattr(model_wrapper, 'model') and hasattr(model_wrapper, 'loras'): + logger.info("✅ Model is already wrapped (detected via attributes)") + transformer = model_wrapper.model + elif ( + model_wrapper_type_name in ("NunchakuQwenImageTransformer2DModel", "NunchakuSanaTransformer2DModel") + or model_wrapper_type_name.endswith("NunchakuQwenImageTransformer2DModel") + or model_wrapper_type_name.endswith("NunchakuSanaTransformer2DModel") + ): + logger.info("🔧 Wrapping Nunchaku*Qwen/Sana* Transformer with ComfyQwenImageWrapper") + wrapped_model = ComfyQwenImageWrapper( + model_wrapper, + getattr(model_wrapper, 'config', {}), + None, + {}, + "auto", + vram_margin_gb, + lora_offload_policy=offload_policy, + offload_num_blocks_on_gpu=offload_num_blocks_on_gpu, + offload_use_pin_memory=offload_use_pin_memory, + offload_auto_tune=offload_auto_tune, + ) + # Forward composition mode flag (attribute-based to avoid strict kwargs requirements) + try: + setattr(wrapped_model, "lora_composition_mode", composition_mode) + except Exception: + pass + model.model.diffusion_model = wrapped_model + model_wrapper = wrapped_model + transformer = model_wrapper.model + else: + logger.error(f"❌ Model type mismatch! Type: {model_wrapper_type_name}, Module: {model_wrapper_module}") + raise TypeError( + f"This LoRA loader works with Nunchaku Qwen Image models; got {model_wrapper_type_name}." + ) + + # Remove expensive deepcopy (caused device divergence under offload); mutate in place + lora_path = folder_paths.get_full_path_or_raise("loras", lora_name) + try: + setattr(model_wrapper, "lora_composition_mode", composition_mode) + except Exception: + pass + model_wrapper.loras.append((lora_path, strength_val)) + + # Ensure wrapper model resides fully on the original device (avoid mixed cpu/cuda modules) + try: + target_device = next(transformer.parameters()).device + if target_device.type == "cuda": + for p in transformer.parameters(): + if p.device != target_device: + p.data = p.data.to(target_device) + for b in transformer.buffers(): + if b.device != target_device: + b.data = b.data.to(target_device) + except Exception: + pass + + logger.info(f"LoRA added: {lora_name} (strength={strength_val})") + return (model,) + + diff --git a/iamccs_qwen_monkeypatch.py b/iamccs_qwen_monkeypatch.py new file mode 100644 index 0000000..5daa54b --- /dev/null +++ b/iamccs_qwen_monkeypatch.py @@ -0,0 +1,56 @@ +import logging + + +def _patch_qwen_wrapper_device_sync(): + try: + from importlib import import_module + mod = import_module("ComfyUI-QwenImageLoraLoader.wrappers.qwenimage") + ComfyQwenImageWrapper = getattr(mod, "ComfyQwenImageWrapper", None) + if ComfyQwenImageWrapper is None: + return False + except Exception: + return False + + if getattr(ComfyQwenImageWrapper, "_iamccs_device_sync_patched", False): + return True + + orig_execute = getattr(ComfyQwenImageWrapper, "_execute_model", None) + if orig_execute is None: + return False + + def _execute_model_patched(self, x, timestep, context, guidance, control, transformer_options, **kwargs): + # Ensure all params/buffers are on the same device as input x (prevents CPU/CUDA mix) + try: + dev = getattr(x, "device", None) + if dev is not None and dev.type in ("cuda", "cpu") and hasattr(self, "model") and self.model is not None: + needs_move = False + # Quick scan: if any param/buffer is on a different device, move whole model once + for _, p in self.model.named_parameters(recurse=True): + if p.device.type != dev.type: + needs_move = True + break + if not needs_move: + for _, b in self.model.named_buffers(recurse=True): + if b.device.type != dev.type: + needs_move = True + break + if needs_move: + try: + self.model.to(dev) + except Exception: + pass + except Exception: + pass + return orig_execute(self, x, timestep, context, guidance, control, transformer_options, **kwargs) + + setattr(ComfyQwenImageWrapper, "_execute_model", _execute_model_patched) + setattr(ComfyQwenImageWrapper, "_iamccs_device_sync_patched", True) + logging.getLogger(__name__).info("[IAMCCS] Applied device-sync monkeypatch to ComfyQwenImageWrapper") + return True + + +# Execute at import time +try: + _patch_qwen_wrapper_device_sync() +except Exception: + pass diff --git a/iamccs_wan_lora_stack_simple.py b/iamccs_wan_lora_stack_simple.py new file mode 100644 index 0000000..5100ae6 --- /dev/null +++ b/iamccs_wan_lora_stack_simple.py @@ -0,0 +1,112 @@ +# iamccs_wan_lora_stack_simple.py +# =============================================================== +# IAMCCS_WanLoRAStackModelIO +# Multi-LoRA loader (WAN-style remap) that takes MODEL in and outputs MODEL +# =============================================================== + +import logging +import comfy.utils +import comfy.sd +import folder_paths + +from .iamccs_wan_lora_stack import ( + standardize_wan_lora_keys, + SuppressOptionalKeysFilter, +) + + +class IAMCCS_WanLoRAStackModelIO: + @classmethod + def INPUT_TYPES(cls): + lora_list = folder_paths.get_filename_list("loras") + ["no"] + return { + "required": { + "model": ("MODEL",), + "lora1": (lora_list, {"default": "no"}), + "strength1": ("FLOAT", {"default": 1.0, "min": -5.0, "max": 5.0, "step": 0.01}), + "lora2": (lora_list, {"default": "no"}), + "strength2": ("FLOAT", {"default": 0.0, "min": -5.0, "max": 5.0, "step": 0.01}), + "lora3": (lora_list, {"default": "no"}), + "strength3": ("FLOAT", {"default": 0.0, "min": -5.0, "max": 5.0, "step": 0.01}), + "lora4": (lora_list, {"default": "no"}), + "strength4": ("FLOAT", {"default": 0.0, "min": -5.0, "max": 5.0, "step": 0.01}), + "model_type": (["wan2x", "flow", "standard"], {"default": "flow"}), + }, + "optional": { + # Allow chaining in externally prepared LORA stacks if provided (optional) + "lora": ("LORA",), + } + } + + RETURN_TYPES = ("MODEL",) + FUNCTION = "apply_stack" + CATEGORY = "IAMCCS/LoRA" + + def _build_lora_entries(self, lora1, strength1, lora2, strength2, lora3, strength3, lora4, strength4, model_type): + loras = [] + for name, strength in [ + (lora1, strength1), + (lora2, strength2), + (lora3, strength3), + (lora4, strength4), + ]: + if not name or name == "no" or strength == 0.0: + continue + path = folder_paths.get_full_path_or_raise("loras", name) + sd = comfy.utils.load_torch_file(path, safe_load=True) + if model_type != "standard": + sd = standardize_wan_lora_keys(sd) + loras.append({"name": name, "strength": strength, "state_dict": sd}) + return loras + + def apply_stack(self, model, + lora1, strength1, + lora2, strength2, + lora3, strength3, + lora4, strength4, + model_type="flow", + lora=None): + model_out = model + + loras = self._build_lora_entries( + lora1, strength1, + lora2, strength2, + lora3, strength3, + lora4, strength4, + model_type, + ) + + if lora is not None and isinstance(lora, list): + loras.extend(lora) + + if not loras: + logging.warning("[IAMCCS_WanLoRAStackModelIO] ⚠ No LoRA selected; returning input model unchanged") + return (model_out,) + + logger = logging.getLogger() + optional_filter = SuppressOptionalKeysFilter() + logger.addFilter(optional_filter) + + try: + for entry in loras: + sd = entry["state_dict"] + strength = entry["strength"] + model_out, _ = comfy.sd.load_lora_for_models(model_out, None, sd, strength, 0) + logging.info(f"[IAMCCS_WanLoRAStackModelIO] ✅ '{entry['name']}' strength={strength}") + + if optional_filter.suppressed_count > 0: + keys_types = ", ".join(sorted(optional_filter.suppressed_keys)) + logging.info(f"[IAMCCS_WanLoRAStackModelIO] ℹ {optional_filter.suppressed_count} optional keys not present in LORA ({keys_types})") + finally: + logger.removeFilter(optional_filter) + + return (model_out,) + + +NODE_CLASS_MAPPINGS = { + "IAMCCS_WanLoRAStackModelIO": IAMCCS_WanLoRAStackModelIO, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "IAMCCS_WanLoRAStackModelIO": "LoRA Stack (Model In→Out) WAN", +} diff --git a/pyproject.toml b/pyproject.toml index ac8684a..748158e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "iamccs-wan-lora-fixer-stack" -version = "1.2.3" -description = "Nodo IAMCCS per ComfyUI che applica fino a 4 LoRA (WAN 2.1 / 2.2 compatibili) con fix automatico e input/output MODEL. Aggiornamento v1.2.3: ADD Lora input for Lora stack adding." +version = "1.3.0" +description = "IAMCCS multi-LoRA stack & MODEL IO WAN remap + Qwen Image LoRA loader improvements. v1.3.0 adds direct MODEL in→out LoRA stack and updated low VRAM Qwen instructions." license = { text = "MIT" } authors = [ { name = "Carmine Cristallo Scalzi (IAMCCS)", email = "info@carminecristalloscalzi.com" } diff --git a/version.json b/version.json index 960651e..fd1091c 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "name": "iamccs-wan-lora-fixer-stack", - "version": "1.2.3", + "version": "1.3.0", "author": "Carmine Cristallo Scalzi (IAMCCS)", - "description": "Nodo IAMCCS per ComfyUI che applica fino a 8 LoRA in stack (concatenabili), compatibile con WAN 2.2 (Flow). Aggiornamento per compatibilità estesa a WAN 2.1." + "description": "IAMCCS nodes for ComfyUI: multi-LoRA stack + direct MODEL IO WAN/Flow remap, Qwen Image LoRA loader improvements. v1.3.0 adds MODEL in→out stack node and updated low VRAM Qwen instructions. WAN 2.1 + 2.2 compatible." }