Save for Judge
The front door to a human curation queue for your LoRA dataset
- images
The name is a lie: Save for Judge (class ImageJudge_Save) doesn't judge a thing. It saves your images into a "pending" pile and stamps "judgment": "pending" into a sidecar JSON next to each one. The actual OK/NG triage happens in a web UI that ships in the same pack - and that split is the whole design. Think of this node as the front door to a human-run curation pipeline, built for the part of LoRA training everyone keeps rediscovering the hard way: dataset curation beats every training knob, and a good dataset is still sorted by eyeballs, not by an auto-filter.
You wire it to the end of your workflow where SaveImage would go, generate a big batch of character or style variations, then work through them in the judge UI pressing O for keep and 1–7 for different kinds of reject. The keepers land in a folder that's basically your dataset, captions already written and formatted for training. It slots into the exact spot where people usually fall back to renaming files by hand.
What it actually writes
Drop it in and every image becomes a three-file trio in output/judge/<dataset>/pending/, named with a YYYYMMDD_HHMMSS_NNN timestamp stem:
.png- the image, with the fullpromptandworkflowJSON embedded as PNGtEXtchunks. That's the ComfyUI convention: drag the file back onto the canvas and the whole generation graph rebuilds, seed and all. The image is the project file, and this pack preserves that instead of flattening it away..txt- a kohya-compatible caption intrigger_word, captionform, ready to sit next to the image for most trainers..json- the metadata record: dataset, caption, timestamp, and the judgment state (judgment,judged_at,comment,ng_reason) that the judge UI reads and updates.
When you hit judge, the whole trio moves from pending/ into ok/ or ng/. Nothing is regenerated - just files being moved between folders. Simple, auditable, and you can sort a thousand generated images in an afternoon.
The inputs that matter
Only four, and you'll set most of them once:
images(IMAGE) - your generated tensor. Wire the output of your sampler or whatever node feeds your preview.dataset_name(defaultmy_dataset) - becomes a folder name underoutput/judge/. This is your grouping key, so name it like a dataset, not a run.caption(optional, multiline) - the natural-language description, e.g. "1girl, white dress, outdoor cafe, golden hour". Multi-line supported.trigger_word(optional) - your rare-token trigger, written in front of the caption automatically.
The last two combine into the .txt as "trigger_word, caption". Leave the caption empty and you just get the trigger word alone. Note it's one static caption applied to the whole batch - for per-image captions you'll want to vary the caption input per run or edit the text files afterward.
It has no outputs - it's an output node that terminates the graph, and it previews the saved PNGs in ComfyUI's results panel for convenience.
The judging UI (the other half)
This node exists to feed it. While ComfyUI is running, open http://127.0.0.1:8188/imagejudge/ui in a second tab (use your ComfyUI port if it isn't 8188), or hit the green Image Judge button at the bottom-right of the canvas. Then it's a keyboard-driven sorting session: O = OK, 1–7 = NG with a specific reason (character mismatch, technical breakage, pose/composition, etc.), arrow keys to move. There's also an "All" mode that aggregates pending images from every dataset and routes them into one target dataset as you judge - handy when your images are scattered across several workflow runs.
Install
No models to download, no heavy deps - requirements are just Pillow and numpy, both already inside ComfyUI. So:
cd <ComfyUI>/custom_nodes
git clone https://github.com/o-ankomochi-o/comfyui-image-judge.git
Restart ComfyUI and Save for Judge appears under the ImageJudge category. ComfyUI Manager support is waiting on the Registry listing - the repo already carries registry metadata, so it may show up in Manager soon, but the clone is the reliable path today.
Gotchas
- The node doesn't auto-evaluate. If you were hoping for a CLIP-score filter, this isn't it - and for LoRA datasets that's honestly fine; automatic quality filters burn you more than they help.
- The NG categories are hardcoded Japanese strings (キャラ違い, 技術破綻, …) and the server validates against them. The UI leans Japanese-first; your own rejection reasons mean editing source.
dataset_nameis a path component - names with slashes or..get rejected. Keep it simple.- It's v0.1 alpha. The kohya_ss special export isn't implemented yet; OK images accumulate as plain PNG+txt+json trios in
ok/, which you feed to your trainer (ai-toolkit, kohya, OneTrainer) directly or after a small conversion script.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| dataset_name | STRING | my_dataset | — |
| captionopt | STRING | — | |
| trigger_wordopt | STRING | — |
Outputs (0)
No outputs