Fix for comments in prompts with styles (#1948)

(#1862)
a fix for the 0.01% who use comments in prompts. Before this, styles could be considered part of a comment.

strips comments from prompts first, then from each applied style before merge
same process for extracting styles from prompts
updated tooltips for toolbuttons to apply styles
removed code made redundant by this change, from modules.processing_scripts.comments
This commit is contained in:
DenOfEquity
2024-09-30 11:16:55 +01:00
committed by GitHub
parent 22e2bc3bc0
commit 86d003266b
5 changed files with 32 additions and 64 deletions

View File

@@ -1,49 +1,13 @@
from modules import scripts, shared, script_callbacks
from modules import shared
import re
def strip_comments(text):
text = re.sub('(^|\n)#[^\n]*(\n|$)', '\n', text) # while line comment
text = re.sub('#[^\n]*(\n|$)', '\n', text) # in the middle of the line comment
if shared.opts.enable_prompt_comments:
text = re.sub('(^|\n)#[^\n]*(\n|$)', '\n', text) # whole line comment
text = re.sub('#[^\n]*(\n|$)', '\n', text) # in the middle of the line comment
return text
class ScriptStripComments(scripts.Script):
def title(self):
return "Comments"
def show(self, is_img2img):
return scripts.AlwaysVisible
def process(self, p, *args):
if not shared.opts.enable_prompt_comments:
return
p.all_prompts = [strip_comments(x) for x in p.all_prompts]
p.all_negative_prompts = [strip_comments(x) for x in p.all_negative_prompts]
p.main_prompt = strip_comments(p.main_prompt)
p.main_negative_prompt = strip_comments(p.main_negative_prompt)
if getattr(p, 'enable_hr', False):
p.all_hr_prompts = [strip_comments(x) for x in p.all_hr_prompts]
p.all_hr_negative_prompts = [strip_comments(x) for x in p.all_hr_negative_prompts]
p.hr_prompt = strip_comments(p.hr_prompt)
p.hr_negative_prompt = strip_comments(p.hr_negative_prompt)
def before_token_counter(params: script_callbacks.BeforeTokenCounterParams):
if not shared.opts.enable_prompt_comments:
return
params.prompt = strip_comments(params.prompt)
script_callbacks.on_before_token_counter(before_token_counter)
shared.options_templates.update(shared.options_section(('sd', "Stable Diffusion", "sd"), {
"enable_prompt_comments": shared.OptionInfo(True, "Enable comments").info("Use # anywhere in the prompt to hide the text between # and the end of the line from the generation."),
}))

View File

@@ -1,10 +1,10 @@
from __future__ import annotations
from pathlib import Path
from modules import errors
import csv
import os
import typing
import shutil
import modules.processing_scripts.comments as comments
class PromptStyle(typing.NamedTuple):
@@ -14,19 +14,18 @@ class PromptStyle(typing.NamedTuple):
path: str | None = None
def merge_prompts(style_prompt: str, prompt: str) -> str:
if "{prompt}" in style_prompt:
res = style_prompt.replace("{prompt}", prompt)
else:
parts = filter(None, (prompt.strip(), style_prompt.strip()))
res = ", ".join(parts)
return res
def apply_styles_to_prompt(prompt, styles):
prompt = comments.strip_comments(prompt).strip()
for style in styles:
prompt = merge_prompts(style, prompt)
style = comments.strip_comments(style).strip()
if "{prompt}" in style:
prompt = style.replace("{prompt}", prompt)
elif style != "":
if prompt != "":
prompt += ", "
prompt += style
return prompt
@@ -40,7 +39,7 @@ def extract_style_text_from_prompt(style_text, prompt):
"""
stripped_prompt = prompt.strip()
stripped_style_text = style_text.strip()
stripped_style_text = comments.strip_comments(style_text).strip()
if "{prompt}" in stripped_style_text:
left, _, right = stripped_style_text.partition("{prompt}")
@@ -207,28 +206,30 @@ class StyleDatabase:
{k: v for k, v in style._asdict().items() if k != "path"}
)
def extract_styles_from_prompt(self, prompt, negative_prompt):
def extract_styles_from_prompt(self, positive, negative):
extracted = []
applicable_styles = list(self.styles.values())
positive = comments.strip_comments(positive)
negative = comments.strip_comments(negative)
while True:
found_style = None
for style in applicable_styles:
is_match, new_prompt, new_neg_prompt = extract_original_prompts(
style, prompt, negative_prompt
is_match, new_positive, new_negative = extract_original_prompts(
style, positive, negative
)
if is_match:
found_style = style
prompt = new_prompt
negative_prompt = new_neg_prompt
positive = new_positive
negative = new_negative
applicable_styles.remove(found_style)
extracted.append(found_style.name)
break
if not found_style:
break
applicable_styles.remove(found_style)
extracted.append(found_style.name)
return list(reversed(extracted)), prompt, negative_prompt
return list(reversed(extracted)), positive, negative

View File

@@ -27,6 +27,7 @@ from modules import prompt_parser
from modules.infotext_utils import image_from_url_text, PasteField
from modules_forge.forge_canvas.canvas import ForgeCanvas, canvas_head
from modules_forge import main_entry, forge_space
import modules.processing_scripts.comments as comments
create_setting_component = ui_settings.create_setting_component
@@ -173,6 +174,8 @@ def update_token_counter(text, steps, styles, *, is_positive=True):
if shared.opts.include_styles_into_token_counters:
apply_styles = shared.prompt_styles.apply_styles_to_prompt if is_positive else shared.prompt_styles.apply_negative_styles_to_prompt
text = apply_styles(text, styles)
else:
text = comments.strip_comments(text).strip()
try:
text, _ = extra_networks.parse_prompt(text)

View File

@@ -67,7 +67,7 @@ class UiPromptStyles:
with gr.Row():
self.selection = gr.Dropdown(label="Styles", elem_id=f"{tabname}_styles_edit_select", choices=list(shared.prompt_styles.styles), value=[], allow_custom_value=True, info="Styles allow you to add custom text to prompt. Use the {prompt} token in style text, and it will be replaced with user's prompt when applying style. Otherwise, style's text will be added to the end of the prompt.")
ui_common.create_refresh_button([self.dropdown, self.selection], shared.prompt_styles.reload, lambda: {"choices": list(shared.prompt_styles.styles)}, f"refresh_{tabname}_styles")
self.materialize = ui_components.ToolButton(value=styles_materialize_symbol, elem_id=f"{tabname}_style_apply_dialog", tooltip="Apply all selected styles from the style selection dropdown in main UI to the prompt.")
self.materialize = ui_components.ToolButton(value=styles_materialize_symbol, elem_id=f"{tabname}_style_apply_dialog", tooltip="Apply all selected styles from the style selection dropdown in main UI to the prompt. Strips comments, if enabled.")
self.copy = ui_components.ToolButton(value=styles_copy_symbol, elem_id=f"{tabname}_style_copy", tooltip="Copy main UI prompt to style.")
with gr.Row():

View File

@@ -119,7 +119,7 @@ class Toprow:
self.paste = ToolButton(value=paste_symbol, elem_id="paste", tooltip="Read generation parameters from prompt or last generation if prompt is empty into user interface.")
self.clear_prompt_button = ToolButton(value=clear_prompt_symbol, elem_id=f"{self.id_part}_clear_prompt", tooltip="Clear prompt")
self.apply_styles = ToolButton(value=ui_prompt_styles.styles_materialize_symbol, elem_id=f"{self.id_part}_style_apply", tooltip="Apply all selected styles to prompts.")
self.apply_styles = ToolButton(value=ui_prompt_styles.styles_materialize_symbol, elem_id=f"{self.id_part}_style_apply", tooltip="Apply all selected styles to prompts. Strips comments, if enabled.")
if self.is_img2img:
self.button_interrogate = ToolButton('📎', tooltip='Interrogate CLIP - use CLIP neural network to create a text describing the image, and put it into the prompt field', elem_id="interrogate")