Skip to content

Repository files navigation

turbovec

A fast, from-scratch approximate-nearest-neighbor (ANN) vector search engine.
Python-first API · SIMD-accelerated C++ core (HNSW) · zero-copy NumPy interop via nanobind.

CI Python C++17 License: MIT


Why this project?

Vector search is the engine behind RAG, semantic search, and recommender systems. Instead of importing a library, turbovec implements the core of a FAISS-style engine from first principles to explore the systems-engineering that makes similarity search fast:

  • SIMD distance kernels (AVX2 + FMA) with an automatic scalar fallback for non-x86 CPUs.
  • A hand-written HNSW graph index with the proper neighbor-selection heuristic.
  • A clean Python API with zero-copy float32 hand-off to C++ via nanobind.
  • Modern, reproducible packaging & CI/CD: uv, pyproject.toml, scikit-build-core, and cross-platform wheels via cibuildwheel.

It's small enough to read in an afternoon, but reaches 100% recall at ~11k queries/second on a single core.

Quickstart

import numpy as np
import turbovec

rng = np.random.default_rng(0)
data = rng.random((100_000, 128), dtype=np.float32)

# Build an index
index = turbovec.Index(dim=128, metric="l2", M=16, ef_construction=200)
index.add(data)

# Query it — returns (ids[n, k], distances[n, k])
queries = rng.random((10, 128), dtype=np.float32)
ids, distances = index.search(queries, k=10, ef=64)

Supported metrics: "l2" · "ip" (inner product) · "cosine".

Live demo: search real text by meaning

Turn real sentences into vectors and let turbovec find the closest ones — the core of semantic search and RAG. It runs with no extra dependencies (a small pure-NumPy TF-IDF embedding), and can optionally upgrade to true semantic matching with sentence-transformers.

python examples/text_search_demo.py               # runs the example queries below
python examples/text_search_demo.py --interactive # type your own queries

Real output (each query returns the most similar sentences, with a similarity score):

Query: "italian pizza and pasta for dinner"
  1. (0.58)  I love eating pizza and pasta.
  2. (0.27)  Paris is famous for the Eiffel Tower and its museums.

Query: "an exciting football match with a winning goal"
  1. (0.42)  The football match last night was incredibly exciting.
  2. (0.27)  She scored the winning goal in the final minute.

Query: "the stock market and rising interest rates"
  1. (0.44)  Investors are worried about rising interest rates.
  2. (0.43)  The stock market dropped sharply after the announcement.

Query: "a cat sleeping on the windowsill"
  1. (0.61)  The cat curled up and slept on the warm windowsill.
  2. (0.39)  The best way to cook a steak is on a hot grill.

See examples/ for details.

Benchmarks

Single core · N = 20,000 clustered vectors · dim = 128 · 200 queries · M = 16, ef_construction = 200 · ground truth from exact brute force. Accuracy vs. speed is tuned entirely at query time via ef — no rebuild needed.

ef Recall@10 QPS p50 (ms) p99 (ms)
10 0.9365 21,489 0.044 0.092
20 0.9890 18,441 0.052 0.087
50 1.0000 11,351 0.085 0.132
100 1.0000 7,492 0.132 0.190
200 1.0000 4,332 0.228 0.324

Index build: 20,000 vectors in 6.75 s (~2,963 vectors/s). Reproduce with uv run python benchmarks/benchmark.py --n 20000 --dim 128 --queries 200.

Installation

# From source (needs a C++17 compiler; CMake & ninja are fetched automatically)
pip install .

# Or, for development, with uv:
uv sync --group dev

How it works

  1. Insert — each vector is assigned a random level and linked to its M nearest neighbors per layer. Neighbors are chosen with the HNSW heuristic (keep a candidate only if it's closer to the new node than to any already-selected neighbor) → a diverse graph with long-range links → high recall.
  2. Search — a greedy descent through the upper layers finds a good entry point, then a best-first beam search of breadth ef runs on layer 0.
  3. Distance — the hot loop is AVX2/FMA-vectorized (8 floats per instruction), with a portable scalar path for CPUs without AVX2 (e.g. Apple Silicon).

Project layout

turbovec/
├── src/turbovec_core/     # C++17 core
│   ├── distance.hpp       #   SIMD (AVX2/FMA) distance kernels
│   ├── hnsw.hpp           #   HNSW index (graph build + search)
│   └── bindings.cpp       #   nanobind bindings (zero-copy NumPy)
├── python/turbovec/       # Python package (high-level API + ship CLI)
├── examples/              # live text-search demo
├── tests/                 # pytest suite (recall, correctness, API)
├── benchmarks/            # recall / latency / QPS benchmark
├── CMakeLists.txt         # scikit-build-core / nanobind build
├── pyproject.toml         # metadata, uv groups, cibuildwheel config
└── .github/workflows/     # CI (lint + tests) · wheels (build)

Development

uv sync --group dev            # build the C++ core + install dev deps
uv run pytest tests/ -q        # run the test suite (24 tests)
uv run ruff check .            # lint
uv run python benchmarks/benchmark.py   # benchmark

Tech stack

C++17 · nanobind · NumPy · CMake / scikit-build-core · uv · Ruff · pytest · cibuildwheel · GitHub Actions

Roadmap

  • Index serialization (save / load)
  • Multi-threaded index construction
  • Product Quantization (IVF-PQ) for lower memory
  • Filtered / hybrid search

License

Released under the MIT License.

About

Fast, from-scratch ANN vector search engine — SIMD-accelerated C++ (HNSW) core with a Python-first API. 100% recall at ~11k QPS.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages