Improve prompt handling and formatting features

Enhanced Prompt_Extender to support flexible separators and intelligent tag merging.
This commit is contained in:
hexxacubic
2026-05-09 20:21:35 +02:00
committed by GitHub
parent 7021725a66
commit 5d6c1c5aee
+70 -47
View File
@@ -1,3 +1,4 @@
# Prompt_Extender.py
import re
class Prompt_Extender:
@@ -5,6 +6,12 @@ class Prompt_Extender:
A ComfyUI node for building double prompts from two text fields.
Can also extend existing prompts when connected.
Can prepend or append the additions based on the prepend_mode setting.
Features:
- Supports separator (---, ----, -----) anywhere: own line or mid-text
- Output: always clean --- on its own line
- Intelligent tag merging: deduplication, comma-separated
- Preserves positive/negative separation
"""
@classmethod
@@ -15,7 +22,11 @@ class Prompt_Extender:
"multiline": True,
"default": "beautiful, high quality\n---\nblurry, low quality"
}),
"prepend_mode": ("BOOLEAN", {"default": False, "label_on": "Prepend", "label_off": "Append"}),
"prepend_mode": ("BOOLEAN", {
"default": False,
"label_on": "Prepend",
"label_off": "Append"
}),
},
"optional": {
"double_prompt": ("STRING", {"forceInput": True}),
@@ -28,80 +39,92 @@ class Prompt_Extender:
CATEGORY = "hexxacubic"
def extend_prompts(self, prompt_additions, prepend_mode, double_prompt=""):
# If no input connected, prompt_additions becomes the main prompt
# If no input connected, return additions as-is
if not double_prompt:
# Just return the additions as the output
return (prompt_additions,)
return (prompt_additions.strip(),)
# Parse input double prompt
# Parse both inputs
positive_prompt, negative_prompt = self._parse_double_prompt(double_prompt)
# Parse additions
positive_addition, negative_addition = self._parse_double_prompt(prompt_additions)
# Combine the prompts based on prepend_mode
# Combine based on mode
if prepend_mode:
# Prepend mode: additions come first
combined_positive = self._combine_prompts(positive_addition, positive_prompt)
combined_negative = self._combine_prompts(negative_addition, negative_prompt)
else:
# Append mode (default): additions come last
combined_positive = self._combine_prompts(positive_prompt, positive_addition)
combined_negative = self._combine_prompts(negative_prompt, negative_addition)
# Return as double prompt format
if combined_positive and combined_negative:
return (f"{combined_positive}\n---\n{combined_negative}",)
elif combined_positive:
return (combined_positive,)
elif combined_negative:
return (f"\n---\n{combined_negative}",)
else:
return ("",)
# Format output with clean separator
return (self._format_double_prompt(combined_positive, combined_negative),)
def _parse_double_prompt(self, text):
"""Parse double prompt format into positive and negative parts"""
if not text.strip():
"""Parse double prompt: supports --- anywhere in text (mid-line or own line)"""
if not text or not text.strip():
return "", ""
lines = text.split('\n')
# Find separator (---, ----, or -----)
separator_idx = -1
for i, line in enumerate(lines):
if line.strip() in ["---", "----", "-----"]:
separator_idx = i
break
# Match ---, ----, -----, ----- (with optional spaces/dashes)
pattern = r'\s*[-—]{3,}\s*' # includes en-dash, em-dash
match = re.search(pattern, text)
if separator_idx != -1:
positive = "\n".join(lines[:separator_idx]).strip()
negative = "\n".join(lines[separator_idx+1:]).strip()
if match:
sep_start = match.start()
sep_end = match.end()
positive = text[:sep_start].strip()
negative = text[sep_end:].strip()
else:
positive = text.strip()
negative = ""
return positive, negative
def _combine_prompts(self, base_prompt, addition):
"""Intelligently combines base prompt and addition"""
base_prompt = base_prompt.strip()
def _split_tags(self, text):
"""Split prompt into clean list of tags (by comma, semicolon, or newline)"""
if not text:
return []
# Split by comma, semicolon, or newline
parts = re.split(r'[,;\n]+', text)
tags = [p.strip() for p in parts if p.strip()]
return tags
def _combine_prompts(self, base, addition):
"""Combine two prompt parts: deduplicate, comma-separated"""
base = base.strip()
addition = addition.strip()
if not base_prompt:
if not base:
return addition
if not addition:
return base_prompt
return base
# Add comma between prompts if none exists
if base_prompt and addition:
if not base_prompt.endswith(',') and not base_prompt.endswith('.'):
return f"{base_prompt}, {addition}"
else:
return f"{base_prompt} {addition}"
base_tags = self._split_tags(base)
add_tags = self._split_tags(addition)
return base_prompt
# Merge and deduplicate (preserve base order, then additions)
seen = set()
combined = []
for tag in base_tags + add_tags:
if tag not in seen:
seen.add(tag)
combined.append(tag)
return ", ".join(combined)
def _format_double_prompt(self, positive, negative):
"""Format positive and negative into clean double prompt with --- on own line"""
positive = positive.strip()
negative = negative.strip()
if positive and negative:
return f"{positive}\n---\n{negative}"
elif positive:
return positive
elif negative:
return f"\n---\n{negative}"
else:
return ""
@classmethod
def IS_CHANGED(s, prompt_additions, prepend_mode, double_prompt=""):
# Cache based on all inputs
def IS_CHANGED(cls, prompt_additions, prepend_mode, double_prompt=""):
"""Cache busting based on all inputs"""
return hash(prompt_additions + str(prepend_mode) + double_prompt)