@juspay/neurolink
Version:
The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002
91 lines (90 loc) • 4.01 kB
TypeScript
/**
* Chroma vector store adapter
*
* Implements the `VectorStore` contract (see `src/lib/types/rag.ts`) against
* a Chroma collection. This module has zero runtime dependency on the
* `chromadb` package: callers construct their own `ChromaClient` (or any
* compatible object) and inject it here. The structural interfaces below
* mirror the subset of the `chromadb` API this adapter relies on
* (`getOrCreateCollection`, `collection.upsert/query/delete`).
*
* ## Distance -> similarity scoring
*
* Chroma returns *distances*, not similarities, and the meaning of that
* distance depends entirely on the collection's configured `hnsw:space`
* (this adapter does not — and cannot — set that; it is chosen when the
* collection is created on the Chroma side). `distanceMetric` tells this
* adapter which space the collection uses so it can invert the distance
* into a `score` consistent with `InMemoryVectorStore` (higher = more
* similar):
*
* - `"cosine"` (default): Chroma returns `distance = 1 - cosineSimilarity`,
* so `score = 1 - distance` reproduces `InMemoryVectorStore`'s cosine
* score exactly.
* - `"ip"`: Chroma returns `distance = 1 - dot(a, b)`, so
* `score = 1 - distance` yields the raw dot product — only equal to
* cosine similarity if both vectors are unit-normalized.
* - `"l2"`: Chroma returns squared Euclidean distance, range
* `[0, Infinity)`, which has no exact inverse into a cosine-similarity
* scale. It is converted via `score = 1 / (1 + distance)`, a
* monotonically decreasing-in-distance map into `(0, 1]`. This preserves
* result ordering but is NOT numerically comparable to cosine scores.
*
* Passing a `distanceMetric` that does not match the collection's actual
* `hnsw:space` will silently produce meaningless scores (Chroma has no way
* to report its configured space back to the client), so callers must keep
* the two in sync.
*
* ## Metadata round-tripping
*
* Chroma metadata values must be strings, numbers, or booleans. Values that
* are `undefined` are dropped (Chroma rejects `undefined`); any other
* non-primitive value (object, array, `null`) is `JSON.stringify`-ed on
* write. This is lossy: such values come back as JSON-encoded strings on
* read, not their original type. Store only primitive metadata values if
* you need exact round-tripping.
*
* ## indexName -> collection mapping
*
* `indexName` is used verbatim as the Chroma collection name (1:1,
* lazily created via `getOrCreateCollection` and cached for the lifetime of
* this adapter instance).
*/
import type { ChromaClientLike, ChromaVectorStoreOptions, ChromaWhere, MetadataFilter, VectorQueryResult, VectorStore } from "../../types/index.js";
/**
* Translates a `MetadataFilter` into a Chroma `where` clause.
*
* Throws a clear error for any operator Chroma's metadata `where` clause
* cannot express ($not, $nor, $exists, $contains, $regex, $size) rather than
* silently dropping the constraint and mis-filtering results.
*/
export declare function translateMetadataFilter(filter: MetadataFilter): ChromaWhere;
export declare class ChromaVectorStore implements VectorStore {
private readonly client;
private readonly collections;
private readonly distanceMetric;
constructor(client: ChromaClientLike, options?: ChromaVectorStoreOptions);
private getCollection;
/**
* Add or update vectors in an index (Chroma collection).
*/
upsert(indexName: string, items: Array<{
id: string;
vector: number[];
metadata?: Record<string, unknown>;
}>): Promise<void>;
/**
* Query vectors by similarity.
*/
query(params: {
indexName: string;
queryVector: number[];
topK?: number;
filter?: MetadataFilter;
includeVectors?: boolean;
}): Promise<VectorQueryResult[]>;
/**
* Delete vectors from an index (Chroma collection) by id.
*/
delete(indexName: string, ids: string[]): Promise<void>;
}