KIE • Consistency Board
Judge the face yourself, no fake score attached
- approved_reference
- candidate_1
- candidate_2
- candidate_3
- candidate_4
- comparison_board
- saved_files_json
What it is
Character consistency is the problem this whole corner of the workflow exists to fight, and it has never been "solved" - it got rerouted into "generate once, then edit from the reference." Which means the decision you make most often is which of these four candidates looks most like my approved reference. KIE • Consistency Board is a node for making that call with your eyes, and it deliberately refuses to make it for you.
No identity score, no embedding distance, no confidence number. It renders a fixed-width board - approved reference on the left, up to four candidates beside it - and saves it as an image so you can come back to the decision in three weeks.
How it works
It's pure local Pillow and numpy; no API call, no credits. Each card is 300×390 with a 320-pixel-high photo area, and images are contain-fitted so nothing is cropped or stretched - which matters, because a stretched face is exactly the kind of thing that fools a human comparing two thumbnails. The reference card is captioned APPROVED REFERENCE in amber, candidates in light grey with your label (truncated to 30 characters).
The board is then pushed through the pack's persistent preview image node, which writes it into ComfyUI's output folder under KIE-Consistency/Comparison and returns the file records. That's why the node's description says the board is persistent: a plain PreviewImage would leave you with a temp file that vanishes on restart.
You get two outputs: comparison_board (the IMAGE itself, if you want to feed it onward, annotate it, or stack boards) and saved_files_json (the records).
Wiring the inputs
approved_reference- the image you already decided is the character. It's usually the same file you saved into a Character Pack orKIE • Save Element.candidate_1pluslabel_1are required, so a board is always at least a two-up.candidate_2..4and their labels are optional; connect as many as you have.
The pack's templates/compare-character-consistency.json wires three LoadImage nodes into one of these, which is the intended shape. If you're comparing outputs from a generation, drop in the image output of two paid nodes instead - but note every connected node upstream still executes.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/felipederosilva/ComfyUI-KIE-Nodes-Next
python -m pip install -r ComfyUI-KIE-Nodes-Next/requirements.txt
Pillow and numpy do the rendering, and the save path needs ComfyUI's own SaveImage machinery available (it is, in any normal install). No key needed for this node.
Where people get burned
- Feeding it a batch. Each socket must be exactly one RGB/RGBA image. If your loader or generator emits four images on one wire, you'll get "
candidate_1must be one RGB/RGBA IMAGE." Use an image-picker/split node upstream. - Labels as notes. The caption is capped at 30 characters, so
take 2 - the one with the shorter hairgets chopped. Keep labels short and put detail in a note node. - Trusting it as an identity verdict. It's a contact sheet. If two candidates look alike at 300 px, open both full size before you commit - that's the node's whole philosophy, and it's a good one.
- Expecting it to fix drift. It shows drift. The fix is upstream: a reference-image-capable edit model, or a LoRA, depending on how many times you'll need this character.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| approved_reference | IMAGE | — | |
| candidate_1 | IMAGE | — | |
| label_1 | STRING | TAKE 1 | — |
| candidate_2opt | IMAGE | — | |
| label_2opt | STRING | TAKE 2 | — |
| candidate_3opt | IMAGE | — | |
| label_3opt | STRING | TAKE 3 | — |
| candidate_4opt | IMAGE | — | |
| label_4opt | STRING | TAKE 4 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| comparison_board | IMAGE | — |
| saved_files_json | STRING | — |