Open-source project
MinishLab/vicinity avatar
MinishLab/vicinity

MinishLab/vicinity: one interface for BASIC, HNSW, FAISS, Annoy and Voyager backends

Lightweight Nearest Neighbors with Flexible Backends

351 stars13 forksPythonMIT

At a glance

What is it?
Vicinity is a small Python vector store that wraps several nearest neighbor libraries behind one API and adds a built-in evaluation step. It is useful when you want to compare backends on your own data without rewriting your search code each time.
Who is it for?
Adopt Vicinity if you are still choosing between ANN libraries and want one API plus a qps/recall measurement on your own vectors; skip it if you need dynamic deletion on an ANN index or a persistent multi-writer service. Before committing, install the specific backend extra you intend to ship, confirm that the metric you need is listed for that backend in the README table, and check whether your workload requires insertion, since only FAISS, HNSW and Usearch support it.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 114 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The comparison problem Vicinity is built around

The README states the motivation plainly: nearest neighbor packages are hard to compare because "every package has its own interface, quirks, and limitations, and learning a new package can be time-consuming." Vicinity's answer is a single Vicinity class that takes vectors, the original items, a Backend enum and a Metric enum, and then exposes the same query methods no matter which library sits underneath. The intended user is a developer or researcher who has embeddings in hand and has not yet settled on an index type. If you already know you are shipping FAISS ivfpq and nothing else, the abstraction buys you less. The project is classified in pyproject.toml as "Development Status :: 4 - Beta", which is worth reading literally: the API is stable enough to use, and the authors are not claiming a 1.0 contract.

How the backend abstraction actually works

A Vicinity instance is constructed from vectors and items rather than from an index object. Vicinity.from_vectors_and_items receives the numpy array, the parallel list of serializable items, a backend_type and a metric, and builds the underlying index for you. Queries come in three shapes: query with k for top-k, query_threshold with a similarity threshold, and query with a 2D array of query vectors for batch search. The README example shows all three against a 128-dimensional random array of five strings.

Persistence is handled at the Vicinity level, not the backend level. save writes a directory and load reads it back, so the backend choice is part of what gets serialized. The same object can be pushed to the Hugging Face Hub with push_to_hub and restored with load_from_hub, and the README notes that you can attach the embedding model to metadata, for example vicinity.metadata["model"] = "minishlab/potion-base-8M", so a loaded store can record what produced its vectors. Evaluation is the other half of the design: evaluate takes full_vectors and query_vectors and returns queries per second and recall, which is the number you actually want when comparing an exact BASIC index against an approximate one.

Installing Vicinity and running a first query

The base install pulls only numpy, orjson and tqdm, so it is cheap. Backends are optional extras, and the README lists them by name: hnsw, annoy, faiss, usearch, voyager, pynndescent, plus backends for all of them together and all for backends plus the datasets integration. The README gives the install command as follows.

bash
pip install vicinity

To pull in every backend and integration at once, the README shows the all extra:

bash
pip install vicinity[all]

The README's quickstart builds a store from five strings and 128-dimensional vectors, then queries it. Note that the backend and metric are chosen at construction time, so switching from BASIC to HNSW means constructing a new instance, not changing a parameter on an existing one.

python
import numpy as np
from vicinity import Vicinity, Backend, Metric

items = ["triforce", "master sword", "hylian shield", "boomerang", "hookshot"]
vectors = np.random.rand(len(items), 128)

vicinity = Vicinity.from_vectors_and_items(
    vectors=vectors,
    items=items,
    backend_type=Backend.BASIC,
    metric=Metric.COSINE
)

query_vector = np.random.rand(128)
results = vicinity.query(query_vector, k=3)

After that, save and load round-trip the store, and evaluate gives you the two numbers that decide whether an approximate backend is worth its recall loss.

python
vicinity.save('my_vector_store')
vicinity = Vicinity.load('my_vector_store')

query_vectors = vectors[:1000]
qps, recall = vicinity.evaluate(
    full_vectors=vectors,
    query_vectors=query_vectors,
)

The README does not document what evaluate returns when the query set is larger than the full vector set, so keep the query slice smaller than the corpus as shown.

Deletion, insertion and the limits of the unified API

The README is unusually direct about the biggest constraint: "the ANN backends do not support dynamic deletion. To delete items, you need to recreate the index." Insertion is supported only in FAISS, HNSW and Usearch, and the BASIC backend is the only one that supports both insertion and deletion. That is a real architectural boundary, not a missing flag. If your workload deletes documents regularly, you either rebuild the index or run BASIC, and BASIC is exact search, which is the thing you were probably trying to avoid at scale.

The second boundary is metric coverage. The README's backend parameter table lists metrics per backend, and they are not identical: BASIC lists cosine and euclidean, ANNOY lists dot, euclidean and cosine. A metric that works on one backend may simply not exist on another, so a backend swap is not always a one-line change even though the query methods are. The README also does not document rollback or migration between saved store formats, so treat a saved directory as tied to the version that wrote it until you have checked otherwise.

Vicinity against using a single ANN library directly

The obvious alternative is to pick one library and call it directly: hnswlib for a small in-process HNSW index, or faiss-cpu for the IVF and product-quantizer family. Those give you the full parameter surface of the underlying library and no abstraction layer between your code and the index. What they do not give you is a common query signature across libraries, a shared save/load format, or a built-in qps and recall measurement.

A server-based vector database is the other alternative, and the difference is deployment shape rather than algorithm. Vicinity runs in your process with no service to operate, which is why the base install is three dependencies. The trade is that you get no concurrent writers, no replication and no server-side filtering, none of which the README claims. If you need those, a hosted vector store is the right tool and Vicinity is not. If you need to answer "which of these seven indexes is fastest at acceptable recall on my embeddings", that is precisely the question Vicinity is shaped around.

Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-05-24. The most recent release listed is v0.4.4 from 2026-04-14, following v0.4.3 and v0.4.2 in October 2025. The version history is short and the release cadence is irregular, so pin the version in your requirements and read the release notes before moving between minor versions.

The licence is MIT, declared both in the repository and in the pyproject.toml classifier, which is permissive and compatible with commercial use. That covers Vicinity itself only. The optional backends carry their own licences, and faiss-cpu, hnswlib, annoy, usearch and voyager are separate distributions with separate terms, so an audit of a Vicinity deployment has to include whichever extras you installed. Nothing here is legal advice; read the licence file of each backend you ship.

Editorial conclusion

Adopt Vicinity if you are still choosing between ANN libraries and want one API plus a qps/recall measurement on your own vectors; skip it if you need dynamic deletion on an ANN index or a persistent multi-writer service. Before committing, install the specific backend extra you intend to ship, confirm that the metric you need is listed for that backend in the README table, and check whether your workload requires insertion, since only FAISS, HNSW and Usearch support it.

Frequently asked questions

What is Vicinity from MinishLab?

Vicinity is described in its README as a light-weight, low-dependency vector store that provides a unified interface for nearest neighbor search across multiple backends, plus evaluation of queries per second and recall. It is a Python package published as vicinity on PyPI under the MIT licence.

How do you use Vicinity?

Install it with pip install vicinity, then build a store with Vicinity.from_vectors_and_items using vectors, the matching items, a Backend and a Metric. From there, query with k, query_threshold with a similarity threshold, or query with a batch of vectors, and save or load the store with the save and load methods.

Which backends does Vicinity support?

The README lists BASIC, HNSW via hnswlib, USEARCH, ANNOY, PYNNDESCENT, FAISS (with flat, ivf, hnsw, lsh, scalar, pq, ivf_scalar, ivfpq and ivfpqr indexes) and VOYAGER. Each is installed as an optional extra such as vicinity[hnsw] or vicinity[faiss], or all at once with vicinity[all].

Can Vicinity delete vectors from an index?

The README states that the ANN backends do not support dynamic deletion and that deleting items requires recreating the index. Only the BASIC backend supports both insertion and deletion; insertion alone is supported in FAISS, HNSW and Usearch.

How do you save and reload a Vicinity vector store?

Call vicinity.save('my_vector_store') to write it to a directory and Vicinity.load('my_vector_store') to read it back. The README also shows push_to_hub and load_from_hub for storing a vector store on the Hugging Face Hub.

Official sources

  1. License: MIT
  2. MinishLab/vicinity on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes