2025-08-24 15:19:04 -04:00
2025-08-24 15:16:45 -04:00
2025-08-24 11:55:42 -04:00
2025-08-23 14:40:22 -04:00
2025-08-24 15:16:45 -04:00
2025-08-24 15:19:04 -04:00

ComfyUI Dynamic Prompting Simplified

A minimal dynamic prompting + mirrored wildcards node for ComfyUI.

Overview

  • {a|b|{c|d}} nested choice expansion (deterministic by seed).
  • __name__ loads wildcards/name.txt.
  • __name-mir__ strictly loads wildcards/name-mir.txt.
  • In negative phase, if __name__ is used and name-mir.txt exists, it auto-mirrors to all options except the chosen one.
  • Deterministic selection per seed.

Install

  1. Copy this folder to: <ComfyUI>/custom_nodes/ComfyUI-DynPromptSimplified
  2. (Optional) Put your wildcard files in ComfyUI-DynPromptSimplified/wildcards/ or set wildcard_dir to any folder.
  3. Restart ComfyUI.

Node

DynPrompt Expand (mirrored wildcards)

  • Inputs: text, negative, seed, wildcard_dir, auto_neg_from_mir
  • Outputs: expanded text, expanded negative

Node Inputs

  • positive: positive prompt
  • negative: negative prompt
  • Seed: this is used to determine how the node will select tags
  • allow neg from mir: automatically adds -mir tags to negative prompt without explicitly needing to add it to the negative prompt
  • variety: int between 0-10; creates extra randomness 'lanes' Variety
    Wire the outputs into your usual CLIP Text Encode node
    You can preview what the output is with the "preview any" node in utils
    Preview 1

✨ Features

  • Nested choices with {option1|option2|{nested1|nested2}}

  • Wildcard expansion with __name__ → expands from wildcards/name.txt

  • Line-separated wildcard files that may themselves contain braces and wildcards

  • Mirrored wildcards with __name-mir__:

    • Positive prompt gets the chosen option
    • Negative prompt gets all the other options, comma-separated
    • Strict resolution: __name-mir__ reads only wildcards/name-mir.txt (no fallback to name.txt)
  • Deterministic behavior using the current generation seed

  • Works for both positive and negative prompts

  • Expanded prompts are saved into PNG metadata

    📑 Wildcard Files

  • Located in the wildcards/ directory (configurable).

  • Each line is one possible expansion.

  • Lines may contain further braces {} and wildcard calls.

Example: wildcards/hats.txt

{red hat|blue hat|{green hat|yellow hat|{black hat|gold hat}}}
beret
top hat

🔄 Mirrored Wildcards

  • File name: name-mir.txt (called via __name-mir__).
  • Ensures complementary picks between positive/negative prompts.

Example: wildcards/hats-mir.txt

{red hat|blue hat|green hat}
{tall hat|short hat|medium hat}
  • Positive prompt: portrait, __hats-mir__
  • Negative prompt: lowres, __hats-mir__
    • If pos → red hat, neg → blue hat, green hat
    • If pos → short hat, neg → tall hat, medium hat

This ensures that the negative prompt excludes the token chosen in the positive prompt.

🧩 Nested -mir behavior (auto-discovery)

Mirrored tokens can be nested inside other wildcards. If a wildcard you use in the positive prompt expands to another token like __foo-mir__, the extension can automatically inject the mirrored complement into the negative prompt (so you don’t have to add __foo-mir__ manually).

  • This requires the checkbox in the UI:
    “Automatically mirror -mir wildcards without explicitly adding them to the negative prompt.” (enabled by default)
  • The auto-inject only happens if the negative prompt does not already contain that __*-mir__ token.
  • Resolution is strict: __foo-mir__ reads wildcards/foo-mir.txt only.

Example (nested):

wildcards/outfits.txt
---------------------
__hats-mir__, {casual|formal}

wildcards/hats-mir.txt
----------------------
{red hat|blue hat|green hat}

Usage:

  • Positive: portrait, __outfits__
  • Negative: (leave blank or put your usual negatives)
  • add node from: add node -> prompt -> DSynPrompt Expand (deep-mirrored)
    Preview 1

Behavior:

  • The positive prompt expands __outfits__ → which contains __hats-mir__.
  • With the checkbox enabled, the extension auto-injects __hats-mir__ into the negative and expands it there as the comma‑separated “other” options.
  • If the seed picks red hat for positive, the negative gets blue hat, green hat automatically.

🎲 Variety (extra randomness lanes)

What it is: An integer knob that creates alternate, reproducible randomness lanes without changing your seed or prompt.

Deterministic: With the same (seed, variety, prompt, files), you get the same positive & negative outputs every time.

Independence from fixed text: Only decision points advance randomness—each {…} block and each __wildcard__ / __*-mir__. Fixed words/commas/spaces do not affect picks.

How it works (under the hood):

  • Choices use choice#0, choice#1, …
  • Wildcards use wild#0, wild#1, … (also salted with the token name)
  • We hash (seed, counter[, token], variety) to pick an index.

When to use: Keep seed fixed and sweep variety = 0,1,2… to explore different, reproducible variants from the same prompt.

Example

Prompt: __color__, {A|B|{C|D}}, __pose-mir__

(seed=123, variety=0) → picks one set of branches (seed=123, variety=1) → different set of branches (still reproducible)

⚙️ Usage

  • Write prompts as usual with {} and __wildcards__.
  • Wildcards are recursively expanded.
  • Mirrored wildcards respect complement logic.

Prompt Example:

Positive: portrait, {cinematic|studio|outdoor}, __hats__, soft lighting
Negative: lowres, bad anatomy, __hats-mir__

Notes

  • Missing wildcard files resolve to empty strings.
  • Choice/wildcard expansion is capped to prevent runaway recursion.
  • If negative is blank and auto_neg_from_mir is ON, the node scans the positive for __tokens__ and auto-builds a mirrored negative when possible.

Changelog

2025-08-24 — Counter-Based Randomness & “Variety” lanes

Why: fixed tokens could cause prompt to converge.

What changed

  • Decision-only RNG: Random choices now depend only on decision points (each {…} block and each __wildcard__ / __*-mir__ call), not on surrounding fixed text.
    • Internally we hash (seed, decision_counter[, token], variety) where counters advance as we hit choices/wildcards left→right.
    • Adding/removing fixed words, commas, or spacing no longer shifts picks.
  • Deterministic lanes via variety: New integer input that adds an extra salt.
    • Same (seed, variety, prompt, files) ⇒ same outputs.
    • Sweep variety = 0,1,2… to get reproducible alternates without touching seed or prompt.
  • Deep mirroring (strict): __foo-mir__ contributes mirrored exclusions to Negative even when nested inside other wildcards, and only reads foo-mir.txt (never falls back).
  • Empty-branch support in *-mir.txt: {option|} is honored.
    • If Positive picks option, Negative adds nothing for that token; if Positive picks the empty branch, Negative adds the non-empty options.
  • Single-line *-mir.txt with nested braces: {1|2|{3|4}} is flattened to leaves so mirroring can compute “all-except-chosen” correctly.

Behavior notes

  • Fixed text no longer influences randomness. Only the number/order of decision points matters.
  • Changing decision points (e.g., adding a {…} or another __wildcard__) will change the sequence of draws—as expected.
  • Deep mirror uses the same counters as Positive, ensuring the Negative always gets the correct complement.

Example

Prompt: __color__, {A|B|{C|D}}, __pose-mir__
Same seed, same variety → same picks (pos & neg)
Change only fixed words → picks stay identical
Bump variety (e.g., 0→1) → different, reproducible picks

License: GPLv3 (same as the original)

S
Description
No description provided
Readme
416 KiB
Languages
Python 100%