usearch 2.8.6 → 2.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CITATION.cff +1 -1
- package/CMakeLists.txt +3 -3
- package/CONTRIBUTING.md +3 -3
- package/Cargo.toml +1 -1
- package/Dockerfile +16 -0
- package/README.md +41 -38
- package/VERSION +1 -0
- package/binding.gyp +57 -8
- package/conanfile.py +1 -1
- package/include/usearch/index.hpp +1 -1
- package/include/usearch/index_plugins.hpp +27 -23
- package/package.json +4 -3
- package/setup.py +76 -15
- package/wasmer.toml +1 -1
- package/. npmignore +0 -14
- package/.gitignore +0 -95
- package/.vscode/launch.json +0 -181
- package/.vscode/settings.json +0 -180
- package/.vscode/tasks.json +0 -71
- package/Package.swift +0 -41
- package/csharp/.editorconfig +0 -361
- package/csharp/Cloud.Unum.USearch.sln +0 -34
- package/csharp/DEV_SETUP.md +0 -51
- package/csharp/Directory.Build.props +0 -29
- package/csharp/README.md +0 -74
- package/csharp/build_and_test.cmd +0 -31
- package/csharp/build_and_test.sh +0 -30
- package/csharp/nuget/nuget-package.props +0 -33
- package/csharp/pack.sh +0 -56
- package/csharp/src/Cloud.Unum.USearch.Tests/Cloud.Unum.USearch.Tests.csproj +0 -39
- package/csharp/src/Cloud.Unum.USearch.Tests/USearchIndexTests.cs +0 -1013
- package/csharp/src/Cloud.Unum.USearch.Tests/Usings.cs +0 -1
- package/docs/_static/custom.css +0 -26
- package/docs/_static/custom.js +0 -7
- package/docs/benchmarks.md +0 -245
- package/docs/benchmarks.rst +0 -5
- package/docs/c/index.rst +0 -11
- package/docs/c/reference.rst +0 -7
- package/docs/conf.dox +0 -2668
- package/docs/conf.py +0 -53
- package/docs/contributing.rst +0 -5
- package/docs/cpp/index.rst +0 -11
- package/docs/cpp/reference.rst +0 -17
- package/docs/csharp/index.rst +0 -6
- package/docs/format.md +0 -86
- package/docs/format.rst +0 -5
- package/docs/golang/index.rst +0 -6
- package/docs/index.rst +0 -33
- package/docs/java/index.rst +0 -11
- package/docs/java/reference.rst +0 -7
- package/docs/javascript/index.rst +0 -11
- package/docs/javascript/reference.rst +0 -12
- package/docs/python/index.rst +0 -11
- package/docs/python/reference.rst +0 -42
- package/docs/rust/index.rst +0 -6
- package/docs/swift/index.rst +0 -6
- package/docs/wolfram/index.rst +0 -6
- package/golang/README.md +0 -95
- package/golang/go.mod +0 -3
- package/golang/lib.go +0 -379
- package/golang/lib_test.go +0 -108
- package/java/README.md +0 -22
- package/java/cloud/unum/usearch/Index.java +0 -337
- package/java/cloud/unum/usearch/cloud_unum_usearch_Index.cpp +0 -197
- package/java/cloud/unum/usearch/cloud_unum_usearch_Index.h +0 -125
- package/java/test/IndexTest.java +0 -30
- package/objc/USearchObjective.mm +0 -299
- package/objc/include/USearchObjective.h +0 -154
- package/python/README.md +0 -292
- package/python/lib.cpp +0 -1216
- package/python/scripts/bench.ipynb +0 -193
- package/python/scripts/bench.py +0 -137
- package/python/scripts/bench_exact.py +0 -44
- package/python/scripts/cluster.ipynb +0 -160
- package/python/scripts/index_faiss.py +0 -100
- package/python/scripts/join.py +0 -155
- package/python/scripts/test_index.py +0 -247
- package/python/scripts/test_jit.py +0 -231
- package/python/scripts/test_sparse.py +0 -32
- package/python/scripts/test_tooling.py +0 -133
- package/python/usearch/__init__.py +0 -0
- package/python/usearch/client.py +0 -124
- package/python/usearch/eval.py +0 -470
- package/python/usearch/index.py +0 -1401
- package/python/usearch/io.py +0 -113
- package/python/usearch/numba.py +0 -121
- package/python/usearch/server.py +0 -137
- package/rust/README.md +0 -66
- package/rust/lib.cpp +0 -136
- package/rust/lib.hpp +0 -69
- package/rust/lib.rs +0 -610
- package/swift/Index+Sugar.swift +0 -153
- package/swift/README.md +0 -48
- package/swift/Test.swift +0 -37
- package/swift/USearch.swift +0 -8
- package/wasm/CMakeLists.txt +0 -7
- package/wasm/README.md +0 -13
- package/wasm/lib.cpp +0 -5
- package/wolfram/CMakeLists.txt +0 -18
- package/wolfram/README.md +0 -13
- package/wolfram/lib.cpp +0 -160
- package/wolfram/test.wls +0 -27
package/CITATION.cff
CHANGED
package/CMakeLists.txt
CHANGED
|
@@ -19,7 +19,7 @@ option(USEARCH_INSTALL "Install CMake targets" OFF)
|
|
|
19
19
|
option(USEARCH_USE_OPENMP "Use OpenMP for a thread pool" OFF)
|
|
20
20
|
option(USEARCH_USE_SIMSIMD "Use SimSIMD hardware-accelerated metrics" OFF)
|
|
21
21
|
option(USEARCH_USE_JEMALLOC "Use JeMalloc for faster memory allocations" OFF)
|
|
22
|
-
option(
|
|
22
|
+
option(USEARCH_USE_FP16LIB "Use software emulation for half-precision types" ON)
|
|
23
23
|
|
|
24
24
|
option(USEARCH_BUILD_TEST_CPP "Compile a native unit test in C++" ${USEARCH_IS_MAIN_PROJECT})
|
|
25
25
|
option(USEARCH_BUILD_BENCH_CPP "Compile a native benchmark in C++" ${USEARCH_IS_MAIN_PROJECT})
|
|
@@ -69,7 +69,7 @@ target_compile_definitions(
|
|
|
69
69
|
|
|
70
70
|
# Supplementary compilation settings affecting "index_plugins.hpp"
|
|
71
71
|
target_compile_definitions(
|
|
72
|
-
${USEARCH_TARGET_NAME} INTERFACE $<$<NOT:$<BOOL:${
|
|
72
|
+
${USEARCH_TARGET_NAME} INTERFACE $<$<NOT:$<BOOL:${USEARCH_USE_FP16LIB}>>:USEARCH_USE_FP16LIB=1>
|
|
73
73
|
)
|
|
74
74
|
|
|
75
75
|
target_compile_definitions(
|
|
@@ -302,7 +302,7 @@ function (setup_target TARGET_NAME)
|
|
|
302
302
|
|
|
303
303
|
# Supplementary compilation settings affecting "index_plugins.hpp"
|
|
304
304
|
target_compile_definitions(
|
|
305
|
-
${TARGET_NAME} PRIVATE $<$<NOT:$<BOOL:${
|
|
305
|
+
${TARGET_NAME} PRIVATE $<$<NOT:$<BOOL:${USEARCH_USE_FP16LIB}>>:USEARCH_USE_FP16LIB=1>
|
|
306
306
|
)
|
|
307
307
|
|
|
308
308
|
target_compile_definitions(${TARGET_NAME} PRIVATE $<$<NOT:$<BOOL:${USEARCH_USE_SIMSIMD}>>:USEARCH_USE_SIMSIMD=0>)
|
package/CONTRIBUTING.md
CHANGED
|
@@ -49,7 +49,7 @@ The CMakeLists.txt file has a number of options you can pass:
|
|
|
49
49
|
- `USEARCH_USE_OPENMP` - use OpenMP for parallelism
|
|
50
50
|
- `USEARCH_USE_SIMSIMD` - use SimSIMD for vectorization
|
|
51
51
|
- `USEARCH_USE_JEMALLOC` - use Jemalloc for memory management
|
|
52
|
-
- `
|
|
52
|
+
- `USEARCH_USE_FP16LIB` - use software emulation for half-precision floating point
|
|
53
53
|
|
|
54
54
|
Putting all of this together on Ubuntu and compiling the "release" version using the GCC 12 compiler:
|
|
55
55
|
|
|
@@ -58,7 +58,7 @@ cmake \
|
|
|
58
58
|
-DCMAKE_BUILD_TYPE=Release \
|
|
59
59
|
-DCMAKE_C_COMPILER=gcc-12 \
|
|
60
60
|
-DCMAKE_CXX_COMPILER=g++-12 \
|
|
61
|
-
-
|
|
61
|
+
-DUSEARCH_USE_FP16LIB=1 \
|
|
62
62
|
-DUSEARCH_USE_OPENMP=1 \
|
|
63
63
|
-DUSEARCH_USE_SIMSIMD=1 \
|
|
64
64
|
-DUSEARCH_USE_JEMALLOC=1 \
|
|
@@ -80,7 +80,7 @@ cmake \
|
|
|
80
80
|
-DCMAKE_BUILD_TYPE=Release \
|
|
81
81
|
-DCMAKE_C_COMPILER="/opt/homebrew/opt/llvm/bin/clang" \
|
|
82
82
|
-DCMAKE_CXX_COMPILER="/opt/homebrew/opt/llvm/bin/clang++" \
|
|
83
|
-
-
|
|
83
|
+
-DUSEARCH_USE_FP16LIB=1 \
|
|
84
84
|
-DUSEARCH_USE_OPENMP=1 \
|
|
85
85
|
-DUSEARCH_USE_SIMSIMD=1 \
|
|
86
86
|
-DUSEARCH_USE_JEMALLOC=1 \
|
package/Cargo.toml
CHANGED
package/Dockerfile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
|
|
3
|
+
FROM ubuntu:23.04
|
|
4
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
5
|
+
|
|
6
|
+
RUN apt-get update && \
|
|
7
|
+
apt-get install -y --no-install-recommends python3.11 python3-pip && \
|
|
8
|
+
apt-get clean && \
|
|
9
|
+
rm -rf /var/lib/apt/lists/*
|
|
10
|
+
RUN pip3 install --no-cache-dir --break-system-packages ucall usearch
|
|
11
|
+
|
|
12
|
+
WORKDIR /usearch
|
|
13
|
+
COPY python/usearch/server.py server.py
|
|
14
|
+
|
|
15
|
+
ENTRYPOINT ["python3", "./server.py"]
|
|
16
|
+
EXPOSE 8545
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<h1 align="center">USearch</h1>
|
|
2
2
|
<h3 align="center">
|
|
3
|
-
Smaller & <a href="https://www.unum.cloud/blog/2023-11-
|
|
3
|
+
Smaller & <a href="https://www.unum.cloud/blog/2023-11-07-scaling-vector-search-with-intel">Faster</a> Single-File<br/>
|
|
4
4
|
Similarity Search Engine for <a href="https://github.com/ashvardanian/simsimd">Vectors</a> & 🔜 <a href="https://github.com/ashvardanian/stringzilla">Texts</a>
|
|
5
5
|
</h3>
|
|
6
6
|
<br/>
|
|
@@ -47,7 +47,7 @@ Linux • MacOS • Windows • iOS • WebAssembly
|
|
|
47
47
|
|
|
48
48
|
---
|
|
49
49
|
|
|
50
|
-
- ✅
|
|
50
|
+
- ✅ [20x faster than][faster-than-faiss] [FAISS][faiss] implementation of [HNSW algorithm][hnsw-algorithm].
|
|
51
51
|
- ✅ Simple and extensible [single C++11 header][usearch-header] implementation.
|
|
52
52
|
- ✅ Compatible with a dozen programming languages out of the box.
|
|
53
53
|
- ✅ [SIMD][simd]-optimized and [user-defined metrics](#user-defined-functions) with JIT compilation.
|
|
@@ -57,7 +57,7 @@ Linux • MacOS • Windows • iOS • WebAssembly
|
|
|
57
57
|
- ✅ Variable dimensionality vectors for unique applications, including search over compressed data.
|
|
58
58
|
- ✅ Binary Tanimoto and Sorensen coefficients for [Genomics and Chemistry applications](#usearch--rdkit--molecular-search).
|
|
59
59
|
- ✅ Space-efficient point-clouds with `uint40_t`, accommodating 4B+ size.
|
|
60
|
-
- ✅ Compatible with OpenMP and custom "executors"
|
|
60
|
+
- ✅ Compatible with OpenMP and custom "executors" for fine-grained control over CPU utilization.
|
|
61
61
|
- ✅ Near-real-time [clustering and sub-clustering](#clustering) for Tens or Millions of clusters.
|
|
62
62
|
- ✅ [Semantic Search](#usearch--ai--multi-modal-semantic-search) and [Joins](#joins).
|
|
63
63
|
|
|
@@ -66,6 +66,7 @@ Linux • MacOS • Windows • iOS • WebAssembly
|
|
|
66
66
|
[obscure-use-cases]: https://ashvardanian.com/posts/abusing-vector-search
|
|
67
67
|
[hnsw-algorithm]: https://arxiv.org/abs/1603.09320
|
|
68
68
|
[simd]: https://en.wikipedia.org/wiki/Single_instruction,_multiple_data
|
|
69
|
+
[faster-than-faiss]: https://www.unum.cloud/blog/2023-11-07-scaling-vector-search-with-intel
|
|
69
70
|
|
|
70
71
|
## Comparison with FAISS
|
|
71
72
|
|
|
@@ -73,22 +74,22 @@ FAISS is a widely recognized standard for high-performance vector search engines
|
|
|
73
74
|
USearch and FAISS both employ the same HNSW algorithm, but they differ significantly in their design principles.
|
|
74
75
|
USearch is compact and broadly compatible without sacrificing performance, primarily focusing on user-defined metrics and fewer dependencies.
|
|
75
76
|
|
|
76
|
-
| | FAISS | USearch |
|
|
77
|
-
| :------------------------------------------- | ----------------------------: | -----------------------------: |
|
|
78
|
-
| Indexing time
|
|
79
|
-
| 100 Million 96d `f32`, `f16`, `i8` vectors | 2.6 h, 2.6 h, 2.6 h | 0.3 h, 0.2 h, 0.2 h | __9.6x, 10.4x, 10.7x__
|
|
80
|
-
| 100 Million 1536d `f32`, `f16`, `i8` vectors | 5.0 h, 4.1 h, 3.8 h | 2.1 h, 1.1 h, 0.8 h | __2.3x 3.6x, 4.4x__
|
|
81
|
-
| | | |
|
|
82
|
-
| Codebase length
|
|
83
|
-
| Supported metrics
|
|
84
|
-
| Supported languages
|
|
85
|
-
| Supported ID types
|
|
86
|
-
| Required dependencies
|
|
87
|
-
| Bindings
|
|
77
|
+
| | FAISS | USearch | Improvement |
|
|
78
|
+
| :------------------------------------------- | ----------------------------: | -----------------------------: | ---------------------: |
|
|
79
|
+
| Indexing time ⁰ | | | |
|
|
80
|
+
| 100 Million 96d `f32`, `f16`, `i8` vectors | 2.6 h, 2.6 h, 2.6 h | 0.3 h, 0.2 h, 0.2 h | __9.6x, 10.4x, 10.7x__ |
|
|
81
|
+
| 100 Million 1536d `f32`, `f16`, `i8` vectors | 5.0 h, 4.1 h, 3.8 h | 2.1 h, 1.1 h, 0.8 h | __2.3x 3.6x, 4.4x__ |
|
|
82
|
+
| | | | |
|
|
83
|
+
| Codebase length ¹ | 84 K [SLOC][sloc] in `faiss/` | 3 K [SLOC][sloc] in `usearch/` | maintainable |
|
|
84
|
+
| Supported metrics ² | 9 fixed metrics | any user-defined metrics | extendible |
|
|
85
|
+
| Supported languages ³ | C++, Python | 10 languages | portable |
|
|
86
|
+
| Supported ID types ⁴ | 32-bit, 64-bit | 32-bit, 40-bit, 64-bit | efficient |
|
|
87
|
+
| Required dependencies ⁵ | BLAS, OpenMP | - | light-weight |
|
|
88
|
+
| Bindings ⁶ | SWIG | Native | low-latency |
|
|
88
89
|
|
|
89
90
|
[sloc]: https://en.wikipedia.org/wiki/Source_lines_of_code
|
|
90
91
|
|
|
91
|
-
> ⁰ [Tested][intel-benchmarks] on Intel Sapphire Rapids, with the simplest inner-product distance, equivalent recall, and memory consumption
|
|
92
|
+
> ⁰ [Tested][intel-benchmarks] on Intel Sapphire Rapids, with the simplest inner-product distance, equivalent recall, and memory consumption while also providing far superior search speed.
|
|
92
93
|
> ¹ A shorter codebase makes the project easier to maintain and audit.
|
|
93
94
|
> ² User-defined metrics allow you to customize your search for various applications, from GIS to creating custom metrics for composite embeddings from multiple AI models or hybrid full-text and semantic search.
|
|
94
95
|
> ³ With USearch, you can reuse the same preconstructed index in various programming languages.
|
|
@@ -96,12 +97,12 @@ USearch is compact and broadly compatible without sacrificing performance, prima
|
|
|
96
97
|
> ⁵ Lack of obligatory dependencies makes USearch much more portable.
|
|
97
98
|
> ⁶ Native bindings introduce lower call latencies than more straightforward approaches.
|
|
98
99
|
|
|
99
|
-
[intel-benchmarks]: https://www.unum.cloud/blog/2023-11-
|
|
100
|
+
[intel-benchmarks]: https://www.unum.cloud/blog/2023-11-07-scaling-vector-search-with-intel
|
|
100
101
|
|
|
101
102
|
Base functionality is identical to FAISS, and the interface must be familiar if you have ever investigated Approximate Nearest Neighbors search:
|
|
102
103
|
|
|
103
104
|
```py
|
|
104
|
-
$ pip install usearch
|
|
105
|
+
$ pip install numpy usearch
|
|
105
106
|
|
|
106
107
|
import numpy as np
|
|
107
108
|
from usearch.index import Index
|
|
@@ -125,16 +126,16 @@ index = Index(
|
|
|
125
126
|
ndim=3, # Define the number of dimensions in input vectors
|
|
126
127
|
metric='cos', # Choose 'l2sq', 'haversine' or other metric, default = 'ip'
|
|
127
128
|
dtype='f32', # Quantize to 'f16' or 'i8' if needed, default = 'f32'
|
|
128
|
-
connectivity=16, # Optional:
|
|
129
|
+
connectivity=16, # Optional: Limit number of neighbors per graph node
|
|
129
130
|
expansion_add=128, # Optional: Control the recall of indexing
|
|
130
|
-
expansion_search=64, # Optional: Control the quality of search
|
|
131
|
+
expansion_search=64, # Optional: Control the quality of the search
|
|
131
132
|
)
|
|
132
133
|
```
|
|
133
134
|
|
|
134
135
|
## User-Defined Functions
|
|
135
136
|
|
|
136
|
-
While most vector search packages concentrate on just a
|
|
137
|
-
This flexibility allows you to customize your search for
|
|
137
|
+
While most vector search packages concentrate on just a few metrics - "Inner Product distance" and "Euclidean distance," USearch extends this list to include any user-defined metrics.
|
|
138
|
+
This flexibility allows you to customize your search for various applications, from computing geospatial coordinates with the rare [Haversine][haversine] distance to creating custom metrics for composite embeddings from multiple AI models.
|
|
138
139
|
|
|
139
140
|

|
|
140
141
|
|
|
@@ -165,7 +166,7 @@ USearch supports multiple forms of serialization:
|
|
|
165
166
|
|
|
166
167
|
- Into a __file__ defined with a path.
|
|
167
168
|
- Into a __stream__ defined with a callback, serializing or reconstructing incrementally.
|
|
168
|
-
- Into a __buffer__ of fixed length
|
|
169
|
+
- Into a __buffer__ of fixed length or a memory-mapped file that supports random access.
|
|
169
170
|
|
|
170
171
|
The latter allows you to serve indexes from external memory, enabling you to optimize your server choices for indexing speed and serving costs.
|
|
171
172
|
This can result in __20x cost reduction__ on AWS and other public clouds.
|
|
@@ -198,7 +199,7 @@ one_in_many: Matches = search(vectors, vector, 50, MetricKind.L2sq, exact=True)
|
|
|
198
199
|
many_in_many: BatchMatches = search(vectors, vectors, 50, MetricKind.L2sq, exact=True)
|
|
199
200
|
```
|
|
200
201
|
|
|
201
|
-
|
|
202
|
+
If you pass the `exact=True` argument, the system bypasses indexing altogether and performs a brute-force search through the entire dataset using SIMD-optimized similarity metrics from [SimSIMD](https://github.com/ashvardanian/simsimd).
|
|
202
203
|
When compared to FAISS's `IndexFlatL2` in Google Colab, __[USearch may offer up to a 20x performance improvement](https://github.com/unum-cloud/usearch/issues/176#issuecomment-1666650778)__:
|
|
203
204
|
|
|
204
205
|
- `faiss.IndexFlatL2`: __55.3 ms__.
|
|
@@ -207,7 +208,7 @@ When compared to FAISS's `IndexFlatL2` in Google Colab, __[USearch may offer up
|
|
|
207
208
|
## `Indexes` for Multi-Index Lookups
|
|
208
209
|
|
|
209
210
|
For larger workloads targeting billions or even trillions of vectors, parallel multi-index lookups become invaluable.
|
|
210
|
-
|
|
211
|
+
Instead of constructing one extensive index, you can build multiple smaller ones and view them together.
|
|
211
212
|
|
|
212
213
|
```py
|
|
213
214
|
from usearch.index import Indexes
|
|
@@ -223,8 +224,8 @@ multi_index.search(...)
|
|
|
223
224
|
|
|
224
225
|
## Clustering
|
|
225
226
|
|
|
226
|
-
Once the index is constructed, it can
|
|
227
|
-
|
|
227
|
+
Once the index is constructed, it can cluster entries much faster than using a separate clustering algorithm implementation.
|
|
228
|
+
Essentially, the `Index` itself can be seen as a clustering, allowing iterative deepening.
|
|
228
229
|
|
|
229
230
|
```py
|
|
230
231
|
clustering = index.cluster(
|
|
@@ -236,7 +237,7 @@ clustering = index.cluster(
|
|
|
236
237
|
# Get the clusters and their sizes
|
|
237
238
|
centroid_keys, sizes = clustering.centroids_popularity
|
|
238
239
|
|
|
239
|
-
# Use Matplotlib draw a histogram
|
|
240
|
+
# Use Matplotlib to draw a histogram
|
|
240
241
|
clustering.plot_centroids_popularity()
|
|
241
242
|
|
|
242
243
|
# Export a NetworkX graph of the clusters
|
|
@@ -245,24 +246,26 @@ g = clustering.network
|
|
|
245
246
|
# Get members of a specific cluster
|
|
246
247
|
first_members = clustering.members_of(centroid_keys[0])
|
|
247
248
|
|
|
248
|
-
# Deepen into that cluster splitting it into more parts, all same arguments supported
|
|
249
|
+
# Deepen into that cluster, splitting it into more parts, all the same arguments supported
|
|
249
250
|
sub_clustering = clustering.subcluster(min_count=..., max_count=...)
|
|
250
251
|
```
|
|
251
252
|
|
|
252
|
-
|
|
253
|
+
The resulting clustering isn't identical to K-Means or other conventional approaches but serves the same purpose.
|
|
254
|
+
Alternatively, using Scikit-Learn on a 1 Million point dataset, one may expect queries to take anywhere from minutes to hours, depending on the number of clusters you want to highlight.
|
|
255
|
+
For 50'000 clusters, the performance difference between USearch and conventional clustering methods may easily reach 100x.
|
|
253
256
|
|
|
254
257
|
## Joins, One-to-One, One-to-Many, and Many-to-Many Mappings
|
|
255
258
|
|
|
256
|
-
One of the big questions these days is how will
|
|
259
|
+
One of the big questions these days is how AI will change the world of databases and data management.
|
|
257
260
|
Most databases are still struggling to implement high-quality fuzzy search, and the only kind of joins they know are deterministic.
|
|
258
|
-
A `join`
|
|
261
|
+
A `join` differs from searching for every entry, requiring a one-to-one mapping banning collisions among separate search results.
|
|
259
262
|
|
|
260
263
|
| Exact Search | Fuzzy Search | Semantic Search ? |
|
|
261
264
|
| :----------: | :----------: | :---------------: |
|
|
262
265
|
| Exact Join | Fuzzy Join ? | Semantic Join ?? |
|
|
263
266
|
|
|
264
|
-
Using USearch one can implement sub-quadratic complexity approximate, fuzzy, and semantic joins.
|
|
265
|
-
This can
|
|
267
|
+
Using USearch, one can implement sub-quadratic complexity approximate, fuzzy, and semantic joins.
|
|
268
|
+
This can be useful in any fuzzy-matching tasks common to Database Management Software.
|
|
266
269
|
|
|
267
270
|
```py
|
|
268
271
|
men = Index(...)
|
|
@@ -270,7 +273,7 @@ women = Index(...)
|
|
|
270
273
|
pairs: dict = men.join(women, max_proposals=0, exact=False)
|
|
271
274
|
```
|
|
272
275
|
|
|
273
|
-
> Read more in post: [
|
|
276
|
+
> Read more in the post: [Combinatorial Stable Marriages for Semantic Search 💍](https://ashvardanian.com/posts/searching-stable-marriages)
|
|
274
277
|
|
|
275
278
|
## Functionality
|
|
276
279
|
|
|
@@ -345,7 +348,7 @@ We have pre-processed some commonly used datasets, cleaned the images, produced
|
|
|
345
348
|
Comparing molecule graphs and searching for similar structures is expensive and slow.
|
|
346
349
|
It can be seen as a special case of the NP-Complete Subgraph Isomorphism problem.
|
|
347
350
|
Luckily, domain-specific approximate methods exist.
|
|
348
|
-
The one commonly used in Chemistry
|
|
351
|
+
The one commonly used in Chemistry is to generate structures from [SMILES][smiles] and later hash them into binary fingerprints.
|
|
349
352
|
The latter are searchable with binary similarity metrics, like the Tanimoto coefficient.
|
|
350
353
|
Below is an example using the RDKit package.
|
|
351
354
|
|
|
@@ -379,7 +382,7 @@ matches = index.search(fingerprints, 10)
|
|
|
379
382
|
With Objective-C and Swift iOS bindings, USearch can be easily used in mobile applications.
|
|
380
383
|
The [SwiftVectorSearch](https://github.com/ashvardanian/SwiftVectorSearch) project illustrates how to build a dynamic, real-time search system on iOS.
|
|
381
384
|
In this example, we use 2-dimensional vectors—encoded as latitude and longitude—to find the closest Points of Interest (POIs) on a map.
|
|
382
|
-
The search is based on the Haversine distance metric
|
|
385
|
+
The search is based on the Haversine distance metric but can easily be extended to support high-dimensional vectors.
|
|
383
386
|
|
|
384
387
|
## Integrations
|
|
385
388
|
|
|
@@ -397,7 +400,7 @@ doi = {10.5281/zenodo.7949416},
|
|
|
397
400
|
author = {Vardanian, Ash},
|
|
398
401
|
title = {{USearch by Unum Cloud}},
|
|
399
402
|
url = {https://github.com/unum-cloud/usearch},
|
|
400
|
-
version = {2.8.
|
|
403
|
+
version = {2.8.8},
|
|
401
404
|
year = {2023},
|
|
402
405
|
month = oct,
|
|
403
406
|
}
|
package/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.8.8
|
package/binding.gyp
CHANGED
|
@@ -3,14 +3,6 @@
|
|
|
3
3
|
{
|
|
4
4
|
"target_name": "usearch",
|
|
5
5
|
"sources": ["javascript/lib.cpp"],
|
|
6
|
-
"include_dirs": [
|
|
7
|
-
"<!@(node -p \"require('node-addon-api').include\")",
|
|
8
|
-
"include",
|
|
9
|
-
"fp16/include",
|
|
10
|
-
"simsimd/include",
|
|
11
|
-
],
|
|
12
|
-
"dependencies": ["<!(node -p \"require('node-addon-api').gyp\")"],
|
|
13
|
-
"defines": ["USEARCH_USE_SIMSIMD=1", "USEARCH_USE_NATIVE_F16=0"],
|
|
14
6
|
"cflags": [
|
|
15
7
|
"-fexceptions",
|
|
16
8
|
"-Wno-unknown-pragmas",
|
|
@@ -22,6 +14,13 @@
|
|
|
22
14
|
"-Wno-maybe-uninitialized",
|
|
23
15
|
"-std=c++17",
|
|
24
16
|
],
|
|
17
|
+
"include_dirs": [
|
|
18
|
+
"<!@(node -p \"require('node-addon-api').include\")",
|
|
19
|
+
"include",
|
|
20
|
+
"fp16/include",
|
|
21
|
+
"simsimd/include",
|
|
22
|
+
],
|
|
23
|
+
"dependencies": ["<!(node -p \"require('node-addon-api').gyp\")"],
|
|
25
24
|
"xcode_settings": {
|
|
26
25
|
"GCC_ENABLE_CPP_EXCEPTIONS": "YES",
|
|
27
26
|
"CLANG_CXX_LIBRARY": "libc++",
|
|
@@ -33,6 +32,56 @@
|
|
|
33
32
|
"AdditionalOptions": ["-std:c++17"],
|
|
34
33
|
}
|
|
35
34
|
},
|
|
35
|
+
"conditions": [
|
|
36
|
+
[
|
|
37
|
+
'OS=="linux"',
|
|
38
|
+
{
|
|
39
|
+
"cflags_cc": [
|
|
40
|
+
'<!(if [ "$USEARCH_USE_OPENMP" = "1" ]; then echo \'-fopenmp\'; fi)',
|
|
41
|
+
],
|
|
42
|
+
"ldflags": [
|
|
43
|
+
'<!(if [ "$USEARCH_USE_OPENMP" = "1" ]; then echo \'-lgomp\'; fi)'
|
|
44
|
+
],
|
|
45
|
+
"defines": [
|
|
46
|
+
"USEARCH_USE_OPENMP=<!(echo ${USEARCH_USE_OPENMP:-0})",
|
|
47
|
+
"USEARCH_USE_SIMSIMD=<!(echo ${USEARCH_USE_SIMSIMD:-1})",
|
|
48
|
+
"USEARCH_USE_FP16LIB=<!(echo ${USEARCH_USE_FP16LIB:-1})",
|
|
49
|
+
"SIMSIMD_TARGET_X86_AVX512=<!(echo ${SIMSIMD_TARGET_X86_AVX512:-1})",
|
|
50
|
+
"SIMSIMD_TARGET_ARM_SVE=<!(echo ${SIMSIMD_TARGET_ARM_SVE:-1})",
|
|
51
|
+
"SIMSIMD_TARGET_X86_AVX2=<!(echo ${SIMSIMD_TARGET_X86_AVX2:-1})",
|
|
52
|
+
"SIMSIMD_TARGET_ARM_NEON=<!(echo ${SIMSIMD_TARGET_ARM_NEON:-1})",
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
[
|
|
57
|
+
'OS=="mac"',
|
|
58
|
+
{
|
|
59
|
+
"defines": [
|
|
60
|
+
"USEARCH_USE_OPENMP=<!(echo ${USEARCH_USE_OPENMP:-0})",
|
|
61
|
+
"USEARCH_USE_SIMSIMD=<!(echo ${USEARCH_USE_SIMSIMD:-0})",
|
|
62
|
+
"USEARCH_USE_FP16LIB=<!(echo ${USEARCH_USE_FP16LIB:-1})",
|
|
63
|
+
"SIMSIMD_TARGET_X86_AVX512=<!(echo ${SIMSIMD_TARGET_X86_AVX512:-0})",
|
|
64
|
+
"SIMSIMD_TARGET_ARM_SVE=<!(echo ${SIMSIMD_TARGET_ARM_SVE:-0})",
|
|
65
|
+
"SIMSIMD_TARGET_X86_AVX2=<!(echo ${SIMSIMD_TARGET_X86_AVX2:-1})",
|
|
66
|
+
"SIMSIMD_TARGET_ARM_NEON=<!(echo ${SIMSIMD_TARGET_ARM_NEON:-1})",
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
[
|
|
71
|
+
'OS=="win"',
|
|
72
|
+
{
|
|
73
|
+
"defines": [
|
|
74
|
+
"USEARCH_USE_OPENMP=0",
|
|
75
|
+
"USEARCH_USE_SIMSIMD=0",
|
|
76
|
+
"USEARCH_USE_FP16LIB=1",
|
|
77
|
+
"SIMSIMD_TARGET_X86_AVX512=0",
|
|
78
|
+
"SIMSIMD_TARGET_ARM_SVE=0",
|
|
79
|
+
"SIMSIMD_TARGET_X86_AVX2=0",
|
|
80
|
+
"SIMSIMD_TARGET_ARM_NEON=0",
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
],
|
|
36
85
|
}
|
|
37
86
|
]
|
|
38
87
|
}
|
package/conanfile.py
CHANGED
|
@@ -7,7 +7,7 @@ required_conan_version = ">=1.53.0"
|
|
|
7
7
|
class USearchConan(ConanFile):
|
|
8
8
|
|
|
9
9
|
name = "usearch"
|
|
10
|
-
version = '2.8.
|
|
10
|
+
version = '2.8.8'
|
|
11
11
|
license = "Apache-2.0"
|
|
12
12
|
description = "Smaller & Faster Single-File Vector Search Engine from Unum"
|
|
13
13
|
homepage = "https://github.com/unum-cloud/usearch"
|
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
|
|
14
14
|
#include <usearch/index.hpp> // `expected_gt` and macros
|
|
15
15
|
|
|
16
|
+
#if !defined(USEARCH_USE_OPENMP)
|
|
17
|
+
#define USEARCH_USE_OPENMP 0
|
|
18
|
+
#endif
|
|
19
|
+
|
|
16
20
|
#if USEARCH_USE_OPENMP
|
|
17
21
|
#include <omp.h> // `omp_get_num_threads()`
|
|
18
22
|
#endif
|
|
@@ -21,18 +25,18 @@
|
|
|
21
25
|
#include <sys/auxv.h> // `getauxval()`
|
|
22
26
|
#endif
|
|
23
27
|
|
|
24
|
-
#if !defined(
|
|
28
|
+
#if !defined(USEARCH_USE_FP16LIB)
|
|
25
29
|
#if defined(__AVX512F__)
|
|
26
|
-
#define
|
|
30
|
+
#define USEARCH_USE_FP16LIB 0
|
|
27
31
|
#elif defined(USEARCH_DEFINED_ARM)
|
|
28
32
|
#include <arm_fp16.h> // `__fp16`
|
|
29
|
-
#define
|
|
33
|
+
#define USEARCH_USE_FP16LIB 0
|
|
30
34
|
#else
|
|
31
|
-
#define
|
|
35
|
+
#define USEARCH_USE_FP16LIB 1
|
|
32
36
|
#endif
|
|
33
37
|
#endif
|
|
34
38
|
|
|
35
|
-
#if
|
|
39
|
+
#if USEARCH_USE_FP16LIB
|
|
36
40
|
#include <fp16/fp16.h>
|
|
37
41
|
#endif
|
|
38
42
|
|
|
@@ -41,27 +45,27 @@
|
|
|
41
45
|
#endif
|
|
42
46
|
|
|
43
47
|
#if USEARCH_USE_SIMSIMD
|
|
48
|
+
|
|
44
49
|
// Propagate the `f16` settings
|
|
45
|
-
#define SIMSIMD_NATIVE_F16
|
|
46
|
-
|
|
50
|
+
#define SIMSIMD_NATIVE_F16 !USEARCH_USE_FP16LIB
|
|
51
|
+
|
|
52
|
+
#if !defined(SIMSIMD_TARGET_X86_AVX512) && defined(USEARCH_DEFINED_LINUX)
|
|
47
53
|
#define SIMSIMD_TARGET_X86_AVX512 1
|
|
54
|
+
#endif
|
|
55
|
+
|
|
56
|
+
#if !defined(SIMSIMD_TARGET_ARM_SVE) && defined(USEARCH_DEFINED_LINUX)
|
|
48
57
|
#define SIMSIMD_TARGET_ARM_SVE 1
|
|
58
|
+
#endif
|
|
59
|
+
|
|
60
|
+
#if !defined(SIMSIMD_TARGET_X86_AVX2) && (defined(USEARCH_DEFINED_LINUX) || defined(USEARCH_DEFINED_APPLE))
|
|
49
61
|
#define SIMSIMD_TARGET_X86_AVX2 1
|
|
62
|
+
#endif
|
|
63
|
+
|
|
64
|
+
#if !defined(SIMSIMD_TARGET_ARM_NEON) && (defined(USEARCH_DEFINED_LINUX) || defined(USEARCH_DEFINED_APPLE))
|
|
50
65
|
#define SIMSIMD_TARGET_ARM_NEON 1
|
|
51
|
-
#include <simsimd/simsimd.h>
|
|
52
|
-
#elif defined(USEARCH_DEFINED_APPLE)
|
|
53
|
-
#define SIMSIMD_TARGET_X86_AVX512 0
|
|
54
|
-
#define SIMSIMD_TARGET_ARM_SVE 0
|
|
55
|
-
#define SIMSIMD_TARGET_X86_AVX2 1
|
|
56
|
-
#define SIMSIMD_TARGET_ARM_NEON 1
|
|
57
|
-
#include <simsimd/simsimd.h>
|
|
58
|
-
#else
|
|
59
|
-
#define SIMSIMD_TARGET_X86_AVX512 0
|
|
60
|
-
#define SIMSIMD_TARGET_ARM_SVE 0
|
|
61
|
-
#define SIMSIMD_TARGET_X86_AVX2 0
|
|
62
|
-
#define SIMSIMD_TARGET_ARM_NEON 0
|
|
63
|
-
#include <simsimd/simsimd.h>
|
|
64
66
|
#endif
|
|
67
|
+
|
|
68
|
+
#include <simsimd/simsimd.h>
|
|
65
69
|
#endif
|
|
66
70
|
|
|
67
71
|
namespace unum {
|
|
@@ -77,7 +81,7 @@ struct uuid_t {
|
|
|
77
81
|
class f16_bits_t;
|
|
78
82
|
class i8_converted_t;
|
|
79
83
|
|
|
80
|
-
#if
|
|
84
|
+
#if !USEARCH_USE_FP16LIB
|
|
81
85
|
#if defined(USEARCH_DEFINED_ARM)
|
|
82
86
|
using f16_native_t = __fp16;
|
|
83
87
|
#else
|
|
@@ -298,7 +302,7 @@ inline expected_gt<metric_kind_t> metric_from_name(char const* name) {
|
|
|
298
302
|
}
|
|
299
303
|
|
|
300
304
|
inline float f16_to_f32(std::uint16_t u16) noexcept {
|
|
301
|
-
#if
|
|
305
|
+
#if !USEARCH_USE_FP16LIB
|
|
302
306
|
f16_native_t f16;
|
|
303
307
|
std::memcpy(&f16, &u16, sizeof(std::uint16_t));
|
|
304
308
|
return float(f16);
|
|
@@ -308,7 +312,7 @@ inline float f16_to_f32(std::uint16_t u16) noexcept {
|
|
|
308
312
|
}
|
|
309
313
|
|
|
310
314
|
inline std::uint16_t f32_to_f16(float f32) noexcept {
|
|
311
|
-
#if
|
|
315
|
+
#if !USEARCH_USE_FP16LIB
|
|
312
316
|
f16_native_t f16 = f16_native_t(f32);
|
|
313
317
|
std::uint16_t u16;
|
|
314
318
|
std::memcpy(&u16, &f16, sizeof(std::uint16_t));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "usearch",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.8",
|
|
4
4
|
"description": "Smaller & Faster Single-File Vector Search Engine from Unum",
|
|
5
5
|
"author": "Ash Vardanian (https://ashvardanian.com/)",
|
|
6
6
|
"license": "Apache 2.0",
|
|
@@ -24,9 +24,10 @@
|
|
|
24
24
|
"node-addon-api": "^3.0.0"
|
|
25
25
|
},
|
|
26
26
|
"scripts": {
|
|
27
|
-
"test": "node --test ./javascript/usearch.test.js"
|
|
27
|
+
"test": "node --test ./javascript/usearch.test.js",
|
|
28
|
+
"install": "node-gyp rebuild"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
31
|
"typescript": "^5.1.6"
|
|
31
32
|
}
|
|
32
|
-
}
|
|
33
|
+
}
|