- Improve indentation and spacing - Normalize string quotes - Simplify return statements - Clean up optional arguments handling
480 lines
13 KiB
Python
480 lines
13 KiB
Python
import comfy.samplers
|
|
import folder_paths
|
|
import os
|
|
import re
|
|
|
|
|
|
def clamp(value, min_value, max_value):
|
|
return max(min_value, min(value, max_value))
|
|
|
|
|
|
def numeric_range(value):
|
|
if "-" in value:
|
|
parts = value.split("-")
|
|
return (float(parts[0]), float(parts[1]))
|
|
return (float(value), float(value))
|
|
|
|
|
|
def clamp_in_list(value, lst):
|
|
if value in list(lst):
|
|
return value
|
|
return lst[0]
|
|
|
|
|
|
def extract_setup(checkpoint_setups, cleanup_name, default_setup, delmiter="/"):
|
|
index = checkpoint_setups.find(cleanup_name)
|
|
return_string = ""
|
|
|
|
if index == -1:
|
|
return default_setup
|
|
|
|
substring = checkpoint_setups[index + len(cleanup_name) :]
|
|
|
|
if substring.startswith("="):
|
|
substring = substring[1:]
|
|
|
|
if substring.startswith('"'):
|
|
end_quote = substring.find('"', 1)
|
|
if end_quote != -1:
|
|
return_string = substring[1:end_quote]
|
|
else:
|
|
return_string = default_setup
|
|
else:
|
|
space_index = substring.find(" ")
|
|
if space_index != -1:
|
|
return_string = substring[:space_index]
|
|
else:
|
|
return_string = substring
|
|
else:
|
|
return_string = default_setup
|
|
|
|
settings = return_string.split(delmiter)
|
|
|
|
return settings
|
|
|
|
|
|
class CheckpointSelector:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"checkpoint_name": (folder_paths.get_filename_list("checkpoints"),),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = (folder_paths.get_filename_list("checkpoints"), "STRING")
|
|
RETURN_NAMES = ("ckpt_name", "name_str")
|
|
CATEGORY = "Foxpack/Smart Sampler Setup"
|
|
FUNCTION = "main"
|
|
|
|
def main(self, checkpoint_name):
|
|
cleanup_name = os.path.splitext(os.path.basename(checkpoint_name))[0]
|
|
|
|
return (checkpoint_name, str(cleanup_name))
|
|
|
|
|
|
class SetupSelector:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"checkpoint_name": ("STRING", {"forceInput": True, "multiline": False}),
|
|
"checkpoint_setups": ("STRING", {"forceInput": True, "multiline": True}),
|
|
"setup_prefix": ("STRING", {"default": "!", "multiline": False}),
|
|
"delmiter": ("STRING", {"default": "/", "multiline": False}),
|
|
"default_setup": (
|
|
"STRING",
|
|
{"default": "5/20/karras/dpmpp_2m", "multiline": False},
|
|
),
|
|
"default_meta": ("STRING", {"default": "0,-2,0", "multiline": False}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING", "LIST", "STRING")
|
|
RETURN_NAMES = (
|
|
"set_cfg",
|
|
"set_steps",
|
|
"set_scheduler",
|
|
"set_sampler",
|
|
"setup_text",
|
|
"setup",
|
|
"meta",
|
|
)
|
|
|
|
FUNCTION = "main"
|
|
# OUTPUT_NODE = True
|
|
|
|
CATEGORY = "Foxpack/Smart Sampler Setup"
|
|
|
|
def main(
|
|
self,
|
|
checkpoint_name,
|
|
checkpoint_setups,
|
|
setup_prefix,
|
|
delmiter,
|
|
default_setup,
|
|
default_meta,
|
|
):
|
|
return_string = ""
|
|
prefixed_name = str(setup_prefix) + str(checkpoint_name)
|
|
|
|
index = checkpoint_setups.find(prefixed_name)
|
|
|
|
if index != -1:
|
|
if checkpoint_setups[index + len(prefixed_name)] == "=":
|
|
if checkpoint_setups[index + len(prefixed_name) + 1] == '"':
|
|
start_quote = index + len(prefixed_name) + 2
|
|
end_quote = checkpoint_setups.find('"', start_quote + 1)
|
|
if end_quote != -1:
|
|
return_string = checkpoint_setups[start_quote:end_quote]
|
|
print(return_string)
|
|
else:
|
|
space_index = checkpoint_setups.find(" ", index + len(prefixed_name))
|
|
if space_index != -1:
|
|
return_string = checkpoint_setups[index + len(prefixed_name) : space_index]
|
|
else:
|
|
return_string = checkpoint_setups[index + len(prefixed_name) :]
|
|
else:
|
|
return_string = prefixed_name[1:]
|
|
|
|
if return_string == "":
|
|
return_string = default_setup
|
|
|
|
if return_string.startswith("="):
|
|
return_string = return_string[1:]
|
|
|
|
settings = return_string.split(delmiter)
|
|
|
|
if len(settings) < 5:
|
|
# meta infos: version (0:sdxl, 1:sd15), clip, vae (0: baked, 1: sdxl load vae, 2: sd15 load vae)
|
|
meta = default_meta
|
|
else:
|
|
meta = settings[4]
|
|
|
|
setup = list(settings)
|
|
setup_text = f"cfg: {settings[0]} | steps: {settings[1]} | scheduler: {settings[2]} | sampler: {settings[3]}"
|
|
|
|
return (
|
|
str(settings[0]),
|
|
str(settings[1]),
|
|
str(settings[2]),
|
|
str(settings[3]),
|
|
str(setup_text),
|
|
list(setup),
|
|
str(meta),
|
|
)
|
|
|
|
|
|
class CheckpointMetaExtractor:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"meta": ("STRING", {"forceInput": True, "multiline": False}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("INT", "INT", "INT")
|
|
RETURN_NAMES = ("version", "clip", "vae baked?")
|
|
|
|
CATEGORY = "Foxpack/Smart Sampler Setup"
|
|
|
|
FUNCTION = "metaFun"
|
|
|
|
def metaFun(self, meta):
|
|
meta = meta.split(",")
|
|
version = meta[0]
|
|
clip = int(meta[1])
|
|
vae = meta[2]
|
|
|
|
return (int(version), int(-abs(clip)), int(vae))
|
|
|
|
|
|
class BaseSamplerSetup:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"setup": ("LIST", {"forceInput": True}),
|
|
"cfg": (
|
|
"FLOAT",
|
|
{"default": 1.0, "min": 0.0, "max": 16.0, "step": 0.1, "display": "number"},
|
|
),
|
|
"steps": (
|
|
"INT",
|
|
{"default": 5, "min": 1, "max": 100, "step": 1, "display": "number"},
|
|
),
|
|
"scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
|
|
"sampler": (comfy.samplers.KSampler.SAMPLERS,),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("FLOAT", "INT", "STRING", "STRING", "STRING", "LIST")
|
|
RETURN_NAMES = (
|
|
"cfg",
|
|
"steps",
|
|
"scheduler",
|
|
"sampler",
|
|
"setup_text",
|
|
"selected_setup",
|
|
)
|
|
FUNCTION = "main"
|
|
|
|
def main(self, setup, cfg, steps, scheduler, sampler):
|
|
cfg_range = numeric_range(setup[0])
|
|
clamp_cfg = clamp(cfg, cfg_range[0], cfg_range[1])
|
|
|
|
steps_range = numeric_range(setup[1])
|
|
clamp_steps = clamp(steps, steps_range[0], steps_range[1])
|
|
|
|
clamp_scheduler = clamp_in_list(scheduler, setup[2].split(","))
|
|
clamp_sampler = clamp_in_list(sampler, setup[3].split(","))
|
|
|
|
selected_setup = [clamp_cfg, clamp_steps, clamp_scheduler, clamp_sampler]
|
|
setup_text = f"cfg: {clamp_cfg} | steps: {clamp_steps} | scheduler: {clamp_scheduler} | sampler: {clamp_sampler}"
|
|
|
|
return (
|
|
float(clamp_cfg),
|
|
int(clamp_steps),
|
|
str(clamp_scheduler),
|
|
str(clamp_sampler),
|
|
str(setup_text),
|
|
list(selected_setup),
|
|
)
|
|
|
|
CATEGORY = "Foxpack/Smart Sampler Setup"
|
|
|
|
|
|
class OverrideSamplerSetup:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"setup": ("LIST", {"forceInput": True}),
|
|
"override": ("BOOLEAN", {"default": False}),
|
|
"cfg": (
|
|
"FLOAT",
|
|
{"default": 1.0, "min": 0.0, "max": 16.0, "step": 0.1, "display": "number"},
|
|
),
|
|
"steps": (
|
|
"INT",
|
|
{"default": 5, "min": 1, "max": 100, "step": 1, "display": "number"},
|
|
),
|
|
"scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
|
|
"sampler": (comfy.samplers.KSampler.SAMPLERS,),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = (
|
|
"FLOAT",
|
|
"INT",
|
|
comfy.samplers.KSampler.SAMPLERS,
|
|
comfy.samplers.KSampler.SCHEDULERS,
|
|
"STRING",
|
|
)
|
|
RETURN_NAMES = ("cfg", "steps", "sampler", "scheduler", "setup_text")
|
|
FUNCTION = "main"
|
|
|
|
def main(self, override, setup, steps, cfg, sampler, scheduler):
|
|
cfg_output = cfg if override else setup[0]
|
|
steps_output = steps if override else setup[1]
|
|
scheduler_output = scheduler if override else setup[2]
|
|
sampler_output = sampler if override else setup[3]
|
|
|
|
setup_text = f"cfg: {cfg_output} | steps: {steps_output} | scheduler: {scheduler_output} | sampler: {sampler_output}"
|
|
|
|
return (
|
|
float(cfg_output),
|
|
int(steps_output),
|
|
sampler_output,
|
|
scheduler_output,
|
|
str(setup_text),
|
|
)
|
|
|
|
CATEGORY = "Foxpack/Smart Sampler Setup"
|
|
|
|
|
|
class Complete_Setup:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"checkpoint_setups": ("STRING", {"forceInput": True, "multiline": True}),
|
|
"checkpoint_name": (folder_paths.get_filename_list("checkpoints"),),
|
|
"cfg": (
|
|
"FLOAT",
|
|
{"default": 5.0, "min": 0.0, "max": 16.0, "step": 0.1, "display": "number"},
|
|
),
|
|
"steps": (
|
|
"INT",
|
|
{"default": 20, "min": 1, "max": 100, "step": 1, "display": "number"},
|
|
),
|
|
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, {"default": "karras"}),
|
|
"sampler": (comfy.samplers.KSampler.SAMPLERS, {"default": "dpmpp_2m"}),
|
|
"override": ("BOOLEAN", {"default": False}),
|
|
"cfg_override": (
|
|
"FLOAT",
|
|
{"default": 5.0, "min": 0.0, "max": 16.0, "step": 0.1, "display": "number"},
|
|
),
|
|
"steps_override": (
|
|
"INT",
|
|
{"default": 20, "min": 1, "max": 100, "step": 1, "display": "number"},
|
|
),
|
|
"scheduler_override": (
|
|
comfy.samplers.KSampler.SCHEDULERS,
|
|
{"default": "karras"},
|
|
),
|
|
"sampler_override": (comfy.samplers.KSampler.SAMPLERS, {"default": "dpmpp_2m"}),
|
|
},
|
|
"optional": {"optional_setups": ("STRING", {"default": "", "multiline": True})},
|
|
}
|
|
|
|
RETURN_TYPES = (
|
|
folder_paths.get_filename_list("checkpoints"),
|
|
"STRING",
|
|
"STRING",
|
|
"INT",
|
|
"INT",
|
|
"INT",
|
|
"FLOAT",
|
|
"INT",
|
|
comfy.samplers.KSampler.SAMPLERS,
|
|
comfy.samplers.KSampler.SCHEDULERS,
|
|
"LIST",
|
|
"STRING",
|
|
"STRING",
|
|
)
|
|
RETURN_NAMES = (
|
|
"ckpt_name",
|
|
"recommended_setup_str",
|
|
"used_setup_str",
|
|
"version",
|
|
"clip",
|
|
"vae_variant",
|
|
"cfg",
|
|
"steps",
|
|
"sampler",
|
|
"scheduler",
|
|
"meta_list",
|
|
"opt_setup_dict",
|
|
"comb_sampler_settings",
|
|
)
|
|
|
|
FUNCTION = "main"
|
|
CATEGORY = "Foxpack/Smart Sampler Setup"
|
|
|
|
def main(
|
|
self,
|
|
checkpoint_setups,
|
|
checkpoint_name,
|
|
cfg,
|
|
steps,
|
|
scheduler,
|
|
sampler,
|
|
override,
|
|
cfg_override,
|
|
steps_override,
|
|
scheduler_override,
|
|
sampler_override,
|
|
optional_setups,
|
|
):
|
|
cleanup_name = os.path.splitext(os.path.basename(checkpoint_name))[0]
|
|
settings = ""
|
|
selected_optional_setup = "{}"
|
|
used_default_setup = False
|
|
|
|
if cleanup_name:
|
|
pattern = rf"!{cleanup_name}:(.+)"
|
|
pattern_optional = rf"!{cleanup_name}:(.+)"
|
|
|
|
match = re.search(pattern, checkpoint_setups)
|
|
match_optional = re.search(pattern_optional, optional_setups)
|
|
|
|
if match:
|
|
settings = match.group(1).split("/")
|
|
else:
|
|
pattern = rf"!DEFAULT:(.+)"
|
|
match = re.search(pattern, checkpoint_setups)
|
|
used_default_setup = True
|
|
if match:
|
|
settings = match.group(1).split("/")
|
|
else:
|
|
settings = ["5", "20", "karras", "dpmpp_2m", "0", "-2", "0"]
|
|
|
|
if match_optional:
|
|
selected_optional_setup = match_optional.group(1)
|
|
|
|
# version 0 = sdxl, 1 = sd15, 2 = flux
|
|
version = 0
|
|
clip = -2
|
|
vae_variant = 0
|
|
|
|
version = settings[4]
|
|
clip = int(settings[5])
|
|
vae_variant = settings[6]
|
|
|
|
vae_string = "baked" if vae_variant == 0 else "external"
|
|
versionname = {"0": "sdxl", "1": "sd15", "2": "flux"}.get(version, "sdxl")
|
|
|
|
used_default_setup_str = " (used default setup)" if used_default_setup else ""
|
|
recommended_setup_str = f"Checkpoint ({versionname}): {cleanup_name}{used_default_setup_str}\ncfg: {settings[0]}, steps: {settings[1]}, scheduler: {settings[2]}, sampler: {settings[3]}\nvae: {vae_string}, clip: {clip}, version: {version}"
|
|
|
|
cfg_range = numeric_range(settings[0])
|
|
clamp_cfg = clamp(cfg, cfg_range[0], cfg_range[1])
|
|
steps_range = numeric_range(settings[1])
|
|
clamp_steps = clamp(steps, steps_range[0], steps_range[1])
|
|
clamp_scheduler = clamp_in_list(scheduler, settings[2].split(","))
|
|
clamp_sampler = clamp_in_list(sampler, settings[3].split(","))
|
|
|
|
cfg_output = cfg_override if override else clamp_cfg
|
|
steps_output = steps_override if override else clamp_steps
|
|
scheduler_output = scheduler_override if override else clamp_scheduler
|
|
sampler_output = sampler_override if override else clamp_sampler
|
|
|
|
is_override = " (overridden settings)" if override else ""
|
|
|
|
used_setup_str = f"Checkpoint ({versionname}): {cleanup_name}{is_override}\ncfg: {cfg_output}, steps: {int(steps_output)}, scheduler: {scheduler_output}, sampler: {sampler_output}"
|
|
|
|
filename = f"%date_%seed_%counter_{versionname}"
|
|
|
|
sampler_settings = (
|
|
f"{cfg_output},{int(steps_output)},{sampler_output},{scheduler_output}"
|
|
)
|
|
|
|
meta_list = [
|
|
checkpoint_name,
|
|
filename,
|
|
float(cfg_output),
|
|
int(steps_output),
|
|
sampler_output,
|
|
scheduler_output,
|
|
]
|
|
|
|
return (
|
|
checkpoint_name,
|
|
recommended_setup_str,
|
|
used_setup_str,
|
|
int(version),
|
|
int(-abs(clip)),
|
|
int(vae_variant),
|
|
float(cfg_output),
|
|
int(steps_output),
|
|
sampler_output,
|
|
scheduler_output,
|
|
meta_list,
|
|
selected_optional_setup,
|
|
sampler_settings,
|
|
)
|