Files
Extraltodeus-ComfyUI-Automa…/nodes.py
T

555 lines
31 KiB
Python

import math
from copy import deepcopy
import comfy.samplers
import numpy as np
import torch
import torch.nn.functional as F
from colorama import Fore, Style
original_sampling_function = None
def sampling_function_patched(model, x, timestep, uncond, cond, cond_scale, model_options={}, seed=None, **kwargs):
if "sampler_pre_cfg_function" in model_options:
uncond, cond, cond_scale = model_options["sampler_pre_cfg_function"](
sigma=timestep, uncond=uncond, cond=cond, cond_scale=cond_scale
)
if math.isclose(cond_scale, 1.0) and model_options.get("disable_cfg1_optimization", False) == False:
uncond_ = None
else:
uncond_ = uncond
conds = [cond, uncond_]
out = comfy.samplers.calc_cond_batch(model, conds, x, timestep, model_options)
cond_pred = out[0]
uncond_pred = out[1]
if "sampler_cfg_function" in model_options:
args = {"cond": x - cond_pred, "uncond": x - uncond_pred, "cond_scale": cond_scale, "timestep": timestep, "input": x, "sigma": timestep,
"cond_denoised": cond_pred, "uncond_denoised": uncond_pred, "model": model, "model_options": model_options, "cond_pos": cond, "cond_neg": uncond}
cfg_result = x - model_options["sampler_cfg_function"](args)
else:
cfg_result = uncond_pred + (cond_pred - uncond_pred) * cond_scale
for fn in model_options.get("sampler_post_cfg_function", []):
args = {"denoised": cfg_result, "cond": cond, "uncond": uncond, "model": model, "uncond_denoised": uncond_pred, "cond_denoised": cond_pred,
"sigma": timestep, "model_options": model_options, "input": x}
cfg_result = fn(args)
return cfg_result
def monkey_patching_comfy_sampling_function():
global original_sampling_function
if original_sampling_function is None:
original_sampling_function = comfy.samplers.sampling_function
# Make sure to only patch once
if hasattr(comfy.samplers.sampling_function, '_automatic_cfg_decorated'):
return
comfy.samplers.sampling_function = sampling_function_patched
comfy.samplers.sampling_function._automatic_cfg_decorated = True # flag to check monkey patch
def make_sampler_pre_cfg_function(minimum_sigma_to_disable_uncond=0, maximum_sigma_to_enable_uncond=1000000):
def sampler_pre_cfg_function(sigma, uncond, cond, cond_scale, **kwargs):
if sigma[0] < minimum_sigma_to_disable_uncond or sigma[0] > maximum_sigma_to_enable_uncond:
uncond = None
return uncond, cond, cond_scale
return sampler_pre_cfg_function
def get_entropy(tensor):
hist = np.histogram(tensor.cpu(), bins=100)[0]
hist = hist / hist.sum()
hist = hist[hist > 0]
return -np.sum(hist * np.log2(hist))
def map_sigma(sigma, sigmax, sigmin):
return 1 + ((sigma - sigmax) * (0 - 1)) / (sigmin - sigmax)
def center_latent_mean_values(latent, per_channel, mult):
for b in range(len(latent)):
if per_channel:
for c in range(len(latent[b])):
latent[b][c] -= latent[b][c].mean() * mult
else:
latent[b] -= latent[b].mean() * mult
return latent
def get_denoised_ranges(latent, measure="hard", top_k=0.25):
chans = []
for x in range(len(latent)):
max_values = torch.topk(latent[x] - latent[x].mean() if measure == "range" else latent[x], k=int(len(latent[x])*top_k), largest=True).values
min_values = torch.topk(latent[x] - latent[x].mean() if measure == "range" else latent[x], k=int(len(latent[x])*top_k), largest=False).values
max_val = torch.mean(max_values).item()
min_val = abs(torch.mean(min_values).item()) if measure == "soft" else torch.mean(torch.abs(min_values)).item()
denoised_range = (max_val + min_val) / 2
chans.append(denoised_range**2 if measure == "hard_squared" else denoised_range)
return chans
def get_sigmin_sigmax(model):
model_sampling = model.get_model_object("model_sampling")
sigmin = model_sampling.sigma(model_sampling.timestep(model_sampling.sigma_min))
sigmax = model_sampling.sigma(model_sampling.timestep(model_sampling.sigma_max))
return sigmin, sigmax
def get_sigmas_start_end(sigmin, sigmax, start_percentage, end_percentage):
high_sigma_threshold = (sigmax - sigmin) / 100 * start_percentage
low_sigma_threshold = (sigmax - sigmin) / 100 * end_percentage
return high_sigma_threshold, low_sigma_threshold
def gaussian_similarity(x, y, sigma=1.0):
diff = (x - y) ** 2
return torch.exp(-diff / (2 * sigma ** 2))
def check_skip(sigma, high_sigma_threshold, low_sigma_threshold):
return sigma > high_sigma_threshold or sigma < low_sigma_threshold
def gaussian_kernel(size, sigma):
ax = torch.arange(-size // 2 + 1., size // 2 + 1.)
xx, yy = torch.meshgrid(ax, ax, indexing='ij')
kernel = torch.exp(-(xx**2 + yy**2) / (2. * sigma**2))
return kernel / kernel.sum()
def blur_tensor(input_tensor, sigma=2, kernel_size=7):
device = input_tensor.device
kernel = gaussian_kernel(kernel_size, sigma).unsqueeze(0).unsqueeze(0).to(device).to(input_tensor[0][0].dtype)
padding = kernel_size // 2
blurred_batch = []
for batch in input_tensor: # Iterate over each batch
blurred_channels = []
for channel in batch: # Iterate over each channel
blurred_channel = F.conv2d(channel.unsqueeze(0).unsqueeze(0), kernel, padding=padding)
blurred_channels.append(blurred_channel.squeeze(0).squeeze(0)) # Corrected squeezing step
blurred_batch.append(torch.stack(blurred_channels))
return torch.stack(blurred_batch).to(device)
def square_and_norm(cond_input, method, exp_value, exp_normalize, pcp, psi, sigma, sigmax, args, eval_string = ""):
"""
There may or may not be an actual reasoning behind each of these methods.
Some like the sine value have interesting properties. Enabled for both cond and uncond preds it somehow make them stronger.
Note that there is a "normalize" toggle and it may change greatly the end result since some operation will totaly butcher the values.
"theDaRkNeSs" for example without normalizing seems to darken if used for cond/uncond (not with the cond as the uncond or something).
Maybe just with the positive. I don't remember. I leave it for now if you want to play around.
The eval_string can be used to create the uncond replacement.
I made it so it's split by semicolons and only the last split is the value in used.
What is before is added in an array named "v".
pcp is previous cond_pred
psi is previous sigma
args is the CFG function input arguments with the added cond/unconds (like the actual activation conditionings) named respectively "cond_pos" and "cond_neg"
So if you write:
pcp if sigma < 7 else -pcp;
print("it works too just don't use the output I guess");
v[0] if sigma < 14 else torch.zeros_like(cond);
v[-1]*2
Well the first line becomes v[0], second v[1] etc.
The last one becomes the result.
Note that it's just an example, I don't see much interest in that one.
Using comfy.samplers.calc_cond_batch(args["model"], [args["cond_pos"], None], args["input"]-cond, args["timestep"], args["model_options"])[0]
can work too.
This whole mess has for initial goal to attempt to find the best way (or have some bruteforcing fun) to replace the uncond pred for as much as possible.
"""
if method == "normal":
return cond_input
# print()
# print(get_entropy(cond))
cond = cond_input.clone()
cond_norm = cond.norm()
if method == "amplify":
mask = torch.abs(cond) >= 1
cond_copy = cond.clone()
cond = torch.pow(torch.abs(cond), ( 1 / exp_value)) * cond.sign()
cond[mask] = torch.pow(torch.abs(cond_copy[mask]), exp_value) * cond[mask].sign()
elif method == "root":
cond = torch.pow(torch.abs(cond), ( 1 / exp_value)) * cond.sign()
elif method == "power":
cond = torch.pow(torch.abs(cond), exp_value) * cond.sign()
elif method == "erf":
cond = torch.erf(cond)
elif method == "exp_erf":
cond = torch.pow(torch.erf(cond), exp_value)
elif method == "root_erf":
cond = torch.erf(cond)
cond = torch.pow(torch.abs(cond), 1 / exp_value ) * cond.sign()
elif method == "erf_amplify":
cond = torch.erf(cond)
mask = torch.abs(cond) >= 1
cond_copy = cond.clone()
cond = torch.pow(torch.abs(cond), 1 / exp_value ) * cond.sign()
cond[mask] = torch.pow(torch.abs(cond_copy[mask]), exp_value) * cond[mask].sign()
elif method == "sine":
cond = torch.sin(torch.abs(cond)) * cond.sign()
elif method == "sine_exp":
cond = torch.sin(torch.abs(cond)) * cond.sign()
cond = torch.pow(torch.abs(cond), exp_value) * cond.sign()
elif method == "sine_exp_diff":
cond = torch.sin(torch.abs(cond)) * cond.sign()
cond = torch.pow(torch.abs(cond_input), exp_value) * cond.sign() - cond
elif method == "sine_exp_diff_to_sine":
cond = torch.sin(torch.abs(cond)) * cond.sign()
cond = torch.pow(torch.abs(cond), exp_value) * cond.sign() - cond
elif method == "sine_root":
cond = torch.sin(torch.abs(cond)) * cond.sign()
cond = torch.pow(torch.abs(cond), ( 1 / exp_value)) * cond.sign()
elif method == "sine_root_diff":
cond = torch.sin(torch.abs(cond)) * cond.sign()
cond = torch.pow(torch.abs(cond_input), 1 / exp_value) * cond.sign() - cond
elif method == "sine_root_diff_to_sine":
cond = torch.sin(torch.abs(cond)) * cond.sign()
cond = torch.pow(torch.abs(cond), 1 / exp_value) * cond.sign() - cond
elif method == "theDaRkNeSs":
cond = torch.sin(cond)
cond = torch.pow(torch.abs(cond), 1 / exp_value) * cond.sign() - cond
elif method == "cosine":
cond = torch.cos(torch.abs(cond)) * cond.sign()
elif method == "sign":
cond = cond.sign()
elif method == "zero":
cond = torch.zeros_like(cond)
elif method == "previous_average":
if sigma > (sigmax - 1):
cond = torch.zeros_like(cond)
else:
cond = (pcp / psi * sigma + cond) / 2
elif method == "eval":
v = []
evals_strings = eval_string.split(";")
if len(evals_strings) > 1:
for i in range(len(evals_strings[:-1])):
v.append(eval(evals_strings[i]))
cond = eval(evals_strings[-1])
if exp_normalize and torch.all(cond != 0):
cond = cond * cond_norm / cond.norm()
# print(get_entropy(cond))
return cond
class advancedDynamicCFG:
def __init__(self):
self.last_cfg_ht_one = 8
@classmethod
def INPUT_TYPES(s):
return {"required": {
"model": ("MODEL",),
"automatic_cfg" : (["None", "soft", "hard", "hard_squared", "range"], {"default": "hard"},),
"skip_uncond" : ("BOOLEAN", {"default": True}),
"fake_uncond_start" : ("BOOLEAN", {"default": False}),
"uncond_sigma_start": ("FLOAT", {"default": 5, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"uncond_sigma_end": ("FLOAT", {"default": 1, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"lerp_uncond" : ("BOOLEAN", {"default": False}),
"lerp_uncond_strength": ("FLOAT", {"default": 2, "min": 0.0, "max": 10.0, "step": 0.1, "round": 0.1}),
"lerp_uncond_sigma_start": ("FLOAT", {"default": 15, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"lerp_uncond_sigma_end": ("FLOAT", {"default": 1, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"subtract_latent_mean" : ("BOOLEAN", {"default": False}),
"subtract_latent_mean_sigma_start": ("FLOAT", {"default": 15, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"subtract_latent_mean_sigma_end": ("FLOAT", {"default": 1, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"latent_intensity_rescale" : ("BOOLEAN", {"default": False}),
"latent_intensity_rescale_method" : (["soft","hard","range"], {"default": "hard"},),
"latent_intensity_rescale_cfg": ("FLOAT", {"default": 8, "min": 0.0, "max": 100.0, "step": 0.1, "round": 0.1}),
"latent_intensity_rescale_sigma_start": ("FLOAT", {"default": 15, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"latent_intensity_rescale_sigma_end": ("FLOAT", {"default": 3, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"cond_exp": ("BOOLEAN", {"default": False}),
"cond_exp_normalize": ("BOOLEAN", {"default": False}),
"cond_exp_sigma_start": ("FLOAT", {"default": 15, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"cond_exp_sigma_end": ("FLOAT", {"default": 1, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"cond_exp_method": (["amplify", "root", "power", "erf", "erf_amplify", "exp_erf", "root_erf", "sine", "sine_exp", "sine_exp_diff", "sine_exp_diff_to_sine", "sine_root", "sine_root_diff", "sine_root_diff_to_sine", "theDaRkNeSs", "cosine", "sign", "zero"],),
"cond_exp_value": ("FLOAT", {"default": 2, "min": 1, "max": 100, "step": 0.1, "round": 0.01}),
"uncond_exp": ("BOOLEAN", {"default": False}),
"uncond_exp_normalize": ("BOOLEAN", {"default": False}),
"uncond_exp_sigma_start": ("FLOAT", {"default": 15, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"uncond_exp_sigma_end": ("FLOAT", {"default": 1, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"uncond_exp_method": (["normal", "amplify", "root", "power", "erf", "erf_amplify", "exp_erf", "root_erf", "sine", "sine_exp", "sine_exp_diff", "sine_exp_diff_to_sine", "sine_root", "sine_root_diff", "sine_root_diff_to_sine", "theDaRkNeSs", "cosine", "sign", "zero"],),
"uncond_exp_value": ("FLOAT", {"default": 2, "min": 1, "max": 100, "step": 0.1, "round": 0.01}),
"fake_uncond_exp": ("BOOLEAN", {"default": False}),
"fake_uncond_exp_normalize": ("BOOLEAN", {"default": False}),
"fake_uncond_exp_method" : (["normal", "previous_average", "amplify", "root", "power", "erf", "erf_amplify", "exp_erf", "root_erf", "sine", "sine_exp", "sine_exp_diff", "sine_exp_diff_to_sine", "sine_root", "sine_root_diff", "sine_root_diff_to_sine", "theDaRkNeSs", "cosine", "sign", "zero", "eval"],),
"fake_uncond_exp_value": ("FLOAT", {"default": 2, "min": 1, "max": 1000, "step": 0.1, "round": 0.01}),
"fake_uncond_multiplier": ("INT", {"default": 1, "min": -1, "max": 1, "step": 1}),
"fake_uncond_sigma_start": ("FLOAT", {"default": 15, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"fake_uncond_sigma_end": ("FLOAT", {"default": 5.5, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
},
"optional":{
"eval_string": ("STRING", {"multiline": True}),
"args_filter": ("STRING", {"multiline": True, "forceInput": True})
}
}
RETURN_TYPES = ("MODEL","STRING",)
FUNCTION = "patch"
CATEGORY = "model_patches/automatic_cfg"
def patch(self, model, automatic_cfg = "None",
skip_uncond = False, fake_uncond_start = False, uncond_sigma_start = 15, uncond_sigma_end = 0,
lerp_uncond = False, lerp_uncond_strength = 1, lerp_uncond_sigma_start = 15, lerp_uncond_sigma_end = 1,
subtract_latent_mean = False, subtract_latent_mean_sigma_start = 15, subtract_latent_mean_sigma_end = 1,
latent_intensity_rescale = False, latent_intensity_rescale_sigma_start = 15, latent_intensity_rescale_sigma_end = 1,
cond_exp = False, cond_exp_sigma_start = 15, cond_exp_sigma_end = 14, cond_exp_method = "amplify", cond_exp_value = 2, cond_exp_normalize = False,
uncond_exp = False, uncond_exp_sigma_start = 15, uncond_exp_sigma_end = 14, uncond_exp_method = "amplify", uncond_exp_value = 2, uncond_exp_normalize = False,
fake_uncond_exp = False, fake_uncond_exp_method = "amplify", fake_uncond_exp_value = 2, fake_uncond_exp_normalize = False, fake_uncond_multiplier = 1, fake_uncond_sigma_start = 15, fake_uncond_sigma_end = 5.5,
latent_intensity_rescale_cfg = 8, latent_intensity_rescale_method = "hard",
ignore_pre_cfg_func = False, eval_string = "", args_filter = ""):
monkey_patching_comfy_sampling_function()
args = locals()
if args_filter != "":
args_filter = args_filter.split(",")
else:
args_filter = [k for k, v in locals().items()]
not_in_filter = ['self','model','args','args_filter']
if fake_uncond_exp_method != "eval":
not_in_filter.append("eval_string")
args_str = '\n'.join(f'{k}: {v}' for k, v in locals().items() if k not in not_in_filter and k in args_filter)
sigmin, sigmax = get_sigmin_sigmax(model)
lerp_start, lerp_end = lerp_uncond_sigma_start, lerp_uncond_sigma_end
subtract_start, subtract_end = subtract_latent_mean_sigma_start, subtract_latent_mean_sigma_end
rescale_start, rescale_end = latent_intensity_rescale_sigma_start, latent_intensity_rescale_sigma_end
print(f"Model maximum sigma: {sigmax} / Model minimum sigma: {sigmin}")
m = model.clone()
if skip_uncond:
# set model_options sampler_pre_cfg_function
m.model_options["sampler_pre_cfg_function"] = make_sampler_pre_cfg_function(uncond_sigma_end, uncond_sigma_start)
print(f"Sampling function patched. Uncond enabled from {round(uncond_sigma_start,2)} to {round(uncond_sigma_end,2)}")
elif not ignore_pre_cfg_func:
m.model_options.pop("sampler_pre_cfg_function", None)
uncond_sigma_start, uncond_sigma_end = 1000000, 0
top_k = 0.25
reference_cfg = 8
previous_cond_pred = None
previous_sigma = None
def automatic_cfg_function(args):
nonlocal previous_cond_pred, previous_sigma
cond_scale = args["cond_scale"]
input_x = args["input"]
cond_pred = args["cond_denoised"]
uncond_pred = args["uncond_denoised"]
sigma = args["sigma"][0]
model_options = args["model_options"]
if previous_cond_pred is None:
previous_cond_pred = deepcopy(cond_pred)
if previous_sigma is None:
previous_sigma = sigma.item()
def fake_uncond_step():
return fake_uncond_start and skip_uncond and (sigma > uncond_sigma_start or sigma < uncond_sigma_end) and sigma <= fake_uncond_sigma_start and sigma >= fake_uncond_sigma_end
if fake_uncond_step():
uncond_pred = cond_pred.clone() * fake_uncond_multiplier
if cond_exp and sigma <= cond_exp_sigma_start and sigma >= cond_exp_sigma_end:
cond_pred = square_and_norm(cond_pred, cond_exp_method, cond_exp_value, cond_exp_normalize, previous_cond_pred, previous_sigma, sigma.item(), sigmax, args)
if uncond_exp and sigma <= uncond_exp_sigma_start and sigma >= uncond_exp_sigma_end and not fake_uncond_step():
uncond_pred = square_and_norm(uncond_pred, uncond_exp_method, uncond_exp_value, uncond_exp_normalize, previous_cond_pred, previous_sigma, sigma.item(), sigmax, args)
if fake_uncond_step() and fake_uncond_exp:
uncond_pred = square_and_norm(uncond_pred, fake_uncond_exp_method, fake_uncond_exp_value, fake_uncond_exp_normalize, previous_cond_pred, previous_sigma, sigma.item(), sigmax, args, eval_string)
previous_cond_pred = deepcopy(cond_pred)
if sigma >= sigmax or cond_scale > 1:
self.last_cfg_ht_one = cond_scale
target_intensity = self.last_cfg_ht_one / 10
if ((check_skip(sigma, uncond_sigma_start, uncond_sigma_end) and skip_uncond) and not fake_uncond_step()) or cond_scale == 1:
return input_x - cond_pred
if lerp_uncond and not check_skip(sigma, lerp_start, lerp_end) and lerp_uncond_strength != 1:
uncond_pred = torch.lerp(cond_pred, uncond_pred, lerp_uncond_strength)
cond = input_x - cond_pred
uncond = input_x - uncond_pred
if automatic_cfg == "None":
return uncond + cond_scale * (cond - uncond)
denoised_tmp = input_x - (uncond + reference_cfg * (cond - uncond))
for b in range(len(denoised_tmp)):
denoised_ranges = get_denoised_ranges(denoised_tmp[b], automatic_cfg, top_k)
for c in range(len(denoised_tmp[b])):
fixeds_scale = reference_cfg * target_intensity / denoised_ranges[c]
denoised_tmp[b][c] = uncond[b][c] + fixeds_scale * (cond[b][c] - uncond[b][c])
return denoised_tmp
def center_mean_latent_post_cfg(args):
denoised = args["denoised"]
sigma = args["sigma"][0]
if check_skip(sigma, subtract_start, subtract_end):
return denoised
denoised = center_latent_mean_values(denoised, False, 1)
return denoised
def rescale_post_cfg(args):
denoised = args["denoised"]
sigma = args["sigma"][0]
if check_skip(sigma, rescale_start, rescale_end):
return denoised
target_intensity = latent_intensity_rescale_cfg / 10
for b in range(len(denoised)):
denoised_ranges = get_denoised_ranges(denoised[b], latent_intensity_rescale_method)
for c in range(len(denoised[b])):
scale_correction = target_intensity / denoised_ranges[c]
denoised[b][c] = denoised[b][c] * scale_correction
return denoised
if not ignore_pre_cfg_func:
m.set_model_sampler_cfg_function(automatic_cfg_function, disable_cfg1_optimization = False)
if subtract_latent_mean:
m.set_model_sampler_post_cfg_function(center_mean_latent_post_cfg)
if latent_intensity_rescale:
m.set_model_sampler_post_cfg_function(rescale_post_cfg)
return (m, args_str, )
class simpleDynamicCFG:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"model": ("MODEL",),
"hard_mode" : ("BOOLEAN", {"default": True}),
"boost" : ("BOOLEAN", {"default": True}),
}}
RETURN_TYPES = ("MODEL",)
FUNCTION = "patch"
CATEGORY = "model_patches/automatic_cfg/presets"
def patch(self, model, hard_mode, boost):
advcfg = advancedDynamicCFG()
m = advcfg.patch(model,
skip_uncond = boost,
uncond_sigma_start = 15, uncond_sigma_end = 1,
automatic_cfg = "hard" if hard_mode else "soft"
)[0]
return (m, )
class simpleDynamicCFGlerpUncond:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"model": ("MODEL",),
"boost" : ("BOOLEAN", {"default": True}),
"negative_strength": ("FLOAT", {"default": 1, "min": 0.0, "max": 5.0, "step": 0.1, "round": 0.1}),
}}
RETURN_TYPES = ("MODEL",)
FUNCTION = "patch"
CATEGORY = "model_patches/automatic_cfg/presets"
def patch(self, model, boost, negative_strength):
advcfg = advancedDynamicCFG()
m = advcfg.patch(model=model,
automatic_cfg="hard", skip_uncond=boost,
uncond_sigma_start = 15, uncond_sigma_end = 1,
lerp_uncond=negative_strength != 1, lerp_uncond_strength=negative_strength,
lerp_uncond_sigma_start = 15, lerp_uncond_sigma_end = 1
)[0]
return (m, )
class postCFGrescaleOnly:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"model": ("MODEL",),
"subtract_latent_mean" : ("BOOLEAN", {"default": True}),
"subtract_latent_mean_sigma_start": ("FLOAT", {"default": 15, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.1}),
"subtract_latent_mean_sigma_end": ("FLOAT", {"default": 7.5, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.1}),
"latent_intensity_rescale" : ("BOOLEAN", {"default": True}),
"latent_intensity_rescale_method" : (["soft","hard","range"], {"default": "hard"},),
"latent_intensity_rescale_cfg" : ("FLOAT", {"default": 7.6, "min": 0.0, "max": 100.0, "step": 0.1, "round": 0.1}),
"latent_intensity_rescale_sigma_start": ("FLOAT", {"default": 15, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.1}),
"latent_intensity_rescale_sigma_end": ("FLOAT", {"default": 7.5, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.1}),
}}
RETURN_TYPES = ("MODEL",)
FUNCTION = "patch"
CATEGORY = "model_patches/automatic_cfg"
def patch(self, model,
subtract_latent_mean, subtract_latent_mean_sigma_start, subtract_latent_mean_sigma_end,
latent_intensity_rescale, latent_intensity_rescale_method, latent_intensity_rescale_cfg, latent_intensity_rescale_sigma_start, latent_intensity_rescale_sigma_end
):
advcfg = advancedDynamicCFG()
m = advcfg.patch(model=model,
subtract_latent_mean = subtract_latent_mean,
subtract_latent_mean_sigma_start = subtract_latent_mean_sigma_start, subtract_latent_mean_sigma_end = subtract_latent_mean_sigma_end,
latent_intensity_rescale = latent_intensity_rescale, latent_intensity_rescale_cfg = latent_intensity_rescale_cfg, latent_intensity_rescale_method = latent_intensity_rescale_method,
latent_intensity_rescale_sigma_start = latent_intensity_rescale_sigma_start, latent_intensity_rescale_sigma_end = latent_intensity_rescale_sigma_end,
ignore_pre_cfg_func = True
)[0]
return (m, )
class simpleDynamicCFGHighSpeed:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"model": ("MODEL",),
}}
RETURN_TYPES = ("MODEL",)
FUNCTION = "patch"
CATEGORY = "model_patches/automatic_cfg/presets"
def patch(self, model):
advcfg = advancedDynamicCFG()
m = advcfg.patch(model=model, automatic_cfg = "hard",
skip_uncond = True, uncond_sigma_start = 7.5, uncond_sigma_end = 1)[0]
return (m, )
class simpleDynamicCFGwarpDrive:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"model": ("MODEL",),
"uncond_sigma_start": ("FLOAT", {"default": 5.5, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"uncond_sigma_end": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"fake_uncond_sigma_end": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10000.0, "step": 0.1, "round": 0.01}),
"less_clutter": ("BOOLEAN", {"default": False}),
}}
RETURN_TYPES = ("MODEL",)
FUNCTION = "patch"
CATEGORY = "model_patches/automatic_cfg/presets"
def patch(self, model, uncond_sigma_start, uncond_sigma_end, fake_uncond_sigma_end, less_clutter):
advcfg = advancedDynamicCFG()
print(f" {Fore.CYAN}WARP DRIVE MODE ENGAGED!{Style.RESET_ALL}\n Settings suggestions:\n"
f" {Fore.GREEN}1/1/1: {Fore.YELLOW}Maaaxxxiiimum speeeeeed.{Style.RESET_ALL} {Fore.RED}Uncond disabled.{Style.RESET_ALL} {Fore.MAGENTA}Fasten your seatbelt!{Style.RESET_ALL}\n"
f" {Fore.GREEN}3/1/1: {Fore.YELLOW}Risky space-time continuum distortion.{Style.RESET_ALL} {Fore.MAGENTA}Awesome for prompts with a clear subject!{Style.RESET_ALL}\n"
f" {Fore.GREEN}5.5/1/1: {Fore.YELLOW}Frameshift Drive Autopilot: {Fore.GREEN}Engaged.{Style.RESET_ALL} {Fore.MAGENTA}Should work with anything but do it better and faster!{Style.RESET_ALL}")
m = advcfg.patch(model=model, automatic_cfg = "hard",
skip_uncond = True, uncond_sigma_start = uncond_sigma_start, uncond_sigma_end = uncond_sigma_end,
fake_uncond_sigma_end = fake_uncond_sigma_end, fake_uncond_sigma_start = 1000, fake_uncond_start=True,
fake_uncond_exp=True,fake_uncond_exp_normalize=True,fake_uncond_exp_method="previous_average",
cond_exp = less_clutter, cond_exp_sigma_start = 9, cond_exp_sigma_end = uncond_sigma_start, cond_exp_method = "erf", cond_exp_normalize = True,
)[0]
return (m, )
class simpleDynamicCFGunpatch:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"model": ("MODEL",),
}}
RETURN_TYPES = ("MODEL",)
FUNCTION = "unpatch"
CATEGORY = "model_patches/automatic_cfg"
def unpatch(self, model):
m = model.clone()
m.model_options.pop("sampler_pre_cfg_function", None)
return (m, )