⚗ Alchemica · Face match (identity score) [1.0, use Alchemica Face Match (ArcFace identity score)]
A real identity score instead of squinting at two faces
- riferimento
- immagine
- similarita
- accettata
- report
Everyone who generates the same character over and over has the same problem: eventually you can't tell whether a render is off, or you've just been looking at it too long. This node gives you a number.
What it is
AlchemicaVolto compares a reference photo against generated faces and returns a cosine similarity between their ArcFace embeddings - the same measure face-recognition systems use, computed by insightface. Not a vibe, not a perceptual hash: the geometry of the face as a recognition network sees it.
The workflow it's built for is generate → measure → keep. Run a batch, check the score, throw out the ones that drift, and stop trusting your eyes at 2am. It's also the honest way to answer "did this LoRA actually hold the likeness" and "which of these three seeds is closest to her".
It's a 1.0 node: Italian socket names, appearing as "⚗ Alchemica · Face match (identity score) [1.0, use Alchemica Face Match (ArcFace identity score)]". The English twin, AlchemicaFaceMatch, is the same code with standard names (reference, image, threshold, model_name → similarity, accepted, report). Use the twin for new graphs; this one keeps old workflows opening.
How to read the score
This is the part worth memorising, because the number means nothing without a scale. For buffalo_l on in-the-wild photos and AI renders: ≥ 0.60 very likely the same person; 0.45–0.60 same person in another pose, light or age; 0.30–0.45 doubtful, family resemblance; below 0.30 a different person. Two sentinel values exist so the node can't lie to you: −1 means no face was found, and −2 means the check didn't run at all - insightface or its model is missing, and the report says why.
It also never raises. If the face pipeline isn't available the score is −2 and the workflow carries on, which is deliberate: a graph whose job is to make images shouldn't die because a measuring tool is missing.
Inputs and outputs
riferimento(IMAGE) - the reference photo. Only the first image is used, and it's cached by shape and pixel statistics, so re-queueing doesn't re-embed it.immagine(IMAGE) - the generated image or batch to check.soglia(FLOAT) - the threshold for accepting a match, default 0.45. 0.45 is "same person, different pose or lighting"; 0.60 is strict.modello-buffalo_l(the default) orantelopev2, the more accurate pack.
Outputs: similarita (FLOAT), accettata (BOOLEAN) and report (STRING). Two details behind them. First, accettata is simply similarity >= soglia - set the threshold to what your workflow can tolerate and let the boolean drive a filter. Second, on a batch the returned score is the minimum across the images, so one bad frame fails the whole batch. That's the right default for "keep only what holds", and worth knowing before you wonder why a batch of eight scored 0.41.
Everything runs on the CPU via onnxruntime, so it never competes with the image model for VRAM. It only ever looks at the largest face in each image.
Installing it
ComfyUI Manager, search "AlchemicaSampler", or:
cd ComfyUI/custom_nodes
git clone https://github.com/Nessuno76/ComfyUI-AlchemicaSampler
# restart the ComfyUI server, not just the page
The pack has no Python dependencies of its own, but this node needs insightface plus onnxruntime. That library earned its terrible reputation - for three years there was no wheel for current Pythons and Windows users needed Visual Studio build tools to compile it. Version 1.0 (May 2026) dropped the C++ build requirement, so an up-to-date install is far less of an ordeal. The model packs are separate: buffalo_l (~326MB) downloads itself into ~/.insightface or a models/insightface folder, while antelopev2 has to be fetched by hand from its own link and unzipped under ~/.insightface/models/. That manual step is a classic cause of "why is my score always −2".
Worth knowing if you're commercial: insightface's code is MIT, but the models are non-commercial research weights.
Where it goes wrong
- Every score is −2. insightface isn't installed, or the model folder is missing. The report names the exception.
- Every score is −1. Detection ran and found no face. Frame the subject's face, and avoid extreme profiles.
- Stylised or heavily filtered faces score low. It's measuring embedding distance on rendered pixels - a very illustrated face can score 0.35 and still read as the right character to a human. Treat the thresholds as calibrated for photographic renders.
- A good likeness scores 0.5 and you expected 0.9. That's the scale working as documented; 0.60 is an unusually tight match, not a passing grade.
- You're using it to create consistency. Wrong direction. This measures identity; it doesn't enforce it. For holding a character across generations, the tools that do are the identity-conditioning ones - this is the scoreboard, not the engine.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| riferimento | IMAGE | The reference photo (only the first image is used) | |
| immagine | IMAGE | The generated image(s) to check | |
| soglia | FLOAT | 0.450–1 | Minimum similarity to accept. 0.45 = same person in another pose/light; 0.60 = very strict |
| modello | COMBO | buffalo_l | 2 options: buffalo_l, antelopev2 |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| similarita | FLOAT | — |
| accettata | BOOLEAN | — |
| report | STRING | — |