Skip to main content

Fast embedded vector database with Python bindings

Project description

Quiver

An embedded vector database written in Rust with a Python SDK. No server, no network — runs fully in-process.

Installation

pip install quiver-vector-db

Or build from source:

python3 -m venv .venv && source .venv/bin/activate
pip install maturin
maturin develop --release -m crates/quiver-python/Cargo.toml

Quick start

import quiver_vector_db as quiver

db  = quiver.Client(path="./my_data")
col = db.create_collection("docs", dimensions=384, metric="cosine")

col.upsert(id=1, vector=[0.12, 0.45, ...], payload={"title": "Hello world"})
col.upsert(id=2, vector=[0.98, 0.01, ...], payload={"title": "Vector search"})

hits = col.search(query=[0.13, 0.44, ...], k=5)
for hit in hits:
    print(hit["id"], hit["distance"], hit["payload"])

Collections are persisted via WAL — reopen the same path and everything is restored.

Index types

Seven index types, all usable from Python:

db = quiver.Client(path="./data")

col = db.create_collection("name", dimensions=768, metric="cosine", index_type="hnsw")          # default
col = db.create_collection("name", dimensions=768, metric="cosine", index_type="flat")           # exact
col = db.create_collection("name", dimensions=768, metric="cosine", index_type="quantized_flat") # int8, ~4x less RAM
col = db.create_collection("name", dimensions=768, metric="cosine", index_type="fp16_flat")      # float16, 2x less RAM
col = db.create_collection("name", dimensions=768, metric="l2",     index_type="ivf")            # cluster-based ANN
col = db.create_collection("name", dimensions=768, metric="l2",     index_type="ivf_pq")         # PQ compressed, ~96x less RAM
col = db.create_collection("name", dimensions=768, metric="cosine", index_type="mmap_flat")      # disk-mapped, near-zero RAM
Index Recall RAM Best for
hnsw 95-99% Vectors + graph General purpose (default)
flat 100% All vectors (f32) Small datasets, exact required
quantized_flat ~99% ~4x less (int8) Memory-constrained exact search
fp16_flat >99.5% ~2x less (float16) Balanced memory vs accuracy
ivf Tunable Vectors + centroids Large datasets
ivf_pq ~90%+ ~96x less (PQ codes) Million-scale, extreme compression
mmap_flat 100% Near-zero RSS Dataset larger than RAM

In-memory indexes

Low-level index objects live in RAM only. Nothing hits disk unless you call .save().

import quiver_vector_db as quiver

# Exact brute-force
idx = quiver.FlatIndex(dimensions=384, metric="cosine")
idx.add(id=1, vector=[...])
idx.add_batch([(2, [...]), (3, [...])])
results = idx.search(query=[...], k=10)
idx.save("index.bin")
loaded = quiver.FlatIndex.load("index.bin")

# HNSW approximate
hnsw = quiver.HnswIndex(dimensions=384, metric="cosine", ef_construction=200, ef_search=50, m=12)
hnsw.add(id=1, vector=[...])
hnsw.flush()  # build graph after bulk inserts
results = hnsw.search(query=[...], k=10)

# Int8 quantized          — same API as FlatIndex
idx = quiver.QuantizedFlatIndex(dimensions=384, metric="cosine")

# Float16 quantized       — same API as FlatIndex
idx = quiver.Fp16FlatIndex(dimensions=384, metric="cosine")

# IVF cluster-based
idx = quiver.IvfIndex(dimensions=384, metric="l2", n_lists=256, nprobe=16, train_size=4096)

# IVF + Product Quantization
idx = quiver.IvfPqIndex(dimensions=384, metric="l2", n_lists=256, nprobe=16, train_size=4096, pq_m=8, pq_k_sub=256)

# Memory-mapped flat
idx = quiver.MmapFlatIndex(dimensions=384, metric="cosine", path="./vectors.qvec")

Payload & filtered search

Attach metadata to vectors and filter at query time:

col.upsert(id=1, vector=[...], payload={"category": "tech", "score": 4.8})

# Filter operators: $eq, $ne, $in, $gt, $gte, $lt, $lte, $and, $or
hits = col.search(query=[...], k=5, filter={"category": {"$eq": "tech"}})
hits = col.search(query=[...], k=5, filter={"score": {"$gte": 4.0}})
hits = col.search(query=[...], k=5, filter={
    "$and": [
        {"category": {"$in": ["tech", "science"]}},
        {"score": {"$gte": 4.0}},
    ]
})

Hybrid dense+sparse search

Combine dense vector similarity with sparse keyword signals (e.g. BM25/SPLADE weights):

# Upsert with both dense and sparse vectors
col.upsert_hybrid(
    id=1, vector=[...],
    sparse_vector={42: 0.8, 100: 0.5, 3001: 0.3},
    payload={"title": "Rust guide"},
)

# Hybrid search — weighted fusion of dense and sparse scores
hits = col.search_hybrid(
    dense_query=[...],
    sparse_query={42: 0.7, 100: 0.6},
    k=10,
    dense_weight=0.7,
    sparse_weight=0.3,
    filter={"category": {"$eq": "tech"}},  # optional
)

for hit in hits:
    print(hit["id"], hit["score"], hit["dense_distance"], hit["sparse_score"])

Regular upsert() and upsert_hybrid() can be mixed freely in the same collection.

Collection management

db = quiver.Client(path="./data")

col = db.get_or_create_collection("docs", dimensions=768, metric="cosine")
col = db.get_collection("docs")

db.list_collections()       # ['docs', ...]
col.count                   # number of dense vectors
col.sparse_count            # number of sparse vectors

col.delete(id=42)
db.delete_collection("docs")

Distance metrics

Metric String Use when
Cosine "cosine" Text/image embeddings (most common)
L2 "l2" Geometry, sensor data
Dot product "dot_product" Pre-normalised vectors

Parameter tuning

HNSW: ef_construction (build quality, default 200), ef_search (query quality, default 50), m (graph connectivity, default 12).

IVF / IVF-PQ: n_lists (clusters, default 256, rule of thumb: sqrt(N)), nprobe (clusters scanned, default 16), train_size (auto-train threshold, default 4096).

PQ-specific: pq_m (sub-quantizers, must divide dimensions), pq_k_sub (centroids per sub-quantizer, default 256). Memory per vector = pq_m bytes.

Build

./dev_build.sh               # build + test Rust core
./dev_build.sh --python       # also build Python wheel
./dev_build.sh --faiss --python  # with FAISS support

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

quiver_vector_db-0.1.0.tar.gz (5.7 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

quiver_vector_db-0.1.0-cp311-abi3-macosx_11_0_arm64.whl (571.1 kB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

quiver_vector_db-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (584.4 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

quiver_vector_db-0.1.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (552.2 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARM64

quiver_vector_db-0.1.0-cp38-abi3-macosx_11_0_arm64.whl (556.7 kB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

quiver_vector_db-0.1.0-cp38-abi3-macosx_10_12_x86_64.whl (587.7 kB view details)

Uploaded CPython 3.8+macOS 10.12+ x86-64

File details

Details for the file quiver_vector_db-0.1.0.tar.gz.

File metadata

  • Download URL: quiver_vector_db-0.1.0.tar.gz
  • Upload date:
  • Size: 5.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.12.6

File hashes

Hashes for quiver_vector_db-0.1.0.tar.gz
Algorithm Hash digest
SHA256 aceceeea12184426c89dde0032bee1ad08e3beccd8025b9010c02240478cf109
MD5 9f4f72fa0e545da442454d0b064429d1
BLAKE2b-256 57557b12bd767abbb05c82efb9668c6bcbf51aceb5250e2da4d59c726f812b21

See more details on using hashes here.

File details

Details for the file quiver_vector_db-0.1.0-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for quiver_vector_db-0.1.0-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 12cdf9b91ddd97d1214665e068c8ce40b4580a7fd3aeced50c7679cc921623c0
MD5 8a828e5d3fe21b78886d279f4e7c72fa
BLAKE2b-256 f3cb65dabd8078786a4f0cabe04eb6ddf135a73230a807883d2eb9a3165164ed

See more details on using hashes here.

File details

Details for the file quiver_vector_db-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for quiver_vector_db-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 66719b14b8537c656e39813e9e1aaa79e617229a09b47b843a33b615444295e2
MD5 b1ca1ed9b69ae16aaf0780d18e96c422
BLAKE2b-256 5ff12eeff815793903a7082b4d6aef6d83a3c7e6b9e6c8d98668a32c1330f98a

See more details on using hashes here.

File details

Details for the file quiver_vector_db-0.1.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for quiver_vector_db-0.1.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 b0686629e234e00bcded758817da0bc1033b65937f03added7df0b30e2080a51
MD5 13060f40aade794db9a9d5a1e6237aa0
BLAKE2b-256 86477f55bc9b6b2bb5559f3d1b25ad018b869fe58d1a19a84cd44c07eb5261b4

See more details on using hashes here.

File details

Details for the file quiver_vector_db-0.1.0-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for quiver_vector_db-0.1.0-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 35633af6d510dab4a2cb112025b77894e9ee989ef631c388d1e7aab04a4c8b3d
MD5 aa45b65de178f7a37f77fde4cadf01a0
BLAKE2b-256 b6b950d1a6bff1b9a2d04bb04024dd9303bde7f1a9f290f1285df6407a4b93a8

See more details on using hashes here.

File details

Details for the file quiver_vector_db-0.1.0-cp38-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for quiver_vector_db-0.1.0-cp38-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 bcd802d377778d3805b53dcf77fef1bd08cb624e03f0729ef34f383f9341034c
MD5 8eabe668eac6b08c673ee55bbeabb30a
BLAKE2b-256 bb6edf9668cc5395c372933a20d8615606d869b19f640f4c534136217c12e408

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page