Skip to main content

tinyhnsw - the littlest vector database

TinyHNSW is a tiny, simple vector database. It weighs in at a measly few hundred lines of code. It's built on a straightforward (but not fast) implementation of HNSW in Python with minimal dependencies. It has an associated set of tutorials that build up to understanding how HNSW works, and how you can build your own TinyHNSW.

⚠️ The vector database part of this works, but the tutorial is not yet complete. I will update the README checklist below as chapters and code are completed.

⚠️ tinyhnsw is NOT production-quality. Compared to literally any standard implementation, it's slow and probably buggy. If you want to use an Approximate Nearest Neighbor library in a real application, consider something like FAISS.

Tutorial Outline

  1. Introduction
  2. Nearest Neighbor Search
  3. An Overview of HNSW
  4. Skip Lists
  5. Navigable Small Worlds
  6. HNSW
  7. Limitations
  8. Filtering and Hybrid Search
  9. Multimodal Retrieval with CLIP
  10. Searching Text with Sentence Transformers

Code

  1. Nearest Neighbor Search
  2. Skip Lists
  3. Navigable Small Worlds
  4. HNSW
  5. Filtering and Hybrid Search
  6. Multimodal Retrieval with CLIP
  7. Searching Text with Sentence Transformers

Library Usage

With the disclaimers out of the way, here is how you use it/set it up.

Installation

To install tinyhnsw, run the following command:

pip install -Ue .

This will install the library and all its dependencies (numpy, networkx, scipy, tqdm).

Usage

HNSW Index

from tinyhnsw import HNSWIndex

import numpy

vectors = numpy.random.randn(100, 10)

index = HNSWIndex(d=10)
index.add(vectors)

print(index.ntotal)
# => 100

HNSW Visualizations

You can also visualize each layer of the HNSW graph using the following code:

from tinyhnsw.visualization import visualize_hnsw_index

# ... set up index here

visualize_hnsw_index(index)

Which will generate a representation like the following:

HNSW layers visualization

Full NN Index

You can evaluate the full nearest neighbors index with the following command:

from tinyhnsw.utils import load_sift, evaluate
from tinyhnsw import FullNNIndex

data, queries, labels = load_sift()

index = FullNNIndex(128)
index.add(data)

D, I = index.search(queries, k=10)

print(f"Recall@1: {evaluate(labels, I[:, 0])}")

On my M2 MacBook Air with numpy=1.26.2, that runs in 0.25s and results in a recall@1 of 98%.

Skip Lists

📝 As part of understanding how HNSW works, the tutorial walks you through how skip lists work and how to implement one. However, this implementation is not particularly robust and only works with integer keys. It's there for teaching purposes, as understanding skip lists will really help understand how HNSW works.

You can use the skip lists as follows:

from tinyhnsw.skip_list import SkipList

list = [3, 2, 1, 7, 14, 9, 6]
s = SkipList(list)
print(s)

Which will return something like the following (but not exactly, it's a random data structure after all):

2 |   2 3     9
1 |   2 3 6   9 14
0 | 1 2 3 6 7 9 14

You have a few basic operations:

s.find(3)
# => Node(value=3, pointers=[...])
s.delete(3)
# => None ; removes item from skiplist
s.insert(5)
# => None ; inserts the element 5
s.tolist()
# => [1, 2, 5, 6, 7, 9, 14]

Navigable Small Worlds (NSWs)

📝 The second part of understanding how HNSW works is understanding how NSWs work. Again, we provide a teaching implementation in this repo, but it's not meant for much more than teaching.

Proofs of Concept with CLIP and Sentence Transformers

python examples/multimodal_retrieval/multimodal_retrieval.py "animated scene"

Searching for "animated scene" Searching for "landscape"

Testing

There are a few different kinds of tests in this repo:

  1. correctness tests
  2. timing tests
  3. accuracy tests

Correctness Tests

To run the correctness tests, simply run:

poetry run pytest

Timing Tests

Make sure you've downloaded the data:

python tinyhnsw/utils.py

Which will download the SIFT10K dataset to the data/ folder.

On my machine, index creation for 10k vectors to get to 100% recall takes 22 seconds.

Accuracy Tests

We use SIFT10k to evaluate the different indexes, scoring them with Recall@1 (on my machine, with a random seed):

Index Recall@1
FullNNIndex 1.00
HNSWIndex (simple) 1.00
HNSWIndex (heuristic) 1.00

Metadata

Release files for tinyhnsw 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tinyhnsw 0.1.0
File Size Uploaded Provenance Actions
tinyhnsw-0.1.0.tar.gz 12.2 kB Without provenance Details for tinyhnsw-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for tinyhnsw 0.1.0
File Interpreter ABI Platform Actions
tinyhnsw-0.1.0-py3-none-any.whl Python 3 none any Details for tinyhnsw-0.1.0-py3-none-any.whl

Total release size: 25.3 kB

Release files / tinyhnsw-0.1.0.tar.gz

Download URL tinyhnsw-0.1.0.tar.gz
Size 12.2 kB
Tags Source
SHA-256 checksum
How to use checksums
b7574c3ffdb3f25ba26b5a3a1a7d35252a4b7af53b6779f7464ea646548d27a3
BLAKE2b-256 checksum
How to use checksums
86cf30da05ec7b39798ee622f5706edf4bfe6935e52d4f8259408ed30e260ed4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.7.1 CPython/3.11.5 Darwin/23.1.0

Release files / tinyhnsw-0.1.0-py3-none-any.whl

Download URL tinyhnsw-0.1.0-py3-none-any.whl
Size 13.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1ea6faac38864ac65233b44f01286b6ee7d1be05347a8c869e9239c6dc0beb86
BLAKE2b-256 checksum
How to use checksums
18d5ea6f974e622848cb76c0c396f932e27b9f1c0952a2980ec8735da878ce1c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.7.1 CPython/3.11.5 Darwin/23.1.0

Security for tinyhnsw 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page