Skip to content

Commit 2a346b2

Browse files
committed
add nested wildcard syntax support
1 parent 26fed34 commit 2a346b2

File tree

2 files changed

+134
-8
lines changed

2 files changed

+134
-8
lines changed

mikey_nodes.py

Lines changed: 132 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
module = importlib.util.module_from_spec(spec)
3838
sys.modules[module_name] = module
3939
spec.loader.exec_module(module)
40+
import comfy_extras
4041
from nodes_upscale_model import UpscaleModelLoader, ImageUpscaleWithModel
4142
from comfy.model_management import soft_empty_cache, free_memory, get_torch_device, current_loaded_models, load_model_gpu
4243
from nodes import LoraLoader, ConditioningAverage, common_ksampler, ImageScale, ImageScaleBy, VAEEncode, VAEDecode
@@ -320,11 +321,12 @@ def process_wildcard_syntax(text, seed):
320321
# wildcard sytax is {like|this}
321322
# select a random word from the | separated list
322323
random.seed(seed)
323-
wc_re = re.compile(r'{([^}]+)}')
324+
wc_re = re.compile(r'{([^{}]*)}')
324325
def repl(m):
325-
return random.choice(m.group(1).split('|'))
326-
for m in wc_re.finditer(text):
327-
text = text.replace(m.group(0), repl(m))
326+
parts = m.group(1).split('|')
327+
return random.choice(parts)
328+
while wc_re.search(text):
329+
text = wc_re.sub(repl, text)
328330
return text
329331

330332
def search_and_replace(text, extra_pnginfo, prompt):
@@ -5212,6 +5214,122 @@ def process(self, positive_prompt, negative_prompt, clip, option_positive_clip_l
52125214
[[negative_conditioning, {'pooled_output': negative_pooled}]],
52135215
)
52145216

5217+
# model merge PixArtSigmaXL2_1024MS
5218+
# blocks.0 to 27
5219+
# final_layer, pos_embed, t_block.1, t_embedder, x_embedder, y_embedder
5220+
class ModelMergePixArtSigmaXL2_1024MS(comfy_extras.nodes_model_merging.ModelMergeBlocks):
5221+
CATEGORY = 'Mikey/Model Merging/model_specific'
5222+
5223+
@classmethod
5224+
def INPUT_TYPES(s):
5225+
arg_dict = {'model1': ('MODEL',),
5226+
'model2': ('MODEL',)}
5227+
5228+
argument = ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})
5229+
5230+
for i in range(28):
5231+
arg_dict['blocks.{}.'.format(i)] = argument
5232+
5233+
arg_dict['final_layer'] = argument
5234+
arg_dict['pos_embed'] = argument
5235+
arg_dict['t_block.1'] = argument
5236+
arg_dict['t_embedder'] = argument
5237+
arg_dict['x_embedder'] = argument
5238+
arg_dict['y_embedder'] = argument
5239+
5240+
return {'required': arg_dict}
5241+
5242+
class ModelMergeTrainDiff:
5243+
# https://github.com/hako-mikan/sd-webui-supermerger
5244+
@classmethod
5245+
def INPUT_TYPES(s):
5246+
return {'required': {'model1': ('MODEL',),
5247+
'model2': ('MODEL',),
5248+
'model3': ('MODEL',),
5249+
'ratio': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01})}}
5250+
5251+
RETURN_TYPES = ('MODEL',)
5252+
FUNCTION = 'traindiff'
5253+
CATEGORY = 'Mikey/Model Merging'
5254+
5255+
def traindiff(self, model1, model2, model3, **kwargs):
5256+
theta_0 = model1.clone()
5257+
m = model1.clone()
5258+
mp = m.get_key_patches("diffusion_model.")
5259+
theta_1 = model2.get_key_patches("diffusion_model.")
5260+
theta_2 = model3.get_key_patches("diffusion_model.")
5261+
5262+
default_ratio = next(iter(kwargs.values()))
5263+
5264+
for k in mp:
5265+
ratio = default_ratio
5266+
k_unet = k[len("diffusion_model."):]
5267+
5268+
last_arg_size = 0
5269+
for arg in kwargs:
5270+
if k_unet.startswith(arg) and last_arg_size < len(arg):
5271+
ratio = kwargs[arg]
5272+
last_arg_size = len(arg)
5273+
5274+
diff_AB = theta_1[k][0].float() - theta_2[k][0].float()
5275+
5276+
distance_A0 = torch.abs(theta_1[k][0].float() - theta_2[k][0].float())
5277+
distance_A1 = torch.abs(theta_1[k][0].float() - mp[k][0].float())
5278+
5279+
sum_distances = distance_A0 + distance_A1
5280+
5281+
scale = torch.where(sum_distances != 0, distance_A1 / sum_distances, torch.tensor(0.).float())
5282+
sign_scale = torch.sign(theta_1[k][0].float() - theta_2[k][0].float())
5283+
scale = sign_scale * torch.abs(scale)
5284+
5285+
new_diff = scale * torch.abs(diff_AB)
5286+
weight = new_diff * (ratio*1.8)
5287+
mp[k] = (weight,)
5288+
theta_0.add_patches({k: mp[k]}, 1.0, 1.0)
5289+
return (theta_0,)
5290+
5291+
class ModelMergeTrainDiffPixartSigmaXL2_1024MS(ModelMergeTrainDiff):
5292+
CATEGORY = 'Mikey/Model Merging/Model Specific'
5293+
5294+
@classmethod
5295+
def INPUT_TYPES(s):
5296+
arg_dict = {'model1': ('MODEL',),
5297+
'model2': ('MODEL',),
5298+
'model3': ('MODEL',)}
5299+
5300+
argument = ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01})
5301+
5302+
for i in range(28):
5303+
arg_dict['blocks.{}.'.format(i)] = argument
5304+
5305+
arg_dict['final_layer'] = argument
5306+
arg_dict['pos_embed'] = argument
5307+
arg_dict['t_block.1'] = argument
5308+
arg_dict['t_embedder'] = argument
5309+
arg_dict['x_embedder'] = argument
5310+
arg_dict['y_embedder'] = argument
5311+
5312+
return {'required': arg_dict}
5313+
5314+
class CheckpointSaveModelOnly:
5315+
def __init__(self):
5316+
self.output_dir = folder_paths.get_output_directory()
5317+
5318+
@classmethod
5319+
def INPUT_TYPES(s):
5320+
return {"required": { "model": ("MODEL",),
5321+
"vae": ("VAE",),
5322+
"filename_prefix": ("STRING", {"default": "checkpoints/ComfyUI"}),},
5323+
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"},}
5324+
RETURN_TYPES = ()
5325+
FUNCTION = "save"
5326+
OUTPUT_NODE = True
5327+
5328+
CATEGORY = "Mikey/Model Merging"
5329+
5330+
def save(self, model, vae, filename_prefix, clip=None, prompt=None, extra_pnginfo=None):
5331+
comfy_extras.nodes_model_merging.save_checkpoint(model, clip=clip, vae=vae, filename_prefix=filename_prefix, output_dir=self.output_dir, prompt=prompt, extra_pnginfo=extra_pnginfo)
5332+
return {}
52155333

52165334
NODE_CLASS_MAPPINGS = {
52175335
'Wildcard Processor': WildcardProcessor,
@@ -5281,7 +5399,11 @@ def process(self, positive_prompt, negative_prompt, clip, option_positive_clip_l
52815399
'MosaicExpandImage': MosaicExpandImage,
52825400
'GetSubdirectories': GetSubdirectories,
52835401
'TextPadderMikey': TextPadderMikey,
5284-
'SD3TextConditioningWithOptionsOnePrompt': SD3TextConditioningWithOptionsOnePrompt
5402+
'SD3TextConditioningWithOptionsOnePrompt': SD3TextConditioningWithOptionsOnePrompt,
5403+
'ModelMergePixArtSigmaXL2_1024MS': ModelMergePixArtSigmaXL2_1024MS,
5404+
'ModelMergeTrainDiff': ModelMergeTrainDiff,
5405+
'ModelMergeTrainDiffPixartSigmaXL2_1024MS': ModelMergeTrainDiffPixartSigmaXL2_1024MS,
5406+
'CheckpointSaveModelOnly': CheckpointSaveModelOnly,
52855407
}
52865408

52875409
NODE_DISPLAY_NAME_MAPPINGS = {
@@ -5352,5 +5474,9 @@ def process(self, positive_prompt, negative_prompt, clip, option_positive_clip_l
53525474
'MosaicExpandImage': 'Mosaic Expand Image (Mikey)',
53535475
'GetSubdirectories': 'Get Subdirectories (Mikey)',
53545476
'TextPadderMikey': 'Text Padder (Mikey)',
5355-
'SD3TextConditioningWithOptionsOnePrompt': 'SD3 Text Conditioning With Options. One Prompt (Mikey)'
5477+
'SD3TextConditioningWithOptionsOnePrompt': 'SD3 Text Conditioning With Options. One Prompt (Mikey)',
5478+
'ModelMergePixArtSigmaXL2_1024MS': 'Model Merge PixArtSigmaXL2_1024MS (Mikey)',
5479+
'ModelMergeTrainDiff': 'Train Diff (Mikey)',
5480+
'ModelMergeTrainDiffPixartSigmaXL2_1024MS': 'Train Diff PixArtSigmaXL2_1024MS (Mikey)',
5481+
'CheckpointSaveModelOnly': 'Save Model Only (Mikey)',
53565482
}

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[project]
22
name = "mikey_nodes"
33
description = "Collection of convenient nodes. Wildcard, style, image, llm, haldclut, metadata, and more."
4-
version = "1.0.0"
5-
license = "MIT License"
4+
version = "1.0.1"
5+
license = { text = "MIT License" }
66

77
[project.urls]
88
Repository = "https://github.com/bash-j/mikey_nodes"

0 commit comments

Comments
 (0)