Random Prompt {A|B|C} Selector
Random Prompt {A|B|C} Selector
- text
- seed
Type "a photo of {red|blue} {ball|box} on a table" and this node hands you a random one of the four combinations every run - red ball, blue box, all of them. That's the whole promise, and it's the same {A|B|C} wildcard idea A1111 users have known forever, done as a ComfyUI node you can drop mid-graph. It's from ComfyUI-M-Nodes (oMo.Studio), and it's the node that makes the pack's "master prompt" workflow tick: organize a giant prompt in a Multi Note, then let this thing shake the variations.
How it works
The backend does the expansion in two steps. First it regex-splits your text on every {...} group, splits each group on |, and builds every possible combination with itertools.product. {red|blue} {ball|box} becomes 4 complete strings, not 4 fragments. Then it picks one based on the mode you've set.
The four modes, straight from the dropdown:
- 🎲 new random - new seed,
random.choice, every execution. The default, and what you want when you're hunting. - 🔄 fix last seed (cycle text) - walks through the combination list in order, one per run, so you can see all the variations without duplicates.
- ✍️ custom seed (cycle text) - same cycling, but
custom_seedsets the seed you see in theseedoutput. - 🛑 fix last seed and text - freezes completely. Same text out every time, and the node stops forcing itself to rerun.
Inputs and outputs
text(multiline) - your template with{A|B|C}groups. The README's "master prompt" flow wires a Multi Note'scombined_textinto this via Convert text to input.mode- the four-way dropdown above.custom_seed- an INT, only meaningful in the custom-seed mode.
Outputs: text (STRING) - the resolved prompt, straight into a CLIP Text Encode - and seed (INT), which reports the seed of the run.
One honest caveat about that seed output: it's informational, not a replay key. In random mode the pick is random.choice, and in cycle modes the pick is sequential, not seed-derived - so you can log which seed produced which image, but you can't punch a seed back in and expect the same text. If you need true seed→result reproducibility, this isn't that node; grab one of the dedicated seed-managed randomizers. For batch exploration, it's great.
The always-rerun trick (and its cost)
Look under the hood and you'll see the node opts out of ComfyUI's execution cache: its IS_CHANGED returns NaN in every mode except the freeze one, which is the standard "run me every time" idiom. The side effect is that while it's live, everything downstream recomputes each run even if its own inputs didn't change. That's the intended behavior for a randomizer, but if your workflow suddenly feels like it's re-encoding every step, a permanently-dirty randomizer is a classic culprit - which is exactly why the freeze mode exists, and why it returns text instead of NaN (so it caches normally when you lock it).
Installing it
ComfyUI Manager: search "ComfyUI-M-Nodes". Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/oMoStudio/ComfyUI-M-Nodes
Restart after. No requirements.txt, no model downloads, MIT licensed - pure Python string handling, about as safe an install as the ecosystem offers.
Where people get burned
- Blank groups are the catch. The parser splits on
|literally, so a stray|or an empty option ({red|}) creates an empty combination. Keep your options clean. - Freeze mode hides in plain sight. If your variations have "stopped working," check that you're not stuck in 🛑 fix last seed and text - it does exactly what it says.
- Nested braces won't nest. It's one level of
{A|B|C}; there's no{A|{B|C}}recursion, so don't build syntax you'd expect from a full wildcard system.
For quick randomized prompt exploration in ComfyUI, this is about as simple as it gets - and paired with the pack's Multi Note, it's a genuinely nice way to run structured variations.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| text | STRING | Photo of {red|blue} {ball|box} on table | — |
| mode | COMBO | 🎲 new random | 4 options: 🎲 new random, 🔄 fix last seed (cycle text), ✍️ custom seed (cycle text), 🛑 fix last seed and text |
| custom_seed | INT | 00–18446744073709550000 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| text | STRING | — |
| seed | INT | — |