Update to latest ComfyUI

This commit is contained in:
doctorpangloss 2025-04-21 14:11:56 -07:00
parent 5823497d55
commit 17b14110ab
15 changed files with 54 additions and 27 deletions

View File

@ -20,9 +20,15 @@ from ..cmd.folder_paths import add_model_folder_path # pylint: disable=import-e
REQUEST_TIMEOUT = 10 # seconds
def check_frontend_version():
return None
def frontend_install_warning_message() -> str:
return ""
class Asset(TypedDict):
url: str
@ -141,8 +147,6 @@ class FrontendManager:
comfyui-workflow-templates is not installed.
{frontend_install_warning_message()}
********** ERROR ***********
""".strip()
)

View File

@ -131,7 +131,7 @@ def _create_parser() -> EnhancedConfigArgParser:
parser.add_argument("--deterministic", action="store_true",
help="Make pytorch use slower deterministic algorithms when it can. Note that this might not make images deterministic in all cases.")
parser.add_argument("--fast", nargs="*", type=PerformanceFeature, help="Enable some untested and potentially quality deteriorating optimizations. Pass a list specific optimizations if you only want to enable specific ones. Current valid optimizations: fp16_accumulation fp8_matrix_mult cublas_ops")
parser.add_argument("--fast", nargs="*", type=PerformanceFeature, help="Enable some untested and potentially quality deteriorating optimizations. Pass a list specific optimizations if you only want to enable specific ones. Current valid optimizations: fp16_accumulation fp8_matrix_mult cublas_ops", default=set())
parser.add_argument("--dont-print-server", action="store_true", help="Don't print server output.")
parser.add_argument("--quick-test-for-ci", action="store_true", help="Quick test for CI. Raises an error if nodes cannot be imported,")

View File

@ -71,7 +71,8 @@ async def __execute_prompt(
args.update(configuration)
with tracer.start_as_current_span("Initialize Prompt Executor", context=span_context):
prompt_executor = PromptExecutor(progress_handler, lru_size=configuration.cache_lru if configuration is not None else 0)
# todo: deal with new caching features
prompt_executor = PromptExecutor(progress_handler)
prompt_executor.raise_exceptions = True
_prompt_executor.executor = prompt_executor

View File

@ -1,5 +1,6 @@
import json
import logging
from typing import Optional
import torch
@ -116,7 +117,8 @@ def convert_to_transformers(sd, prefix):
return sd
def load_clipvision_from_sd(sd, prefix="", convert_keys=False):
def load_clipvision_from_sd(sd, prefix="", convert_keys=False) -> Optional[ClipVisionModel]:
json_config: dict = {}
if convert_keys:
sd = convert_to_transformers(sd, prefix)
if "vision_model.encoder.layers.47.layer_norm1.weight" in sd:

View File

@ -745,7 +745,7 @@ def validate_inputs(prompt, item, validated: typing.Dict[str, ValidateInputsTupl
r = get_nodes().NODE_CLASS_MAPPINGS[o_class_type].RETURN_TYPES
received_type = r[val[1]]
received_types[x] = received_type
any_enum = received_type == [] and (isinstance(type_input, list) or isinstance(type_input, tuple))
any_enum = received_type == [] and (isinstance(input_type, list) or isinstance(input_type, tuple))
if 'input_types' not in validate_function_inputs and not validate_node_input(received_type, input_type) and not any_enum:
details = f"{x}, {received_type} != {input_type}"
@ -857,8 +857,8 @@ def validate_inputs(prompt, item, validated: typing.Dict[str, ValidateInputsTupl
if "\\" in val:
# try to normalize paths for comparison purposes
val = canonicalize_path(val)
if all(isinstance(item, (str, PathLike)) for item in type_input):
type_input = [canonicalize_path(item) for item in type_input]
if all(isinstance(item, (str, PathLike)) for item in combo_options):
combo_options = [canonicalize_path(item) for item in combo_options]
if val not in combo_options:
input_config = info
list_info = ""

View File

@ -36,6 +36,10 @@ _session = Session()
_hf_fs = HfFileSystem()
def get_filename_list(folder_name: str) -> list[str]:
return get_filename_list_with_downloadable(folder_name)
def get_filename_list_with_downloadable(folder_name: str, known_files: Optional[List[Downloadable] | KnownDownloadables] = None) -> List[str]:
if known_files is None:
known_files = _get_known_models_for_folder_name(folder_name)
@ -45,6 +49,13 @@ def get_filename_list_with_downloadable(folder_name: str, known_files: Optional[
return list(map(canonicalize_path, sorted(list(existing | downloadable))))
def get_full_path_or_raise(folder_name: str, filename: str) -> str:
res = get_or_download(folder_name, filename)
if res is None:
raise FileNotFoundError(f"{folder_name} does not contain {filename}")
return res
def get_or_download(folder_name: str, filename: str, known_files: Optional[List[Downloadable] | KnownDownloadables] = None) -> Optional[str]:
if known_files is None:
known_files = _get_known_models_for_folder_name(folder_name)

View File

@ -102,6 +102,7 @@ def string_to_torch_dtype(string):
def image_alpha_fix(destination, source):
import torch
if destination.shape[-1] < source.shape[-1]:
source = source[..., :destination.shape[-1]]
elif destination.shape[-1] > source.shape[-1]:

View File

@ -1714,8 +1714,9 @@ class LoadImage:
mask = np.array(i.getchannel('A')).astype(np.float32) / 255.0
mask = 1. - torch.from_numpy(mask)
elif i.mode == 'P' and 'transparency' in i.info:
mask = np.array(i.convert('RGBA').getchannel('A')).astype(np.float32) / 255.0
mask = 1. - torch.from_numpy(mask)else:
mask = np.array(i.convert('RGBA').getchannel('A')).astype(np.float32) / 255.0
mask = 1. - torch.from_numpy(mask)
else:
mask = torch.zeros((64,64), dtype=torch.float32, device="cpu")
output_images.append(image)
output_masks.append(mask.unsqueeze(0))

View File

@ -1,6 +1,5 @@
import uuid
from . import conds
from . import model_management
from . import patcher_extension
from . import utils
@ -113,9 +112,9 @@ def cleanup_additional_models(models):
def prepare_sampling(model: ModelPatcher, noise_shape, conds, model_options=None):
executor = comfy.patcher_extension.WrapperExecutor.new_executor(
executor = patcher_extension.WrapperExecutor.new_executor(
_prepare_sampling,
comfy.patcher_extension.get_all_wrappers(comfy.patcher_extension.WrappersMP.PREPARE_SAMPLING, model_options, is_model_options=True)
patcher_extension.get_all_wrappers(patcher_extension.WrappersMP.PREPARE_SAMPLING, model_options, is_model_options=True)
)
return executor.execute(model, noise_shape, conds, model_options=model_options)

View File

@ -16,6 +16,7 @@ class PT5XlModel(sd1_clip.SDClipModel):
class PT5XlTokenizer(sd1_clip.SDTokenizer):
def __init__(self, embedding_directory=None, **kwargs):
tokenizer_path = resources.files("comfy.text_encoders.t5_pile_tokenizer") / "tokenizer.model"
tokenizer_data = kwargs.pop("tokenizer_data", {})
super().__init__(tokenizer_path, pad_with_end=False, embedding_size=2048, embedding_key='pile_t5xl', tokenizer_class=SPieceTokenizer, has_start_token=False, pad_to_max_length=False, max_length=99999999, min_length=256, pad_token=1, tokenizer_data=tokenizer_data)

View File

@ -21,6 +21,7 @@ class HyditBertModel(sd1_clip.SDClipModel):
class HyditBertTokenizer(sd1_clip.SDTokenizer):
def __init__(self, **kwargs):
tokenizer_path = get_package_as_path(f"{__package__}.hydit_clip_tokenizer")
tokenizer_data = kwargs.pop("tokenizer_data", {})
super().__init__(tokenizer_path, pad_with_end=False, embedding_size=1024, embedding_key='chinese_roberta', tokenizer_class=BertTokenizer, pad_to_max_length=False, max_length=512, min_length=77, tokenizer_data=tokenizer_data)

View File

@ -1,16 +1,18 @@
import folder_paths
import comfy.sd
import comfy.model_management
import comfy.sd
from comfy.cmd import folder_paths
from comfy import model_downloader
class QuadrupleCLIPLoader:
@classmethod
def INPUT_TYPES(s):
return {"required": { "clip_name1": (folder_paths.get_filename_list("text_encoders"), ),
"clip_name2": (folder_paths.get_filename_list("text_encoders"), ),
"clip_name3": (folder_paths.get_filename_list("text_encoders"), ),
"clip_name4": (folder_paths.get_filename_list("text_encoders"), )
return {"required": {"clip_name1": (model_downloader.get_filename_list("text_encoders"),),
"clip_name2": (model_downloader.get_filename_list("text_encoders"),),
"clip_name3": (model_downloader.get_filename_list("text_encoders"),),
"clip_name4": (model_downloader.get_filename_list("text_encoders"),)
}}
RETURN_TYPES = ("CLIP",)
FUNCTION = "load_clip"
@ -19,35 +21,37 @@ class QuadrupleCLIPLoader:
DESCRIPTION = "[Recipes]\n\nhidream: long clip-l, long clip-g, t5xxl, llama_8b_3.1_instruct"
def load_clip(self, clip_name1, clip_name2, clip_name3, clip_name4):
clip_path1 = folder_paths.get_full_path_or_raise("text_encoders", clip_name1)
clip_path2 = folder_paths.get_full_path_or_raise("text_encoders", clip_name2)
clip_path3 = folder_paths.get_full_path_or_raise("text_encoders", clip_name3)
clip_path4 = folder_paths.get_full_path_or_raise("text_encoders", clip_name4)
clip_path1 = model_downloader.get_full_path_or_raise("text_encoders", clip_name1)
clip_path2 = model_downloader.get_full_path_or_raise("text_encoders", clip_name2)
clip_path3 = model_downloader.get_full_path_or_raise("text_encoders", clip_name3)
clip_path4 = model_downloader.get_full_path_or_raise("text_encoders", clip_name4)
clip = comfy.sd.load_clip(ckpt_paths=[clip_path1, clip_path2, clip_path3, clip_path4], embedding_directory=folder_paths.get_folder_paths("embeddings"))
return (clip,)
class CLIPTextEncodeHiDream:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"clip": ("CLIP", ),
"clip": ("CLIP",),
"clip_l": ("STRING", {"multiline": True, "dynamicPrompts": True}),
"clip_g": ("STRING", {"multiline": True, "dynamicPrompts": True}),
"t5xxl": ("STRING", {"multiline": True, "dynamicPrompts": True}),
"llama": ("STRING", {"multiline": True, "dynamicPrompts": True})
}}
}}
RETURN_TYPES = ("CONDITIONING",)
FUNCTION = "encode"
CATEGORY = "advanced/conditioning"
def encode(self, clip, clip_l, clip_g, t5xxl, llama):
tokens = clip.tokenize(clip_g)
tokens["l"] = clip.tokenize(clip_l)["l"]
tokens["t5xxl"] = clip.tokenize(t5xxl)["t5xxl"]
tokens["llama"] = clip.tokenize(llama)["llama"]
return (clip.encode_from_tokens_scheduled(tokens), )
return (clip.encode_from_tokens_scheduled(tokens),)
NODE_CLASS_MAPPINGS = {
"QuadrupleCLIPLoader": QuadrupleCLIPLoader,

View File

@ -447,6 +447,8 @@ class VoxelToMesh:
mesh_function = voxel_to_mesh
elif algorithm == "surface net":
mesh_function = voxel_to_mesh_surfnet
else:
mesh_function = None
for x in voxel.data:
v, f = mesh_function(x, threshold=threshold, device=None)