nabled-embeddings
A lightweight, ndarray-native, Arrow-zero-copy compute and rerank layer for embedding vectors - bring vectors from any model, compute exactly, deploy anywhere.
nabled-embeddings is the exact rerank/compute step that sits next to a vector store, not a
vector database. It composes nabled-linalg vector kernels and nabled-ml PCA into the
post-embedding numerics a retrieval pipeline needs.
Install
[]
= "0.0.11"
Key modules
normalize: row-wise L2 normalization (normalize_rows/_view/_into).similarity:query_corpus_scoresplus theMetricenum (Cosine,Dot,L2).topk/rerank: direction-aware partial-selectiontop_k, thererankentrypoint, and the id-carryingrerank_with_ids/batch_rerank_with_ids(NeighborWithId+attach_ids).knn: exactbrute_force_knnfor small corpora, evaluation, and golden tests.cache:CorpusWorkspace— build-once / query-many corpus with cached cosine norms.metrics: offline ranking quality (recall_at_k,reciprocal_rank,mean_reciprocal_rank,ndcg_at_k).mmr: Maximal Marginal Relevance diversification (mmr,lambdain[0, 1]).quantize: int8 row quantization (QuantizedMatrix,quantize_rows,dequantize,query_corpus_scores_quantized).compress: PCA fit +compressprojection for dimensionality reduction.
Why use it
- Lightweight: pure Rust + ndarray, minimal dependencies, no C++/FAISS/CUDA build, embeddable.
- Efficient in-pipeline: zero-copy Arrow/Lance ingress at the facade, view-based APIs,
*_intoallocation control, and no Python interpreter in the Rust path. - Exact, BLAS-backed scoring with partial-selection top-k.
This crate does not claim to be faster than FAISS; exact brute-force scoring is memory/BLAS
bound and competitive at parity, not dominant. Any performance number should come from the
criterion bench (benches/embeddings_benchmarks.rs), not assertion.
Bring-your-own-vectors
Any encoder's dense float vectors plug in unchanged (OpenAI, Cohere, Sentence-BERT, CLIP, custom) because the crate depends only on shape and dtype, never the model. Two rules the math cannot enforce:
- Query and corpus must come from the same model and share the same
dim. - Pick the
Metricto match how the model was trained. Dot on un-normalized vectors favors larger-norm rows by design.
Metric selection
| Metric | Polarity | Delegates to | Use when |
|---|---|---|---|
Cosine |
higher is better | vector::pairwise_cosine_similarity |
default; angle-only similarity |
Dot |
higher is better | matrix::matmat(queries, corpusᵀ) |
MIPS-style models; normalized inputs (= cosine) |
L2 |
lower is better | vector::pairwise_l2_distance |
Euclidean models; same ranking as normalized cosine |
Crate graph
- Depends on:
nabled-core,nabled-linalg,nabled-ml. - Used by: facade
nabledvia theembeddingsfeature;pynabledPython bindings.
Quick example
use ;
use arr2;
let corpus = arr2;
let query = arr2;
let top = rerank?;
assert_eq!;
# Ok::
Switch metrics by passing Metric::Dot (maximum inner product) or Metric::L2 (Euclidean
distance); selection (top_k) follows each metric's ranking polarity automatically.
Retrieval extensions
Rerank with ids — thread recall-stage global ids through the exact rerank (single + batch). The
batch path composes brute_force_knn (there is intentionally no bare batch_rerank); the new value
is id mapping.
use ;
use ;
let candidates = arr2;
let query = arr1;
let ids = ;
let top = rerank_with_ids?;
assert_eq!;
# Ok::
Corpus workspace reuse — CorpusWorkspace precomputes the corpus's metric state (cosine row
norms) once and reuses it across many queries against a static corpus; it owns the prepared corpus.
use ;
use arr2;
let corpus = arr2;
let ws = build?;
let query = arr2;
let top = ws.rerank_with?;
# Ok::
MMR — diversity-aware rerank; lambda = 1.0 reproduces plain rerank, lower values diversify.
use ;
use ;
let candidates = arr2;
let query = arr1;
let diversified = mmr?;
# Ok::
int8 quantization — per-row symmetric int8 (scale = amax / 127), ~4× smaller storage; scoring
is dequantize-then-existing-kernel, so results approximate the f32 path within tolerance.
use ;
use arr2;
let corpus = arr2;
let q = quantize_rows?;
let queries = quantize_rows?;
let scores = queries.query_corpus_scores_quantized?;
# Ok::
Evaluation metrics — pure ranking math over retrieved-id lists vs ground-truth sets (binary
relevance): recall_at_k, reciprocal_rank, mean_reciprocal_rank, ndcg_at_k.
Arrow-native rerank wrappers — when embeddings live in Arrow columns, the nabled facade
exposes arrow_query_corpus_scores / arrow_rerank / arrow_normalize_rows /
arrow_brute_force_knn (feature embeddings + arrow), zero-copy from FixedSizeListArray. See
docs/EMBEDDINGS.md.
Performance
Benchmark before claiming. Methodology, reproduction steps, and the honest exact-vs-exact framing
against numpy cosine + argsort live in docs/BENCHMARKS.md. Numbers must come from the criterion
bench (benches/embeddings_benchmarks.rs), not assertion; no "faster than FAISS" claims without
disclosed measurements.
Non-goals
- No ANN index (HNSW/IVF) - use a vector store for recall, then rerank candidates here.
- No storage or persistence.
- No model inference, tokenizers, or ONNX/candle.
Optional features
blas,lapack-provider: forwarded tonabled-linalg/nabled-ml.openblas-system,openblas-static,netlib-system,netlib-static,magma-system.
Docs
- API docs: https://docs.rs/nabled-embeddings
- Workspace repo: https://github.com/MontOpsInc/nabled
- Domain guide:
docs/EMBEDDINGS.md - Facade feature:
nabledwithembeddings