Bare-metal C99 Β· AVX2+FMA Β· ARM NEON Β· FASM x64 Β· Zero Dependencies Β· ~120 KB
- π Found a bug, accuracy issue, or vector index edge case? Please Open an Issue β reports are tracked and resolved quickly!
- π¬ Questions, episodic memory architectures, or feature requests? Join our GitHub Discussions.
- β Find NanoVector useful? Give it a star on GitHub β it helps more AI agent engineers discover the engine!
- β Support development (USDT TRC-20):
TDVbEdnpgNgoAhNcn1EwXxWHiR3RKLit5P(Verify on TronScan)
Quickstart β’ Compatibility β’ Google Colab β’ Why NanoVector? β’ Benchmarks β’ Architecture β’ Ecosystem
| Platform / Manager | Installation Command |
|---|---|
| PyPI (pip) | pip install nanovector |
| PyPI (uv) | uv add nanovector |
| Conda (Conda-Forge) | conda install -c conda-forge nanovector | pixi add nanovector |
| Ubuntu / Debian (APT PPA) | curl -sS https://eminsk.github.io/ppa/setup.sh | sudo bashsudo apt install python3-nanovector |
| Ubuntu / Debian (.deb) | sudo dpkg -i python3-nanovector_0.1.8-1_amd64.deb |
pip install nanovector
# or with uv
uv add nanovector| Runtime / Implementation | Supported Versions | Execution Mode | Status |
|---|---|---|---|
| CPython (Standard) | 3.8, 3.9, 3.10, 3.11, 3.12, 3.13, 3.14, 3.15, 3.16 (Alpha) | Native C AVX2 / NEON extension + Buffer Protocol | β Fully Supported |
| CPython (Free-Threaded) | 3.13t, 3.14t, 3.15t, 3.16t (Alpha) | Multi-core No-GIL (Py_BEGIN_ALLOW_THREADS) |
β Fully Supported |
| PyPy (JIT Accelerated) | 3.8, 3.9, 3.10, 3.11, 3.12 | High-speed JIT tracing / C-API & ctypes | β Fully Supported |
| Operating Systems | Windows (7, 8, 10, 11), Linux, macOS (Intel & Apple Silicon) | x86_64 (AVX2/FMA), ARM64 (NEON) | β Fully Supported |
Modern AI agents and local LLM pipelines are plagued by vector database bloat:
- ChromaDB, Pinecone clients, and FAISS pull hundreds of megabytes of dependencies (
torch,onnxruntime,pydantic,fastapi,duckdb). - Cold Start Penalty: Importing Chroma takes 1.5 to 2.5 seconds, crippling CLI tools, serverless workers (AWS Lambda), and autonomous agent loops.
- The Small-to-Medium Vector Trap: Over 95% of AI agents store between 50 and 50,000 vectors (conversation turns, tool execution history, episodic facts). At this scale, graph traversal (HNSW) incurs heavy pointer indirection, high memory overhead, and non-deterministic recall.
NanoVector solves this by delivering exact, sub-millisecond, brute-force SIMD search directly in CPU cache with zero external dependencies.
| Feature | NanoVector β‘ | ChromaDB π’ | FAISS βοΈ |
|---|---|---|---|
| Distribution Wheel Size | 38 KB (~120 KB unpacked) | ~120 MB+ | ~50 MB+ |
| External Dependencies | 0 (Zero) | 35+ packages | OpenMP, BLAS |
| Python Cold Import Overhead | < 1 ms (3,000x faster) | ~1,850 ms | ~120 ms |
| Search Latency (N=2,000, 384D) | 0.13 ms (7,478 QPS) | 8.2 ms | 0.22 ms |
| Batch Ingestion Throughput | 1,414,000 vectors/sec | ~25,000 vectors/sec | ~400,000 vectors/sec |
| Storage Format | Single file (.nvec) |
SQLite + DuckDB dirs | Custom binary |
| Zero-Copy NumPy | Yes (Buffer Protocol) | No (copies memory) | Partial |
| GIL Release during Search | Yes (Py_BEGIN_ALLOW_THREADS) |
Partial | Partial |
Install the zero-dependency pre-compiled binary wheel in under 1 second:
pip install nanovectorimport nanovector
import numpy as np
# 1. Initialize an index (dim=384 for all-MiniLM-L6-v2, 768 for BERT, 1536 for OpenAI)
index = nanovector.Index(dim=384, metric="cosine")
# 2. Add single embeddings with metadata dict or string
vec = np.random.randn(384).astype(np.float32)
index.add("doc_1", vec, metadata={"author": "eminsk", "tag": "ai", "views": 1500})
# 3. Batch addition (Zero-Copy directly from 2D NumPy array)
batch_vecs = np.random.randn(5000, 384).astype(np.float32)
batch_ids = [f"turn_{i}" for i in range(5000)]
batch_metas = [{"turn_id": i, "role": "agent", "category": "tech" if i % 2 == 0 else "general"} for i in range(5000)]
index.add_batch(batch_ids, batch_vecs, metadatas=batch_metas)
# 4. Search top-k nearest neighbors with metadata filtering (~0.15 ms)
query = np.random.randn(384).astype(np.float32)
results = index.search(query, top_k=5, filter={"role": "agent", "category": "tech"})
for r in results:
print(f"[{r.id}] Score: {r.score:.4f} | Meta: {r.meta}")
# 5. Single-file instant persistence (.nvec)
index.save("agent_memory.nvec")
# 6. Instant reload from disk
loaded_index = nanovector.load("agent_memory.nvec")
print(f"Reloaded {len(loaded_index)} vectors in {loaded_index.dim}D")Give your LLM agents lightning-fast, persistent long-term memory:
import nanovector
import numpy as np
class AgentEpisodicMemory:
def __init__(self, filepath="agent_brain.nvec", dim=384):
self.filepath = filepath
try:
self.index = nanovector.load(filepath)
except Exception:
self.index = nanovector.Index(dim=dim, metric="cosine")
def remember(self, fact_id: str, embedding: np.ndarray, fact_text: str):
self.index.add(fact_id, embedding, metadata=fact_text)
self.index.save(self.filepath)
def recall(self, query_embedding: np.ndarray, top_k=3):
return self.index.search(query_embedding, top_k=top_k)
# Usage in Agent Loop
memory = AgentEpisodicMemory(filepath="agent_brain.nvec")
# Store facts if brain is empty
if len(memory.index) == 0:
memory.remember("mem_1", np.random.randn(384).astype(np.float32), "User prefers Python, C, and FASM.")
memory.remember("mem_2", np.random.randn(384).astype(np.float32), "NanoVector achieves sub-millisecond search.")
memory.remember("mem_3", np.random.randn(384).astype(np.float32), "Episodic memory saves state in single .nvec file.")
query_vec = np.random.randn(384).astype(np.float32)
recalled_facts = memory.recall(query_vec, top_k=3)
for match in recalled_facts:
print(f"Score: {match.score:.4f} -> Memory: {match.metadata}")NanoVector supports expressive, zero-overhead metadata filtering without external query engines.
# Exact match
index.search(query, top_k=5, filter={"author": "eminsk", "published": True})
# Comparison operators: $eq, $ne, $in, $nin, $gt, $gte, $lt, $lte
index.search(query, top_k=5, filter={
"views": {"$gte": 500},
"category": {"$in": ["ai", "systems"]},
"archived": {"$ne": True}
})
# Custom lambda predicates
index.search(query, top_k=5, filter=lambda meta: meta and meta.get("priority", 0) > 3)Replace ChromaDB or FAISS with NanoVector for instant <1ms cold starts and zero dependency bloat:
from nanovector import NanoVectorStore
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()
# 1. Create VectorStore from raw texts (dim automatically inferred)
vectorstore = NanoVectorStore.from_texts(
texts=[
"NanoVector is 3,000x faster to import than ChromaDB.",
"Episodic memory runs in bare-metal C99 AVX2 SIMD.",
"Pure zero-dependency lightweight vector search engine."
],
embedding=embeddings,
metadatas=[{"source": "benchmark"}, {"source": "architecture"}, {"source": "design"}]
)
# 2. Similarity search with metadata filtering
docs = vectorstore.similarity_search("cold start latency", k=1, filter={"source": "benchmark"})
print(docs[0].page_content)
# -> "NanoVector is 3,000x faster to import than ChromaDB."
# 3. Use directly in LCEL (LangChain Expression Language) Chains & Agents
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
# 4. Save & reload single-file persistence
vectorstore.save("agent_brain.nvec")
reloaded_store = NanoVectorStore.load("agent_brain.nvec", embedding=embeddings)NanoVector includes a built-in, zero-dependency MCP JSON-RPC 2.0 Server (nanovector-mcp) with a multilingual (RU/EN) feature-hashing + char n-gram embedder. Connect it to Claude Desktop, Cursor, Windsurf, or Antigravity to give your AI assistant sub-millisecond persistent .nvec episodic memory (nanovector_remember, nanovector_recall, nanovector_stats):
{
"mcpServers": {
"nanovector-memory": {
"command": "nanovector-mcp",
"args": ["--db", "~/.nanovector/memory.nvec", "--dim", "384"]
}
}
}Or launch directly from terminal:
nanovector-mcp --db agent_memory.nvec
# or
python -m nanovector --mcp --db agent_memory.nvecRun NanoVector interactively in your browser with zero local setup:
The Interactive Colab Notebook demonstrates:
- Zero-Setup Installation & Hardware SIMD Detection: Compiles native C/AVX2 on Colab CPU in seconds.
- 10-line Cosine Similarity Search: Indexing and querying embeddings with JSON metadata.
- Real-World AI Agent Episodic Memory: Recalling instructions and preferences using
sentence-transformersembeddings (all-MiniLM-L6-v2). - Single-File
.nvecBrain Persistence: Instant binary save and zero-overhead reload. - Live 50,000-Vector Benchmark: Measuring ingestion throughput (1M+ vectors/sec) and search latency (~0.13 ms at 2k vectors, ~6.7 ms at 50k vectors) directly on Colab VM hardware.
Real-world benchmarks measured on Intel/AMD x86_64 CPU (AVX2+FMA) using standard 384-dimensional sentence embeddings (all-MiniLM-L6-v2) against NumPy 2.x / OpenBLAS:
| Dataset Size ( |
Metric | NanoVector Latency | NanoVector QPS | NumPy Baseline | Speedup |
|---|---|---|---|---|---|
| 500 vectors | Cosine | 0.0347 ms (34.7 Β΅s) | 28,854 QPS | 0.0828 ms | 2.39x faster |
| 2,000 vectors | Cosine | 0.1337 ms (133.7 Β΅s) | 7,478 QPS | 0.1876 ms | 1.40x faster |
| 10,000 vectors | Cosine | 1.4021 ms | 713 QPS | 1.1617 ms | Comparable (1 thread vs multi-core OpenBLAS) |
| 50,000 vectors | Cosine | 6.7479 ms | 148 QPS | 4.8132 ms | Exact 100% Recall |
- Ingestion Throughput: 1,414,447 vectors/sec (20,000 512D vectors ingested in 14.14 ms via Zero-Copy Buffer Protocol).
- Multi-Threaded Concurrency (8 threads): 14,300 QPS (400 concurrent queries executed in 27.97 ms with zero lock contention).
- Persistence Serialization: Save 2,000 vectors in 1.71 ms, load in 3.92 ms (single binary
.nvecfile).
NanoVector is written in standard C99 with a multi-tiered hardware acceleration pipeline:
βββββββββββββββββββββββββββββββββ
β Python C-API β
β (Buffer Protocol / No-GIL) β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββΌββββββββββββββββ
β NanoVector C99 Core β
β Top-K In-Place Heap $O(N\log K)$ β
βββββββββββββββββ¬ββββββββββββββββ
β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββ
β β β
ββββββββββΌβββββββββ ββββββββββΌβββββββββ ββββββββββΌβββββββββ
β x86_64 AVX2 β β ARM64 NEON β β FASM x64 β
β 256-bit FMA β β 128-bit FMA β β Bare-Metal ASM β
β (32 floats/iter)β β (16 floats/iter)β β (Windows x64) β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
-
256-bit AVX2 + FMA (
src/nanovector_avx2.c):- 4-way unrolled kernel processing 32 single-precision floats per loop iteration across 4 YMM accumulators.
- Fused multiply-accumulate (
_mm256_fmadd_ps) eliminates intermediate register spills. - Tail handling handles arbitrary vector dimensions with zero padding penalties.
-
ARM NEON (
src/nanovector_neon.c):- 128-bit vectorization for Apple Silicon (M1/M2/M3/M4) and AWS Graviton processors.
- 4-way unrolling processing 16 floats per iteration using
vfmaq_f32andvaddvq_f32.
-
Pure FASM Assembly (
src/asm/nanovector_x64.asm):- Hand-crafted Windows x64 assembly routines adhering strictly to Microsoft x64 ABI calling conventions (volatile register allocation
ymm0..ymm5, shadow store handling). - Assembles cleanly into a 629-byte object file using Flat Assembler (FASM).
- Hand-crafted Windows x64 assembly routines adhering strictly to Microsoft x64 ABI calling conventions (volatile register allocation
-
In-Place Top-$K$ Heap:
- Min-heap / Max-heap maintains the best
$K$ matches in$O(N \log K)$ . - Branch-predicted pruning: candidate items with scores worse than the current
$K$ -th element are discarded in a single CPU clock cycle.
- Min-heap / Max-heap maintains the best
-
.nvecBinary Specification:- 64-byte aligned header with magic bytes
NVEC\x01. - Contiguous
$N \times D \times 4$ raw float block (zero-copy memory-mappable). - Compact length-prefixed ID and JSON metadata string tables.
- 64-byte aligned header with magic bytes
Initializes an embedded vector index.
-
dim(int): Vector dimensionality (e.g. 384, 768, 1536). -
metric(str): Distance metric:-
"cosine": Cosine similarity ($\frac{u \cdot v}{|u| |v|}$ ), higher is closer. Range$[-1.0, 1.0]$ . -
"dot"or"ip": Inner Product ($u \cdot v$ ), higher is closer. -
"l2"or"euclidean": Squared Euclidean distance ($\sum (u_i - v_i)^2$ ), lower is closer.
-
-
normalize(bool): IfTrue, vectors are automatically L2-normalized upon insertion and search.
| Method | Description |
|---|---|
add(id: str, vector: Any, metadata: Optional[Union[str, dict]] = None) |
Adds a single 1D vector (NumPy array, list, or buffer) with unique ID and optional metadata dict/string. |
add_batch(ids: List[str], vectors: Any, metadatas: Optional[Sequence[Union[str, dict]]] = None) |
Adds multiple vectors in batch directly from 2D numpy.ndarray (Zero-Copy). Releases GIL. |
search(query: Any, top_k: int = 10, filter: Optional[Union[dict, callable]] = None) -> List[Match] |
Searches Top-$K$ nearest neighbors with optional metadata filter ($gte, $in, exact, lambda). Releases GIL. |
save(filepath: str) -> None |
Serializes the entire index to a single .nvec binary file on disk. |
load(filepath: str) -> Index |
Classmethod / function loading an index from a .nvec file in sub-millisecond time. |
index.dim(int): Dimensionality of indexed vectors.index.count(int) orlen(index): Total number of indexed vectors.index.metric(str): Active distance metric.match.id(str): ID of the matching item.match.score(float): Similarity score or distance.match.meta(dict or Any): Automatically parses JSON metadata string into a Python dict or primitive.nanovector.NanoVectorStore: Drop-in LangChainVectorStoreclass compatible with LCEL chains and agents.nanovector.version()(str): Library version string (e.g."0.1.6").nanovector.simd_backend()(str): Active hardware acceleration backend ("AVX2+FMA (x86_64)","ARM NEON", etc.).
Run the full test suite covering bare-metal SIMD indexing, FASM standalone executables & ctypes bindings, query filtering, LangChain LCEL integration, and multi-threaded concurrency:
# Run pytest with uv
uv run pytest -v
# Run under Free-Threaded Python 3.16t (No-GIL)
python -X gil=0 -m unittest discover -s tests -v
# Build and verify native FASM 64-bit & 32-bit suites
cd asm && build.batAll 46 test cases pass with 100% success rate across Python 3.8 through 3.16 (including No-GIL free-threaded 3.13tβ3.16t), PyPy 3.8 through 3.12, and native Flat Assembler (FASM).
nanovector is developed by @eminsk as part of an open-source performance ecosystem:
- π§ AgentJIT β Just-In-Time Compiler for AI Agent Trajectories with speculative de-optimization guards (
pip install agentjit). - β‘ NanoGEMM β Bare-metal AVX2+FMA SIMD matrix multiplication engine in ~100KB for sub-microsecond CPU neural network inference (
pip install nanogemm). - π₯οΈ NanoRecall β 100% Private, offline desktop memory & semantic screen search engine powered by NanoVector (
pip install nanorecall). - π avito-sdk β High-performance headless Avito scraping & data extraction SDK with price tracking, Playwright cookies, and Telegram/VK bots (
pip install avito-sdk). - π yfinance-ta-patterns β Institutional-grade technical pattern scanner with AI Confluence Scoring and LLM prompt generation (
pip install yfinance-ta-patterns). - π xlsx_vievers β Headless Excel formula engine (129+ functions) & desktop spreadsheet processor with SSE2 SIMD math (
pip install xlsx-viewer-pro). - π₯ screenvideo β Desktop screen recorder with WASAPI audio and standalone pure x64 FASM edition.
- π StackOverflowAPI β Bilingual desktop client with native FASM x64 search client.
If you find this project valuable and would like to support ongoing development:
- β Star the Repository: If NanoVector speeds up your similarity searches and embeddings, give us a star on GitHub β it helps more developers discover bare-metal vector search!
- π¬ Join Discussions: Have ideas, use cases, or vector indexing benchmarks? Start or join a thread in GitHub Discussions!
- β Donate (USDT TRC-20):
TDVbEdnpgNgoAhNcn1EwXxWHiR3RKLit5P
(Network: TRON / TRC-20 | Verify on TronScan)
MIT License. See LICENSE for details.