Nodes/ComfyUI-PromptRandomChoice/Runtime Prompt Random Choice
ComfyUI Node

Runtime Prompt Random Choice

Runtime Prompt Random Choice

By ruminar·Created 3 months ago·Updated about 15 hours ago· 3
Runtime Prompt Random Choice
    • selected_text
    • selected_text_safe
    options_texttown, girl's room, park, lake, flower garden, castle, fortress, forest, grasslands, sea, snowy landscape, mountain, flower field, starry sky, coffee shop,
    change_every1
    state_key

    You've got 100 generations queued for overnight and you want every run to roll a different background, time of day, or weather. ComfyUI's built-in {town|park|lake} syntax handles the rolling fine - but once that queue is submitted, you can't touch the pool. This node fixes exactly that: it's a "prompt gacha" (the author's own framing, README and all) that re-rolls on every execution and lets you edit the candidate list while the queue is still running. The next job picks up your latest edit without you re-submitting anything.

    It's the runtime version of the pack's plain Prompt Random Choice, part of the small ruminar/ComfyUI-PromptRandomChoice pack. It sits before your CLIP encoder and outputs a plain STRING, so only the chosen candidate flows downstream.

    How the "runtime" part actually works

    The trick is a server-side state store. As you type in the node's text box, the frontend pushes the text to ComfyUI's backend (/prompt_random_choice/runtime_candidate_state), which validates it and keeps the newest accepted revision, keyed per node. When a job executes, the Python side reads that accepted revision - not what's sitting in the widget - and picks from it. The node's title shows where you are: EDITING, SYNCING, then LIVE once the server has accepted your latest text.

    And it re-rolls every single run because its IS_CHANGED method returns NaN, the standard "always re-execute" idiom that opts a node out of ComfyUI's caching (the same trick every random picker and clock uses under the hood). That's also the one real cost: a node like this stays dirty forever, so don't put it behind anything expensive in a huge graph.

    The inputs that matter

    • options_text - your candidate list, one per line or |-separated (it accepts both, mixed). A candidate starting with # is commented out and never picked; one starting with ! is force-selected - but that's runtime-only, so don't expect it to work on the classic nodes.
    • change_every - default 1 re-rolls every run. Set it to 3 and the same pick is held for three consecutive runs, which is how you compare backgrounds without the noise of a fresh roll each time. Note it's not runtime-synced - the value from queue time wins.
    • state_key - leave it blank. The node builds its own key per instance; you'd only touch it to deliberately share a pool across nodes.

    Outputs

    • selected_text - the chosen string. If the literal () candidate wins, this is an empty string.
    • selected_text_safe - the same text scrubbed for filenames (/, spaces, commas, parens all replaced), or empty when nothing was chosen. Wire this into your Save Image filename and stop fighting invalid character in path errors.

    Why you'd reach for it over {a|b|c}

    Two reasons. First, the queue-editing thing - you genuinely cannot do that with ComfyUI's native syntax, which is resolved at CLIP-encode time and is invisible to you until the image comes out. Second, hygiene: because this node resolves the choice before the encoder and outputs one plain string, candidates that carry LoRA trigger words don't leak into every generation. (That's a string-level guarantee, not a "LoRA loads only sometimes" - the model still loads; only the text is kept clean.)

    The title shows the current pick - Rt: lake or Rt: (empty) (2/3) - so you can glance at the node and know which candidate produced the image in front of you.

    Installing

    ComfyUI Manager (search "Prompt Random Choice"), or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/ruminar/ComfyUI-PromptRandomChoice
    

    then restart ComfyUI. There's no requirements.txt, no model downloads, nothing heavy - it's pure Python plus a small frontend extension. GPL-3.0, same license family as ComfyUI itself.

    Where people get burned

    • Status stuck at EDITING or SYNC ERROR - the sync route didn't accept your latest text (say, you edited on a different browser tab). It falls back to the last accepted revision, not the raw widget contents, so your edit silently doesn't apply until the sync clears.
    • change_every ignores your edits mid-hold - a held pick keeps its old text until the counter runs out; edits only take effect at the next re-selection. If you want edits applied to the very next job, set change_every = 1.
    • ! is a literal character in the non-runtime nodes - the README is explicit about this, and it's the most common way people confuse the two variants.

    Wire selected_text into a string-join node (the README suggests kjnodes' Join String Multi) feeding your positive prompt, and it slots straight into an overnight batch.

    CategoryPrompt Random Choice

    Inputs (3)

    NameTypeDefaultDescription
    options_textSTRINGtown, girl's room, park, lake, flower garden, castle, fortress, forest, grasslands, sea, snowy landscape, mountain, flower field, starry sky, coffee shop,
    change_everyINT11–999999
    state_keySTRING

    Outputs (2)

    NameTypeDescription
    selected_textSTRING
    selected_text_safeSTRING