/v1/embed independently on two images, then
returns their cosine similarity and a boolean match decision against
COMPARE_THRESHOLD.
Request
file
required
First image, as
multipart/form-data. Same constraints as /v1/embed’s
image field.file
required
Second image, same constraints.
Response
float
Cosine similarity between the two embeddings, in
[-1, 1] (in practice,
real face pairs from this model land roughly in [0, 0.7] — see
Models → Similarity threshold for the
actual observed distribution).boolean
similarity >= threshold.float
The threshold that was actually used for this request (echoes
COMPARE_THRESHOLD, so clients don’t have to know the server-side
default out of band).object
{ det_score, bbox } for the face found in image1 — same shape as
/v1/embed’s top-level fields.object
Same, for
image2.Errors
Same as/v1/embed, but every error
response includes a field key ("image1" or "image2") identifying
which upload failed — including missing_field_image1_or_image2 if either
form field is absent entirely.
The two images are processed sequentially within one worker-pool job,
not in parallel — the simplest correct implementation, not the fastest
possible one. If
/v1/compare latency becomes a bottleneck under load,
this is the first thing to split into two parallel enqueue() calls
joined by a result-combiner (see the NOTE comment in
CompareController.cpp).