ann_router.backends.qdrant_backend module

Qdrant backend — persistent HNSW with first-class metadata filtering.

Qdrant is the router’s answer to persistence + metadata filters: it stores an HNSW index plus a JSON payload per point and filters by that payload at query time, and it survives restarts (embedded on-disk, or a remote server). When a workload needs “give me the nearest vectors where lang == 'fr'”, the in-memory engines cannot help and the policy routes here. This adapter defaults to the embedded in-memory/on-disk client so tests need no running server, and exposes a search_filter extension for the payload path.

Consumes: qdrant-client (optional, pip install 'ann-router[qdrant]'). Produces: QdrantIndex.

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

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

Bases: ANNIndex

Qdrant collection wrapper (embedded by default) with payload filtering.

Parameters:
  • dim (int) – Embedding dimensionality.

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

  • location (str, optional) – ":memory:" (default, embedded), a directory path (embedded on-disk), or a URL for a remote server.

  • collection (str, optional) – Collection name. Defaults to "ann_router".

  • kwargs (object)

Examples

>>> QdrantIndex.capabilities().supports_filter
True
add(vectors)[source]

Append vectors with the next contiguous ids.

Parameters:

vectors (numpy.ndarray) – Shape (m, dim).

Return type:

None

add_with_ids(vectors, ids)[source]

Append vectors with explicit ids.

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

  • ids (numpy.ndarray) – Shape (m,) integer ids.

Return type:

None

build(vectors, ids=None, payloads=None)[source]

Create the collection and upsert the initial corpus.

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

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

  • payloads (list of dict, optional) – Per-point metadata for the filtering path.

Return type:

QdrantIndex

classmethod capabilities()[source]

Return the Qdrant capability descriptor (persistent + filterable).

Return type:

Capabilities

classmethod is_available()[source]

Return True if qdrant-client is importable.

Examples

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

bool

load(path)[source]

Reconnect to an on-disk collection at path.

Parameters:

path (str) – The on-disk location to reconnect to.

Returns:

self, reconnected.

Return type:

QdrantIndex

remove(ids)[source]

Delete points by id.

Parameters:

ids (numpy.ndarray) – Shape (m,) integer ids to drop.

Return type:

None

save(path)[source]

No-op for embedded on-disk / remote collections (already persistent).

Parameters:

path (str) – Unused — accepted only to satisfy the shared interface.

Return type:

None

Notes

Qdrant persists itself when location is a directory or a server URL; the :memory: client is ephemeral by design. Point save at a directory location instead of calling this for durability.

search(queries, k)[source]

Return approximate top-k neighbours per query (no filter).

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) scores.

Return type:

tuple[ndarray, ndarray]

search_filter(queries, k, where=None)[source]

Return top-k neighbours, optionally restricted by a payload filter.

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

  • k (int) – Neighbours per query.

  • where (dict, optional) – {field: value} equality constraints ANDed together. None (default) searches the whole collection.

Returns:

  • ids (numpy.ndarray) – Shape (q, k) (-1 pads short rows when a filter is strict).

  • distances (numpy.ndarray) – Shape (q, k) scores.

Return type:

tuple[ndarray, ndarray]