Reach is the lightest-weight vector store. Just put in some vectors, calculate query vectors, and off you go.
pip install reach
Assume you've got some vectors and a model. We'll assume you have a nice model2vec model.
from model2vec import StaticModel
from reach import Reach
model = StaticModel.from_pretrained("minishlab/m2v_output_base")
texts = ["dog walked home", "cat walked home", "robot was in his lab"]
vectors = model.encode(texts)
r = Reach(vectors, texts)
r.most_similar(texts[0])
new_text = "robot went to his house"
similarities = r.nearest_neighbor(model.encode(new_text))
print(similarities)
# Store the vector space
r.save("tempo.json")
# Load it again
new_reach = Reach.load("tempo.json")
And that's it!
Reach is an extremely simple but extremely fast vector store. No magic here, it just uses numpy really effectively to obtain impressive speeds. Reach will be fast enough for your RAG projects until 1M vectors, after which you may have to switch to something heavier.
Reach is designed to load really quickly from disk, see below, making it ideal for just-in-time projects, such as querying texts on the fly. No need to keep a heavy vector database running, just load your reach, do the computation, and then throw it away.
Here's some examples and benchmarks.
For your RAG system, you need fast retrieval. We got it!
import numpy as np
from reach import Reach
dummy_words = list(map(str, range(100_000)))
dummy_vector = np.random.randn(100_000, 768)
r = Reach(dummy_vector, dummy_words)
# Query with a single vector
x = np.random.randn(768)
%timeit r.nearest_neighbor(x)
# 6.8 ms ± 286 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# Query reach with 10 vectors
x = np.random.randn(10, 768)
%timeit r.nearest_neighbor(x)
# 27.5 ms ± 187 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 2.7 ms per vector
# 100 vectors.
x = np.random.randn(100, 768)
%timeit r.nearest_neighbor(x)
# 143 ms ± 943 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 1.4 ms per vector
No need to keep a vector database in memory, or on some server. Just load and save your thing whenever you need it.
import numpy as np
from reach import Reach
dummy_words = list(map(str, range(100_000)))
dummy_vector = np.random.randn(100_000, 768)
r = Reach(dummy_vector, dummy_words)
# Loading from disk
r.save("temp.json")
%timeit Reach.load("temp.json")
# 79.9 ms ± 1.22 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
pip install reach
MIT
Stéphan Tulkens