Nodes/ComfyUI String Tools/StringToolsBalancedChoice
ComfyUI Node

StringToolsBalancedChoice

A random picker that actually weights its inputs

By Taremin·Created 3 years ago·Updated 2 months ago· 3
StringToolsBalancedChoice
    • STRING
    seed0

    The fix for a subtle unfairness bug you didn't know you had

    StringToolsRandomChoice picks uniformly among its top-level inputs. That's fair until your alternatives aren't flat. Say one of your choice-node inputs is itself fed by another choice node holding five styles, while another input is a single fixed string. Uniformly picking among top-level inputs means the single string gets picked 50% of the time and each of the five styles only 10% - your "styles" branch is being starved. StringToolsBalancedChoice exists to fix exactly that. It looks inside the graph, counts how many leaf strings each branch actually contains, and weights accordingly - so every individual string ends up with roughly the same chance. That's the "balanced."

    How it works

    Same dynamic-slot mechanic as StringToolsRandomChoice: text_0, text_1, … slots that appear as you connect, a seed input (INT, default 0), PrimitiveNode refused, double-clicking a slot creates a StringToolsText. So far, identical.

    The difference is the weighting step. Before picking, the node walks the workflow graph backwards from each of its inputs. If an input comes from another StringToolsRandomChoice, StringToolsBalancedChoice, or their List variants, it recursively counts the total number of leaf strings reachable through that branch. Each top-level input gets a weight equal to that count; plain single strings get weight 1. Then it picks with random.choices using those weights, seeded by your seed.

    Net effect: a branch containing a 5-way choice node is five times more likely to be chosen than a single fixed string, which cancels out the unfairness. If none of your inputs connect to another choice node, every weight is 1 and it behaves exactly like StringToolsRandomChoice. The recursion handles nesting arbitrarily deep - a choice inside a choice inside a StringToolsStringsToList bundle still counts correctly.

    It also keeps a per-run tally of how often each input was actually selected, and there's a Debug toggle under ComfyUI's settings (StringTools.StringToolsBalancedChoice.debug) that prints each input's weight and selection count to the console. Handy when you're trying to convince yourself the weighting is doing what you think.

    The inputs that matter

    • seed (INT, default 0) - same determinism contract: same seed, same pick. Wire a StringToolsSeed in for a visible, bumpable number.
    • text_0, text_1, … - your alternatives, any of which may themselves be fed by another choice node.

    Output is a single STRING - the weighted pick.

    Installing it

    ComfyUI Manager: "Install Custom Nodes", search ComfyUI String Tools (repo Taremin/comfyui-string-tools), install, restart. Or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/Taremin/comfyui-string-tools
    

    Restart fully. No pip deps, no model files, MIT license, release 0.0.7. From Taremin, author of the well-liked WebUI Monaco Prompt editor.

    Gotchas

    • If you don't nest choice nodes, this node is pointless - it collapses to plain random choice. Use it when a tree of alternatives feeds your picker, not for a flat list.
    • The weighting needs the workflow metadata to be present, so it works in normal ComfyUI runs; if you're calling the API or hitting odd edge cases where the graph info is missing, it falls back to uniform choice rather than erroring.
    • The same-seed-same-pick rule still applies, but now it also depends on the weights, which depend on the graph structure. Re-wire a branch and the same seed will pick differently. That's correct behavior, just surprising the first time.
    • If you need explicit hand-tuned weights on a list, that's StringToolsBalancedChoiceList with its weight_list input.
    Categorystring-tools

    Inputs (1)

    NameTypeDefaultDescription
    seedINT00–18446744073709550000

    Outputs (1)

    NameTypeDescription
    STRINGSTRING