Nodes/System One (Jev / Laya)/System One Choice
ComfyUI Node

System One Choice

Let the Model Pick a Branch — With a Chicken-Out Option

By dante01yoon·Created 22 days ago·Updated 22 days ago· 6
System One Choice
  • backend
  • choice
  • confidence
  • confident
  • report
◄state—►
◄instructions—►
◄options—►
◄min_confidence0.00►
◄fallback►

You write one prompt, and the picture that comes out is anime. You meant watercolor. System One Choice is the node that reads the prompt first and tells the graph what it's actually looking at, so the sampler can be pointed at the right style before it wastes a run.

It's also the cleanest example of the plumbing doc's thesis in a real pack: ComfyUI stops being a pipeline and becomes a small program, and a natural-language judgment is now a value you can wire.

How it works

The node takes your text, your question, and a list of options, and sends the backend a typed choice question - instructions plus a criteria map of label → description. The model answers with one label, a confidence, and a full probability spread over every option. That last part is the useful bit: you get to see, on the node itself, that it thought "anime 0.65, photo 0.20" rather than just being told which one won.

Then the gate: if confidence lands below min_confidence, the node returns your fallback instead and sets confident to false. That's the whole design goal - an unsure model never picks a branch on a coin flip.

One detail from the source that isn't obvious from the README: if you leave fallback empty, an unconfident answer passes through anyway. The fallback only exists if you fill it in.

Inputs and outputs

  • backend - from System One Backend. Required.
  • state - what the model reads. Usually your prompt. If the text parses as a JSON object or array it gets sent as structured state instead, which is how you'd hand it a dict of shot parameters.
  • instructions - the question. Be specific and narrow; vague questions get vague confidences.
  • options - one per line, label: description or just label.
  • min_confidence - 0 to 1, default 0.
  • fallback - the string returned when it isn't confident.

Outputs: choice (STRING), confidence (FLOAT), confident (BOOLEAN), and report (STRING) - JSON with the question, the raw answer, the backend name, and the latency, which is what you want when a run does something weird at 2am.

Wiring it

choice almost never goes straight into a sampler. It goes into a System One Map, which turns the label into prompt text, and that text gets appended to your positive prompt. The confidence output is the one people forget - put it on a Display or a note node while you're tuning, because on Laya it's the number that tells you whether the routing is real.

Want the side-by-side demo from the README? Two Backend nodes, one on laya and one on jev, feeding two Choice nodes with identical settings. Same prompt, two answers, no rewiring when you switch.

The two traps

Option parsing. At least two options, one per line, and the label is everything before the first colon. A label with a colon in it gets silently split at the colon and the tail becomes the description. Duplicate labels raise Duplicate option label: 'photo'. If you see that error, you probably fat-fingered a line break.

Confidence, on Laya. This is the number the whole node hinges on, and the README's own tests are the cautionary tale: on prompts that imply a style through a reference rather than naming it ("in the style of Studio Ghibli", "loose wet-on-wet brushwork"), Laya's top answer was right 7 times out of 8 but came in under 0.5 confidence on four of them. With min_confidence at 0.5 the node routed 3 of 8 to the intended style and sent the rest to photo. Those same 8 prompts went to Jev, which answered all 8 correctly at 0.99+. So: local and free for prompts that say the word "watercolor", hosted when the style is implied. Laya's confidence is also explicitly uncalibrated, so tune min_confidence on your own prompts rather than trusting a magic number from a README.

Also worth knowing: Laya reads at most 512 tokens of your state, and all your option labels share a 192-token budget. Long descriptions of six options will get truncated somewhere you can't see.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/dante01yoon/ComfyUI-SystemOne
pip install -r ComfyUI-SystemOne/requirements.txt

Or search System One in ComfyUI Manager. The requirements file is a single line (laya>=0.3.24); Jev needs TYPESAFE_API_KEY exported in the shell that launches ComfyUI, and Clef needs CLOUDFLARE_ACCOUNT_ID plus CLOUDFLARE_API_TOKEN.

Why you'd actually use this

The README's demo routes style, which is the obvious use. The less obvious ones are all the same shape: which upscaler should this prompt get, is this a photo or an illustration, does this description belong in the "portrait" bucket or the "landscape" bucket, which of five LoRA-trigger styles is being asked for. Anything where you currently eyeball a prompt and adjust a widget by hand is a candidate - with min_confidence set so the model can hand the decision back to a sane default when it doesn't know.

CategorySystemOne

Inputs (6)

NameTypeDefaultDescription
backendSYSTEMONE_BACKEND—
stateSTRINGWhat the model looks at: plain text, or a JSON object/array.
instructionsSTRINGThe question to answer about the state.
optionsSTRINGOne option per line: 'label: description' or just 'label'.
min_confidenceFLOAT0.000–1—
fallbackSTRINGReturned instead of the choice when confidence is below min_confidence.

Outputs (4)

NameTypeDescription
choiceSTRING—
confidenceFLOAT—
confidentBOOLEAN—
reportSTRING—