mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-01-11 23:00:51 +08:00
(broken) Merge branch 'master' of github.com:comfyanonymous/ComfyUI
This commit is contained in:
commit
272e3ee357
@ -221,6 +221,11 @@ async def main():
|
|||||||
|
|
||||||
if args.windows_standalone_build:
|
if args.windows_standalone_build:
|
||||||
folder_paths.create_directories()
|
folder_paths.create_directories()
|
||||||
|
try:
|
||||||
|
import new_updater
|
||||||
|
new_updater.update_windows_updater()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
server = server_module.PromptServer(loop)
|
server = server_module.PromptServer(loop)
|
||||||
|
|||||||
@ -237,6 +237,10 @@ def convert_text_enc_state_dict_v20(text_enc_dict, prefix=""):
|
|||||||
capture_qkv_bias[k_pre][code2idx[k_code]] = v
|
capture_qkv_bias[k_pre][code2idx[k_code]] = v
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
text_proj = "transformer.text_projection.weight"
|
||||||
|
if k.endswith(text_proj):
|
||||||
|
new_state_dict[k.replace(text_proj, "text_projection")] = v.transpose(0, 1).contiguous()
|
||||||
|
|
||||||
relabelled_key = textenc_pattern.sub(lambda m: protected[re.escape(m.group(0))], k)
|
relabelled_key = textenc_pattern.sub(lambda m: protected[re.escape(m.group(0))], k)
|
||||||
new_state_dict[relabelled_key] = v
|
new_state_dict[relabelled_key] = v
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import torch
|
||||||
|
|
||||||
class LatentFormat:
|
class LatentFormat:
|
||||||
scale_factor = 1.0
|
scale_factor = 1.0
|
||||||
@ -34,6 +35,32 @@ class SDXL(LatentFormat):
|
|||||||
]
|
]
|
||||||
self.taesd_decoder_name = "taesdxl_decoder"
|
self.taesd_decoder_name = "taesdxl_decoder"
|
||||||
|
|
||||||
|
class SDXL_Playground_2_5(LatentFormat):
|
||||||
|
def __init__(self):
|
||||||
|
self.scale_factor = 0.5
|
||||||
|
self.latents_mean = torch.tensor([-1.6574, 1.886, -1.383, 2.5155]).view(1, 4, 1, 1)
|
||||||
|
self.latents_std = torch.tensor([8.4927, 5.9022, 6.5498, 5.2299]).view(1, 4, 1, 1)
|
||||||
|
|
||||||
|
self.latent_rgb_factors = [
|
||||||
|
# R G B
|
||||||
|
[ 0.3920, 0.4054, 0.4549],
|
||||||
|
[-0.2634, -0.0196, 0.0653],
|
||||||
|
[ 0.0568, 0.1687, -0.0755],
|
||||||
|
[-0.3112, -0.2359, -0.2076]
|
||||||
|
]
|
||||||
|
self.taesd_decoder_name = "taesdxl_decoder"
|
||||||
|
|
||||||
|
def process_in(self, latent):
|
||||||
|
latents_mean = self.latents_mean.to(latent.device, latent.dtype)
|
||||||
|
latents_std = self.latents_std.to(latent.device, latent.dtype)
|
||||||
|
return (latent - latents_mean) * self.scale_factor / latents_std
|
||||||
|
|
||||||
|
def process_out(self, latent):
|
||||||
|
latents_mean = self.latents_mean.to(latent.device, latent.dtype)
|
||||||
|
latents_std = self.latents_std.to(latent.device, latent.dtype)
|
||||||
|
return latent * latents_std / self.scale_factor + latents_mean
|
||||||
|
|
||||||
|
|
||||||
class SD_X4(LatentFormat):
|
class SD_X4(LatentFormat):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.scale_factor = 0.08333
|
self.scale_factor = 0.08333
|
||||||
|
|||||||
@ -15,9 +15,10 @@ class ModelType(Enum):
|
|||||||
V_PREDICTION = 2
|
V_PREDICTION = 2
|
||||||
V_PREDICTION_EDM = 3
|
V_PREDICTION_EDM = 3
|
||||||
STABLE_CASCADE = 4
|
STABLE_CASCADE = 4
|
||||||
|
EDM = 5
|
||||||
|
|
||||||
|
|
||||||
from .model_sampling import EPS, V_PREDICTION, ModelSamplingDiscrete, ModelSamplingContinuousEDM, StableCascadeSampling
|
from .model_sampling import EPS, V_PREDICTION, EDM, ModelSamplingDiscrete, ModelSamplingContinuousEDM, StableCascadeSampling
|
||||||
|
|
||||||
|
|
||||||
def model_sampling(model_config, model_type):
|
def model_sampling(model_config, model_type):
|
||||||
@ -33,6 +34,9 @@ def model_sampling(model_config, model_type):
|
|||||||
elif model_type == ModelType.STABLE_CASCADE:
|
elif model_type == ModelType.STABLE_CASCADE:
|
||||||
c = EPS
|
c = EPS
|
||||||
s = StableCascadeSampling
|
s = StableCascadeSampling
|
||||||
|
elif model_type == ModelType.EDM:
|
||||||
|
c = EDM
|
||||||
|
s = ModelSamplingContinuousEDM
|
||||||
|
|
||||||
class ModelSampling(s, c):
|
class ModelSampling(s, c):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@ -17,6 +17,11 @@ class V_PREDICTION(EPS):
|
|||||||
sigma = sigma.view(sigma.shape[:1] + (1,) * (model_output.ndim - 1))
|
sigma = sigma.view(sigma.shape[:1] + (1,) * (model_output.ndim - 1))
|
||||||
return model_input * self.sigma_data ** 2 / (sigma ** 2 + self.sigma_data ** 2) - model_output * sigma * self.sigma_data / (sigma ** 2 + self.sigma_data ** 2) ** 0.5
|
return model_input * self.sigma_data ** 2 / (sigma ** 2 + self.sigma_data ** 2) - model_output * sigma * self.sigma_data / (sigma ** 2 + self.sigma_data ** 2) ** 0.5
|
||||||
|
|
||||||
|
class EDM(V_PREDICTION):
|
||||||
|
def calculate_denoised(self, sigma, model_output, model_input):
|
||||||
|
sigma = sigma.view(sigma.shape[:1] + (1,) * (model_output.ndim - 1))
|
||||||
|
return model_input * self.sigma_data ** 2 / (sigma ** 2 + self.sigma_data ** 2) + model_output * sigma * self.sigma_data / (sigma ** 2 + self.sigma_data ** 2) ** 0.5
|
||||||
|
|
||||||
|
|
||||||
class ModelSamplingDiscrete(torch.nn.Module):
|
class ModelSamplingDiscrete(torch.nn.Module):
|
||||||
def __init__(self, model_config=None):
|
def __init__(self, model_config=None):
|
||||||
@ -92,8 +97,6 @@ class ModelSamplingDiscrete(torch.nn.Module):
|
|||||||
class ModelSamplingContinuousEDM(torch.nn.Module):
|
class ModelSamplingContinuousEDM(torch.nn.Module):
|
||||||
def __init__(self, model_config=None):
|
def __init__(self, model_config=None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.sigma_data = 1.0
|
|
||||||
|
|
||||||
if model_config is not None:
|
if model_config is not None:
|
||||||
sampling_settings = model_config.sampling_settings
|
sampling_settings = model_config.sampling_settings
|
||||||
else:
|
else:
|
||||||
@ -101,9 +104,11 @@ class ModelSamplingContinuousEDM(torch.nn.Module):
|
|||||||
|
|
||||||
sigma_min = sampling_settings.get("sigma_min", 0.002)
|
sigma_min = sampling_settings.get("sigma_min", 0.002)
|
||||||
sigma_max = sampling_settings.get("sigma_max", 120.0)
|
sigma_max = sampling_settings.get("sigma_max", 120.0)
|
||||||
self.set_sigma_range(sigma_min, sigma_max)
|
sigma_data = sampling_settings.get("sigma_data", 1.0)
|
||||||
|
self.set_parameters(sigma_min, sigma_max, sigma_data)
|
||||||
|
|
||||||
def set_sigma_range(self, sigma_min, sigma_max):
|
def set_parameters(self, sigma_min, sigma_max, sigma_data):
|
||||||
|
self.sigma_data = sigma_data
|
||||||
sigmas = torch.linspace(math.log(sigma_min), math.log(sigma_max), 1000).exp()
|
sigmas = torch.linspace(math.log(sigma_min), math.log(sigma_max), 1000).exp()
|
||||||
|
|
||||||
self.register_buffer('sigmas', sigmas) #for compatibility with some schedulers
|
self.register_buffer('sigmas', sigmas) #for compatibility with some schedulers
|
||||||
|
|||||||
@ -591,7 +591,7 @@ def sample(model, noise, positive, negative, cfg, device, sampler, sigmas, model
|
|||||||
calculate_start_end_timesteps(model, negative)
|
calculate_start_end_timesteps(model, negative)
|
||||||
calculate_start_end_timesteps(model, positive)
|
calculate_start_end_timesteps(model, positive)
|
||||||
|
|
||||||
if latent_image is not None:
|
if latent_image is not None and torch.count_nonzero(latent_image) > 0: #Don't shift the empty latent image.
|
||||||
latent_image = model.process_latent_in(latent_image)
|
latent_image = model.process_latent_in(latent_image)
|
||||||
|
|
||||||
if hasattr(model, 'extra_conds'):
|
if hasattr(model, 'extra_conds'):
|
||||||
|
|||||||
@ -358,7 +358,7 @@ def load_embed(embedding_name, embedding_directory, embedding_size, embed_key=No
|
|||||||
return embed_out
|
return embed_out
|
||||||
|
|
||||||
class SDTokenizer:
|
class SDTokenizer:
|
||||||
def __init__(self, tokenizer_path=None, max_length=77, pad_with_end=True, embedding_directory=None, embedding_size=768, embedding_key='clip_l', tokenizer_class=CLIPTokenizer, has_start_token=True, pad_to_max_length=True):
|
def __init__(self, tokenizer_path=None, max_length=77, pad_with_end=True, embedding_directory=None, embedding_size=768, embedding_key='clip_l', tokenizer_class=CLIPTokenizer, has_start_token=True, pad_to_max_length=True, min_length=None):
|
||||||
if tokenizer_path is None:
|
if tokenizer_path is None:
|
||||||
tokenizer_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "sd1_tokenizer")
|
tokenizer_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "sd1_tokenizer")
|
||||||
if not os.path.exists(os.path.join(tokenizer_path, "tokenizer_config.json")):
|
if not os.path.exists(os.path.join(tokenizer_path, "tokenizer_config.json")):
|
||||||
@ -366,6 +366,7 @@ class SDTokenizer:
|
|||||||
tokenizer_path = resource_filename('comfy', 'sd1_tokenizer/')
|
tokenizer_path = resource_filename('comfy', 'sd1_tokenizer/')
|
||||||
self.tokenizer = tokenizer_class.from_pretrained(tokenizer_path)
|
self.tokenizer = tokenizer_class.from_pretrained(tokenizer_path)
|
||||||
self.max_length = max_length
|
self.max_length = max_length
|
||||||
|
self.min_length = min_length
|
||||||
|
|
||||||
empty = self.tokenizer('')["input_ids"]
|
empty = self.tokenizer('')["input_ids"]
|
||||||
if has_start_token:
|
if has_start_token:
|
||||||
@ -483,6 +484,8 @@ class SDTokenizer:
|
|||||||
batch.append((self.end_token, 1.0, 0))
|
batch.append((self.end_token, 1.0, 0))
|
||||||
if self.pad_to_max_length:
|
if self.pad_to_max_length:
|
||||||
batch.extend([(pad_token, 1.0, 0)] * (self.max_length - len(batch)))
|
batch.extend([(pad_token, 1.0, 0)] * (self.max_length - len(batch)))
|
||||||
|
if self.min_length is not None and len(batch) < self.min_length:
|
||||||
|
batch.extend([(pad_token, 1.0, 0)] * (self.min_length - len(batch)))
|
||||||
|
|
||||||
if not return_word_ids:
|
if not return_word_ids:
|
||||||
batched_tokens = [[(t, w) for t, w,_ in x] for x in batched_tokens]
|
batched_tokens = [[(t, w) for t, w,_ in x] for x in batched_tokens]
|
||||||
|
|||||||
@ -163,7 +163,13 @@ class SDXL(supported_models_base.BASE):
|
|||||||
latent_format = latent_formats.SDXL
|
latent_format = latent_formats.SDXL
|
||||||
|
|
||||||
def model_type(self, state_dict, prefix=""):
|
def model_type(self, state_dict, prefix=""):
|
||||||
if "v_pred" in state_dict:
|
if 'edm_mean' in state_dict and 'edm_std' in state_dict: #Playground V2.5
|
||||||
|
self.latent_format = latent_formats.SDXL_Playground_2_5()
|
||||||
|
self.sampling_settings["sigma_data"] = 0.5
|
||||||
|
self.sampling_settings["sigma_max"] = 80.0
|
||||||
|
self.sampling_settings["sigma_min"] = 0.002
|
||||||
|
return model_base.ModelType.EDM
|
||||||
|
elif "v_pred" in state_dict:
|
||||||
return model_base.ModelType.V_PREDICTION
|
return model_base.ModelType.V_PREDICTION
|
||||||
else:
|
else:
|
||||||
return model_base.ModelType.EPS
|
return model_base.ModelType.EPS
|
||||||
@ -190,12 +196,16 @@ class SDXL(supported_models_base.BASE):
|
|||||||
replace_prefix = {}
|
replace_prefix = {}
|
||||||
keys_to_replace = {}
|
keys_to_replace = {}
|
||||||
state_dict_g = diffusers_convert.convert_text_enc_state_dict_v20(state_dict, "clip_g")
|
state_dict_g = diffusers_convert.convert_text_enc_state_dict_v20(state_dict, "clip_g")
|
||||||
if "clip_g.transformer.text_model.embeddings.position_ids" in state_dict_g:
|
|
||||||
state_dict_g.pop("clip_g.transformer.text_model.embeddings.position_ids")
|
|
||||||
for k in state_dict:
|
for k in state_dict:
|
||||||
if k.startswith("clip_l"):
|
if k.startswith("clip_l"):
|
||||||
state_dict_g[k] = state_dict[k]
|
state_dict_g[k] = state_dict[k]
|
||||||
|
|
||||||
|
state_dict_g["clip_l.transformer.text_model.embeddings.position_ids"] = torch.arange(77).expand((1, -1))
|
||||||
|
pop_keys = ["clip_l.transformer.text_projection.weight", "clip_l.logit_scale"]
|
||||||
|
for p in pop_keys:
|
||||||
|
if p in state_dict_g:
|
||||||
|
state_dict_g.pop(p)
|
||||||
|
|
||||||
replace_prefix["clip_g"] = "conditioner.embedders.1.model"
|
replace_prefix["clip_g"] = "conditioner.embedders.1.model"
|
||||||
replace_prefix["clip_l"] = "conditioner.embedders.0"
|
replace_prefix["clip_l"] = "conditioner.embedders.0"
|
||||||
state_dict_g = utils.state_dict_prefix_replace(state_dict_g, replace_prefix)
|
state_dict_g = utils.state_dict_prefix_replace(state_dict_g, replace_prefix)
|
||||||
|
|||||||
@ -112,7 +112,7 @@ def clip_text_transformers_convert(sd, prefix_from, prefix_to):
|
|||||||
|
|
||||||
tp = "{}text_projection".format(prefix_from)
|
tp = "{}text_projection".format(prefix_from)
|
||||||
if tp in sd:
|
if tp in sd:
|
||||||
sd["{}text_projection.weight".format(prefix_to)] = sd.pop(tp).transpose(0, 1)
|
sd["{}text_projection.weight".format(prefix_to)] = sd.pop(tp).transpose(0, 1).contiguous()
|
||||||
return sd
|
return sd
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import comfy.sd
|
import comfy.sd
|
||||||
import comfy.model_sampling
|
import comfy.model_sampling
|
||||||
|
import comfy.latent_formats
|
||||||
import torch
|
import torch
|
||||||
|
|
||||||
class LCM(comfy.model_sampling.EPS):
|
class LCM(comfy.model_sampling.EPS):
|
||||||
@ -134,7 +135,7 @@ class ModelSamplingContinuousEDM:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
return {"required": { "model": ("MODEL",),
|
return {"required": { "model": ("MODEL",),
|
||||||
"sampling": (["v_prediction", "eps"],),
|
"sampling": (["v_prediction", "edm_playground_v2.5", "eps"],),
|
||||||
"sigma_max": ("FLOAT", {"default": 120.0, "min": 0.0, "max": 1000.0, "step":0.001, "round": False}),
|
"sigma_max": ("FLOAT", {"default": 120.0, "min": 0.0, "max": 1000.0, "step":0.001, "round": False}),
|
||||||
"sigma_min": ("FLOAT", {"default": 0.002, "min": 0.0, "max": 1000.0, "step":0.001, "round": False}),
|
"sigma_min": ("FLOAT", {"default": 0.002, "min": 0.0, "max": 1000.0, "step":0.001, "round": False}),
|
||||||
}}
|
}}
|
||||||
@ -147,17 +148,25 @@ class ModelSamplingContinuousEDM:
|
|||||||
def patch(self, model, sampling, sigma_max, sigma_min):
|
def patch(self, model, sampling, sigma_max, sigma_min):
|
||||||
m = model.clone()
|
m = model.clone()
|
||||||
|
|
||||||
|
latent_format = None
|
||||||
|
sigma_data = 1.0
|
||||||
if sampling == "eps":
|
if sampling == "eps":
|
||||||
sampling_type = comfy.model_sampling.EPS
|
sampling_type = comfy.model_sampling.EPS
|
||||||
elif sampling == "v_prediction":
|
elif sampling == "v_prediction":
|
||||||
sampling_type = comfy.model_sampling.V_PREDICTION
|
sampling_type = comfy.model_sampling.V_PREDICTION
|
||||||
|
elif sampling == "edm_playground_v2.5":
|
||||||
|
sampling_type = comfy.model_sampling.EDM
|
||||||
|
sigma_data = 0.5
|
||||||
|
latent_format = comfy.latent_formats.SDXL_Playground_2_5()
|
||||||
|
|
||||||
class ModelSamplingAdvanced(comfy.model_sampling.ModelSamplingContinuousEDM, sampling_type):
|
class ModelSamplingAdvanced(comfy.model_sampling.ModelSamplingContinuousEDM, sampling_type):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
model_sampling = ModelSamplingAdvanced(model.model.model_config)
|
model_sampling = ModelSamplingAdvanced(model.model.model_config)
|
||||||
model_sampling.set_sigma_range(sigma_min, sigma_max)
|
model_sampling.set_parameters(sigma_min, sigma_max, sigma_data)
|
||||||
m.add_object_patch("model_sampling", model_sampling)
|
m.add_object_patch("model_sampling", model_sampling)
|
||||||
|
if latent_format is not None:
|
||||||
|
m.add_object_patch("latent_format", latent_format)
|
||||||
return (m, )
|
return (m, )
|
||||||
|
|
||||||
class RescaleCFG:
|
class RescaleCFG:
|
||||||
|
|||||||
35
new_updater.py
Normal file
35
new_updater.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
base_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
def update_windows_updater():
|
||||||
|
top_path = os.path.dirname(base_path)
|
||||||
|
updater_path = os.path.join(base_path, ".ci/update_windows/update.py")
|
||||||
|
bat_path = os.path.join(base_path, ".ci/update_windows/update_comfyui.bat")
|
||||||
|
|
||||||
|
dest_updater_path = os.path.join(top_path, "update/update.py")
|
||||||
|
dest_bat_path = os.path.join(top_path, "update/update_comfyui.bat")
|
||||||
|
dest_bat_deps_path = os.path.join(top_path, "update/update_comfyui_and_python_dependencies.bat")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(dest_bat_path, 'rb') as f:
|
||||||
|
contents = f.read()
|
||||||
|
except:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not contents.startswith(b"..\\python_embeded\\python.exe .\\update.py"):
|
||||||
|
return
|
||||||
|
|
||||||
|
shutil.copy(updater_path, dest_updater_path)
|
||||||
|
try:
|
||||||
|
with open(dest_bat_deps_path, 'rb') as f:
|
||||||
|
contents = f.read()
|
||||||
|
contents = contents.replace(b'..\\python_embeded\\python.exe .\\update.py ..\\ComfyUI\\', b'call update_comfyui.bat nopause')
|
||||||
|
with open(dest_bat_deps_path, 'wb') as f:
|
||||||
|
f.write(contents)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
shutil.copy(bat_path, dest_bat_path)
|
||||||
|
print("Updated the windows standalone package updater.")
|
||||||
Loading…
Reference in New Issue
Block a user