From c580dcbf9cfaba40b85d5d48c627b112458af366 Mon Sep 17 00:00:00 2001 From: "Dr.Lt.Data" Date: Thu, 7 Sep 2023 12:44:28 +0900 Subject: [PATCH] feat: prompts from file --- README.md | 8 +++ __init__.py | 5 +- prompt_support.py | 100 ++++++++++++++++++++++++++++++++++ prompts/example/prompt1.txt | 2 + prompts/example/prompt2.txt | 4 ++ prompts/put_prompts_dirs_here | 0 6 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 prompt_support.py create mode 100644 prompts/example/prompt1.txt create mode 100644 prompts/example/prompt2.txt create mode 100644 prompts/put_prompts_dirs_here diff --git a/README.md b/README.md index 93cd3f3..1b3127d 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,14 @@ This repository offers various extension nodes for ComfyUI. Nodes here have diff * Other point #1 : Please make sure you haven't forgotten to include 'embedding:' in the embedding used in the prompt, like 'embedding:easynegative.' * Other point #2 : ComfyUI and A1111 have different interpretations of weighting. To align them, you need to use [BlenderNeko/Advanced CLIP Text Encode](https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb). +* Prompt Support - These are nodes for supporting prompt processing. + * `Load Prompts From File (Inspire)`: It sequentially reads prompt files from the specified directory. The output it returns is ZIPPED_PROMPT. + * Specify the directories located under `ComfyUI-Inspire-Pack/prompts/` + * `Unzip Prompt (Inspire)`: Separate ZIPPED_PROMPT into `positive`, `negative`, and name components. + * `positive` and `negative` represent text prompts, while `name` represents the name of the prompt. When loaded from a file using `Load Prompts From File (Inspire)`, the name corresponds to the file name. + * `Zip Prompt (Inspire)`: Create ZIPPED_PROMPT from positive, negative, and name_opt. + * If name_opt is omitted, it will be considered as an empty name. + ## Credits diff --git a/__init__.py b/__init__.py index c1076cc..701f4f9 100644 --- a/__init__.py +++ b/__init__.py @@ -7,12 +7,13 @@ import importlib -print(f"### Loading: ComfyUI-Inspire-Pack (V0.5.1)") +print(f"### Loading: ComfyUI-Inspire-Pack (V0.6)") node_list = [ "lora_block_weight", "segs_support", - "a1111_compat" + "a1111_compat", + "prompt_support", ] NODE_CLASS_MAPPINGS = {} diff --git a/prompt_support.py b/prompt_support.py new file mode 100644 index 0000000..87b2b55 --- /dev/null +++ b/prompt_support.py @@ -0,0 +1,100 @@ +import os +import re + + +class LoadPromptsFromFile: + @classmethod + def INPUT_TYPES(cls): + try: + current_directory = os.path.dirname(os.path.abspath(__file__)) + prompt_dir = os.path.join(current_directory, "prompts") + prompt_dirs = [d for d in os.listdir(prompt_dir) if os.path.isdir(os.path.join(prompt_dir, d))] + except Exception: + prompt_dirs = [] + + return {"required": {"dir": (prompt_dirs,)}} + + RETURN_TYPES = ("ZIPPED_PROMPT",) + OUTPUT_IS_LIST = (True,) + + FUNCTION = "doit" + + CATEGORY = "InspirePack/prompt" + + def doit(self, dir): + current_directory = os.path.dirname(os.path.abspath(__file__)) + prompt_dir = os.path.join(current_directory, "prompts", dir) + files = [f for f in os.listdir(prompt_dir) if f.endswith(".txt")] + files.sort() + + prompts = [] + for file_name in files: + print(f"file_name: {file_name}") + try: + with open(os.path.join(prompt_dir, file_name), "r", encoding="utf-8") as file: + prompt = file.read() + + pattern = r"positive:(.*?)(?:\n*|$)negative:(.*)" + matches = re.search(pattern, prompt, re.DOTALL) + + if matches: + positive_text = matches.group(1).strip() + negative_text = matches.group(2).strip() + result_tuple = (positive_text, negative_text, file_name) + prompts.append(result_tuple) + else: + print(f"[WARN] LoadPromptsFromFile: invalid prompt format in '{file_name}'") + except Exception as e: + print(f"[ERROR] LoadPromptsFromFile: an error occurred while processing '{file_name}': {str(e)}") + + return (prompts, ) + + +class UnzipPrompt: + @classmethod + def INPUT_TYPES(s): + return {"required": {"zipped_prompt": ("ZIPPED_PROMPT",), }} + + RETURN_TYPES = ("STRING", "STRING", "STRING") + RETURN_NAMES = ("positive", "negative", "name") + + FUNCTION = "doit" + + CATEGORY = "InspirePack/prompt" + + def doit(self, zipped_prompt): + return zipped_prompt + + +class ZipPrompt: + @classmethod + def INPUT_TYPES(s): + return {"required": { + "positive": ("STRING", {"forceInput": True, "multiline": True}), + "negative": ("STRING", {"forceInput": True, "multiline": True}), + }, + "optional": { + "name_opt": ("STRING", {"forceInput": True, "multiline": False}) + } + } + + RETURN_TYPES = ("ZIPPED_PROMPT",) + + FUNCTION = "doit" + + CATEGORY = "InspirePack/prompt" + + def doit(self, positive, negative, name_opt=""): + return ((positive, negative, name_opt), ) + + +NODE_CLASS_MAPPINGS = { + "LoadPromptsFromFile //Inspire": LoadPromptsFromFile, + "UnzipPrompt //Inspire": UnzipPrompt, + "ZipPrompt //Inspire": ZipPrompt, +} +NODE_DISPLAY_NAME_MAPPINGS = { + "LoadPromptsFromFile //Inspire": "Load Prompts From File (Inspire)", + "UnzipPrompt //Inspire": "Unzip Prompt (Inspire)", + "ZipPrompt //Inspire": "Zip Prompt (Inspire)", +} diff --git a/prompts/example/prompt1.txt b/prompts/example/prompt1.txt new file mode 100644 index 0000000..0eed7fb --- /dev/null +++ b/prompts/example/prompt1.txt @@ -0,0 +1,2 @@ +positive:beautiful scenery nature glass bottle landscape, , purple galaxy bottle, +negative:text, watermark \ No newline at end of file diff --git a/prompts/example/prompt2.txt b/prompts/example/prompt2.txt new file mode 100644 index 0000000..f6a08d0 --- /dev/null +++ b/prompts/example/prompt2.txt @@ -0,0 +1,4 @@ +positive:1girl is walking through street, +raincoat, yellow umbrella + +negative:text, watermark \ No newline at end of file diff --git a/prompts/put_prompts_dirs_here b/prompts/put_prompts_dirs_here new file mode 100644 index 0000000..e69de29