From fee7e7bf7300ffde16a136d5705445e23e30cfd5 Mon Sep 17 00:00:00 2001 From: yolain Date: Thu, 16 May 2024 01:01:03 +0800 Subject: [PATCH] fix:some models were not successfully written to easyCache,resulting in slow secondary diffusion --- README.md | 1 + py/easyNodes.py | 26 +++++------------- py/libs/controlnet.py | 20 +++----------- py/libs/loader.py | 61 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 62 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 929e70c..10eaadd 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ **v1.1.7** +- 修复 一些模型(如controlnet模型等)未成功写入缓存,导致修改前置节点束参数(如提示词)需要二次载入模型的问题 - 增加 `easy prompt` - 主体和光影预置项,后期可能会调整 - 增加 `easy icLightApply` - 重绘光影, 从[ComfyUI-IC-Light](https://github.com/huchenlei/ComfyUI-IC-Light)优化 - 增加 `easy imageSplitGrid` - 图像网格拆分 diff --git a/py/easyNodes.py b/py/easyNodes.py index 1eec43d..fba62b5 100644 --- a/py/easyNodes.py +++ b/py/easyNodes.py @@ -1942,7 +1942,7 @@ class loraStackLoader: loras.append((lora_name, model_strength, clip_strength)) return (loras,) -class controlnetNameStack: +class controlnetStack: def get_file_list(filenames): return [file for file in filenames if file != "put_models_here.txt" and "lllite" not in file] @@ -1959,7 +1959,7 @@ class controlnetNameStack: "start_percent_1": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}), "end_percent_1": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}), "switch_2": (["Off", "On"],), - "controlnet_2": (s.controlnets,), + "`controlnet`_2": (s.controlnets,), "controlnet_strength_2": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}), "start_percent_2": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}), "end_percent_2": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}), @@ -2003,7 +2003,7 @@ class controlnetSimple: def controlnetApply(self, pipe, image, control_net_name, control_net=None, strength=1, scale_soft_weights=1): - positive, negative = easyControlnet().apply(control_net_name, image, pipe["positive"], pipe["negative"], strength, 0, 1, control_net, scale_soft_weights) + positive, negative = easyControlnet().apply(control_net_name, image, pipe["positive"], pipe["negative"], strength, 0, 1, control_net, scale_soft_weights, None, easyCache) new_pipe = { "model": pipe['model'], @@ -2055,7 +2055,7 @@ class controlnetAdvanced: def controlnetApply(self, pipe, image, control_net_name, control_net=None, strength=1, start_percent=0, end_percent=1, scale_soft_weights=1): positive, negative = easyControlnet().apply(control_net_name, image, pipe["positive"], pipe["negative"], - strength, start_percent, end_percent, control_net, scale_soft_weights) + strength, start_percent, end_percent, control_net, scale_soft_weights, None, easyCache) new_pipe = { "model": pipe['model'], @@ -2972,7 +2972,8 @@ class instantID: # Apply InstantID if "ApplyInstantID" in ALL_NODE_CLASS_MAPPINGS: instantid_apply = ALL_NODE_CLASS_MAPPINGS['ApplyInstantID'] - control_net = easyControlnet().load_controlnet(control_net_name, control_net, cn_soft_weights) + if control_net is None: + control_net = easyCache.load_controlnet(control_net_name, cn_soft_weights) model, positive, negative = instantid_apply().apply_instantid(instantid_model, insightface_model, control_net, image, model, positive, negative, start_at, end_at, weight=weight, ip_weight=None, cn_strength=cn_strength, noise=noise, image_kps=image_kps, mask=mask) else: self.error() @@ -4191,9 +4192,6 @@ class samplerFull(LayerDiffuse): def run(self, pipe, steps, cfg, sampler_name, scheduler, denoise, image_output, link_id, save_prefix, seed=None, model=None, positive=None, negative=None, latent=None, vae=None, clip=None, xyPlot=None, tile_size=None, prompt=None, extra_pnginfo=None, my_unique_id=None, force_full_denoise=False, disable_noise=False, downscale_options=None): - # Clean loaded_objects - easyCache.update_loaded_objects(prompt) - samp_model = model.clone() if model is not None else pipe["model"].clone() samp_positive = positive if positive is not None else pipe["positive"] samp_negative = negative if negative is not None else pipe["negative"] @@ -4314,10 +4312,6 @@ class samplerFull(LayerDiffuse): spent_time = 'Diffusion:' + str((end_time-start_time)/1000)+'″, VAEDecode:' + str((end_decode_time-end_time)/1000)+'″ ' results = easySave(new_images, save_prefix, image_output, prompt, extra_pnginfo) - sampler.update_value_by_id("results", my_unique_id, results) - - # Clean loaded_objects - easyCache.update_loaded_objects(prompt) new_pipe = { **pipe, @@ -4339,8 +4333,6 @@ class samplerFull(LayerDiffuse): } } - sampler.update_value_by_id("pipe_line", my_unique_id, new_pipe) - del pipe if image_output == 'Preview&Choose': @@ -4468,10 +4460,6 @@ class samplerFull(LayerDiffuse): output_images, samp_model) results = easySave(images, save_prefix, image_output, prompt, extra_pnginfo) - sampler.update_value_by_id("results", my_unique_id, results) - - # Clean loaded_objects - easyCache.update_loaded_objects(prompt) new_pipe = { **pipe, @@ -4490,8 +4478,6 @@ class samplerFull(LayerDiffuse): "loader_settings": pipe["loader_settings"], } - sampler.update_value_by_id("pipe_line", my_unique_id, new_pipe) - del pipe if hasattr(ModelPatcher, "original_calculate_weight"): diff --git a/py/libs/controlnet.py b/py/libs/controlnet.py index 034c9b0..57ba51c 100644 --- a/py/libs/controlnet.py +++ b/py/libs/controlnet.py @@ -7,26 +7,12 @@ class easyControlnet: def __init__(self): pass - def load_controlnet(self, control_net_name, control_net, scale_soft_weights): - if control_net is None: - if scale_soft_weights < 1: - if "ScaledSoftControlNetWeights" in NODE_CLASS_MAPPINGS: - soft_weight_cls = NODE_CLASS_MAPPINGS['ScaledSoftControlNetWeights'] - (weights, timestep_keyframe) = soft_weight_cls().load_weights(scale_soft_weights, False) - cn_adv_cls = NODE_CLASS_MAPPINGS['ControlNetLoaderAdvanced'] - control_net, = cn_adv_cls().load_controlnet(control_net_name, timestep_keyframe) - else: - raise Exception(f"[Advanced-ControlNet Not Found] you need to install 'COMFYUI-Advanced-ControlNet'") - else: - controlnet_path = folder_paths.get_full_path("controlnet", control_net_name) - control_net = comfy.controlnet.load_controlnet(controlnet_path) - return control_net - - def apply(self, control_net_name, image, positive, negative, strength, start_percent=0, end_percent=1, control_net=None, scale_soft_weights=1, mask=None): + def apply(self, control_net_name, image, positive, negative, strength, start_percent=0, end_percent=1, control_net=None, scale_soft_weights=1, mask=None, easyCache=None): if strength == 0: return (positive, negative) - control_net = self.load_controlnet(control_net_name, control_net, scale_soft_weights) + if control_net is None: + control_net = easyCache.load_controlnet(control_net_name, scale_soft_weights) if mask is not None: mask = mask.to(self.device) diff --git a/py/libs/loader.py b/py/libs/loader.py index b3b92dc..11a89a6 100644 --- a/py/libs/loader.py +++ b/py/libs/loader.py @@ -1,16 +1,19 @@ import time, os, psutil import comfy.utils import comfy.sd +import comfy.controlnet import folder_paths from nodes import NODE_CLASS_MAPPINGS from collections import defaultdict from ..log import log_node_info, log_node_error -stable_diffusion_loaders = ["easy a1111Loader", "easy comfyLoader", "easy zero123Loader", "easy svdLoader"] +stable_diffusion_loaders = ["easy fullLoader", "easy a1111Loader", "easy comfyLoader", "easy zero123Loader", "easy svdLoader"] stable_cascade_loaders = ["easy cascadeLoader"] +controlnet_loaders = ["easy controlnetLoader", "easy controlnetLoaderADV"] +instant_loaders = ["easy instantIDApply", "easy instantIDApplyADV"] cascade_vae_node = ["easy preSamplingCascade", "easy fullCascadeKSampler"] model_merge_node = ["easy XYInputs: ModelMergeBlocks"] -lora_widget = ["easy a1111Loader", "easy comfyLoader"] +lora_widget = ["easy fullLoader", "easy a1111Loader", "easy comfyLoader"] class easyLoader: def __init__(self): @@ -22,8 +25,9 @@ class easyLoader: "bvae": defaultdict(tuple), "vae": defaultdict(object), "lora": defaultdict(dict), # {lora_name: {UID: (model_lora, clip_lora)}} + "controlnet": defaultdict(dict), } - self.memory_threshold = self.determine_memory_threshold(0.7) + self.memory_threshold = self.determine_memory_threshold(0.9) self.lora_name_cache = [] def clean_values(self, values: str): @@ -50,9 +54,17 @@ class easyLoader: for key in keys - desired_names: del self.loaded_objects[object_type][key] - def get_input_value(self, entry, key): + def get_input_value(self, entry, key, prompt=None): val = entry["inputs"][key] - return val if isinstance(val, str) else val[0] + if isinstance(val, str): + return val + elif isinstance(val, list): + if prompt is not None and val[0]: + return prompt[val[0]]['inputs'][key] + else: + return val[0] + else: + return str(val) def process_pipe_loader(self, entry, desired_ckpt_names, desired_vae_names, desired_lora_names, desired_lora_settings, num_loras=3, suffix=""): for idx in range(1, num_loras + 1): @@ -71,10 +83,10 @@ class easyLoader: desired_vae_names = set() desired_lora_names = set() desired_lora_settings = set() + desired_controlnet_names = set() for entry in prompt.values(): class_type = entry["class_type"] - if class_type in lora_widget: lora_name = self.get_input_value(entry, "lora_name") desired_lora_names.add(lora_name) @@ -82,7 +94,7 @@ class easyLoader: desired_lora_settings.add(setting) if class_type in stable_diffusion_loaders: - desired_ckpt_names.add(self.get_input_value(entry, "ckpt_name")) + desired_ckpt_names.add(self.get_input_value(entry, "ckpt_name", prompt)) desired_vae_names.add(self.get_input_value(entry, "vae_name")) elif class_type in stable_cascade_loaders: @@ -99,6 +111,16 @@ class easyLoader: if decode_vae_name and decode_vae_name != 'None': desired_vae_names.add(decode_vae_name) + elif class_type in controlnet_loaders: + control_net_name = self.get_input_value(entry, "control_net_name", prompt) + scale_soft_weights = self.get_input_value(entry, "scale_soft_weights") + desired_controlnet_names.add(f'{control_net_name};{scale_soft_weights}') + + elif class_type in instant_loaders: + control_net_name = self.get_input_value(entry, "control_net_name", prompt) + scale_soft_weights = self.get_input_value(entry, "cn_soft_weights") + desired_controlnet_names.add(f'{control_net_name};{scale_soft_weights}') + elif class_type in model_merge_node: desired_ckpt_names.add(self.get_input_value(entry, "ckpt_name_1")) desired_ckpt_names.add(self.get_input_value(entry, "ckpt_name_2")) @@ -106,7 +128,7 @@ class easyLoader: if vae_use != 'Use Model 1' and vae_use != 'Use Model 2': desired_vae_names.add(vae_use) - object_types = ["ckpt", "unet", "clip", "bvae", "vae", "lora"] + object_types = ["ckpt", "unet", "clip", "bvae", "vae", "lora", "controlnet"] for object_type in object_types: if object_type == 'unet': desired_names = desired_unet_names @@ -117,6 +139,8 @@ class easyLoader: desired_names = desired_ckpt_names elif object_type == "vae": desired_names = desired_vae_names + elif object_type == "controlnet": + desired_names = desired_controlnet_names else: desired_names = desired_lora_names self.clear_unused_objects(desired_names, object_type) @@ -155,7 +179,7 @@ class easyLoader: current_memory = self.get_memory_usage() if current_memory < self.memory_threshold: return - eviction_order = ["vae", "lora", "bvae", "clip", "ckpt"] + eviction_order = ["vae", "lora", "bvae", "clip", "ckpt", "controlnet"] for obj_type in eviction_order: if current_memory < self.memory_threshold: break @@ -225,6 +249,25 @@ class easyLoader: return model + def load_controlnet(self, control_net_name, scale_soft_weights=1): + unique_id = f'{control_net_name};{str(scale_soft_weights)}' + if unique_id in self.loaded_objects["controlnet"]: + return self.loaded_objects["controlnet"][unique_id][0] + if scale_soft_weights < 1: + if "ScaledSoftControlNetWeights" in NODE_CLASS_MAPPINGS: + soft_weight_cls = NODE_CLASS_MAPPINGS['ScaledSoftControlNetWeights'] + (weights, timestep_keyframe) = soft_weight_cls().load_weights(scale_soft_weights, False) + cn_adv_cls = NODE_CLASS_MAPPINGS['ControlNetLoaderAdvanced'] + control_net, = cn_adv_cls().load_controlnet(control_net_name, timestep_keyframe) + else: + raise Exception( + f"[Advanced-ControlNet Not Found] you need to install 'COMFYUI-Advanced-ControlNet'") + else: + controlnet_path = folder_paths.get_full_path("controlnet", control_net_name) + control_net = comfy.controlnet.load_controlnet(controlnet_path) + self.add_to_cache("controlnet", unique_id, control_net) + self.eviction_based_on_memory() + return control_net def load_clip(self, clip_name, type='stable_diffusion'): if type == 'stable_diffusion': clip_type = comfy.sd.CLIPType.STABLE_DIFFUSION