Pi Wildcard Prompt
Seeded prompt variety without a folder of text files
- positive_prompt
- negative_prompt
- selected
A wildcard node with no file system
Wildcards are one of the oldest tricks in the diffusion playbook: drop {a|b|c} alternatives into a prompt, batch it, and every image comes out different. Most ComfyUI wildcard packs take that one step further and read from folders of .txt files, which means setup before you ever get variety. Pi Wildcard Prompt skips all that. Your fragment lists live in the node's own text boxes - likes, dislikes, characters, clothing, styles, extra - it samples from them per run, and hands you ready-made positive and negative prompts. Zero files.
It's a pure-Python text composer, so despite the Pi branding it needs nothing from Pi itself. It's the "generate variety without writing more prompts" machine, in the same lineage as the bracket trick from the classic wildcard syntax.
How it works
Each category box is one option per line; blank lines and lines starting with # are ignored as comments. On every run the node uses random.Random(seed) to pick *_count entries from each list - counts are clamped to the list length, so asking for 5 characters from a 3-line list just gives you 3 - then joins them with your separator: comma, space, or newline. dedupe (on by default) drops case-insensitive duplicates while preserving order; shuffle_positive shuffles the selected fragments but always keeps base_prompt first.
The composition logic is simple:
prompt_template/negative_templateblank → selected fragments get appended tobase_prompt/base_negative.- Template set → placeholders get replaced. Available:
{base_prompt},{base_negative},{likes},{dislikes},{characters},{clothing},{styles},{extra}, and{all_positive}(base plus everything positive).
The README's example tells the story:
{base_prompt} of {characters}, wearing {clothing}, {styles}, {likes}, {extra}
Inputs and outputs that matter
You'll set base_prompt (the stable subject), the category lists, and seed. The six *_count fields decide how much variety each category contributes - all default to 1, and an empty list contributes nothing. Three outputs come out:
positive_prompt- wire into your CLIP Text Encode positive.negative_prompt- wire into the negative. It'sbase_negativeplus selected dislikes.selected- the underrated one. It's a readable dump of exactly what was picked for this seed ("seed: 42 / characters: - …"). Wire it to a text preview while you iterate.
The seed trap
Here's where beginners get bitten. This node runs its own Python RNG, seeded by the seed widget - it has nothing to do with the sampler's seed. Leave seed at 0 and run the queue five times and you get the exact same fragments five times, even though your images vary. That's correct behavior, but it's also why "nothing changes!" is the #1 confused complaint. To get real variety you have to randomize this node's seed per run - convert the seed widget to an input and feed it from a primitive whose control_after_generate is set to randomize, or any node that rolls a fresh int each queue. And because it's a separate RNG, a fixed wildcard seed with a random sampler seed means your text stays identical while the image drifts - sometimes exactly what you want for controlled comparisons, sometimes not.
One more gotcha: setting a template replaces the default append behavior. Leave a placeholder you want out of a template and it's gone - a prompt_template with no {base_prompt} silently drops your base text. If the composed output looks wrong, the selected output tells you whether the problem is the picking or the templating.
Install
Same pack, same two ways - ComfyUI Manager (search "ComfyUI-Pi-LLM") or:
cd ComfyUI/custom_nodes
git clone https://github.com/felixowens/ComfyUI-Pi-LLM.git
Restart and the node shows up under Pi. No dependencies beyond ComfyUI's own Python, no Pi CLI required, no downloads. Worth a look purely as a self-contained dynamic-prompt node - just remember the seed is yours to randomize.
Inputs (20)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt_template | STRING | — | |
| negative_template | STRING | — | |
| base_prompt | STRING | — | |
| base_negative | STRING | — | |
| likes | STRING | — | |
| dislikes | STRING | — | |
| characters | STRING | — | |
| clothing | STRING | — | |
| styles | STRING | — | |
| extra | STRING | — | |
| seed | INT | 00–18446744073709550000 | — |
| likes_count | INT | 10–64 | — |
| dislikes_count | INT | 10–64 | — |
| characters_count | INT | 10–64 | — |
| clothing_count | INT | 10–64 | — |
| styles_count | INT | 10–64 | — |
| extra_count | INT | 10–64 | — |
| separator | COMBO | comma | 3 options: comma, space, newline |
| dedupe | BOOLEAN | true | — |
| shuffle_positive | BOOLEAN | false | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| positive_prompt | STRING | — |
| negative_prompt | STRING | — |
| selected | STRING | — |