ann_router.backends.annoy_backend module

Annoy backend — read-only, memory-mapped, very lean.

Annoy (Spotify) builds a forest of random-projection trees, freezes it, and memory-maps it from disk — so many processes share one on-disk index at almost zero RAM cost. That frugality is the whole point: the router picks Annoy for a read-only corpus under a tight memory budget. The flip side is rigidity — once build is called the index is immutable, so add/remove genuinely cannot work and honestly raise NotSupported rather than pretending.

Consumes: annoy (optional, pip install 'ann-router[annoy]'). Produces: AnnoyIndex.

Author: Warith Harchaoui <warith.harchaoui@deraison.ai>

class ann_router.backends.annoy_backend.AnnoyIndex(dim, metric='cosine', **kwargs)[source]

Bases: ANNIndex

Annoy random-projection-forest index: build once, then read-only.

Because Annoy has no external-id concept, this adapter keeps its own position -> id table so search returns the caller’s ids. External ids must therefore be supplied at build time and are fixed thereafter.

Parameters:
  • dim (int) – Embedding dimensionality.

  • metric ({"cosine", "l2", "ip"}, optional) – Distance metric. Defaults to "cosine" (Annoy “angular”).

  • n_trees (int, optional) – Number of projection trees (more == better recall, larger index). Defaults to 50.

  • search_k (int, optional) – Nodes inspected at query time (-1 == Annoy’s n_trees * k default).

  • kwargs (object)

Examples

>>> AnnoyIndex.capabilities().supports_remove
False
add(vectors)[source]

Not supported — Annoy is frozen after build().

Parameters:

vectors (numpy.ndarray) – Shape (m, dim). Unused — always raises.

Raises:

NotSupported – Always; the forest is frozen after build().

Return type:

None

add_with_ids(vectors, ids)[source]

Not supported — Annoy is frozen after build().

Parameters:
  • vectors (numpy.ndarray) – Shape (m, dim). Unused — always raises.

  • ids (numpy.ndarray) – Shape (m,). Unused — always raises.

Raises:

NotSupported – Always; the forest is frozen after build().

Return type:

None

build(vectors, ids=None)[source]

Build and freeze the projection forest.

Parameters:
  • vectors (numpy.ndarray) – Shape (n, dim).

  • ids (numpy.ndarray, optional) – Shape (n,); defaults to range(n).

Returns:

self.

Return type:

AnnoyIndex

classmethod capabilities()[source]

Return the Annoy capability descriptor (frozen: no add/remove).

Return type:

Capabilities

classmethod is_available()[source]

Return True if annoy is importable.

Examples

>>> isinstance(AnnoyIndex.is_available(), bool)
True
Return type:

bool

load(path)[source]

Memory-map a forest written by save().

Parameters:

path (str) – Source path produced by save().

Returns:

self, populated from disk.

Return type:

AnnoyIndex

remove(ids)[source]

Not supported — Annoy cannot delete; rebuild without the ids.

Parameters:

ids (numpy.ndarray) – Shape (m,). Unused — always raises.

Raises:

NotSupported – Always; Annoy has no delete operation.

Return type:

None

save(path)[source]

Persist the forest and the id table.

The Annoy file itself has no room for external ids, so the id table is written alongside as <path>.ids.npy.

Parameters:

path (str) – Destination file path.

Return type:

None

search(queries, k)[source]

Return approximate top-k neighbours per query.

Parameters:
  • queries (numpy.ndarray) – Shape (q, dim).

  • k (int) – Neighbours per query.

Returns:

  • ids (numpy.ndarray) – Shape (q, k) neighbour ids.

  • distances (numpy.ndarray) – Shape (q, k) distances under the index metric.

Return type:

tuple[ndarray, ndarray]