Image Text Pair Selector
Build a library of image+prompt pairs and pull one per run
- image
- text
Wildcards are great at varying text and useless at carrying a picture along with it. If your variety lives in a pair - a style reference plus the prompt that describes it, a character sheet plus their caption, a pose image plus the direction - you want this node: you wire in as many pairs as you like, and each run it hands you one image and one text that belong together.
What it is, and why it exists
The pattern it serves is the "walk away and come back pleasantly surprised" loop that keeps showing up in batch-generation threads. Someone queues fifty generations and wants framing, subject and styling to wander instead of being frozen by one prompt and one reference. The usual answers are Impact Pack's __wildcard__ syntax or the {brown|blonde|black} bracket trick, and both are fine - until the variation needs to be visual. A wildcard can't pick a reference image; it can only pick words. This node picks both, from the same row.
It's the sibling of Any Input Selector in the same pack, but where that one is deliberately type-erased, this one is strictly typed: IMAGE in, IMAGE and STRING out.
How it works
Each row on the node is a pair of sockets: an image_N (IMAGE) and a text_N (STRING). Rows are created dynamically as you fill them - connect a pair and the frontend adds the next one, and a row with only half a pair wired doesn't count as a pair at all, so you can leave gaps while you're building the library.
At execution it collects the complete pairs in index order and reads selected_index:
1for the first complete pair,2for the second, and so on.- Anything out of range, including the default
-1, makes it pick a random pair usingsecrets.randbelow. - With no complete pair it stops with
Connect an image/text pair before executing Image Text Pair Selector.- that's the author's own error text, and it's the message you'll see if you wired the image and forgot the text.
Inputs and outputs that matter
image_N/text_N- your library. Both sides of a row must be wired for the row to exist.selected_index(INT, default-1) --1means "surprise me, one pair per run". Set a number to lock the workflow to one entry while you tune.image(IMAGE) andtext(STRING) - the two outputs. The image goes wherever you'd put a Load Image result:VAE Encodefor img2img, an IPAdapter or reference node for style, whatever your loop uses. The text goes into a CLIP Text Encode, exactly where a prompt went before.
Note that whatever you wired to image_N comes out intact - if that upstream node emits a batch of eight images, you get the batch of eight, not one frame. And the string you get is precisely what's on the text_N input, so if you want the caption to come from a wildcard or an LLM, wire that into the text side and let the node do the pairing.
Installing it
Manager, search ComfyUI Useful Stuff Nodes; or:
cd ComfyUI/custom_nodes
git clone https://github.com/ArtemKo7v/ComfyUI-UsefulStuffNodes
# restart ComfyUI, then reload the browser page
The reload matters - the growing pairs are a frontend script, not part of the Python class. No pip dependencies, no models to download; the pack declares empty dependencies and uses only the standard library.
Common issues
"Connect an image/text pair before executing". You wired an image and left the text row empty (or vice versa). Half a pair is not a pair.
It reruns every queue, and so does everything downstream. Deliberate - the node reports itself as always-changed so you actually get a new pair per run. That's what makes the auto-queue variation loop work, and it's also why a graph with one of these in it feels slower than it should: nothing behind it stays cached. Build the rest of the graph first, add the selector last.
Nothing changes between runs. Two candidates: you set selected_index to a fixed value and forgot, or you're looking at a cached downstream node - a Save Image node always executes, but a decode feeding a Preview that you didn't re-queue may not. Pin the index, verify it works, then set it back to -1.
Mixed junk on the sockets. The outputs are typed, so a MASK wired into image_N won't link at all - that's the friendly failure mode, and one reason to prefer this over a wildcard-type switch when your inputs are already images and strings.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| selected_indexopt | INT | -1 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| text | STRING | — |