A high-performance semantic search engine built with a Rust core exposed to Python via PyO3. Vectors are indexed with an IVF (Inverted File Index) structure trained by K-means, and similarity is computed using AVX2 SIMD dot-product instructions.
Also available in Ukrainian 🇺🇦
- Rust IVF engine — K-means clustering + bucket-based ANN search
- AVX2 SIMD — hardware-accelerated dot-product (falls back to scalar automatically)
- Rayon — parallel K-means assignments across all CPU cores
- PyO3 zero-copy interface — numpy arrays passed to Rust without data copying
- FastAPI REST API —
/searchendpoint with timing breakdown - Web UI — dark-theme search interface served at
/ - 100 000 vectors indexed from the DBpedia-14 dataset (MiniLM-L6-v2, 384 dims)
| N_PROBE | Recall@5 | Latency | Speedup vs brute-force |
|---|---|---|---|
| 1 | 57.3% | 0.22 ms | 154× |
| 6 | 84.0% | 0.99 ms | 45× |
| 10 | 90.7% | 1.5 ms | 30× |
| 30 | 94.7% | 4.0 ms | 11× |
| 40 | 96.0% | 5.2 ms | 8× |
| 80 | 98.7% | 10.7 ms | 4× |
| 316 | 100.0% | 44.0 ms | 1× |
Default N_PROBE = 10 — 90.7% recall at 1.5 ms per query (encode excluded).
.
├── src/
│ ├── lib.rs # PyO3 bindings
│ └── vector_engine.rs # IVF index, K-means, AVX2 dot-product
├── scripts/
│ ├── build_db.py # Build the vector database from DBpedia-14
│ ├── accuracy_test.py # Recall@K vs NumPy brute-force
│ ├── nprobe_benchmark.py # Recall & latency sweep over all N_PROBE values
│ ├── benchmark.py # Synthetic stress-test (random vectors)
│ └── search_app.py # Interactive CLI search
├── data/
│ ├── news_index.bin # Serialised Rust IVF index (git-ignored)
│ └── news_texts.json # Raw document store (git-ignored)
├── config.py # All tuneable parameters
├── server.py # FastAPI server + HTML frontend
├── Cargo.toml
└── requirements.txt
- Python 3.10+
- Rust toolchain — rustup.rs
- CPU with AVX2 support (Intel Haswell 2013+ / AMD Ryzen 2017+)
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt. "$HOME/.cargo/env"
maturin develop --releaseDownloads DBpedia-14 from HuggingFace (~560 MB), encodes 100 000 articles and builds the IVF index (~15 min on CPU).
python scripts/build_db.pyuvicorn server:app --reloadOpen http://localhost:8000 in your browser.
{
"query": "Boeing commercial aircraft history",
"top_k": 5
}Response:
{
"search_query": "Boeing commercial aircraft history",
"search_time_ms": 13.4,
"encode_ms": 11.9,
"rust_search_ms": 1.5,
"results_count": 5,
"results": [
{ "id": 42301, "score": 0.871, "text": "Boeing: Boeing Company is..." }
]
}All tuneable constants live in config.py:
| Parameter | Default | Description |
|---|---|---|
EMBEDDING_MODEL |
all-MiniLM-L6-v2 |
SentenceTransformer model |
DIMENSION |
384 |
Vector size |
NUM_RECORDS |
100_000 |
Articles to index |
N_PROBE |
10 |
IVF buckets probed per query |
DEFAULT_TOP_K |
5 |
Results returned by default |
KMEANS_MAX_ITER |
15 |
K-means iterations during index build |
# Recall@5 vs NumPy brute-force (50 real DBpedia queries)
python scripts/accuracy_test.py
# Recall & latency chart for every N_PROBE value → data/nprobe_benchmark.png
python scripts/nprobe_benchmark.py
# Synthetic stress-test with 200K random vectors
python scripts/benchmark.py
# Interactive CLI search
python scripts/search_app.py| Layer | Technology |
|---|---|
| Core | Rust 1.78, PyO3 0.20, numpy-pyo3 |
| Parallelism | Rayon (work-stealing thread pool) |
| SIMD | AVX2 (_mm256_fmadd_ps) |
| Serialisation | Bincode + Serde |
| Embeddings | sentence-transformers/all-MiniLM-L6-v2 |
| Dataset | HuggingFace dbpedia_14 (14 categories) |
| API | FastAPI + Uvicorn |
| Build | Maturin |