diff --git a/docs/CONFIG.md b/docs/CONFIG.md index a358ea3..93f3ed2 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -9,6 +9,7 @@ * **seed**: Connect here the seed used. By default it is -1 (random). * **pos_prompt**: Connect here the prompt text, or fill it as a widget. * **neg_prompt**: Connect here the negative prompt text, or fill it as a widget. +* **wc_wildcards_input**: Wildcards definitions (in yaml or json format). Direct input added to the ones found in the wildcards folders. Allows wildcards to be included in the workflow. Other common settings (see [below](#common-settings)) also appear as inputs or widgets. diff --git a/ppp.py b/ppp.py index ac8ad7a..25f11e6 100644 --- a/ppp.py +++ b/ppp.py @@ -121,7 +121,7 @@ class PromptPostProcessor: # pylint: disable=too-few-public-methods,too-many-in self.wil_keep_choices_order = options.get("keep_choices_order", False) self.wil_choice_separator = options.get("choice_separator", self.DEFAULT_CHOICE_SEPARATOR) self.wil_ifwildcards = self.IFWILDCARDS_CHOICES( - options.get("if_wildcards", self.IFWILDCARDS_CHOICES.ignore.value) + options.get("if_wildcards", self.IFWILDCARDS_CHOICES.stop.value) ) # Send to negative options self.stn_ignore_repeats = options.get("stn_ignore_repeats", True) diff --git a/ppp_comfyui.py b/ppp_comfyui.py index a1b6919..8ef877d 100644 --- a/ppp_comfyui.py +++ b/ppp_comfyui.py @@ -1,5 +1,3 @@ -# pylint: disable=missing-module-docstring, missing-class-docstring, missing-function-docstring, invalid-name - import os # pylint: disable=import-error @@ -48,8 +46,6 @@ class PromptPostProcessorComfyUINode: "multiline": True, "default": "", "dynamicPrompts": False, - "defaultInput": True, - "forceInput": False, }, ), "neg_prompt": ( @@ -58,8 +54,6 @@ class PromptPostProcessorComfyUINode: "multiline": True, "default": "", "dynamicPrompts": False, - "defaultInput": True, - "forceInput": False, }, ), }, @@ -77,16 +71,13 @@ class PromptPostProcessorComfyUINode: { "default": "", "placeholder": "full path of the model", - "defaultInput": True, - "forceInput": False, + "dynamicPrompts": False, }, ), "seed": ( "INT", { "default": -1, - "defaultInput": True, - "forceInput": False, }, ), "debug_level": ( @@ -94,8 +85,6 @@ class PromptPostProcessorComfyUINode: { "default": DEBUG_LEVEL.minimal.value, "tooltip": "Debug level", - "defaultInput": False, - "forceInput": False, }, ), "variants_definitions": ( @@ -105,8 +94,7 @@ class PromptPostProcessorComfyUINode: "multiline": True, "placeholder": "", "tooltip": "Definitions for variant models to be recognized based on strings found in the full filename. Format for each line is: 'name(kind)=comma separated list of substrings (case insensitive)' with kind being one of the base model types or not specified", - "defaultInput": False, - "forceInput": False, + "dynamicPrompts": False, }, ), "wc_process_wildcards": ( @@ -116,8 +104,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Process wildcards in the prompt", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), "wc_wildcards_folders": ( @@ -125,17 +111,24 @@ class PromptPostProcessorComfyUINode: { "default": "", "tooltip": "Comma separated list of wildcards folders", - "defaultInput": False, - "forceInput": False, + "dynamicPrompts": False, + }, + ), + "wc_wildcards_input": ( + "STRING", + { + "default": "", + "multiline": True, + "placeholder": "wildcards definitions", + "tooltip": "Wildcards definitions in yaml/json format", + "dynamicPrompts": False, }, ), "wc_if_wildcards": ( [e.value for e in PromptPostProcessor.IFWILDCARDS_CHOICES], { - "default": PromptPostProcessor.IFWILDCARDS_CHOICES.ignore.value, + "default": PromptPostProcessor.IFWILDCARDS_CHOICES.stop.value, "tooltip": "How to handle invalid wildcards in the prompt", - "defaultInput": False, - "forceInput": False, }, ), "wc_choice_separator": ( @@ -143,8 +136,7 @@ class PromptPostProcessorComfyUINode: { "default": PromptPostProcessor.DEFAULT_CHOICE_SEPARATOR, "tooltip": "Default separator for selected choices", - "defaultInput": False, - "forceInput": False, + "dynamicPrompts": False, }, ), "wc_keep_choices_order": ( @@ -154,8 +146,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Keep the order of the choices in the prompt", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), "stn_separator": ( @@ -163,8 +153,7 @@ class PromptPostProcessorComfyUINode: { "default": PromptPostProcessor.DEFAULT_STN_SEPARATOR, "tooltip": "Separator for the content added to the negative prompt", - "defaultInput": False, - "forceInput": False, + "dynamicPrompts": False, }, ), "stn_ignore_repeats": ( @@ -174,8 +163,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Ignore repeated content added to the negative prompt", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), "cleanup_extra_spaces": ( @@ -185,8 +172,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Remove extra spaces", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), "cleanup_empty_constructs": ( @@ -196,8 +181,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Remove empty constructs", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), "cleanup_extra_separators": ( @@ -207,8 +190,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Remove extra separators", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), "cleanup_extra_separators2": ( @@ -218,8 +199,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Remove extra separators (additional cases)", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), "cleanup_breaks": ( @@ -229,8 +208,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Cleanup around BREAKs", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), "cleanup_breaks_eol": ( @@ -240,8 +217,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Set BREAKs in their own line", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), "cleanup_ands": ( @@ -251,8 +226,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Cleanup around ANDs", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), "cleanup_ands_eol": ( @@ -262,8 +235,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Set ANDs in their own line", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), "cleanup_extranetwork_tags": ( @@ -273,8 +244,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Clean up around extra network tags", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), "cleanup_merge_attention": ( @@ -284,8 +253,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Merge nested attention constructs", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), "remove_extranetwork_tags": ( @@ -295,8 +262,6 @@ class PromptPostProcessorComfyUINode: "tooltip": "Remove extra network tags", "label_on": "Yes", "label_off": "No", - "defaultInput": False, - "forceInput": False, }, ), }, @@ -342,6 +307,7 @@ class PromptPostProcessorComfyUINode: variants_definitions, wc_process_wildcards, wc_wildcards_folders, + wc_wildcards_input, wc_if_wildcards, wc_choice_separator, wc_keep_choices_order, @@ -372,6 +338,7 @@ class PromptPostProcessorComfyUINode: "variants_definitions": variants_definitions, "process_wildcards": wc_process_wildcards, "wildcards_folders": wc_wildcards_folders, + "wildcards_input": wc_wildcards_input, "if_wildcards": wc_if_wildcards, "choice_separator": wc_choice_separator, "keep_choices_order": wc_keep_choices_order, @@ -403,6 +370,7 @@ class PromptPostProcessorComfyUINode: variants_definitions, wc_process_wildcards, wc_wildcards_folders, + wc_wildcards_input, wc_if_wildcards, wc_choice_separator, wc_keep_choices_order, @@ -427,13 +395,14 @@ class PromptPostProcessorComfyUINode: self.logger.warning("Model class is not provided. System variables might not be properly set.") if modelname == "": self.logger.warning("Modelname is not provided. System variables will not be properly set.") + # model class values in ComfyUI\comfy\supported_models.py env_info = { "app": "comfyui", "models_path": folder_paths.models_dir, "model_filename": modelname or "", # path is relative to checkpoints folder "model_class": modelclass, "is_sd1": modelclass in ("SD15", "SD15_instructpix2pix"), - "is_sd2": modelclass in ("SD20", "SD21UnclipL", "SD21UnclipH"), + "is_sd2": modelclass in ("SD20", "SD21UnclipL", "SD21UnclipH", "LotusD"), "is_sdxl": ( modelclass in ("SDXL", "SDXLRefiner", "SDXL_instructpix2pix", "Segmind_Vega", "KOALA_700M", "KOALA_1B") ), @@ -441,9 +410,18 @@ class PromptPostProcessorComfyUINode: "is_sd3": modelclass in ("SD3",), "is_flux": modelclass in ("Flux", "FluxInpaint", "FluxSchnell"), "is_auraflow": modelclass in ("AuraFlow",), + "is_pixart": modelclass in ("PixArtAlpha", "PixArtSigma"), + "is_lumina2": modelclass in ("Lumina2",), + "is_ltxv": modelclass in ("LTXV",), + "is_cosmos": modelclass in ("CosmosT2V", "CosmosI2V"), + "is_genmomochi": modelclass in ("GenmoMochi",), + "is_hunyuan": modelclass in ("HunyuanDiT", "HunyuanDiT1"), + "is_hunyuanvideo": modelclass in ("HunyuanVideo", "HunyuanVideoI2V", "HunyuanVideoSkyreelsI2V"), + "is_hunyuan3d": modelclass in ("Hunyuan3Dv2", "Hunyuan3Dv2mini"), + "is_wanvideo": modelclass in ("WAN21_T2V", "WAN21_I2V", "WAN21_FunControl2V"), + "is_hidream": modelclass in ("HiDream",), } - # Also supported: SVD_img2vid, SVD3D_u, SVD3_p, Stable_Zero123, SD_X4Upscaler, - # Stable_Cascade_C, Stable_Cascade_B, StableAudio, HunyuanDiT, HunyuanDiT1, GenmoMochi, LTXV + # Also supported: SVD_img2vid, SVD3D_u, SVD3_p, Stable_Zero123, SD_X4Upscaler, Stable_Cascade_C, Stable_Cascade_B, StableAudio if wc_wildcards_folders == "": wc_wildcards_folders = ",".join(folder_paths.get_folder_paths("wildcards") or []) @@ -477,7 +455,11 @@ class PromptPostProcessorComfyUINode: "cleanup_merge_attention": cleanup_merge_attention, "remove_extranetwork_tags": remove_extranetwork_tags, } - self.wildcards_obj.refresh_wildcards(debug_level, wildcards_folders if options["process_wildcards"] else None) + self.wildcards_obj.refresh_wildcards( + debug_level, + wildcards_folders if options["process_wildcards"] else None, + wc_wildcards_input, + ) ppp = PromptPostProcessor( self.logger, self.interrupt, env_info, options, self.grammar_content, self.wildcards_obj ) @@ -519,8 +501,6 @@ class PromptPostProcessorSelectVariableComfyUINode: "multiline": False, "default": "", "dynamicPrompts": False, - "defaultInput": False, - "forceInput": False, }, ), }, diff --git a/ppp_wildcards.py b/ppp_wildcards.py index 4263110..dea87d8 100644 --- a/ppp_wildcards.py +++ b/ppp_wildcards.py @@ -1,6 +1,5 @@ import fnmatch import os -import json from typing import Optional import logging import yaml @@ -20,12 +19,11 @@ def deep_freeze(obj): """ if isinstance(obj, dict): return tuple((k, deep_freeze(v)) for k, v in sorted(obj.items())) - elif isinstance(obj, list): + if isinstance(obj, list): return tuple(deep_freeze(i) for i in obj) - elif isinstance(obj, set): + if isinstance(obj, set): return tuple(deep_freeze(i) for i in sorted(obj)) - else: - return obj + return obj class PPPWildcard: @@ -70,6 +68,7 @@ class PPPWildcards: """ DEFAULT_WILDCARDS_FOLDER = "wildcards" + LOCALINPUT_FILENAME = "#INPUT" def __init__(self, logger): self.__logger: logging.Logger = logger @@ -84,31 +83,38 @@ class PPPWildcards: def __sizeof__(self): return self.wildcards.__sizeof__() + self.__wildcards_folders.__sizeof__() + self.__wildcard_files.__sizeof__() - def refresh_wildcards(self, debug_level: DEBUG_LEVEL, wildcards_folders: Optional[list[str]]): + def refresh_wildcards( + self, debug_level: DEBUG_LEVEL, wildcards_folders: Optional[list[str]], wildcards_input: str = None + ): """ Initialize the wildcards. """ self.__debug_level = debug_level - self.__wildcards_folders = wildcards_folders - if wildcards_folders is not None: - # if self.debug_level != DEBUG_LEVEL.none: - # self.logger.info("Initializing wildcards...") - # t1 = time.time() - for fullpath in list(self.__wildcard_files.keys()): + self.__wildcards_folders = wildcards_folders or [] + # if self.debug_level != DEBUG_LEVEL.none: + # self.logger.info("Refreshing wildcards...") + # t1 = time.time() + for fullpath in list(self.__wildcard_files.keys()): + if fullpath != self.LOCALINPUT_FILENAME: path = os.path.dirname(fullpath) if not os.path.exists(fullpath) or not any( os.path.commonpath([path, folder]) == folder for folder in self.__wildcards_folders ): - self.__remove_wildcards_from_file(fullpath) - for f in self.__wildcards_folders: - self.__get_wildcards_in_directory(f, f) - # t2 = time.time() - # if self.debug_level != DEBUG_LEVEL.none: - # self.logger.info(f"Wildcards init time: {t2 - t1:.3f} seconds") + self.__remove_wildcards_from_path(fullpath) + elif wildcards_input is None: + self.__remove_wildcards_from_path(fullpath) + if wildcards_folders is not None or wildcards_input is not None: + if wildcards_folders is not None: + for f in self.__wildcards_folders: + self.__get_wildcards_in_directory(f, f) + if wildcards_input is not None: + self.__get_wildcards_in_input(wildcards_input) else: - self.__wildcards_folders = [] self.wildcards = {} self.__wildcard_files = {} + # t2 = time.time() + # if self.debug_level != DEBUG_LEVEL.none: + # self.logger.info(f"Wildcards refresh time: {t2 - t1:.3f} seconds") def get_wildcards(self, key: str) -> list[PPPWildcard]: """ @@ -161,7 +167,7 @@ class PPPWildcards: return None return current_dict - def __remove_wildcards_from_file(self, full_path: str, debug=True): + def __remove_wildcards_from_path(self, full_path: str, debug=True): """ Clear all wildcards in a file. @@ -169,9 +175,12 @@ class PPPWildcards: full_path (str): The path to the file. debug (bool): Whether to print debug messages or not. """ - last_modified_cached = self.__wildcard_files.get(full_path, None) + last_modified_cached = self.__wildcard_files.get(full_path, None) # a time or a hash if debug and last_modified_cached is not None and self.__debug_level != DEBUG_LEVEL.none: - self.__logger.debug(f"Removing wildcards from file: {full_path}") + if full_path == self.LOCALINPUT_FILENAME: + self.__logger.debug("Removing wildcards from input") + else: + self.__logger.debug(f"Removing wildcards from file: {full_path}") if full_path in self.__wildcard_files.keys(): del self.__wildcard_files[full_path] for key in list(self.wildcards.keys()): @@ -194,7 +203,7 @@ class PPPWildcards: _, extension = os.path.splitext(filename) if extension not in (".txt", ".json", ".yaml", ".yml"): return - self.__remove_wildcards_from_file(full_path, False) + self.__remove_wildcards_from_path(full_path, False) if last_modified_cached is not None and self.__debug_level != DEBUG_LEVEL.none: self.__logger.debug(f"Updating wildcards from file: {full_path}") if extension == ".txt": @@ -203,6 +212,31 @@ class PPPWildcards: self.__get_wildcards_in_structured_file(full_path, base) self.__wildcard_files[full_path] = last_modified + def __get_wildcards_in_input(self, wildcards_input: str): + """ + Get all wildcards in the string. + + Args: + wildcards_input (str): The input string containing wildcards in json or yaml format. + """ + new_h = hash(wildcards_input) + h = self.__wildcard_files.get(self.LOCALINPUT_FILENAME, None) + if h == new_h: + return + self.__remove_wildcards_from_path(self.LOCALINPUT_FILENAME, False) + if h is not None and self.__debug_level != DEBUG_LEVEL.none: + self.__logger.debug("Updating wildcards from input") + wildcards_input = wildcards_input.strip() + if wildcards_input != "": + try: + content = yaml.safe_load(wildcards_input) + except yaml.YAMLError as e: + self.__logger.warning(f"Invalid format for input wildcards: {e}") + return + if content is not None: + self.__add_wildcard(content, self.LOCALINPUT_FILENAME, [self.LOCALINPUT_FILENAME]) + self.__wildcard_files[self.LOCALINPUT_FILENAME] = new_h + def is_dict_choices_options(self, d: dict) -> bool: """ Check if a dictionary is a valid choices options dictionary. @@ -374,12 +408,8 @@ class PPPWildcards: """ external_key: str = os.path.relpath(os.path.splitext(full_path)[0], base) external_key_parts = external_key.split(os.sep) - _, extension = os.path.splitext(full_path) with open(full_path, "r", encoding="utf-8") as file: - if extension == ".json": - content = json.loads(file.read()) - else: - content = yaml.safe_load(file) + content = yaml.safe_load(file) self.__add_wildcard(content, full_path, external_key_parts) def __get_wildcards_in_text_file(self, full_path, base): diff --git a/scripts/ppp_script.py b/scripts/ppp_script.py index a186f19..6a32e71 100644 --- a/scripts/ppp_script.py +++ b/scripts/ppp_script.py @@ -226,6 +226,16 @@ class PromptPostProcessorA1111Script(scripts.Script): "is_sd3": False, # Stable Diffusion 3 "is_flux": False, # Flux "is_auraflow": False, # AuraFlow + "is_pixart": False, # PixArt + "is_lumina2": False, # Lumina2 + "is_ltxv": False, # LTXV + "is_cosmos": False, # Cosmos + "is_genmomochi": False, # GenmoMochi + "is_hunyuan": False, # Hunyuan + "is_hunyuanvideo": False, # HunyuanVideo + "is_hunyuan3d": False, # Hunyuan3D + "is_wanvideo": False, # WanVideo + "is_hidream": False, # HiDream } if app == "sdnext": # cannot differentiate SD1 and SD2, we set True to both @@ -283,7 +293,7 @@ class PromptPostProcessorA1111Script(scripts.Script): opts, "ppp_gen_variantsdefinitions", PromptPostProcessor.DEFAULT_VARIANTS_DEFINITIONS ), "process_wildcards": getattr(opts, "ppp_wil_processwildcards", True), - "if_wildcards": getattr(opts, "ppp_wil_ifwildcards", PromptPostProcessor.IFWILDCARDS_CHOICES.ignore.value), + "if_wildcards": getattr(opts, "ppp_wil_ifwildcards", PromptPostProcessor.IFWILDCARDS_CHOICES.stop.value), "choice_separator": getattr(opts, "ppp_wil_choice_separator", PromptPostProcessor.DEFAULT_CHOICE_SEPARATOR), "keep_choices_order": getattr(opts, "ppp_wil_keep_choices_order", False), "stn_separator": getattr(opts, "ppp_stn_separator", PromptPostProcessor.DEFAULT_STN_SEPARATOR), diff --git a/tests/tests.py b/tests/tests.py index d48eef5..fd8e63f 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -68,6 +68,13 @@ class TestPromptPostProcessor(unittest.TestCase): os.path.abspath(os.path.join(os.path.dirname(__file__), "wildcards")), os.path.abspath(os.path.join(os.path.dirname(__file__), "wildcards2")), ], + """ + yaml_input: + wildcardI: + - choice1 + - choice2 + - choice3 + """ ) grammar_filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../grammar.lark") with open(grammar_filename, "r", encoding="utf-8") as file: @@ -934,6 +941,13 @@ class TestPromptPostProcessor(unittest.TestCase): ppp=self.__nocupppp, ) + def test_wc_wildcard_input(self): # simple yaml wildcard input + self.__process( + PromptPair("the choices are: __yaml_input/wildcardI__", ""), + PromptPair("the choices are: choice2", ""), + ppp=self.__nocupppp, + ) + # Model variants tests def test_variants(self): diff --git a/workflows/PPP example.json b/workflows/PPP example.json new file mode 100644 index 0000000..fd59c95 --- /dev/null +++ b/workflows/PPP example.json @@ -0,0 +1 @@ +{"id":"0f75c56e-adb4-41f6-b957-81b6772cb8b5","revision":0,"last_node_id":24,"last_link_id":52,"nodes":[{"id":8,"type":"VAEDecode","pos":[1620,-560],"size":[210,46],"flags":{},"order":9,"mode":0,"inputs":[{"localized_name":"samples","name":"samples","type":"LATENT","link":7},{"localized_name":"vae","name":"vae","type":"VAE","link":20}],"outputs":[{"localized_name":"IMAGE","name":"IMAGE","type":"IMAGE","slot_index":0,"links":[9]}],"properties":{"cnr_id":"comfy-core","ver":"0.3.27","Node name for S&R":"VAEDecode"},"widgets_values":[]},{"id":9,"type":"SaveImage","pos":[1860,-560],"size":[210,58],"flags":{},"order":10,"mode":0,"inputs":[{"localized_name":"images","name":"images","type":"IMAGE","link":9},{"localized_name":"filename_prefix","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.3.27"},"widgets_values":["ComfyUI"]},{"id":17,"type":"PrimitiveInt","pos":[0,-480],"size":[315,82],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"value","name":"value","type":"INT","widget":{"name":"value"},"link":null}],"outputs":[{"localized_name":"INT","name":"INT","type":"INT","links":[24,49]}],"title":"Seed","properties":{"cnr_id":"comfy-core","ver":"0.3.27","Node name for S&R":"PrimitiveInt"},"widgets_values":[801,"randomize"]},{"id":16,"type":"Checkpoint Loader with Name (Image Saver)","pos":[-200,-660],"size":[516.5999755859375,118],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"ckpt_name","name":"ckpt_name","type":"COMBO","widget":{"name":"ckpt_name"},"link":null}],"outputs":[{"localized_name":"MODEL","name":"MODEL","type":"MODEL","links":[16,47]},{"localized_name":"CLIP","name":"CLIP","type":"CLIP","links":[19,45]},{"localized_name":"VAE","name":"VAE","type":"VAE","links":[20]},{"localized_name":"model_name","name":"model_name","type":"STRING","links":[48]}],"properties":{"cnr_id":"comfyui-image-saver","ver":"f8520bcfe5339ba7b4bb64ba96f6ed03da87fb89","Node name for S&R":"Checkpoint Loader with Name (Image Saver)"},"widgets_values":["ponyDiffusionV6XL_v6StartWithThisOne.safetensors"]},{"id":5,"type":"EmptyLatentImage","pos":[0,-840],"size":[315,106],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"width","name":"width","type":"INT","widget":{"name":"width"},"link":null},{"localized_name":"height","name":"height","type":"INT","widget":{"name":"height"},"link":null},{"localized_name":"batch_size","name":"batch_size","type":"INT","widget":{"name":"batch_size"},"link":null}],"outputs":[{"localized_name":"LATENT","name":"LATENT","type":"LATENT","slot_index":0,"links":[2]}],"properties":{"cnr_id":"comfy-core","ver":"0.3.27","Node name for S&R":"EmptyLatentImage"},"widgets_values":[1024,1024,1]},{"id":3,"type":"KSampler","pos":[1220,-540],"size":[315,262],"flags":{},"order":7,"mode":0,"inputs":[{"localized_name":"model","name":"model","type":"MODEL","link":16},{"localized_name":"positive","name":"positive","type":"CONDITIONING","link":4},{"localized_name":"negative","name":"negative","type":"CONDITIONING","link":6},{"localized_name":"latent_image","name":"latent_image","type":"LATENT","link":2},{"localized_name":"seed","name":"seed","type":"INT","widget":{"name":"seed"},"link":24},{"localized_name":"steps","name":"steps","type":"INT","widget":{"name":"steps"},"link":null},{"localized_name":"cfg","name":"cfg","type":"FLOAT","widget":{"name":"cfg"},"link":null},{"localized_name":"sampler_name","name":"sampler_name","type":"COMBO","widget":{"name":"sampler_name"},"link":null},{"localized_name":"scheduler","name":"scheduler","type":"COMBO","widget":{"name":"scheduler"},"link":null},{"localized_name":"denoise","name":"denoise","type":"FLOAT","widget":{"name":"denoise"},"link":null}],"outputs":[{"localized_name":"LATENT","name":"LATENT","type":"LATENT","slot_index":0,"links":[7]}],"properties":{"cnr_id":"comfy-core","ver":"0.3.27","Node name for S&R":"KSampler"},"widgets_values":[523681707962952,"randomize",20,8,"euler","normal",1]},{"id":6,"type":"CLIPTextEncode","pos":[940,-380],"size":[240,88],"flags":{"collapsed":true},"order":4,"mode":0,"inputs":[{"localized_name":"clip","name":"clip","type":"CLIP","link":19},{"localized_name":"text","name":"text","type":"STRING","widget":{"name":"text"},"link":50}],"outputs":[{"localized_name":"CONDITIONING","name":"CONDITIONING","type":"CONDITIONING","slot_index":0,"links":[4]}],"properties":{"cnr_id":"comfy-core","ver":"0.3.27","Node name for S&R":"CLIPTextEncode"},"widgets_values":[""]},{"id":7,"type":"CLIPTextEncode","pos":[940,-300],"size":[220,88],"flags":{"collapsed":true},"order":5,"mode":0,"inputs":[{"localized_name":"clip","name":"clip","type":"CLIP","link":45},{"localized_name":"text","name":"text","type":"STRING","widget":{"name":"text"},"link":51}],"outputs":[{"localized_name":"CONDITIONING","name":"CONDITIONING","type":"CONDITIONING","slot_index":0,"links":[6]}],"properties":{"cnr_id":"comfy-core","ver":"0.3.27","Node name for S&R":"CLIPTextEncode"},"widgets_values":[""]},{"id":22,"type":"ShowText|pysssss","pos":[1260,100],"size":[260,200],"flags":{},"order":8,"mode":0,"inputs":[{"localized_name":"text","name":"text","type":"STRING","link":36}],"outputs":[{"localized_name":"STRING","name":"STRING","shape":6,"type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-custom-scripts","ver":"9f7b3215e6af317603056a9a1666bf6e83e28835","Node name for S&R":"ShowText|pysssss"},"widgets_values":[]},{"id":20,"type":"ACBPPPSelectVariable","pos":[900,100],"size":[315,58],"flags":{},"order":6,"mode":0,"inputs":[{"localized_name":"variables","name":"variables","type":"PPP_DICT","link":52},{"localized_name":"name","name":"name","shape":7,"type":"STRING","widget":{"name":"name"},"link":null}],"outputs":[{"localized_name":"value","name":"value","type":"STRING","links":[36]}],"properties":{"cnr_id":"sd-webui-prompt-postprocessor","ver":"5e3c8cbc44bacd3b4da2ef33588f152a571775dd","Node name for S&R":"ACBPPPSelectVariable"},"widgets_values":[""]},{"id":24,"type":"ACBPromptPostProcessor","pos":[420,-380],"size":[380,820],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"model","name":"model","shape":7,"type":"MODEL,STRING","link":47},{"localized_name":"pos_prompt","name":"pos_prompt","type":"STRING","widget":{"name":"pos_prompt"},"link":null},{"localized_name":"neg_prompt","name":"neg_prompt","type":"STRING","widget":{"name":"neg_prompt"},"link":null},{"localized_name":"modelname","name":"modelname","shape":7,"type":"STRING","widget":{"name":"modelname"},"link":48},{"localized_name":"seed","name":"seed","shape":7,"type":"INT","widget":{"name":"seed"},"link":49},{"localized_name":"debug_level","name":"debug_level","shape":7,"type":"COMBO","widget":{"name":"debug_level"},"link":null},{"localized_name":"variants_definitions","name":"variants_definitions","shape":7,"type":"STRING","widget":{"name":"variants_definitions"},"link":null},{"localized_name":"wc_process_wildcards","name":"wc_process_wildcards","shape":7,"type":"BOOLEAN","widget":{"name":"wc_process_wildcards"},"link":null},{"localized_name":"wc_wildcards_folders","name":"wc_wildcards_folders","shape":7,"type":"STRING","widget":{"name":"wc_wildcards_folders"},"link":null},{"localized_name":"wc_wildcards_input","name":"wc_wildcards_input","shape":7,"type":"STRING","widget":{"name":"wc_wildcards_input"},"link":null},{"localized_name":"wc_if_wildcards","name":"wc_if_wildcards","shape":7,"type":"COMBO","widget":{"name":"wc_if_wildcards"},"link":null},{"localized_name":"wc_choice_separator","name":"wc_choice_separator","shape":7,"type":"STRING","widget":{"name":"wc_choice_separator"},"link":null},{"localized_name":"wc_keep_choices_order","name":"wc_keep_choices_order","shape":7,"type":"BOOLEAN","widget":{"name":"wc_keep_choices_order"},"link":null},{"localized_name":"stn_separator","name":"stn_separator","shape":7,"type":"STRING","widget":{"name":"stn_separator"},"link":null},{"localized_name":"stn_ignore_repeats","name":"stn_ignore_repeats","shape":7,"type":"BOOLEAN","widget":{"name":"stn_ignore_repeats"},"link":null},{"localized_name":"cleanup_extra_spaces","name":"cleanup_extra_spaces","shape":7,"type":"BOOLEAN","widget":{"name":"cleanup_extra_spaces"},"link":null},{"localized_name":"cleanup_empty_constructs","name":"cleanup_empty_constructs","shape":7,"type":"BOOLEAN","widget":{"name":"cleanup_empty_constructs"},"link":null},{"localized_name":"cleanup_extra_separators","name":"cleanup_extra_separators","shape":7,"type":"BOOLEAN","widget":{"name":"cleanup_extra_separators"},"link":null},{"localized_name":"cleanup_extra_separators2","name":"cleanup_extra_separators2","shape":7,"type":"BOOLEAN","widget":{"name":"cleanup_extra_separators2"},"link":null},{"localized_name":"cleanup_breaks","name":"cleanup_breaks","shape":7,"type":"BOOLEAN","widget":{"name":"cleanup_breaks"},"link":null},{"localized_name":"cleanup_breaks_eol","name":"cleanup_breaks_eol","shape":7,"type":"BOOLEAN","widget":{"name":"cleanup_breaks_eol"},"link":null},{"localized_name":"cleanup_ands","name":"cleanup_ands","shape":7,"type":"BOOLEAN","widget":{"name":"cleanup_ands"},"link":null},{"localized_name":"cleanup_ands_eol","name":"cleanup_ands_eol","shape":7,"type":"BOOLEAN","widget":{"name":"cleanup_ands_eol"},"link":null},{"localized_name":"cleanup_extranetwork_tags","name":"cleanup_extranetwork_tags","shape":7,"type":"BOOLEAN","widget":{"name":"cleanup_extranetwork_tags"},"link":null},{"localized_name":"cleanup_merge_attention","name":"cleanup_merge_attention","shape":7,"type":"BOOLEAN","widget":{"name":"cleanup_merge_attention"},"link":null},{"localized_name":"remove_extranetwork_tags","name":"remove_extranetwork_tags","shape":7,"type":"BOOLEAN","widget":{"name":"remove_extranetwork_tags"},"link":null}],"outputs":[{"localized_name":"pos_prompt","name":"pos_prompt","type":"STRING","links":[50]},{"localized_name":"neg_prompt","name":"neg_prompt","type":"STRING","links":[51]},{"localized_name":"variables","name":"variables","type":"PPP_DICT","links":[52]}],"properties":{"cnr_id":"sd-webui-prompt-postprocessor","ver":"5e3c8cbc44bacd3b4da2ef33588f152a571775dd","Node name for S&R":"ACBPromptPostProcessor"},"widgets_values":["score_9, score_8_up, score_7_up, score_6_up, woman with __color__ hair, __action__","score_4, score_5","",-1,"randomize","minimal","pony(sdxl)=pony,pny,pdxl\nillustrious(sdxl)=illustrious,illust,ilxl",true,"","color:\n - red\n - blonde\n - brunette\naction:\n - running\n - sleeping","stop",", ",true,", ",true,true,true,true,true,false,false,false,false,false,true,false]}],"links":[[2,5,0,3,3,"LATENT"],[4,6,0,3,1,"CONDITIONING"],[6,7,0,3,2,"CONDITIONING"],[7,3,0,8,0,"LATENT"],[9,8,0,9,0,"IMAGE"],[16,16,0,3,0,"MODEL"],[19,16,1,6,0,"CLIP"],[20,16,2,8,1,"VAE"],[24,17,0,3,4,"INT"],[36,20,0,22,0,"STRING"],[45,16,1,7,0,"CLIP"],[47,16,0,24,0,"MODEL,STRING"],[48,16,3,24,3,"STRING"],[49,17,0,24,4,"INT"],[50,24,0,6,1,"STRING"],[51,24,1,7,1,"STRING"],[52,24,2,20,0,"PPP_DICT"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.9438000000000003,"offset":[357.48769227266587,962.8709670594865]},"frontendVersion":"1.16.8","reroutes":[{"id":2,"pos":[1560,-620],"linkIds":[20]},{"id":3,"pos":[880,-480],"linkIds":[19,45]},{"id":4,"pos":[380,-540],"linkIds":[16]}],"VHS_latentpreview":true,"VHS_latentpreviewrate":0,"VHS_MetadataImage":true,"VHS_KeepIntermediate":true,"linkExtensions":[{"id":16,"parentId":4},{"id":19,"parentId":3},{"id":20,"parentId":2},{"id":45,"parentId":3}]},"version":0.4} \ No newline at end of file