From 5c52bffc9d5255f4fd270b00c23b5f34e7b1f487 Mon Sep 17 00:00:00 2001 From: asagi4 <130366179+asagi4@users.noreply.github.com> Date: Mon, 2 Jun 2025 22:16:42 +0300 Subject: [PATCH] Docs --- README.md | 4 +-- doc/syntax.md | 58 +++++++++++++++++++++++++-------------- prompt_control/prompts.py | 6 ++-- 3 files changed, 42 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index bd11ca6..e535a97 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ A `Basic Text to Image` template is included with the extension, and can be load You can use text prompts to control the following: -- Prompt scheduling and filtering without noodle soup. +- A1111-style prompt scheduling and filtering without noodle soup. - LoRA loading and scheduling via ComfyUI's hook system - Masking, composition and area control (regional prompting) with an implementation of Attention Couple, also fully schedulable. - Per-encoder prompts for models with multiple text encoders, such as SDXL and Flux -- Prompt operations like `BREAK`, `AVG()` and `AND` corresponding to ComfyUI's `ConditioningConcat`, `ConditioningAverage` and `ConditioningCombine` +- Prompt combinators like `BREAK`, as well as `CAT`, `AVG()` and `AND` corresponding to ComfyUI's `ConditioningConcat`, `ConditioningAverage` and `ConditioningCombine` nodes. - Different weight interpretation types (ComfyUI, A1111, compel, etc.) - Prompt masking with an implementation of [cutoff](https://github.com/BlenderNeko/ComfyUI_Cutoff) - Simple prompt macros with `DEF` diff --git a/doc/syntax.md b/doc/syntax.md index 06d5d8a..d146ce6 100644 --- a/doc/syntax.md +++ b/doc/syntax.md @@ -95,26 +95,9 @@ generates a LoRA schedule based on a sinewave # Basic prompt syntax -This syntax is also available in outside scheduled prompts, where applicable. +This syntax is also available in outside scheduled with the `PCTextEncode` node, where applicable. -## LoRA loading - -The A111-style syntax `` can be used to load LoRAs via the prompt. See LoRA scheduling above. - -## Combining prompts, A1111-style - -### BREAK -The keyword `BREAK` causes the prompt to be encoded in separate chunks, and the resulting tensors are then concatenated. This is equivalent to the `ConditioningConcat` node. - -An older implementation of this tokenized prompts in chunks instead, but it had bugs with non-CLIP text encoders. Use `OLDBREAK` to get the old behaviour. - -### AVG() - -`prompt1 AVG(weight) prompt2` encodes prompt1 and prompt2 separately, and then combines them using `ConditioningAverage`. The default for `weight` is `0.5`. - -`AVG` is processed before `BREAK` but after `AND` - -`p1 AVG() p2 AVG() p3` combines `p1` and `p2` first, then combines the result with `p3`. +## Combining prompts ### AND @@ -135,7 +118,21 @@ cat [\:0::0.5] AND dog ``` Note that the `:` needs to be escaped with a `\` or it will be interpreted as scheduling syntax. -# Functions +## Note about processing order + +Prompt operators are processed in the following order, meaning that all features "below" another can be affected by the feature above it. That is, `BREAK` can go inside a `TE()` call, but not `AND` or `CAT`. + +- DEF macros are expanded +- Scheduling is expanded +- Prompts are split by AND +- Most functions (like STYLE, MASK) and cutoffs are evaluated +- prompts are split by AVG() +- prompts are split by CAT +- the TE() function is evaluated to set per-encoder prompts +- BREAK is evaluated +- Everything else + +## Functions There are some "functions" that can be included in a prompt to affect how it is interpreted. @@ -147,7 +144,26 @@ Note: Whitespace is usually *not* stripped from string parameters by default. Co Like `AND`, functions are parsed after regular scheduling syntax has been expanded, allowing things like `[AREA:MASK:0.3](...)`, in case that's somehow useful. -### STYLE: Configure prompt weighting (also known as "Advanced CLIP Encode") +### BREAK +The keyword `BREAK` causes the prompt to be tokenized in separate chunks, padding each chunk to the text encoder's maximum size before encoding. + +For some text encoders (like t5), this operation doesn't really make sense and BREAKs are simply ignored. + +### CAT + +`CAT` encodes each prompt separately before concatenating the resulting tensors into a single conditioning. It behaves identically to ComfyUI's `ConditioningConcat`. + +### AVG() + +`prompt1 AVG(weight) prompt2` encodes prompt1 and prompt2 separately, and then combines them using `ConditioningAverage`. The default for `weight` is `0.5`. + +`AVG` is processed before `BREAK` but after `AND` + +`p1 AVG() p2 AVG() p3` combines `p1` and `p2` first, then combines the result with `p3`. + +## Prompt weighting (also known as "Advanced CLIP Encode") + +### STYLE Use the syntax `STYLE(weight_interpretation, normalization)` in a prompt to affect how prompts are interpreted. diff --git a/prompt_control/prompts.py b/prompt_control/prompts.py index df598ba..0530533 100644 --- a/prompt_control/prompts.py +++ b/prompt_control/prompts.py @@ -321,11 +321,11 @@ def hook_te(clip, te_names, style, normalization, extra): return clip newclip = clip.clone() for te_name in te_names: - if hasattr(clip.tokenizer, 'clip_' + te_name): + if hasattr(clip.tokenizer, "clip_" + te_name): x = extra.copy() - x["tokenizer"] = getattr(clip.tokenizer, 'clip_' + te_name) + x["tokenizer"] = getattr(clip.tokenizer, "clip_" + te_name) if not hasattr(clip.patcher.model, te_name): - te_name = 'clip_' + te_name + te_name = "clip_" + te_name if not hasattr(clip.patcher.model, te_name): log.warning("TE model %s not found on model patcher. Skipping...", te_name) continue