Skip to content

Token API: server-side kNN /similarity endpoint + concurrency guard (don't starve live users)#1648

Open
JasonWildMe wants to merge 1 commit into
mainfrom
feature/similarity-endpoint
Open

Token API: server-side kNN /similarity endpoint + concurrency guard (don't starve live users)#1648
JasonWildMe wants to merge 1 commit into
mainfrom
feature/similarity-endpoint

Conversation

@JasonWildMe

Copy link
Copy Markdown
Collaborator

The headline of the API-feedback series (MMF/Sharkbook): a server-side k-NN re-ID endpoint that kills the critical scaling bottleneck (no more downloading every 2,152-float vector — a 200-record page took ~176s), plus a concurrency guard so a high-volume agent can do unlimited work without crowding out interactive Wildbook users.

POST /api/v3/similarity (token, read-only)

Given an annotation the caller can see, returns the most visually similar annotations with scores and no vectors — surfacing Wildbook's existing OpenSearch kNN.

  • Filtered ANN: ACL + same viewpoint + method/methodVersion + optional taxonomy/locationId scope + self/encounter exclusion all go inside the native knn.filter (an outer bool.filter would post-filter ANN results → recall loss/leak). Non-admins additionally get an outer ACL wrap (defense in depth). Filtered nested kNN was verified empirically on the live cluster (knn.filter honors nested and parent fields).
  • Never returns vectors (_source excludes embeddings + defensive remove()).
  • No-oracle visibility gate on the query annotation (not-visible == not-found == 404).
  • Deterministic single-embedding resolution; viewpoint required; k 1–100.
  • Re-ID metric wildbook_token_reid_queries_total — this is user-run identification compute on our servers, kept distinct from the pipeline wildbook_identification_tasks* gauges.

Concurrency guard (TokenApiConcurrency) — "unlimited volume, no interference"

Per-instance semaphores cap how many token requests run at once (not total volume); excess gets 429 + Retry-After. Wired into all token endpoints: a tight SIMILARITY pool (default 2) for the heavy kNN, a GENERAL pool (default 8) for search + media/resolve. Only token requests are throttled — interactive session/UI traffic is never. AutoCloseable permits (no leak/over-release, released on every path incl. exceptions), best-effort inflight/rejected Prometheus gauges. Sizes via OpenSearch.properties (restart to resize).

Request-scoped PITs (OpenSearch.queryPitPrivate)

The similarity endpoint uses a private point-in-time and never touches the shared static PIT_CACHE, so a token call can't delete or race a PIT a live UI search is using.

Process / tests

Both specs Codex design-reviewed before coding; code Codex-reviewed (3 rounds, converged). 46 tests across the touched suites: TokenApiConcurrencyTest (3), SimilarityApiTest (9: auth/validation, embeddings-stripped, ambiguous-embedding 400, filtered-ANN shape + self-exclusion, no-oracle 404, 429), plus GENERAL-guard 429 tests on MediaResolveApi/SearchApi.

Merge notes / fast-follows

🤖 Generated with Claude Code

…st-scoped PITs

Addresses the critical scaling bottleneck from live API feedback (downloading every
2152-float vector to find matches) AND the operator requirement that high-volume
agents must not interfere with interactive Wildbook use.

POST /api/v3/similarity (token, read-only): server-side k-NN re-identification —
given an annotation the caller can see, return the most similar annotations with
scores, WITHOUT shipping any vectors. Surfaces Wildbook's existing OpenSearch kNN.
- Filtered ANN: ACL + same viewpoint + method/version + optional taxonomy/locationId
  scope + self/encounter exclusion all go INSIDE the native knn.filter (an outer
  bool.filter would post-filter ANN results). For non-admin, also an outer ACL wrap
  (defense in depth). Filtered nested kNN verified empirically on the deployed cluster.
- Never returns vectors (_source excludes embeddings + defensive remove()).
- No-oracle visibility gate on the query annotation (not-visible == not-found == 404).
- Deterministic single-embedding resolution; viewpoint required (400 if null); k 1-100.
- Re-ID metric wildbook_token_reid_queries_total, distinct from pipeline ID gauges.

Concurrency guard (TokenApiConcurrency): per-instance semaphores bound how many token
requests run at once so volume is unlimited but live users aren't starved. Wired into
ALL token endpoints: SIMILARITY pool (default 2) for the heavy kNN; GENERAL pool
(default 8) for search + media/resolve. AutoCloseable permit (no leak/over-release);
best-effort metrics; instant 429 + Retry-After; inflight + rejected Prometheus gauges.
Sizes via OpenSearch.properties (restart to resize).

Request-scoped PITs (OpenSearch.queryPitPrivate): the similarity endpoint never
touches the shared static PIT_CACHE, so a token call can't delete/race a PIT an
interactive UI search is using. (Migrating existing token search/media-resolve to
private PITs is the recommended fast-follow.)

Specs Codex design-reviewed before implementation; code Codex-reviewed. Tests (46
across the touched suites): TokenApiConcurrencyTest (3); SimilarityApiTest (9: auth/
validation, embeddings-stripped, ambiguous-embedding 400, filtered-ANN shape +
self-exclusion, no-oracle 404, 429 guard); MediaResolveApi + SearchApi GENERAL-guard
429 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@JasonWildMe JasonWildMe force-pushed the feature/similarity-endpoint branch from f8db3e3 to d93749c Compare June 29, 2026 17:27
@JasonWildMe JasonWildMe self-assigned this Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant