usearch 2.8.2 → 2.8.4
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/.github/workflows/release.yml +1 -1
- package/.vscode/settings.json +1 -0
- package/CITATION.cff +1 -1
- package/CONTRIBUTING.md +258 -6
- package/Cargo.toml +1 -1
- package/README.md +57 -53
- package/conanfile.py +1 -1
- package/cpp/README.md +89 -21
- package/csharp/DEV_SETUP.md +1 -1
- package/csharp/nuget/nuget-package.props +1 -1
- package/docs/{compilation.rst → contributing.rst} +2 -2
- package/docs/index.rst +1 -1
- package/include/usearch/index.hpp +7 -6
- package/include/usearch/index_dense.hpp +11 -7
- package/javascript/usearch.js +4 -4
- package/javascript/usearch.test.js +22 -0
- package/package-ci.json +10 -0
- package/package.json +1 -5
- package/python/README.md +1 -1
- package/simsimd/CMakeLists.txt +1 -1
- package/simsimd/README.md +7 -1
- package/simsimd/include/simsimd/probability.h +24 -24
- package/simsimd/include/simsimd/types.h +8 -0
- package/simsimd/javascript/{test.js → test/simsimd.test.js} +15 -15
- package/simsimd/package.json +4 -8
- package/simsimd/setup.py +3 -0
- package/wasmer.toml +1 -1
- package/docs/compilation.md +0 -215
- package/simsimd/.clang-format +0 -10
- package/simsimd/.github/workflows/prerelease.yml +0 -89
- package/simsimd/.github/workflows/release.yml +0 -141
- package/simsimd/.github/workflows/update_version.sh +0 -5
- package/simsimd/.vscode/launch.json +0 -53
- package/simsimd/.vscode/settings.json +0 -114
- package/simsimd/.vscode/tasks.json +0 -23
- package/simsimd/go.mod +0 -3
- package/simsimd/golang/bench_test.go +0 -40
- package/simsimd/golang/simsimd.go +0 -47
- package/simsimd/golang/unit_test.go +0 -40
- package/simsimd/pyproject.toml +0 -42
- package/simsimd/python/bench.ipynb +0 -187
- package/simsimd/python/bench.py +0 -268
- package/simsimd/python/lib.c +0 -492
- package/simsimd/python/test.py +0 -195
|
@@ -25,7 +25,7 @@ jobs:
|
|
|
25
25
|
with:
|
|
26
26
|
persist-credentials: false
|
|
27
27
|
- uses: actions/setup-node@v3
|
|
28
|
-
- run: npm install --save-dev @semantic-release/exec @semantic-release/git conventional-changelog-eslint semantic-release && npx semantic-release
|
|
28
|
+
- run: npm install --save-dev --prefix ./package-ci @semantic-release/exec @semantic-release/git conventional-changelog-eslint semantic-release && npx --prefix ./package-ci semantic-release
|
|
29
29
|
|
|
30
30
|
rebase:
|
|
31
31
|
name: Rebase Dev. Branch
|
package/.vscode/settings.json
CHANGED
package/CITATION.cff
CHANGED
package/CONTRIBUTING.md
CHANGED
|
@@ -1,12 +1,264 @@
|
|
|
1
1
|
# Contribution Guide
|
|
2
2
|
|
|
3
|
-
Thank you for
|
|
4
|
-
It's always nice to have third-party contributors
|
|
3
|
+
Thank you for coming here!
|
|
4
|
+
It's always nice to have third-party contributors 🤗
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
To keep the quality of the code high, we have a set of guidelines common to all Unum projects.
|
|
8
|
+
To keep the quality of the code high, we have a set of guidelines common to [all Unum projects](https://github.com/unum-cloud).
|
|
9
9
|
|
|
10
|
-
-
|
|
11
|
-
- How to organize branches?
|
|
12
|
-
- How to style commits?
|
|
10
|
+
- [What's the procedure?](https://github.com/unum-cloud/awesome/blob/main/Workflow.md#organizing-software-development)
|
|
11
|
+
- [How to organize branches?](https://github.com/unum-cloud/awesome/blob/main/Workflow.md#branches)
|
|
12
|
+
- [How to style commits?](https://github.com/unum-cloud/awesome/blob/main/Workflow.md#commits)
|
|
13
|
+
|
|
14
|
+
## Before you start
|
|
15
|
+
|
|
16
|
+
Before building the first time, please pull `git` submodules.
|
|
17
|
+
That's how we bring in SimSIMD and other optional dependencies to test all of the available functionality.
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
git submodule update --init --recursive
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## C++ 11 and C 99
|
|
24
|
+
|
|
25
|
+
Our primary C++ implementation uses CMake for builds.
|
|
26
|
+
If this is your first experience with CMake, use the following commands to get started:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
sudo apt-get update && sudo apt-get install cmake build-essential libjemalloc-dev g++-12 gcc-12 # Ubuntu
|
|
30
|
+
brew install libomp llvm # MacOS
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Using modern syntax, this is how you build and run the test suite:
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
cmake -DUSEARCH_BUILD_TEST_CPP=1 -B ./build_debug
|
|
37
|
+
cmake --build ./build_debug --config Debug
|
|
38
|
+
./build_debug/test_cpp
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The CMakeLists.txt file has a number of options you can pass:
|
|
42
|
+
|
|
43
|
+
- What to build:
|
|
44
|
+
- `USEARCH_BUILD_TEST_CPP` - build the C++ test suite
|
|
45
|
+
- `USEARCH_BUILD_BENCH_CPP` - build the C++ benchmark suite
|
|
46
|
+
- `USEARCH_BUILD_LIB_C` - build the C library
|
|
47
|
+
- `USEARCH_BUILD_TEST_C` - build the C test suite
|
|
48
|
+
- Which dependencies to use:
|
|
49
|
+
- `USEARCH_USE_OPENMP` - use OpenMP for parallelism
|
|
50
|
+
- `USEARCH_USE_SIMSIMD` - use SimSIMD for vectorization
|
|
51
|
+
- `USEARCH_USE_JEMALLOC` - use Jemalloc for memory management
|
|
52
|
+
- `USEARCH_USE_NATIVE_F16` - use native half-precision floating point
|
|
53
|
+
|
|
54
|
+
Putting all of this together on Ubuntu and compiling the "release" version using the GCC 12 compiler:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
cmake \
|
|
58
|
+
-DCMAKE_BUILD_TYPE=Release \
|
|
59
|
+
-DCMAKE_C_COMPILER=gcc-12 \
|
|
60
|
+
-DCMAKE_CXX_COMPILER=g++-12 \
|
|
61
|
+
-DUSEARCH_USE_NATIVE_F16=1 \
|
|
62
|
+
-DUSEARCH_USE_OPENMP=1 \
|
|
63
|
+
-DUSEARCH_USE_SIMSIMD=1 \
|
|
64
|
+
-DUSEARCH_USE_JEMALLOC=1 \
|
|
65
|
+
-DUSEARCH_BUILD_TEST_CPP=1 \
|
|
66
|
+
-DUSEARCH_BUILD_BENCH_CPP=1 \
|
|
67
|
+
-DUSEARCH_BUILD_LIB_C=1 \
|
|
68
|
+
-DUSEARCH_BUILD_TEST_C=1 \
|
|
69
|
+
-B ./build_release
|
|
70
|
+
|
|
71
|
+
cmake --build ./build_release --config Release
|
|
72
|
+
./build_release/test_cpp
|
|
73
|
+
./build_release/test_c
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Similarly, to use the most recent Clang compiler version from HomeBrew on MacOS:
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
cmake \
|
|
80
|
+
-DCMAKE_BUILD_TYPE=Release \
|
|
81
|
+
-DCMAKE_C_COMPILER="/opt/homebrew/opt/llvm/bin/clang" \
|
|
82
|
+
-DCMAKE_CXX_COMPILER="/opt/homebrew/opt/llvm/bin/clang++" \
|
|
83
|
+
-DUSEARCH_USE_NATIVE_F16=1 \
|
|
84
|
+
-DUSEARCH_USE_OPENMP=1 \
|
|
85
|
+
-DUSEARCH_USE_SIMSIMD=1 \
|
|
86
|
+
-DUSEARCH_USE_JEMALLOC=1 \
|
|
87
|
+
-DUSEARCH_BUILD_TEST_CPP=1 \
|
|
88
|
+
-DUSEARCH_BUILD_BENCH_CPP=1 \
|
|
89
|
+
-DUSEARCH_BUILD_LIB_C=1 \
|
|
90
|
+
-DUSEARCH_BUILD_TEST_C=1 \
|
|
91
|
+
-B ./build_release
|
|
92
|
+
|
|
93
|
+
cmake --build ./build_release --config Release
|
|
94
|
+
./build_release/test_cpp
|
|
95
|
+
./build_release/test_c
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Linting:
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
cppcheck --enable=all --force --suppress=cstyleCast --suppress=unusedFunction \
|
|
102
|
+
include/usearch/index.hpp \
|
|
103
|
+
include/index_dense.hpp \
|
|
104
|
+
include/index_plugins.hpp
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Python 3
|
|
108
|
+
|
|
109
|
+
Python bindings are built using PyBind11 and are available on [PyPi](https://pypi.org/project/usearch/).
|
|
110
|
+
The compilation settings are controlled by the `setup.py` and are independent from CMake used for C/C++ builds.
|
|
111
|
+
Use PyTest to validate the build.
|
|
112
|
+
|
|
113
|
+
- The `-s` option will disable capturing the logs.
|
|
114
|
+
- The `-x` option will exit after first failure to simplify debugging.
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
pip install -e . && pytest python/scripts/ -s -x
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Linting:
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
pip install ruff
|
|
124
|
+
ruff --format=github --select=E9,F63,F7,F82 --target-version=py37 python
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Before merging your changes you may want to test your changes against the entire matrix of Python versions USearch supports.
|
|
128
|
+
For that you need the `cibuildwheel`, which is tricky to use on MacOS and Windows, as it would target just the local environment.
|
|
129
|
+
Still, if you have Docker running on any desktop OS, you can use it to build and test the Python bindings for all Python versions for Linux:
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
pip install cibuildwheel
|
|
133
|
+
cibuildwheel --platform linux
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## JavaScript
|
|
137
|
+
|
|
138
|
+
USearch provides NAPI bindings for NodeJS available on [NPM](https://www.npmjs.com/package/usearch).
|
|
139
|
+
The compilation settings are controlled by the `binding.gyp` and are independent from CMake used for C/C++ builds.
|
|
140
|
+
|
|
141
|
+
```sh
|
|
142
|
+
npm install
|
|
143
|
+
node --test ./javascript/usearch.test.js
|
|
144
|
+
npm publish
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
To compile to WebAssembly make sure you have `emscripten` installed and run the following script:
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
emcmake cmake -B ./build -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -s TOTAL_MEMORY=64MB" && emmake make -C ./build
|
|
151
|
+
node ./build/usearch.test.js
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
If you don't yet have `emcmake` installed:
|
|
155
|
+
|
|
156
|
+
```sh
|
|
157
|
+
git clone https://github.com/emscripten-core/emsdk.git && ./emsdk/emsdk install latest && ./emsdk/emsdk activate latest && source ./emsdk/emsdk_env.sh
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Rust
|
|
161
|
+
|
|
162
|
+
USearch provides Rust bindings available on [Crates.io](https://crates.io/crates/usearch).
|
|
163
|
+
The compilation settings are controlled by the `build.rs` and are independent from CMake used for C/C++ builds.
|
|
164
|
+
|
|
165
|
+
```sh
|
|
166
|
+
cargo test -p usearch
|
|
167
|
+
cargo publish
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Objective-C and Swift
|
|
171
|
+
|
|
172
|
+
USearch provides both Objective-C and Swift bindings through the [Swift Package Manager](https://swiftpackageindex.com/unum-cloud/usearch).
|
|
173
|
+
The compilation settings are controlled by the `Package.swift` and are independent from CMake used for C/C++ builds.
|
|
174
|
+
|
|
175
|
+
```sh
|
|
176
|
+
swift build
|
|
177
|
+
swift test -v
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## GoLang
|
|
181
|
+
|
|
182
|
+
USearch provides GoLang bindings, that depend on the C library that must be installed beforehand.
|
|
183
|
+
So one should first compile the C library, link it with GoLang, and only then run tests.
|
|
184
|
+
|
|
185
|
+
```sh
|
|
186
|
+
cmake -B ./build_release -DUSEARCH_BUILD_LIB_C=1 -DUSEARCH_BUILD_TEST_C=1 -DUSEARCH_USE_OPENMP=1 -DUSEARCH_USE_SIMSIMD=1
|
|
187
|
+
cmake --build ./build_release --config Release -j
|
|
188
|
+
|
|
189
|
+
mv ./c/libusearch_c.so ./golang/ # or .dylib to install the library on MacOS
|
|
190
|
+
cp ./c/usearch.h ./golang/ # to make the header available to GoLang
|
|
191
|
+
|
|
192
|
+
cd golang && go test -v ; cd ..
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Java
|
|
196
|
+
|
|
197
|
+
USearch provides Java bindings available from the [GitHub Maven registry](https://github.com/unum-cloud/usearch/packages/1867475).
|
|
198
|
+
The compilation settings are controlled by the `build.gradle` and are independent from CMake used for C/C++ builds.
|
|
199
|
+
|
|
200
|
+
```sh
|
|
201
|
+
gradle clean build
|
|
202
|
+
java -cp . -Djava.library.path="$(pwd)/build/libs/usearch/shared" java/cloud/unum/usearch/Index.java
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Or step by-step:
|
|
206
|
+
|
|
207
|
+
```sh
|
|
208
|
+
cs java/unum/cloud/usearch
|
|
209
|
+
javac -h . Index.java
|
|
210
|
+
|
|
211
|
+
# Ubuntu:
|
|
212
|
+
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
|
|
213
|
+
g++ -shared -fPIC -o libusearch_c.so cloud_unum_usearch_Index.o -lc
|
|
214
|
+
|
|
215
|
+
# Windows
|
|
216
|
+
g++ -c -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
|
|
217
|
+
g++ -shared -o USearchJNI.dll cloud_unum_usearch_Index.o -Wl,--add-stdcall-alias
|
|
218
|
+
|
|
219
|
+
# MacOS
|
|
220
|
+
g++ -std=c++11 -c -fPIC \
|
|
221
|
+
-I../../../../include \
|
|
222
|
+
-I../../../../fp16/include \
|
|
223
|
+
-I../../../../simsimd/include \
|
|
224
|
+
-I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
|
|
225
|
+
g++ -dynamiclib -o libusearch.dylib cloud_unum_usearch_Index.o -lc
|
|
226
|
+
# Run linking to that directory
|
|
227
|
+
java -cp . -Djava.library.path="$(pwd)/java/cloud/unum/usearch/" Index.java
|
|
228
|
+
java -cp . -Djava.library.path="$(pwd)/java" cloud.unum.usearch.Index
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Wolfram
|
|
232
|
+
|
|
233
|
+
```sh
|
|
234
|
+
brew install --cask wolfram-engine
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Docker
|
|
238
|
+
|
|
239
|
+
```sh
|
|
240
|
+
docker build -t unum/usearch . && docker run unum/usearch
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
For multi-architecture builds and publications:
|
|
244
|
+
|
|
245
|
+
```sh
|
|
246
|
+
version=$(cat VERSION)
|
|
247
|
+
docker buildx create --use &&
|
|
248
|
+
docker login &&
|
|
249
|
+
docker buildx build \
|
|
250
|
+
--platform "linux/amd64,linux/arm64" \
|
|
251
|
+
--build-arg version=$version \
|
|
252
|
+
--file Dockerfile \
|
|
253
|
+
--tag unum/usearch:$version \
|
|
254
|
+
--tag unum/usearch:latest \
|
|
255
|
+
--push .
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Working on Sub-Modules
|
|
259
|
+
|
|
260
|
+
Extending metrics in SimSIMD:
|
|
261
|
+
|
|
262
|
+
```sh
|
|
263
|
+
git push --set-upstream https://github.com/ashvardanian/simsimd.git HEAD:main
|
|
264
|
+
```
|
package/Cargo.toml
CHANGED
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<h1 align="center">USearch</h1>
|
|
2
2
|
<h3 align="center">
|
|
3
|
-
|
|
4
|
-
Search Engine for Vectors & Texts
|
|
3
|
+
Smaller & <a href="https://www.unum.cloud/blog/2023-11-11-scaling-vector-search">Faster</a> Single-File<br/>
|
|
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/>
|
|
7
7
|
|
|
@@ -18,7 +18,7 @@ Search Engine for Vectors & Texts<br/>
|
|
|
18
18
|
</p>
|
|
19
19
|
|
|
20
20
|
<p align="center">
|
|
21
|
-
|
|
21
|
+
Spatial • Binary • Probabilistic • User-Defined Metrics
|
|
22
22
|
<br/>
|
|
23
23
|
<a href="https://unum-cloud.github.io/usearch/cpp">C++ 11</a> •
|
|
24
24
|
<a href="https://unum-cloud.github.io/usearch/python">Python 3</a> •
|
|
@@ -32,7 +32,7 @@ Euclidean • Angular • Bitwise • Haversine • User-Defined Metrics
|
|
|
32
32
|
<a href="https://unum-cloud.github.io/usearch/golang">GoLang</a> •
|
|
33
33
|
<a href="https://unum-cloud.github.io/usearch/wolfram">Wolfram</a>
|
|
34
34
|
<br/>
|
|
35
|
-
Linux • MacOS • Windows • iOS •
|
|
35
|
+
Linux • MacOS • Windows • iOS • WebAssembly
|
|
36
36
|
</p>
|
|
37
37
|
|
|
38
38
|
<div align="center">
|
|
@@ -46,40 +46,57 @@ Linux • MacOS • Windows • iOS • Docker • WebAssembly
|
|
|
46
46
|
|
|
47
47
|
---
|
|
48
48
|
|
|
49
|
-
- ✅
|
|
49
|
+
- ✅ 10x faster than [FAISS][faiss] implementation of [HNSW algorithm][hnsw-algorithm].
|
|
50
50
|
- ✅ Simple and extensible [single C++11 header][usearch-header] implementation.
|
|
51
|
-
- ✅
|
|
52
|
-
- ✅
|
|
53
|
-
- ✅ Bitwise Tanimoto and Sorensen coefficients for [Genomics and Chemistry applications](#usearch--rdkit--molecular-search).
|
|
51
|
+
- ✅ Compatible with a dozen programming languages out of the box.
|
|
52
|
+
- ✅ [SIMD][simd]-optimized and [user-defined metrics](#user-defined-functions) with JIT compilation.
|
|
54
53
|
- ✅ Hardware-agnostic `f16` & `i8` - [half-precision & quarter-precision support](#memory-efficiency-downcasting-and-quantization).
|
|
55
54
|
- ✅ [View large indexes from disk](#serving-index-from-disk) without loading into RAM.
|
|
55
|
+
- ✅ Heterogeneous lookups, renaming/relabeling, and on-the-fly deletions.
|
|
56
|
+
- ✅ Variable dimensionality vectors for unique applications, including search over compressed data.
|
|
57
|
+
- ✅ Binary Tanimoto and Sorensen coefficients for [Genomics and Chemistry applications](#usearch--rdkit--molecular-search).
|
|
56
58
|
- ✅ Space-efficient point-clouds with `uint40_t`, accommodating 4B+ size.
|
|
57
59
|
- ✅ Compatible with OpenMP and custom "executors", for fine-grained control over CPU utilization.
|
|
58
|
-
- ✅
|
|
59
|
-
- ✅ Near-real-time [clustering and sub-clusterings](#clustering) for Tens or Millions of clusters.
|
|
60
|
+
- ✅ Near-real-time [clustering and sub-clustering](#clustering) for Tens or Millions of clusters.
|
|
60
61
|
- ✅ [Semantic Search](#usearch--ai--multi-modal-semantic-search) and [Joins](#joins).
|
|
61
62
|
|
|
63
|
+
[faiss]: https://github.com/facebookresearch/faiss
|
|
62
64
|
[usearch-header]: https://github.com/unum-cloud/usearch/blob/main/include/usearch/index.hpp
|
|
63
65
|
[obscure-use-cases]: https://ashvardanian.com/posts/abusing-vector-search
|
|
66
|
+
[hnsw-algorithm]: https://arxiv.org/abs/1603.09320
|
|
67
|
+
[simd]: https://en.wikipedia.org/wiki/Single_instruction,_multiple_data
|
|
64
68
|
|
|
65
69
|
## Comparison with FAISS
|
|
66
70
|
|
|
67
71
|
FAISS is a widely recognized standard for high-performance vector search engines.
|
|
68
72
|
USearch and FAISS both employ the same HNSW algorithm, but they differ significantly in their design principles.
|
|
69
|
-
USearch is compact and broadly compatible without sacrificing performance,
|
|
70
|
-
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
73
|
+
USearch is compact and broadly compatible without sacrificing performance, primarily focusing on user-defined metrics and fewer dependencies.
|
|
74
|
+
|
|
75
|
+
| | FAISS | USearch | Improvement |
|
|
76
|
+
| :------------------------------------------- | ----------------------------: | -----------------------------: | -----------------------: |
|
|
77
|
+
| Indexing time | | | |
|
|
78
|
+
| 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__ ⁰ |
|
|
79
|
+
| 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__ ⁰ |
|
|
80
|
+
| | | | |
|
|
81
|
+
| Codebase length | 84 K [SLOC][sloc] in `faiss/` | 3 K [SLOC][sloc] in `usearch/` | maintainable ¹ |
|
|
82
|
+
| Supported metrics | 9 fixed metrics | any user-defined metrics | extendible ² |
|
|
83
|
+
| Supported languages | C++, Python | 10 languages | portable ³ |
|
|
84
|
+
| Supported ID types | 32-bit, 64-bit | 32-bit, 40-bit, 64-bit | efficient ⁴ |
|
|
85
|
+
| Required dependencies | BLAS, OpenMP | - | light-weight ⁵ |
|
|
86
|
+
| Bindings | SWIG | Native | low-latency ⁶ |
|
|
80
87
|
|
|
81
88
|
[sloc]: https://en.wikipedia.org/wiki/Source_lines_of_code
|
|
82
89
|
|
|
90
|
+
> ⁰ [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.
|
|
91
|
+
> ¹ A shorter codebase makes the project easier to maintain and audit.
|
|
92
|
+
> ² 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.
|
|
93
|
+
> ³ With USearch, you can reuse the same preconstructed index in various programming languages.
|
|
94
|
+
> ⁴ The 40-bit integer allows you to store 4B+ vectors without allocating 8 bytes for every neighbor reference in the proximity graph.
|
|
95
|
+
> ⁵ Lack of obligatory dependencies makes USearch much more portable.
|
|
96
|
+
> ⁶ Native bindings introduce lower call latencies than more straightforward approaches.
|
|
97
|
+
|
|
98
|
+
[intel-benchmarks]: https://www.unum.cloud/blog/2023-11-11-scaling-vector-search
|
|
99
|
+
|
|
83
100
|
Base functionality is identical to FAISS, and the interface must be familiar if you have ever investigated Approximate Nearest Neighbors search:
|
|
84
101
|
|
|
85
102
|
```py
|
|
@@ -88,44 +105,30 @@ $ pip install usearch
|
|
|
88
105
|
import numpy as np
|
|
89
106
|
from usearch.index import Index
|
|
90
107
|
|
|
91
|
-
index = Index(
|
|
92
|
-
ndim=3, # Define the number of dimensions in input vectors
|
|
93
|
-
metric='cos', # Choose 'l2sq', 'haversine' or other metric, default = 'ip'
|
|
94
|
-
dtype='f32', # Quantize to 'f16' or 'i8' if needed, default = 'f32'
|
|
95
|
-
connectivity=16, # Optional: How frequent should the connections in the graph be
|
|
96
|
-
expansion_add=128, # Optional: Control the recall of indexing
|
|
97
|
-
expansion_search=64, # Optional: Control the quality of search
|
|
98
|
-
)
|
|
108
|
+
index = Index(ndim=3)
|
|
99
109
|
|
|
100
110
|
vector = np.array([0.2, 0.6, 0.4])
|
|
101
111
|
index.add(42, vector)
|
|
112
|
+
|
|
102
113
|
matches = index.search(vector, 10)
|
|
103
114
|
|
|
104
|
-
assert len(index) == 1
|
|
105
|
-
assert len(matches) == 1
|
|
106
115
|
assert matches[0].key == 42
|
|
107
116
|
assert matches[0].distance <= 0.001
|
|
108
117
|
assert np.allclose(index[42], vector)
|
|
109
118
|
```
|
|
110
119
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
| | FAISS, `f32` | USearch, `f32` | USearch, `f16` | USearch, `i8` |
|
|
114
|
-
| :----------- | -----------: | -------------: | -------------: | ----------------: |
|
|
115
|
-
| Batch Insert | 16 K/s | 73 K/s | 100 K/s | 104 K/s __+550%__ |
|
|
116
|
-
| Batch Search | 82 K/s | 103 K/s | 113 K/s | 134 K/s __+63%__ |
|
|
117
|
-
| Bulk Insert | 76 K/s | 105 K/s | 115 K/s | 202 K/s __+165%__ |
|
|
118
|
-
| Bulk Search | 118 K/s | 174 K/s | 173 K/s | 304 K/s __+157%__ |
|
|
119
|
-
| Recall @ 10 | 99% | 99.2% | 99.1% | 99.2% |
|
|
120
|
+
More settings are always available, and the API is designed to be as flexible as possible.
|
|
120
121
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
122
|
+
```py
|
|
123
|
+
index = Index(
|
|
124
|
+
ndim=3, # Define the number of dimensions in input vectors
|
|
125
|
+
metric='cos', # Choose 'l2sq', 'haversine' or other metric, default = 'ip'
|
|
126
|
+
dtype='f32', # Quantize to 'f16' or 'i8' if needed, default = 'f32'
|
|
127
|
+
connectivity=16, # Optional: How frequent should the connections in the graph be
|
|
128
|
+
expansion_add=128, # Optional: Control the recall of indexing
|
|
129
|
+
expansion_search=64, # Optional: Control the quality of search
|
|
130
|
+
)
|
|
131
|
+
```
|
|
129
132
|
|
|
130
133
|
## User-Defined Functions
|
|
131
134
|
|
|
@@ -220,7 +223,7 @@ multi_index.search(...)
|
|
|
220
223
|
## Clustering
|
|
221
224
|
|
|
222
225
|
Once the index is constructed, it can be used to cluster entries much faster.
|
|
223
|
-
In
|
|
226
|
+
In essence, the `Index` itself can be seen as a clustering, and it allows iterative deepening.
|
|
224
227
|
|
|
225
228
|
```py
|
|
226
229
|
clustering = index.cluster(
|
|
@@ -241,7 +244,7 @@ g = clustering.network
|
|
|
241
244
|
# Get members of a specific cluster
|
|
242
245
|
first_members = clustering.members_of(centroid_keys[0])
|
|
243
246
|
|
|
244
|
-
# Deepen into that cluster
|
|
247
|
+
# Deepen into that cluster splitting it into more parts, all same arguments supported
|
|
245
248
|
sub_clustering = clustering.subcluster(min_count=..., max_count=...)
|
|
246
249
|
```
|
|
247
250
|
|
|
@@ -342,7 +345,7 @@ Comparing molecule graphs and searching for similar structures is expensive and
|
|
|
342
345
|
It can be seen as a special case of the NP-Complete Subgraph Isomorphism problem.
|
|
343
346
|
Luckily, domain-specific approximate methods exist.
|
|
344
347
|
The one commonly used in Chemistry, is to generate structures from [SMILES][smiles], and later hash them into binary fingerprints.
|
|
345
|
-
The latter are searchable with
|
|
348
|
+
The latter are searchable with binary similarity metrics, like the Tanimoto coefficient.
|
|
346
349
|
Below is an example using the RDKit package.
|
|
347
350
|
|
|
348
351
|
```python
|
|
@@ -380,9 +383,10 @@ The search is based on the Haversine distance metric, but can easily be extended
|
|
|
380
383
|
## Integrations
|
|
381
384
|
|
|
382
385
|
- [x] GPTCache: [Python](https://github.com/zilliztech/GPTCache/releases/tag/0.1.29).
|
|
383
|
-
- [x] LangChain: [Python](https://github.com/langchain-ai/langchain/releases/tag/v0.0.257) and [
|
|
386
|
+
- [x] LangChain: [Python](https://github.com/langchain-ai/langchain/releases/tag/v0.0.257) and [JavaScript](https://github.com/hwchase17/langchainjs/releases/tag/0.0.125).
|
|
384
387
|
- [x] ClickHouse: [C++](https://github.com/ClickHouse/ClickHouse/pull/53447).
|
|
385
388
|
- [x] Microsoft Semantic Kernel: [Python](https://github.com/microsoft/semantic-kernel/releases/tag/python-0.3.9.dev) and C#.
|
|
389
|
+
- [x] LanternDB: [C++](https://github.com/lanterndata/lantern) and [Rust](https://github.com/lanterndata/lantern_extras).
|
|
386
390
|
|
|
387
391
|
## Citations
|
|
388
392
|
|
|
@@ -392,7 +396,7 @@ doi = {10.5281/zenodo.7949416},
|
|
|
392
396
|
author = {Vardanian, Ash},
|
|
393
397
|
title = {{USearch by Unum Cloud}},
|
|
394
398
|
url = {https://github.com/unum-cloud/usearch},
|
|
395
|
-
version = {2.8.
|
|
399
|
+
version = {2.8.4},
|
|
396
400
|
year = {2023},
|
|
397
401
|
month = oct,
|
|
398
402
|
}
|
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.4'
|
|
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"
|