Nodes/System One (Jev / Laya)/System One Image Check
ComfyUI Node

System One Image Check

Kill the Bad Apples Before They Get Saved

By dante01yoon·Created 22 days ago·Updated 22 days ago· 6
System One Image Check
  • backend
  • images
  • passed
  • passed_count
  • report
◄instructions—►
◄reject_whenyes►
◄threshold0.50►
◄context►
◄true_criteria►
◄false_criteria►

Four images come out of the sampler. One has five apples instead of three and nobody notices until it's posted. System One Image Check asks a yes/no question about every image in the batch and drops the ones that fail, so what reaches your Save node is only the good stuff.

It's the QA half of the pack's 0.2.0 release, and it's the one node here that reads the pixels rather than your prompt - the pack's only provider that can see is Cloudflare's Clef, so a Clef backend is mandatory.

How it works

This is the VLM-as-judge pattern: ask a vision-language model a narrow question about a picture and act on the probability. The node builds a yes/no (noul) question from your instructions and asks it about each image separately - one API call per image, not one call for the batch. Each call returns a probability; anything crossing threshold is judged according to reject_when and the survivors are what come out.

Two mechanical details that matter more than they look:

The images are not what Clef sees. They're converted to JPEG at quality 85 and downscaled to a long side of 512px, stepping down through 384/320/256 until the request fits Cloudflare's 150 KB budget. What you get back on passed is your original full-resolution tensor - the downscale is only ever for the request.

If nothing passes, the graph stops there. The node emits an execution blocker instead of an empty batch, so downstream nodes simply never run and nothing gets saved. That's deliberate, and it's the difference between "QA'd" and "silently wrote zero files".

Inputs and outputs

images is the batch off your sampler or VAEDecode. Beyond that, the three you'll actually set:

  • backend - a Clef provider (clef-flash or clef).
  • instructions - a yes/no question about one image. The tooltip's own example is Does the image show malformed hands?. Keep it binary; this node cannot answer "how many".
  • reject_when - yes or no, which answer drops the image. Default yes, meaning "high probability that the instruction is true" = reject.

Then threshold (default 0.5) and, optionally, context (usually your generation prompt, sent as the state's prompt), true_criteria and false_criteria to spell out what the two answers should mean. Give both criteria or neither - the node raises Give both true_criteria and false_criteria, or neither.

Outputs: passed (IMAGE, the survivors), passed_count (INT), and report (STRING, JSON with every per-image answer and latency). After a run, the node shows a bar per image - image 3 ################.... 0.97 PASS - which is genuinely the fastest way to see whether your question is doing anything.

Does it work?

On the README's own test - SDXL Turbo rendering "exactly three red apples on a white table" - Clef-flash scored the three-apple images 0.96 to 0.97 and the four-apple one 0.03. Counting is exactly the kind of thing a small VLM is good at. Note the mirror test in the README too: asked whether a photo of a knight matched "a watercolor cat", the model said 0.004 with the image attached and 0.90 with no image at all. It's reading the picture, not your prompt.

Where it gets mushy: multi-subject attribution. Every VLM in this family mixes up who's wearing what when two characters share a frame - that's the standing weakness of every captioner and judge, not a bug in this node. Ask about hands, object counts, gross anatomy, visible text, and obvious style mismatches. Don't ask it to referee "is this the better composition".

The license angle nobody mentions

If you're generating on FLUX.1 [dev], Section 2(e) of its license literally requires you to run content filters or review output before distributing. Krea 2 goes further and requires you to implement content filter measures. A node that greps every generated image for a specific failure before it hits disk is the least theatrical way to satisfy that. Put instructions on the thing your base model actually botches, and reject_when: yes.

Install and cost

cd ComfyUI/custom_nodes
git clone https://github.com/dante01yoon/ComfyUI-SystemOne
pip install -r ComfyUI-SystemOne/requirements.txt
export CLOUDFLARE_ACCOUNT_ID=...
export CLOUDFLARE_API_TOKEN=...   # Workers AI permission

Then restart ComfyUI - the keys are read from the environment, and setting them after the server is up does nothing.

Cost is per image, per call, and context counts toward input tokens: a batch of four is four calls at 0.3–0.9 seconds each, at roughly $0.09 per million input tokens on clef-flash. Cheap for four candidates, less cheap if you point it at a 500-image archive. Because it's an API call, your images leave the machine - for a QA gate that's usually the point, but it is the tradeoff, and an API-key-holding node is worth reading before you run it, same as any pack.

Getting burned

  • Asking a Laya or Jev backend to do this gets you cannot see images; use a Clef backend. instantly. That error is the correct one.
  • Expecting the count semantics: this is one yes/no per image. If you want ranked comparison instead, that's System One Pick Best Image.
  • Setting reject_when backwards. You can verify the polarity in one run from the on-node bars before you wire it to a Save node - do that, because "QA gate that rejects the good ones" is a silent, expensive mistake.
CategorySystemOne

Inputs (8)

NameTypeDefaultDescription
backendSYSTEMONE_BACKENDUse a Clef provider; only Clef can see images.
imagesIMAGE—
instructionsSTRINGA yes/no question about one image, e.g. 'Does the image show malformed hands?'
reject_whenCOMBOyesWhich answer drops the image.
thresholdFLOAT0.500–1—
contextoptSTRINGUsually the generation prompt. Sent as the state's 'prompt'.
true_criteriaoptSTRING—
false_criteriaoptSTRING—

Outputs (3)

NameTypeDescription
passedIMAGE—
passed_countINT—
reportSTRING—