* Add support for wildcards.

* Better debug log.
* Set commands support lazy evaluation and content addition.
* Unified in one tree and processing phase.
* Supports Flux.
* Fix evaluation of string variable as truthy.
* Show invalid wildcards.
* Better detection of installed UI.
* Improved cache of results.
* Works as a ComfyUI node.
* Debug setting changed to debug level.
* Fixes in variable use.
* Added timing reporting.
* Detection of more model types.
* Installation script for requirements.
* Extension metadata for A1111.
* Lark grammar in separate file and cached.
* Improved conditions for if command.
* Avoid repeats in the processing of prompts.
* Fix multiple loading of settings.
This commit is contained in:
Antonio Cordero Balcazar
2024-08-31 14:02:46 +02:00
parent bad0d24fbe
commit 8a960df0aa
20 changed files with 3137 additions and 1660 deletions
+179 -56
View File
@@ -1,57 +1,60 @@
# Prompt Postprocessor for Stable Diffusion WebUI
# Prompt Postprocessor for Stable Diffusion WebUI and ComfyUI
The Prompt Postprocessor for Stable Diffusion WebUI, formerly known as "sd-webui-sendtonegative", is an extension designed to process the prompt after other extensions have potentially modified it. This extension is compatible with the [AUTOMATIC1111 Stable Diffusion WebUI](https://github.com/AUTOMATIC1111/stable-diffusion-webui) and [SD.Next](https://github.com/vladmandic/automatic).
The Prompt Postprocessor, formerly known as "sd-webui-sendtonegative", is an extension designed to process the prompt, possibly after other extensions have modified it. This extension is compatible with:
* [AUTOMATIC1111 Stable Diffusion WebUI](https://github.com/AUTOMATIC1111/stable-diffusion-webui)
* [SD.Next](https://github.com/vladmandic/automatic).
* [Forge](https://github.com/lllyasviel/stable-diffusion-webui-forge)
* [reForge](https://github.com/Panchovix/stable-diffusion-webui-reForge)
* ...and probably other forks
* [ComfyUI](https://github.com/comfyanonymous/ComfyUI)
Currently this extension has these functions:
* Allows marking parts of the prompt and moves them to the negative prompt. This allows for useful tricks when using a wildcard extension since you can add negative content from choices made in the positive prompt.
* Set values to local variables.
* Filter content based on the loaded SD model version or a set variable.
* Detect invalid wildcards and act on them.
* Sending parts of the prompt to the negative prompt. This allows for useful tricks when using wildcards since you can add negative content from choices made in the positive prompt.
* Set and modify local variables.
* Filter content based on the loaded SD model or a variable.
* Process wildcards. Compatible with Dynamic Prompts formats. Can also detect invalid wildcards and act as you choose.
* Clean up the prompt and negative prompt.
Note: The extension must be loaded after the installed wildcards extension (or any other that modifies the prompt or has it's own syntax expressions). Extensions load by their folder name in alphanumeric order.
With the ["Dynamic Prompts" extension](https://github.com/adieyal/sd-dynamic-prompts) this happens by default due to default folder names for both extensions. But if this is not the case, you can just rename this extension's folder so the ordering works out.
With the ["AUTOMATIC1111 Wildcards" extension](https://github.com/AUTOMATIC1111/stable-diffusion-webui-wildcards) you will have to rename one of the folders, so that it loads before than this extension.
When in doubt, just rename this extension's folder with a "z" in front (for example) so that it is the last one to load, or manually set such folder name when installing it.
Note: when used in an A1111 compatible webui, the extension must be loaded after any other extension that modifies the prompt (like another wildcards extension). Usually extensions load by their folder name in alphanumeric order, so if the extensions are not loading in the correct order just rename this extension's folder so the ordering works out. When in doubt, just rename this extension's folder with a "z" in front (for example) so that it is the last one to load, or manually set such folder name when installing it.
Notes:
1. It only recognizes regular A1111 prompt formats. So:
1. Other than its own commands, it only recognizes regular A1111 prompt formats. So:
* **Attention**: `\[prompt\] (prompt) (prompt:weight)`
* **Alternation**: `\[prompt1|prompt2|...\]`
* **Scheduling**: `\[prompt1:prompt2:step\]`
* **Extra networks**: `\<kind:model...\>`
* **BREAK**: `prompt1 BREAK prompt2`
* **Composable Diffusion**: `prompt1 AND prompt2`
* **Composable Diffusion**: `prompt1:weight1 AND prompt2:weight2`
In SD.Next that means only the *A1111* or *Full* parsers. It will warn you if you use the *Compel* parser.
2. It only recognizes wildcards in the *\_\_wildcard\_\_* and *{choice|choice}* formats.
3. Since it should run after other extensions that apply to the prompt, the content should have already been processed by them and there should't be any non recognized syntax anymore.
4. It does not create *AND/BREAK* constructs when moving content to the negative prompt.
2. It recognizes wildcards in the *\_\_wildcard\_\_* and *{choice|choice}* formats (and anything that [Dynamic Prompts](https://github.com/adieyal/sd-dynamic-prompts) supports).
3. It does not create *AND/BREAK* constructs when moving content to the negative prompt.
## Installation
On A1111 compatible webuis:
1. Go to Extensions > Install from URL
2. Paste <https://github.com/acorderob/sd-webui-prompt-postprocessor> in the URL for extension's git repository text field
3. Click the Install button
4. Restart the webui
On ComfyUI:
1. Go to Manager > Custom Nodes Manager
2. Install through ComfyUI Manager
3. Click Install via Git URL and enter <https://github.com/acorderob/sd-webui-prompt-postprocessor>
4. Restart
## Usage
### Detection of remaining wildcards
This extension should run after any wildcard extensions, so any remaining wildcards present in the prompt or negative_prompt at this point of processing must be invalid. Usually you might not notice this problem until you check the image metadata, so this option gives you some ways to detect and treat the problem.
If you choose to not ignore wildcards, the extension will look for any *\_\_wildcard\_\_* or *{choice|choice}* constructs and act as configured.
### Commands
The extension uses now a new format for its commands. The format is similar to an extranetwork, but it has a "ppp:" prefix followed by the command, and then a space and any parameters (if any).
The extension uses a format for its commands similar to an extranetwork, but it has a "ppp:" prefix followed by the command, and then a space and any parameters (if any).
```text
<ppp:command parameters>
@@ -63,7 +66,79 @@ When a command is associated with any content, it will be between an opening and
<ppp:command parameters>content<ppp:/command>
```
The `set` and `if` commands are the first to be processed.
For wildcards and choices it uses the formats from the Dynamic Prompts extension, but sometimes with some additional options for more functionality.
### Choices
The generic format is:
```text
{parameters$$opt1::choice1|opt2::choice2|opt3::choice3}
```
Both the construct parameters (up to the '$$') and the individual choice options (up to the '::') are optional.
There is also a format where instead of "parameters$$" you just put the sampler, for compatibility with Dynamic Prompts.
The construct parameters can be written with the following options (all are optional):
* "**~**" or "**@**": sampler (for compatibility with Dynamic Prompts), but only "**~**" (random) is allowed.
* "**r**": means it allows repetition of the choices.
* "**n**" or "**n-m**" or "**n-**" or "**-m**": number or range of choices to select. Allows zero as the start of a range. Default is 1.
* "**$$sep**": separator when multiple choices are selected. Default is set in settings.
* "**$$**": end of the parameters.
The choice options are as follows:
* "**n**": weight of the choice (default 1)
* "**if condition**": filters out the choice if the condition is false (this is an extension to the Dynamic Prompts syntax). Same conditions as in the `if` command.
* "**::**": end of choice options
Whitespace is allowed between parameters.
These are examples of formats you can use to insert a choice construct:
```text
{opt1|5::opt2|3::opt3} # select 1 choice, two have weights
{3$$opt1|5 if _is_sd1::opt2|opt3} # select 3 choices, one has a weight and a condition
{2-3$$opt1|opt2|opt3} # select 2 to 3 choices
{r2-3$$opt1|opt2|opt3} # select 2 to 3 choices allowing repetition
{2-3$$ / $$opt1|opt2|opt3} # select 2 to 3 choices with separator " / "
```
Notes:
* The Dynamic Prompts format `{2$$__flavours__}` does not work as expected. It will only output one value. You can write is as `{r2$$__flavours__}` to get two values, but they may repeat since the evaluation of the wildcard is independent of the choices selection.
* Whitespace in the choices is not ignored like in Dynamic Prompts, but will be cleaned up if the appropiate settings are checked.
### Wildcards
The generic format is:
```text
__parameters$$path/to/wildcard(var=value)__
```
The parameters and the setting of a variable are optional. The parameters follow the same format as for the choices. The variable value only applies during the evaluation of the selected choices and is discarded afterward (the variable keeps its original value if there was one).
In the wildcard definition (which supports the text, json and yaml formats), if the first choice follows the format of these parameters, it will be used as default parameters for that wildcard (see examples in the tests folder). The choices of the wildcard follow the same format as in the choices construct. If using the object format for a choice you can use a new "if" property for the condition in addition to the standard "weight" and "text"/"content".
Wildcards can contain just one choice. In json and yaml formats this allows the use of a string value for the keys, rather than an array.
These are examples of formats you can use to insert a wildcard:
```text
__path/wildcard__ # select 1 choice
__3$$path/wildcard__ # select 3 choices
__2-3$$path/wildcard__ # select 2 to 3 choices
__r2-3$$path/wildcard__ # select 2 to 3 choices allowing repetition
__2-3$$ / $$path/wildcard__ # select 2 to 3 choices with separator " / "
__path/wildcard(var=value)__ # select 1 choice using the specified variable value in the evaluation.
```
#### Detection of remaining wildcards
This extension should run after any other wildcard extensions, so if you don't use the internal wildcards processing, any remaining wildcards present in the prompt or negative_prompt at this point must be invalid. Usually you might not notice this problem until you check the image metadata, so this option gives you some ways to detect and treat the problem.
### Set command
@@ -73,6 +148,27 @@ The format is:
```text
<ppp:set varname>value<ppp:/set>
<ppp:set varname evaluate>value<ppp:/set>
<ppp:set varname add>value<ppp:/set>
<ppp:set varname evaluate add>value<ppp:/set>
```
The `evaluate` parameter makes it so the value of the variable is evaluated at this moment, instead of when it is used.
With the `add` parameter the value is added to the current value of the variable. It does not force an immediate evaluation of the old nor the added value.
The Dynamic Prompts format also works:
```text
${var=value}
${var=!value} # immmediate evaluation
```
If also supports the addition as an extension of the Dynamic Prompts format:
```text
${var+=value}
${var+=!value}
```
### Echo command
@@ -83,23 +179,57 @@ The format is:
```text
<ppp:echo varname>
<ppp:echo varname>default<ppp:/echo>
```
The Dynamic Prompts format is:
```text
${var}
${var:default}
```
### If command
This command allows you to filter content based on conditions.
The format is:
The full format is:
```text
<ppp:if condition1>content one<ppp:elif condition2>content two<ppp:else>other content<ppp:/if>
```
The *conditionN* compares a variable with a value. The operation can be `eq`, `ne`, `gt`, `lt`, `ge`, `le` and the value can be a quoted string or an integer.
The *conditionN* compares a variable with a value or a list of values. The allowed formats are:
The variable can be one set with the `set` command or special variables like:
```text
[not] variable
[not] variable operation value
variable [not] operation value
[not] variable operation (value1,value2...)
variable [not] operation (value1,value2...)
```
When there is no value it will check if the variable is truthy.
For a simple value the allowed operations are `eq`, `ne`, `gt`, `lt`, `ge`, `le`, `contains` and the value can be a quoted string or an integer.
For a list of values the allowed operations are `contains`, `in` and the value of the variable is checked against all the elements of the list until one matches.
The variable can be one set with the `set` or `add` commands or you can use internal variables like these (names starting with an underscore are reserved):
* `_sd` : the loaded model version (`"sd1"`, `"sd2"`, `"sdxl"`)
* `_sdname` : the loaded model filename (without path)
* `_sdfullname`: the loaded model filename (with path)
* `_is_sd`: true if the loaded model version is any version of SD
* `_is_sd1`: true if the loaded model version is SD 1.x
* `_is_sd2`: true if the loaded model version is SD 2.x
* `_is_sdxl`: true if the loaded model version is SDXL (includes Pony models)
* `_is_ssd`: true if the loaded model version is SSD (Segmind Stable Diffusion 1B). Note that for an SSD model `_is_sdxl` will also be true.
* `_is_sdxl_no_ssd`: true if the loaded model version is SDXL and not an SSD model.
* `_is_pony`: true if the loaded model version is SDXL and a Pony model (based on its filename). Note that for a pony model `_is_sdxl` will also be true.
* `_is_sdxl_no_pony`: true if the loaded model version is SDXL and not a Pony model.
* `_is_sd3`: true if the loaded model version is SD 3.x
* `_is_flux`: true if the loaded model is Flux
Any `elif`s (there can be multiple) and the `else` are optional.
@@ -108,9 +238,9 @@ Any `elif`s (there can be multiple) and the `else` are optional.
(multiline to be easier to read)
```text
<ppp:if _sd eq "sd1"><lora:test_sd1> test sd1
<ppp:elif _sd eq "sd2"><lora:test_sd2> test sd2
<ppp:elif _sd eq "sdxl"><lora:test_sdxl> test sdxl
<ppp:if _is_sd1><lora:test_sd1> test sd1x
<ppp:elif _sd_pony><lora:test_pony> test pony
<ppp:elif _sd_sdxl><lora:test_sdxl> test sdxl
<ppp:else>unknown model
<ppp:/if>
```
@@ -153,23 +283,7 @@ Then, if that option is chosen this extension will process it later and move tha
#### Old format
The old format is still supported (for now) and is like this:
```text
<!content!>
```
And an optional position can be specified like this:
```text
<!!position!content!>
```
With the insertion point like this:
```text
<!!iN!!>
```
The old format (`<!...!>`) is not supported anymore.
### Notes on negative commands
@@ -198,35 +312,44 @@ This should still work as intended, and the only negative point i see is the unn
### General settings
* **Debug**: writes debugging information to the console.
* **Debug level**: what to write to the console. Note: in SD.Next debug messages only show if you launch it with the --debug argument.
* **Pony substrings**: list of substrings to detect a Pony model.
* **Apply in img2img**: check if you want to do the processing in img2img processes (does not apply to ComfyUI node).
### Wildcard settings
* **Process wildcards**: you can choose to process them with this extension or use a different one.
* **Wildcards folders**: you can enter multiple folders separated by commas. In ComfyUI you can leave it empty and add a "wildcards" entry in the extra_model_paths.yaml file.
* **What to do with remaining wildcards?**: select what do you want to do with any found wildcards.
* **Ignore**: do not try to detect wildcards.
* **Remove**: detect wildcards and remove them.
* **Add visible warning**: detect wildcards and add a warning text to the prompt, that hopefully produces a noticeable generation.
* **Stop the generation**: detect wildcards and stop the generation.
### Content removal settings
* **Remove extra network tags**: removes all extra network tags.
* **Default separator used when adding multiple choices**: what do you want to use by default to separate multiple choices when the options allow it (by default it's ", ").
* **Keep the order of selected choices**: if checked, a multiple choice construct will return them in the order they are in the construct.
### Send to negative prompt settings
* **Apply in img2img**: check if you want to do this processing in img2img processes.
* **Separator used when adding to the negative prompt**: you can specify the separator used when adding to the negative prompt (by default it's ", ").
* **Ignore repeated content**: it ignores repeated content to avoid repetitions in the negative prompt.
* **Join attention modifiers (weights) when possible**: it joins attention modifiers when possible (joins into one, multipliying their values).
### Clean up settings
* **Apply in img2img**: check if you want to do this processing in img2img processes.
* **Remove empty constructs**: removes attention/scheduling/alternation constructs when they are invalid.
* **Remove extra separators**: removes unnecessary separators. This applies to the configured separator and regular commas.
* **Remove additional extra separators**: removes unnecessary separators at start or end of lines. This applies to the configured separator and regular commas.
* **Clean up around BREAKs**: removes consecutive BREAKs and unnecessary commas and space around them.
* **Use EOL instead of Space before BREAKs**: add a newline before BREAKs.
* **Clean up around ANDs**: removes consecutive ANDs and unnecessary commas and space around them.
* **Use EOL instead of Space before ANDs**: add a newline before ANDs.
* **Clean up around extra network tags**: removes spaces around them.
* **Remove extra spaces**: removes other unnecessary spaces.
### Content removal settings
* **Remove extra network tags**: removes all extra network tags.
## License
MIT