Vector Incremental Nano Kit β Reconfigurated Automatically
βVector DB that self-organizes. Auto-switch, auto-tune, auto-scale.β
Warning
This project is currently in pre-alpha.
Most vector databases force a trade-off: over-engineer for small datasets or hit a performance cliff as you scale. You're left tuning parameters by hand, managing indices, and hoping your hardware keeps up.
Vinkra eliminates the guesswork. It automatically switches from Exact Search (for 100% precision) to ANN (for massive scale with IVF-PQ) based on dataset size and runtime latency. Vinkra adapts its strategy to your hardware and data, whether on a mobile device or a server.
It uses a Power Law model (y = a * x^b) to predict search latency based on the number of vectors in the index. Initial calibration measures raw BLAS performance, then online tuning refines parameters with actual runtime measurements.
| Feature | Description |
|---|---|
| β Incremental Inserts | Add vectors anytime. Your index grows with your data, not against it. |
| π Hardware-Aware Auto-Switch | Automatically switches to ANN when latency exceeds your threshold. |
| βοΈ Self-Tuning Engine | Background reconfiguration adapts clusters as your data evolves. |
| π― Production-Ready Search | Filtered searches, soft deletes, compact, dual-metric (Euclidean + cosine). |
| πΎ Explicit Storage | Disk or memory β you control where your data lives. |
Unlike enterprise solutions (Milvus, Pinecone) that require complex Docker or cloud setup, Vinkra runs entirely local with no dependencies beyond pip install.
First ensure that you have the necessary system dependencies installed.
-
Linux only: Required for building rii
# Debian/Ubuntu sudo apt-get install python3-dev # RedHat/Fedora/CentOS sudo dnf install python3-devel -y # CentOS 7 and older sudo yum install python3-devel
-
Android/Termux:
pkg install -y tur-repo pkg install python-scipy
The simplest way to get started is with pip:
pip install vinkraTip
Termux (Android)
No Rust toolchain? Install pydantic-core pre-built wheels first, then retry:
pip install typing-extensions
pip install pydantic-core --index-url https://termux-user-repository.github.io/pypi/
pip install "pydantic>=2.12.4,<2.13"Prefer building from source? You can clone and install manually for full control:
git clone https://github.com/speedyk-005/vinkra.git
cd vinkra
pip install -e .Run the demo to see auto-switch in action:
# Install and run anywhere
curl -O https://raw.githubusercontent.com/speedyk-005/vinkra/main/demo_poc.py
python demo_poc.pyThe demo uses:
switch_latency_ms=120insideAnnConfigto trigger the switch soonerdim=128- Batches of 10,000 vectors
The switch happens when latency exceeds switch_latency_ms.
Example output:
βββββββββββ³βββββββββββββββββββββ³βββββββββββββββββ³ββββββββββββββββββ³βββββββββββββββββ
β Vectors β Strategy β Avg Query (ms) β Insert Time (s) β Status β
β‘βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β 10,000 β exact_search β 32.486 β 0.806 β Exact Search β
β 20,000 β exact_search β 79.690 β 0.729 β Exact Search β
β 30,000 β exact_search β 107.419 β 0.720 β Exact Search β
β 40,000 β exact_search β 188.063 β 0.771 β β Building ANN β
β 50,000 β approximate_search β 0.000 β 10.051 β β ANN Active β
β 60,000 β approximate_search β 155.239 β 1.323 β β ANN Active β
βββββββββββ΄βββββββββββββββββββββ΄βββββββββββββββββ΄ββββββββββββββββββ΄βββββββββββββββββ
β ANN switch successfully triggered!
Note
Results vary by hardware and system load. Faster machines switch later, and running other programs will affect timing.
Initialization (VinkraDB API)
from vinkra import VinkraDB
# Create a database with 128-dimensional vectors
db = VinkraDB(dim=128, dir_path="./data")
# Or use volatile in-memory mode (omit dir_path)
# db = VinkraDB(dim=128)
# Full configuration capabilities
db = VinkraDB(
dim=384,
dir_path="./data",
metric="euclidean", # or "cosine" (default: euclidean)
force_exact=False, # Set to True to completely lock it out of ANN mode
ann_config=None, # Provide custom AnnConfig instance (default: auto-generated)
embedding_callback=None, # Optional function to generate vectors from raw content text
overwrite=False, # Blow away existing directory index if True
verbose=False # Enable internal runtime diagnostic logs
)VinkraDB fully implements Python's context manager interface. Using a with block guarantees your in-flight buffers flush cleanly to disk and the underlying SQLite engine closes its connections safely without dangling file locks, even if your code raises unhandled exceptions.
from vinkra import VinkraDB
with VinkraDB(dim=384, dir_path="./data") as db:
db.add([{"content": "Seamless storage context"}])
# The database saves and shuts down gracefully right hereAnnConfig (API)
For custom ANN tuning, configure AnnConfig and pass it to VinkraDB:
from vinkra import AnnConfig, VinkraDB
config = AnnConfig(
num_subspaces=16, # number of sub-vectors (default: 32)
quantizer="pq", # "pq" or "opq" (default: pq)
codebook_size=128, # centroids per subspace (default: 256)
switch_latency_ms=150 # Runtime latency milestone to trigger ANN switch (default: 300)
reconfig_threshold=100_000 # Inserts before reconfiguring the index on search performance (default: 100k)
)
db = VinkraDB(dim=384, dir_path="./data", ann_config=config)
# Print all available technical constraints and options:
AnnConfig.help()Add (API)
Records accept the following:
content(required): text payload to trackembedding(required if no callback configured): list of floats or 1D/2D numpy arrayid(optional): string representation of a valid UUIDv7metadata(optional): dictionary containing scalar filtering targets
db.add([
{"content": "Hello world", "embedding": [0.1] * 384, "metadata": {"source": "doc1"}},
{"content": "Another text", "embedding": [0.2] * 384}
])db = VinkraDB(dim=384, dir_path="./data", embedding_callback=my_embedding_fn)
# Omit 'embedding' keys; generated entirely under the hood
db.add([
{"content": "Hello world", "metadata": {"source": "doc1"}},
{"content": "Another text"},
])Search (API)
Results include:
id: vector IDcontent: text contentdistance: similarity score (lower is closer for euclidean)metadata: key-value pairsembedding: (only ifinclude_vectors=True)
results = db.search(query_vec=[0.1] * 384, top_k=5)
# Include source embeddings in output mapping
results = db.search(query_vec=[0.1] * 384, include_vectors=True)Filters are checked before similarity metrics hit vectors. Operators support ==, !=, >, <, >=, <= matching against string, numeric, and boolean literals.
results = db.search(
query_vec=[0.1] * 384,
top_k=10,
filters=["source == 'doc1'", "score >= 50", "new == True"]
)If you manage resources manually instead of using the context manager, write the index to disk:
db.save()Saves state to disk and closes the SQLite connection cleanly. Registered via atexit, so it runs automatically on normal interpreter exit.
db.close()Soft deletion (API)
Marks vectors as deleted without rebuilding the index:
db.soft_delete(["0192a5b4-7f3c-7d6e-9a1b-2c3d4e5f6a7b"])Compaction (API)
Removes soft-deleted vectors and rebuilds the index:
db.compact()Warning
Compaction on an active approximate_search index can block queries for 20-200+ seconds while it rebuilds the codebook. Run during maintenance windows.
Stats (API)
# Check which search strategy is currently active
db.strategy # "exact_search" or "approximate_search"
# Whether the ANN index is currently being built in the background
db.is_ann_building
# Whether there are buffered records (from an ANN transition)
db.has_buffered
# Whether there are no active (non-deleted) records
db.is_empty
# Count vectors
active = db.count() # same as db.count("active") (default)
deleted = db.count("deleted")
total = db.count("all")
stats = db.stats()
# {
# "version": "...",
# "dim": 384,
# "metric": "euclidean",
# "strategy": "exact_search",
# "is_ann_building": false,
# "has_buffered": false,
# "last_saved_at": "...",
# "last_deleted_at": "...",
# "active_count": 1000,
# "deleted_count": 5
# }- Incremental Inserts
- Hardware-Aware Auto-Switch
- Soft deletes + compact
- Save/Load + Context Manager
- Filter DSL
- basic filters: Quick Comparison
- Complex Filters: Content Matching, Null Checks, date/time literals, ...
- Recovery: recover soft-deleted vectors
- REST API: HTTP API for remote vector operations
- Integrations: LangChain, LlamaIndex, and other integrations
rii β’ nanopq β’ scipy β’ numpy β’ SQLite
Bug fixes, features, docs β all welcome. Check out CONTRIBUTING.md for the full details.
Check out the LICENSE file for all the details.
MIT License β use freely, modify, and credit accordingly.