Files
2025-03-25 11:24:00 -04:00

154 lines
6.2 KiB
Python

import os
import folder_paths
import torch
class MultiLoraLoader:
# Class variable to store LoRA list
all_loras = []
@classmethod
def INPUT_TYPES(cls):
# Get all available lora directories and gather all lora files
cls.all_loras = []
lora_dirs = folder_paths.get_folder_paths("loras")
for lora_dir in lora_dirs:
if os.path.isdir(lora_dir):
for filename in os.listdir(lora_dir):
if filename.endswith(('.safetensors', '.ckpt', '.pt')):
cls.all_loras.append(filename)
# Sort and remove duplicates
cls.all_loras = sorted(list(set(cls.all_loras)))
# Print debug info
print(f"Found {len(cls.all_loras)} LoRA files in {len(lora_dirs)} directories")
max_index = max(0, len(cls.all_loras) - 1)
return {
"required": {
"model": ("MODEL",),
"index": ("INT", {"default": 0, "min": 0, "max": max_index, "step": 1}),
"lora_list": (cls.all_loras, {"default": cls.all_loras[0] if cls.all_loras else ""}),
"strength_model": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
"strength_clip": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
},
"optional": {
"clip": ("CLIP", ),
}
}
RETURN_TYPES = ("MODEL", "CLIP")
FUNCTION = "load_lora"
CATEGORY = "loaders"
def load_lora(self, model, index, lora_list, strength_model, strength_clip, clip=None):
lora_dirs = folder_paths.get_folder_paths("loras")
# Use the class variable to access the LoRA list
all_loras = self.__class__.all_loras
# Validate we have LoRAs and index is in range
if len(all_loras) == 0:
print("No LoRAs found. Returning model without changes.")
return (model, clip)
if index < 0 or index >= len(all_loras):
print(f"LoRA index {index} out of range (0-{len(all_loras)-1}). Using index 0.")
index = 0
# Get the LoRA file name based on index
lora_name = all_loras[index]
# Find the LoRA file in any of the lora directories
lora_path = None
for lora_dir in lora_dirs:
potential_path = os.path.join(lora_dir, lora_name)
if os.path.isfile(potential_path):
lora_path = potential_path
break
# If we couldn't find the file
if lora_path is None:
print(f"LoRA file '{lora_name}' not found in any LoRA directories. Returning model without changes.")
return (model, clip)
print(f"Loading LoRA {lora_name} (index {index}/{len(all_loras)-1}) from {lora_path}")
print(f"Model strength: {strength_model}, Clip strength: {strength_clip}")
# Import the reference implementation from ComfyUI's nodes
try:
import importlib.util
import sys
# Get the ComfyUI nodes directory
script_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
comfy_dir = os.path.join(script_dir, "comfy")
nodes_dir = os.path.join(script_dir, "comfy_extras")
if os.path.exists(os.path.join(comfy_dir, "sd.py")) and os.path.exists(os.path.join(nodes_dir, "nodes_lora.py")):
# Load the lora module directly from ComfyUI
spec = importlib.util.spec_from_file_location("nodes_lora", os.path.join(nodes_dir, "nodes_lora.py"))
nodes_lora = importlib.util.module_from_spec(spec)
sys.modules["nodes_lora"] = nodes_lora
spec.loader.exec_module(nodes_lora)
# Use the reference implementation
lora_loader = nodes_lora.LoraLoader()
return lora_loader.load_lora(model, lora_path, strength_model, strength_clip, clip)
else:
print("Could not find ComfyUI's nodes_lora.py, falling back to internal implementation")
except Exception as e:
print(f"Error loading ComfyUI's LoraLoader: {str(e)}")
# If we couldn't use the reference implementation, use our own
try:
import comfy.utils
# Load the LoRA file
lora_sd = comfy.utils.load_torch_file(lora_path)
# We need to import these from comfy's sd module
import comfy.sd as sd
# Apply the LoRA
if hasattr(sd, 'load_lora_for_models'):
return sd.load_lora_for_models(model, clip, lora_sd, strength_model, strength_clip)
else:
model_result = model
clip_result = clip
if hasattr(sd, 'apply_weighted_lora'):
# Newer ComfyUI versions
if model is not None:
model_result = sd.apply_weighted_lora(model, lora_sd, strength_model)
if clip is not None:
clip_result = sd.apply_weighted_lora(clip, lora_sd, strength_clip)
elif hasattr(sd, 'apply_lora'):
# Older ComfyUI versions
if model is not None:
model_result = sd.apply_lora(model, lora_sd, strength_model)
if clip is not None:
clip_result = sd.apply_lora(clip, lora_sd, strength_clip)
else:
print("Could not find apply_lora or apply_weighted_lora in ComfyUI's sd module")
return (model_result, clip_result)
except Exception as e:
print(f"Error loading or applying LoRA: {str(e)}")
# If all else fails, return the original models
print("All LoRA loading methods failed, returning original model")
return (model, clip)
# Add the node to ComfyUI
NODE_CLASS_MAPPINGS = {
"MultiLoraLoader": MultiLoraLoader
}
NODE_DISPLAY_NAME_MAPPINGS = {
"MultiLoraLoader": "LoRA Loader (by Index)"
}