[1] https://ai.googleblog.com/2020/07/announcing-scann-efficient... [2] https://github.com/facebookresearch/faiss/wiki/Fast-accumula...
Many disagree. Pick whatever rocks your boat, there is a FOSS library for almost everything these days :)
The database software behind the ANN algo is probably a little more important in practice than the ANN algo itself, unless you're operating at such scale and speed that its an actual issue (e.g. you're google).
Differences between algorithms are a little more interesting when they let you do something totally different, like, for example, minimize the speed hit from doing searches on disk (SPTAG, DiskANN).
Currently I'm using Annoy (mostly because it's what I've used before) but I am a bit worried that this is well outside what it has been designed for.
Has anyone got specific advice for things I should try? I've used FAISS previously but it seems to have the same design space.
Any kind of acceleration technique to limit the search to a subset of the database (such as cell-probe-ish methods like LSH or IVF, or graph-based methods, etc) would take a ton of time to compute. Simply storing all the data you need for search, even brute force, would rapidly explode, not to mention the compute required.
Most cases with such large vectors I've seen begin with highly sparse vectors. Certainly Faiss (I wrote the GPU side of Faiss), Annoy, or most any similarity search libraries out there are geared to dense vectors in the 20 - 2000ish dimension range (beyond the number of dimensions where exact methods such as BSP or k-D trees work well as in "high" dimensions your nearest neighbor is highly likely to lie on either side of a dividing hyperplane, but below cases where simply storing the data uncompressed / unquantized / etc is hard and the amount of compute is prohibitive as well).
How big is the data set (number of vectors) that you are searching among, and are you performing single queries or batch queries?
You are probably right in the general case.
I'm only searching hundreds of vectors, and it seems to be working surprisingly well (astonishingly well really!) - but I've only spent a few hours working on this and are far from having a proper measure of how good it is.
I'll try the smaller subspace ideas - seems like it'd be easy to try and could work.
> How big is the data set (number of vectors) that you are searching among
The biggest dataset I've tried so far is 400 (it is searching similar scenes in a sports broadcast)
> and are you performing single queries or batch queries?
single - choose a scene and it finds similar ones.
Thanks for Faiss BTW. I love love love it - long time member of the FB group you have. I think I switched to Annoy because I had a packaging issue some time back or something.
Another option is to shard your vectors into N pieces, where N*k is the length of your vector. Since cosine similarity doesn’t care about order, it will be fine. The only requirement is that the k-th vector can only be compared with other k-th vectors for similarity. The benefit of this approach is that it can be parallelized easily.
Search speed is good (although the datasize is pretty small - hundreds of vectors).
So the sharding idea I'd:
slice up the vector
compare each sub vector with the corresponding sub vector ones from other vectors getting the similarities.
sum the similarities
choose the maximum
Is this the general idea? Is there an implementation of this you've seen?I agree with your algorithm, it is equivalent to cosine similarity. But you might also consider whether you need all the shards at all. Maybe you can get away with a half or even a tenth of them. If you have some metric like ndcg you can measure the drop in performance and consider the trade off.
Do you mean the dimension of the vector or the number of vectors?
[1]: https://github.com/openai/openai-cookbook/blob/main/examples...
We have built a few video-search system by now, using USearch and UForm for embedding. They are only 256 dims and you can concatenate a few from different parts of the video. Any chance it would help?
No they aren't.
> metric='cos', # Choose 'l2sq', 'haversine' or other metric, default = 'ip'
As a note, it is actually 'l2_sq' for the Python example.
> index.add(labels=np.arange(len(vectors)), vectors=vectors)
Adding to index appears to be very slow. Also labels are listed as an optional param but the Python SDK has them as required.
Do you have setup of params for 'brute force' approach (100% accuracy)?
> Adding to index appears to be very slow.
Interesting. Can you please elaborate? We benchmark it on daily basis, but there is always a chance we forgot some corner case :)
PS: Thanks for considering us! USearch is already used in production by a few companies (small and very large), and we would be happy to assist with integration!
PS2: Argument name inconsistency is solved on the main-dev, and will be released with a bunch of major changes in 1.0 this week.
We've just hosted one of our first community/contributor calls a few hours ago, discussing the plans for the upcoming 1.0 release, and integration with UCall, UStore, and UForm - our other FOSS libraries. Please don't hesitate to reach out for any questions or feature requests - now is the best time :)
The simplest way with USearch - concatenate 10 embeddings, define a custom metric with Numba, that takes the average of 10 dot-products. Done :)
> Yes, and yes. The last one may be a bit trickier through Python bindings today, but I can easily include that in the next release… shouldn’t take more than 50 LOC.
Appreciate it. That'd be game-changing for me. The ultimate thing I'd like to do is actually use a function of the form score = af1(embedding1) + bf2(embedding2) + ...
That way you could make adjustments like ignoring feature1 unless its score passes a threshold. I'll try looking at Numba to see if that's possible.
If someone here has free time and C++ experience I am open to recommendations on the codebase and style as well: https://github.com/unum-cloud/usearch/blob/main-dev/include/...
If you already use some DBMS to store your data - extension can be a good place to start. Once you scale and want to tune… switch to using the underlying engine directly.
How would I integrate this into a dense passage retriever workflow for RAG? I could not find any examples for document chunk ingestion and similarity query.
Talking about https://github.com/unum-cloud/usearch#disk-based-indexes
For example, filtering by arbitrary time range.
§ Supporting advanced filtering in USearch
In the low-level C++ interface we already support arbitrary predicates (callbacks) evaluated during HNSW graph traversal. JIT-ing them from the Python level is a bit trickier, but we will consider that, if there is demand.
§ Supporting advanced filtering with USearch
We are now in the process of building a bridge between USearch and UStore, that would allow combining Vector Search with a proper Multi-Modal database. This will solve your problem, but will take some time to get it right. Feel free to contribute :)
Great work, and thank you for your contributions.
PS: Love your blog! I have worked on SFCs in the past. Did you?
[1]: https://www.google.com/books/edition/Space_Filling_Curves/zm... [2]: https://github.com/google/s2geometry
They bring essentially nothing of value in vector-vector operations, as compilers can properly auto-vectorize simple dot products... Moreover, they generally only target single and double precision, while we often prefer half or quarter precision. All in all, meaningless dependency.
What do we use? I wrote a tiny package called SimSIMD. It's idea is to utilize less common SIMD instructions, especially in mixed-typed computations, that are hard for compilers to optimize. It was also a fun exercise to evaluate the performance of new SVE instruction on recent Arm CPUs, like the Graviton 3. You can find the code, the benchmarks, and the results in the repo: https://github.com/ashvardanian/simsimd
Still, even without SimSIMD, USearch seems to be one of the faster implementations of vector search. You can find the benchmarks in the first table here: https://github.com/unum-cloud/usearch#memory-efficiency-down...