server/vector library
Dense-vector primitives and a FAISS-style brute-force k-NN index.
This module is pure Dart — no dependency on the SQL layer — so it can be exercised in isolation. It exposes:
- Vector — a fixed-dimension
Float32Listwrapper. - VectorMetric — L2 / L2² / inner-product / cosine.
- encodeVectorBlob / decodeVectorBlob — canonical BLOB layout:
little-endian
uint32 dimfollowed bydim × float32values. - parseVectorText — accepts
[1, 2, 3.5]JSON-array-of-numbers. - Distance helpers used by the SQL scalar functions
(
vecL2Sq,vecL2,vecInnerProduct,vecCosineDistance,vecCosineSimilarity,vecNormalize). - FlatIndex — an
IndexFlatL2/IndexFlatIPequivalent that stores every vector verbatim and answerssearch(q, k)by an O(N·d) scan with an incremental top-k heap.
Higher-level structures (HNSW, IVF, PQ) can be layered on top in a later phase; the SQL front-end only needs the scalar functions and a blob column type today.
Classes
- FlatIndex
-
Brute-force nearest-neighbor index (FAISS
IndexFlatL2/IndexFlatIPequivalent). Stores every added vector verbatim in a contiguousFloat32Listand scans them on each query. - HnswIndex
- Approximate nearest-neighbor index using an HNSW graph. Same public shape as FlatIndex — you can swap it in wherever brute-force gets too slow. Search cost is O(log N · efSearch · d) instead of O(N · d), at the price of small recall loss controlled by efSearch.
- IvfFlatIndex
-
Cell-probe inverted-file index over dense vectors. FAISS
IndexIVFFlatport. - IvfPqIndex
-
IVF cell-probe + PQ residual compression. Requires
train(...)beforeadd(...)(trains coarse quantizer and PQ codebooks in sequence). Ranks in approximate squared L2 always — themetricargument tosearchis accepted for API symmetry but ignored. - LshIndex
-
Sign-projection LSH over dense vectors. See file header for
semantics. Codes are packed into
(nbits + 7) ~/ 8bytes each. - PqIndex
-
Product-quantization search index. Requires
train(...)beforeadd(...). Stores each vector as m bytes; search uses ADC and ranks in approximate squared-L2 space. - Vector
-
A dense
dim-dimensional real vector held asFloat32List. The underlying representation matches FAISS on-disk / on-wire so BLOB I/O is a straight memcpy. - VectorIndexSpec
-
Declarative description of a vector index attached to a
(table, column)pair. Passed toDatabase.createVectorIndexand returned byDatabase.vectorIndexes. - VectorSearchHit
-
One
(id, distance)search result.idis whatever caller-supplied key was passed to FlatIndex.add;distanceis in the metric that was requested atsearchtime (smaller = better for L2/cosine, larger = better for inner-product; the returned list is always sorted best-first).
Enums
- VectorIndexKind
- Which FAISS-style index implementation should back a VectorIndexSpec. See the corresponding index class for parameter semantics.
- VectorMetric
-
Similarity / distance metric identifiers. Mirrors FAISS's
METRIC_L2/METRIC_INNER_PRODUCT; cosine is inner-product on pre-normalized vectors and is exposed as a distance (1 - similarity).
Functions
-
coerceVector(
Object? v) → Vector? - Coerce a SQL value to a Vector. Accepts:
-
decodeVectorBlob(
List< int> bytes) → Vector -
Decode a vector BLOB previously produced by encodeVectorBlob.
Throws FormatException if
bytesdoes not have the expected size or dim header. -
encodeVectorBlob(
Vector v) → Uint8List -
Encode
vas the canonical BLOB layout:LE uint32 dim, thendim × LE float32values. -
parseVectorBatchText(
String s) → List< Vector> -
Parse a batch of vectors from
'[[1,2,3], [4,5,6]]'— a JSON array of arrays-of-numbers. A single-vector literal'[1,2,3]'is accepted and wrapped in a singleton list. All inner vectors must share the same dimension. -
parseVectorText(
String s) → Vector -
Parse a vector from text of the form
[1, 2, 3.5]. Accepts any JSON array of numbers. -
vecAdd(
Vector a, Vector b) → Vector - Element-wise sum, returning a new vector.
-
vecCosineDistance(
Vector a, Vector b) → double -
Cosine distance = 1 − cosine similarity, in
0, 2. -
vecCosineSimilarity(
Vector a, Vector b) → double -
Cosine similarity in
-1, 1. Returns 0 when either vector is the zero vector (mirroring FAISS's behavior of treating undefined directions as maximally dissimilar-ish). -
vecInnerProduct(
Vector a, Vector b) → double - Inner (dot) product a·b.
-
vecL2(
Vector a, Vector b) → double - Euclidean distance ‖a - b‖.
-
vecL2Sq(
Vector a, Vector b) → double - Squared L2 distance ‖a - b‖².
-
vecNorm(
Vector v) → double - L2 norm ‖v‖.
-
vecNormalize(
Vector v) → Vector -
Return a new L2-normalized copy of
v. A zero vector is returned unchanged. -
vecSub(
Vector a, Vector b) → Vector - Element-wise difference a - b, returning a new vector.
-
vectorIndexBuiltStateFromJson(
VectorIndexSpec spec, Map< String, Object?> j) → Object -
Reconstruct a built index from a JSON payload previously produced by
vectorIndexBuiltStateToJson. Dispatches on
spec.kind. -
vectorIndexBuiltStateToJson(
Object idx, {int seed = 1234}) → Map< String, Object?> ? - Dispatch on the runtime type of a built index and return its serialized state, or null when the type isn't recognised.