From 1a4f9ba5a19f5e2f5dc768c56fa6101ed09fa4f3 Mon Sep 17 00:00:00 2001 From: Blyss Sarania Date: Tue, 25 Feb 2025 10:51:52 -0500 Subject: [PATCH] Misc style cleanup (No functionality changes) and version bump Misc style fixes to adhere more closely to PEP guidelines, removing unneeded comments, remove unused import, bump version for Comfy Manager, add multilingual description. --- __init__.py | 3 ++- lora_loader.py | 66 +++++++++++++++++++++++++------------------------- pyproject.toml | 2 +- 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/__init__.py b/__init__.py index cd83851..cc0cd7c 100644 --- a/__init__.py +++ b/__init__.py @@ -1,6 +1,7 @@ """ Hunyuan Video LoRA Loader 支持选择性加载single blocks或double blocks的混元视频LoRA加载器 +Hunyuan Video LoRA loader that supports selective loading of single blocks or double blocks """ from .lora_loader import HunyuanVideoLoraLoader @@ -13,4 +14,4 @@ NODE_DISPLAY_NAME_MAPPINGS = { "HunyuanVideoLoraLoader": "Hunyuan Video LoRA Loader" } -__version__ = "1.0.0" \ No newline at end of file +__version__ = "1.0.2" diff --git a/lora_loader.py b/lora_loader.py index 8e6d360..dbd3163 100644 --- a/lora_loader.py +++ b/lora_loader.py @@ -1,22 +1,26 @@ import os +from typing import Dict +import logging import folder_paths import torch -from typing import Dict +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') +log = logging.getLogger(__name__) + class HunyuanVideoLoraLoader: """ 混元视频LoRA加载器,支持选择性加载blocks - + 这个节点允许您: 1. 从下拉列表选择LoRA文件 2. 调整LoRA的强度 3. 选择要加载的blocks类型(all/single/double) """ - + def __init__(self): self.blocks_type = ["all", "single_blocks", "double_blocks"] self.loaded_lora = None - + @classmethod def INPUT_TYPES(s): return { @@ -39,7 +43,7 @@ class HunyuanVideoLoraLoader: FUNCTION = "load_lora" CATEGORY = "loaders/hunyuan" OUTPUT_NODE = False - DESCRIPTION = "加载并应用混元视频LoRA,支持选择性加载single blocks或double blocks" + DESCRIPTION = "加载并应用混元视频LoRA,支持选择性加载single blocks或double blocks/Load LoRA for HunyuanVideo. Supports selecting single, double or all blocks." def convert_key_format(self, key: str) -> str: """转换LoRA key格式,支持多种命名方式""" @@ -49,24 +53,24 @@ class HunyuanVideoLoraLoader: if key.startswith(prefix): key = key[len(prefix):] break - + return key def filter_lora_keys(self, lora: Dict[str, torch.Tensor], blocks_type: str) -> Dict[str, torch.Tensor]: """根据blocks类型过滤LoRA权重""" if blocks_type == "all": return lora - + filtered_lora = {} for key, value in lora.items(): base_key = self.convert_key_format(key) - + # 检查是否包含目标block - if blocks_type == "single_blocks" in base_key: + if blocks_type == "single_blocks" and "single_blocks" in base_key: filtered_lora[key] = value - elif blocks_type == "double_blocks" in base_key: + elif blocks_type == "double_blocks" and "double_blocks" in base_key: filtered_lora[key] = value - + return filtered_lora def check_for_musubi(self, lora: Dict[str, torch.Tensor]) -> Dict[str, torch.Tensor]: @@ -76,20 +80,19 @@ class HunyuanVideoLoraLoader: lora_alphas = {} for key, value in lora.items(): if key.startswith(prefix): - lora_name = key.split(".", 1)[0] # before first dot + lora_name = key.split(".", 1)[0] if lora_name not in lora_alphas and "alpha" in key: lora_alphas[lora_name] = value musubi = True if musubi: - print("Loading Musubi Tuner format LoRA...") + log.info("Loading Musubi Tuner format LoRA...") converted_lora = {} for key, weight in lora.items(): if key.startswith(prefix): if "alpha" in key: continue - lora_name = key.split(".", 1)[0] # before first dot - # HunyuanVideo lora name to module name: ugly but works - module_name = lora_name[len(prefix) :] # remove "lora_unet_" + lora_name = key.split(".", 1)[0] + module_name = lora_name[len(prefix):] # remove "lora_unet_" module_name = module_name.replace("_", ".") # replace "_" with "." module_name = module_name.replace("double.blocks.", "double_blocks.") # fix double blocks module_name = module_name.replace("single.blocks.", "single_blocks.") # fix single blocks @@ -104,26 +107,24 @@ class HunyuanVideoLoraLoader: new_key = f"{diffusers_prefix}.{module_name}.lora_B.weight" dim = weight.shape[1] else: - print(f"unexpected key: {key} in Musubi LoRA format") + log.info("unexpected key: %s in Musubi LoRA format", key) continue - # scale weight by alpha + # scale weight by alpha, we scale both down and up so scale is sqrt if lora_name in lora_alphas: - # we scale both down and up, so scale is sqrt scale = lora_alphas[lora_name] / dim scale = scale.sqrt() weight = weight * scale else: - print(f"missing alpha for {lora_name}") + log.info("missing alpha for %s", lora_name) converted_lora[new_key] = weight return converted_lora - else: - print("Loading Diffusers format LoRA...") - return lora + log.info("Loading Diffusers format LoRA...") + return lora def load_lora(self, model, lora_name: str, strength: float, blocks_type: str): """ 加载并应用LoRA到模型 - + Parameters ---------- model : ModelPatcher @@ -134,7 +135,7 @@ class HunyuanVideoLoraLoader: LoRA权重强度 blocks_type : str 要加载的blocks类型: "all", "single_blocks" 或 "double_blocks" - + Returns ------- tuple @@ -142,15 +143,14 @@ class HunyuanVideoLoraLoader: """ if not lora_name: return (model,) - + from comfy.utils import load_torch_file from comfy.sd import load_lora_for_models - from comfy.lora import load_lora # 获取LoRA文件路径 lora_path = folder_paths.get_full_path("loras", lora_name) if not os.path.exists(lora_path): - raise Exception(f"Lora {lora_name} not found at {lora_path}") + raise FileNotFoundError(f"Lora {lora_name} not found at {lora_path}") # 缓存LoRA加载 if self.loaded_lora is not None: @@ -158,23 +158,23 @@ class HunyuanVideoLoraLoader: lora = self.loaded_lora[1] else: self.loaded_lora = None - + if self.loaded_lora is None: lora = load_torch_file(lora_path) self.loaded_lora = (lora_path, lora) - + diffusers_lora = self.check_for_musubi(lora) # 过滤并转换LoRA权重 filtered_lora = self.filter_lora_keys(diffusers_lora, blocks_type) - + # 应用LoRA new_model, _ = load_lora_for_models(model, None, filtered_lora, strength, 0) if new_model is not None: return (new_model,) - + return (model,) @classmethod def IS_CHANGED(s, model, lora_name, strength, blocks_type): """当LoRA的配置发生变化时重新执行""" - return f"{lora_name}_{strength}_{blocks_type}" \ No newline at end of file + return f"{lora_name}_{strength}_{blocks_type}" diff --git a/pyproject.toml b/pyproject.toml index 622324e..5219beb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "hunyuanvideomultilora" description = "A custom LoRA-loading node designed to prevent issues such as blurriness and other artifacts when loading multiple LoRAs in HunYuan Video.\nUsage Tips: The connection method remains unchanged from the original. The only difference is the additional blocks_type option. Please select double_blocks." -version = "1.0.1" +version = "1.0.2" license = {file = "LICENSE"} [project.urls]