vicinity 0.2.1__tar.gz → 0.3.1__tar.gz
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.
- {vicinity-0.2.1 → vicinity-0.3.1}/PKG-INFO +75 -98
- {vicinity-0.2.1 → vicinity-0.3.1}/README.md +65 -97
- {vicinity-0.2.1 → vicinity-0.3.1}/pyproject.toml +10 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/tests/test_vicinity.py +20 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/uv.lock +19 -1
- vicinity-0.3.1/vicinity/__init__.py +8 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity/backends/annoy.py +28 -24
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity/backends/base.py +7 -0
- vicinity-0.3.1/vicinity/backends/basic.py +223 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity/backends/faiss.py +33 -51
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity/backends/hnsw.py +19 -6
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity/backends/pynndescent.py +21 -12
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity/backends/usearch.py +26 -22
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity/utils.py +39 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity/version.py +1 -1
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity/vicinity.py +78 -2
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity.egg-info/PKG-INFO +75 -98
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity.egg-info/requires.txt +10 -0
- vicinity-0.2.1/vicinity/__init__.py +0 -7
- vicinity-0.2.1/vicinity/backends/basic.py +0 -149
- {vicinity-0.2.1 → vicinity-0.3.1}/.github/workflows/ci.yaml +0 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/.gitignore +0 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/.pre-commit-config.yaml +0 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/LICENSE +0 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/Makefile +0 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/setup.cfg +0 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/tests/conftest.py +0 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/tests/test_utils.py +0 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity/backends/__init__.py +0 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity/datatypes.py +0 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity/py.typed +0 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity.egg-info/SOURCES.txt +0 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity.egg-info/dependency_links.txt +0 -0
- {vicinity-0.2.1 → vicinity-0.3.1}/vicinity.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: vicinity
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Lightweight Nearest Neighbors with Flexible Backends
|
|
5
5
|
Author-email: Stéphan Tulkens <stephantul@gmail.com>, Thomas van Dongen <thomas123@live.nl>
|
|
6
6
|
License: MIT License
|
|
@@ -67,10 +67,19 @@ Provides-Extra: faiss
|
|
|
67
67
|
Requires-Dist: faiss-cpu; extra == "faiss"
|
|
68
68
|
Provides-Extra: usearch
|
|
69
69
|
Requires-Dist: usearch; extra == "usearch"
|
|
70
|
+
Provides-Extra: all
|
|
71
|
+
Requires-Dist: hnswlib; extra == "all"
|
|
72
|
+
Requires-Dist: pynndescent>=0.5.10; extra == "all"
|
|
73
|
+
Requires-Dist: numba>=0.59.0; extra == "all"
|
|
74
|
+
Requires-Dist: llvmlite>=0.42.0; extra == "all"
|
|
75
|
+
Requires-Dist: numpy>=1.24.0; extra == "all"
|
|
76
|
+
Requires-Dist: annoy; extra == "all"
|
|
77
|
+
Requires-Dist: faiss-cpu; extra == "all"
|
|
78
|
+
Requires-Dist: usearch; extra == "all"
|
|
70
79
|
|
|
71
80
|
<div align="center">
|
|
72
81
|
|
|
73
|
-
# Vicinity:
|
|
82
|
+
# Vicinity: Lightweight Nearest Neighbors
|
|
74
83
|
|
|
75
84
|
</div>
|
|
76
85
|
|
|
@@ -87,18 +96,21 @@ Requires-Dist: usearch; extra == "usearch"
|
|
|
87
96
|
</a>
|
|
88
97
|
<a href="https://github.com/MinishLab/vicinity/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="License - MIT"></a>
|
|
89
98
|
</h2>
|
|
99
|
+
|
|
100
|
+
[Quickstart](#quickstart) •
|
|
101
|
+
[Main Features](#main-features) •
|
|
102
|
+
[Supported Backends](#supported-backends) •
|
|
103
|
+
[Installation](#installation)
|
|
104
|
+
|
|
90
105
|
</div>
|
|
91
106
|
|
|
92
107
|
|
|
93
|
-
|
|
108
|
+
Vicinity is a light-weight, low-dependency vector store. It provides a simple and intuitive interface for nearest neighbor search, with support for different backends and evaluation.
|
|
109
|
+
|
|
110
|
+
There are many nearest neighbors packages and methods out there. However, we found it difficult to compare them. Every package has its own interface, quirks, and limitations, and learning a new package can be time-consuming. In addition to that, how do you effectively evaluate different packages? How do you know which one is the best for your use case?
|
|
94
111
|
|
|
95
|
-
- [Quickstart](#quickstart)
|
|
96
|
-
- [Main Features](#main-features)
|
|
97
|
-
- [Supported Backends](#supported-backends)
|
|
98
|
-
- [Backend Parameters](#backend-parameters)
|
|
99
|
-
- [Usage](#usage)
|
|
100
112
|
|
|
101
|
-
|
|
113
|
+
This is where Vicinity comes in. Instead of learning a new interface for each new package or backend, Vicinity provides a unified interface for all backends. This allows you to easily experiment with different indexing methods and distance metrics and choose the best one for your use case. Vicinity also provides a simple way to evaluate the performance of different backends, allowing you to measure the queries per second and recall.
|
|
102
114
|
|
|
103
115
|
## Quickstart
|
|
104
116
|
|
|
@@ -106,50 +118,80 @@ Install the package with:
|
|
|
106
118
|
```bash
|
|
107
119
|
pip install vicinity
|
|
108
120
|
```
|
|
121
|
+
Optinally, [install any of the supported backends](#installation), or simply install all of them with:
|
|
122
|
+
```bash
|
|
123
|
+
pip install vicinity[all]
|
|
124
|
+
```
|
|
109
125
|
|
|
110
126
|
|
|
111
127
|
The following code snippet demonstrates how to use Vicinity for nearest neighbor search:
|
|
112
128
|
```python
|
|
113
129
|
import numpy as np
|
|
114
|
-
from vicinity import Vicinity
|
|
115
|
-
from vicinity.datatypes import Backend
|
|
130
|
+
from vicinity import Vicinity, Backend, Metric
|
|
116
131
|
|
|
117
132
|
# Create some dummy data
|
|
118
133
|
items = ["triforce", "master sword", "hylian shield", "boomerang", "hookshot"]
|
|
119
134
|
vectors = np.random.rand(len(items), 128)
|
|
120
135
|
|
|
121
|
-
# Initialize the Vicinity instance (using the basic backend)
|
|
122
|
-
vicinity = Vicinity.from_vectors_and_items(vectors=vectors, items=items, backend_type=Backend.BASIC)
|
|
136
|
+
# Initialize the Vicinity instance (using the basic backend and cosine metric)
|
|
137
|
+
vicinity = Vicinity.from_vectors_and_items(vectors=vectors, items=items, backend_type=Backend.BASIC, metric=Metric.COSINE)
|
|
123
138
|
|
|
124
|
-
#
|
|
139
|
+
# Create a query vector
|
|
125
140
|
query_vector = np.random.rand(128)
|
|
141
|
+
|
|
142
|
+
# Query for nearest neighbors with a top-k search
|
|
126
143
|
results = vicinity.query([query_vector], k=3)
|
|
127
144
|
|
|
128
145
|
# Query for nearest neighbors with a threshold search
|
|
129
146
|
results = vicinity.query_threshold([query_vector], threshold=0.9)
|
|
147
|
+
```
|
|
130
148
|
|
|
131
|
-
|
|
149
|
+
Saving and loading a vector store:
|
|
150
|
+
```python
|
|
132
151
|
vicinity.save('my_vector_store')
|
|
133
|
-
|
|
134
|
-
# Load the vector store
|
|
135
152
|
vicinity = Vicinity.load('my_vector_store')
|
|
136
153
|
```
|
|
137
154
|
|
|
155
|
+
Evaluating a backend:
|
|
156
|
+
```python
|
|
157
|
+
# Use the first 1000 vectors as query vectors
|
|
158
|
+
query_vectors = vectors[:1000]
|
|
159
|
+
|
|
160
|
+
# Evaluate the Vicinity instance by measuring the queries per second and recall
|
|
161
|
+
qps, recall = vicinity.evaluate(
|
|
162
|
+
full_vectors=vectors,
|
|
163
|
+
query_vectors=query_vectors,
|
|
164
|
+
)
|
|
165
|
+
```
|
|
166
|
+
|
|
138
167
|
## Main Features
|
|
139
168
|
Vicinity provides the following features:
|
|
140
169
|
- Lightweight: Minimal dependencies and fast performance.
|
|
141
170
|
- Flexible Backend Support: Use different backends for vector storage and search.
|
|
142
171
|
- Serialization: Save and load vector stores for persistence.
|
|
172
|
+
- Evaluation: Easily evaluate the performance of different backends.
|
|
143
173
|
- Easy to Use: Simple and intuitive API.
|
|
144
174
|
|
|
145
175
|
## Supported Backends
|
|
146
176
|
The following backends are supported:
|
|
147
|
-
- `BASIC`: A simple flat index for vector storage and search.
|
|
177
|
+
- `BASIC`: A simple (exact matching) flat index for vector storage and search.
|
|
148
178
|
- [HNSW](https://github.com/nmslib/hnswlib): Hierarchical Navigable Small World Graph (HNSW) for ANN search using hnswlib.
|
|
149
|
-
- [
|
|
179
|
+
- [USEARCH](https://github.com/unum-cloud/usearch): ANN search using Usearch. This uses a highly optimized version of the HNSW algorithm.
|
|
150
180
|
- [ANNOY](https://github.com/spotify/annoy): "Approximate Nearest Neighbors Oh Yeah" for approximate nearest neighbor search.
|
|
151
181
|
- [PYNNDescent](https://github.com/lmcinnes/pynndescent): ANN search using PyNNDescent.
|
|
152
|
-
- [
|
|
182
|
+
- [FAISS](https://github.com/facebookresearch/faiss): All FAISS indexes are supported:
|
|
183
|
+
- `flat`: Exact search.
|
|
184
|
+
- `ivf`: Inverted file search.
|
|
185
|
+
- `hnsw`: Hierarchical Navigable Small World Graph.
|
|
186
|
+
- `lsh`: Locality Sensitive Hashing.
|
|
187
|
+
- `scalar`: Scalar quantizer.
|
|
188
|
+
- `pq`: Product Quantizer.
|
|
189
|
+
- `ivf_scalar`: Inverted file search with scalar quantizer.
|
|
190
|
+
- `ivfpq`: Inverted file search with product quantizer.
|
|
191
|
+
- `ivfpqr`: Inverted file search with product quantizer and refinement.
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
153
195
|
|
|
154
196
|
NOTE: the ANN backends do not support dynamic deletion. To delete items, you need to recreate the index. Insertion is supported in the following backends: `FAISS`, `HNSW`, and `Usearch`. The `BASIC` backend supports both insertion and deletion.
|
|
155
197
|
|
|
@@ -178,87 +220,22 @@ NOTE: the ANN backends do not support dynamic deletion. To delete items, you nee
|
|
|
178
220
|
| | `expansion_search` | Number of candidates considered during search. | `64` |
|
|
179
221
|
|
|
180
222
|
|
|
223
|
+
## Installation
|
|
224
|
+
The following installation options are available:
|
|
225
|
+
```bash
|
|
226
|
+
# Install the base package
|
|
227
|
+
pip install vicinity
|
|
181
228
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
<details>
|
|
185
|
-
<summary> Creating a Vector Store
|
|
186
|
-
</summary>
|
|
187
|
-
<br>
|
|
188
|
-
|
|
189
|
-
You can create a Vicinity instance by providing items and their corresponding vectors:
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
```python
|
|
193
|
-
from vicinity import Vicinity
|
|
194
|
-
import numpy as np
|
|
195
|
-
|
|
196
|
-
items = ["triforce", "master sword", "hylian shield", "boomerang", "hookshot"]
|
|
197
|
-
vectors = np.random.rand(len(items), 128)
|
|
198
|
-
|
|
199
|
-
vicinity = Vicinity.from_vectors_and_items(vectors=vectors, items=items)
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
</details>
|
|
203
|
-
|
|
204
|
-
<details>
|
|
205
|
-
<summary> Querying
|
|
206
|
-
</summary>
|
|
207
|
-
<br>
|
|
208
|
-
|
|
209
|
-
Find the k nearest neighbors for a given vector:
|
|
210
|
-
|
|
211
|
-
```python
|
|
212
|
-
query_vector = np.random.rand(128)
|
|
213
|
-
results = vicinity.query([query_vector], k=3)
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
Find all neighbors within a given threshold:
|
|
217
|
-
|
|
218
|
-
```python
|
|
219
|
-
query_vector = np.random.rand(128)
|
|
220
|
-
results = vicinity.query_threshold([query_vector], threshold=0.9)
|
|
221
|
-
```
|
|
222
|
-
</details>
|
|
223
|
-
|
|
224
|
-
<details>
|
|
225
|
-
|
|
226
|
-
<summary> Inserting and Deleting Items
|
|
227
|
-
</summary>
|
|
228
|
-
<br>
|
|
229
|
-
|
|
230
|
-
Insert new items:
|
|
231
|
-
|
|
232
|
-
```python
|
|
233
|
-
new_items = ["ocarina", "bow"]
|
|
234
|
-
new_vectors = np.random.rand(2, 128)
|
|
235
|
-
vicinity.insert(new_items, new_vectors)
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
Delete items:
|
|
239
|
-
|
|
240
|
-
```python
|
|
241
|
-
vicinity.delete(["hookshot"])
|
|
242
|
-
```
|
|
243
|
-
</details>
|
|
244
|
-
|
|
245
|
-
<details>
|
|
246
|
-
<summary> Saving and Loading
|
|
247
|
-
</summary>
|
|
248
|
-
<br>
|
|
249
|
-
|
|
250
|
-
Save the vector store:
|
|
251
|
-
|
|
252
|
-
```python
|
|
253
|
-
vicinity.save('my_vector_store')
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
Load the vector store:
|
|
229
|
+
# Install all backends
|
|
230
|
+
pip install vicinity[all]
|
|
257
231
|
|
|
258
|
-
|
|
259
|
-
|
|
232
|
+
# Install specific backends
|
|
233
|
+
pip install vicinity[annoy]
|
|
234
|
+
pip install vicinity[faiss]
|
|
235
|
+
pip install vicinity[hnsw]
|
|
236
|
+
pip install vicinity[pynndescent]
|
|
237
|
+
pip install vicinity[usearch]
|
|
260
238
|
```
|
|
261
|
-
</details>
|
|
262
239
|
|
|
263
240
|
## License
|
|
264
241
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
# Vicinity:
|
|
3
|
+
# Vicinity: Lightweight Nearest Neighbors
|
|
4
4
|
|
|
5
5
|
</div>
|
|
6
6
|
|
|
@@ -17,18 +17,21 @@
|
|
|
17
17
|
</a>
|
|
18
18
|
<a href="https://github.com/MinishLab/vicinity/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="License - MIT"></a>
|
|
19
19
|
</h2>
|
|
20
|
+
|
|
21
|
+
[Quickstart](#quickstart) •
|
|
22
|
+
[Main Features](#main-features) •
|
|
23
|
+
[Supported Backends](#supported-backends) •
|
|
24
|
+
[Installation](#installation)
|
|
25
|
+
|
|
20
26
|
</div>
|
|
21
27
|
|
|
22
28
|
|
|
23
|
-
|
|
29
|
+
Vicinity is a light-weight, low-dependency vector store. It provides a simple and intuitive interface for nearest neighbor search, with support for different backends and evaluation.
|
|
30
|
+
|
|
31
|
+
There are many nearest neighbors packages and methods out there. However, we found it difficult to compare them. Every package has its own interface, quirks, and limitations, and learning a new package can be time-consuming. In addition to that, how do you effectively evaluate different packages? How do you know which one is the best for your use case?
|
|
24
32
|
|
|
25
|
-
- [Quickstart](#quickstart)
|
|
26
|
-
- [Main Features](#main-features)
|
|
27
|
-
- [Supported Backends](#supported-backends)
|
|
28
|
-
- [Backend Parameters](#backend-parameters)
|
|
29
|
-
- [Usage](#usage)
|
|
30
33
|
|
|
31
|
-
|
|
34
|
+
This is where Vicinity comes in. Instead of learning a new interface for each new package or backend, Vicinity provides a unified interface for all backends. This allows you to easily experiment with different indexing methods and distance metrics and choose the best one for your use case. Vicinity also provides a simple way to evaluate the performance of different backends, allowing you to measure the queries per second and recall.
|
|
32
35
|
|
|
33
36
|
## Quickstart
|
|
34
37
|
|
|
@@ -36,50 +39,80 @@ Install the package with:
|
|
|
36
39
|
```bash
|
|
37
40
|
pip install vicinity
|
|
38
41
|
```
|
|
42
|
+
Optinally, [install any of the supported backends](#installation), or simply install all of them with:
|
|
43
|
+
```bash
|
|
44
|
+
pip install vicinity[all]
|
|
45
|
+
```
|
|
39
46
|
|
|
40
47
|
|
|
41
48
|
The following code snippet demonstrates how to use Vicinity for nearest neighbor search:
|
|
42
49
|
```python
|
|
43
50
|
import numpy as np
|
|
44
|
-
from vicinity import Vicinity
|
|
45
|
-
from vicinity.datatypes import Backend
|
|
51
|
+
from vicinity import Vicinity, Backend, Metric
|
|
46
52
|
|
|
47
53
|
# Create some dummy data
|
|
48
54
|
items = ["triforce", "master sword", "hylian shield", "boomerang", "hookshot"]
|
|
49
55
|
vectors = np.random.rand(len(items), 128)
|
|
50
56
|
|
|
51
|
-
# Initialize the Vicinity instance (using the basic backend)
|
|
52
|
-
vicinity = Vicinity.from_vectors_and_items(vectors=vectors, items=items, backend_type=Backend.BASIC)
|
|
57
|
+
# Initialize the Vicinity instance (using the basic backend and cosine metric)
|
|
58
|
+
vicinity = Vicinity.from_vectors_and_items(vectors=vectors, items=items, backend_type=Backend.BASIC, metric=Metric.COSINE)
|
|
53
59
|
|
|
54
|
-
#
|
|
60
|
+
# Create a query vector
|
|
55
61
|
query_vector = np.random.rand(128)
|
|
62
|
+
|
|
63
|
+
# Query for nearest neighbors with a top-k search
|
|
56
64
|
results = vicinity.query([query_vector], k=3)
|
|
57
65
|
|
|
58
66
|
# Query for nearest neighbors with a threshold search
|
|
59
67
|
results = vicinity.query_threshold([query_vector], threshold=0.9)
|
|
68
|
+
```
|
|
60
69
|
|
|
61
|
-
|
|
70
|
+
Saving and loading a vector store:
|
|
71
|
+
```python
|
|
62
72
|
vicinity.save('my_vector_store')
|
|
63
|
-
|
|
64
|
-
# Load the vector store
|
|
65
73
|
vicinity = Vicinity.load('my_vector_store')
|
|
66
74
|
```
|
|
67
75
|
|
|
76
|
+
Evaluating a backend:
|
|
77
|
+
```python
|
|
78
|
+
# Use the first 1000 vectors as query vectors
|
|
79
|
+
query_vectors = vectors[:1000]
|
|
80
|
+
|
|
81
|
+
# Evaluate the Vicinity instance by measuring the queries per second and recall
|
|
82
|
+
qps, recall = vicinity.evaluate(
|
|
83
|
+
full_vectors=vectors,
|
|
84
|
+
query_vectors=query_vectors,
|
|
85
|
+
)
|
|
86
|
+
```
|
|
87
|
+
|
|
68
88
|
## Main Features
|
|
69
89
|
Vicinity provides the following features:
|
|
70
90
|
- Lightweight: Minimal dependencies and fast performance.
|
|
71
91
|
- Flexible Backend Support: Use different backends for vector storage and search.
|
|
72
92
|
- Serialization: Save and load vector stores for persistence.
|
|
93
|
+
- Evaluation: Easily evaluate the performance of different backends.
|
|
73
94
|
- Easy to Use: Simple and intuitive API.
|
|
74
95
|
|
|
75
96
|
## Supported Backends
|
|
76
97
|
The following backends are supported:
|
|
77
|
-
- `BASIC`: A simple flat index for vector storage and search.
|
|
98
|
+
- `BASIC`: A simple (exact matching) flat index for vector storage and search.
|
|
78
99
|
- [HNSW](https://github.com/nmslib/hnswlib): Hierarchical Navigable Small World Graph (HNSW) for ANN search using hnswlib.
|
|
79
|
-
- [
|
|
100
|
+
- [USEARCH](https://github.com/unum-cloud/usearch): ANN search using Usearch. This uses a highly optimized version of the HNSW algorithm.
|
|
80
101
|
- [ANNOY](https://github.com/spotify/annoy): "Approximate Nearest Neighbors Oh Yeah" for approximate nearest neighbor search.
|
|
81
102
|
- [PYNNDescent](https://github.com/lmcinnes/pynndescent): ANN search using PyNNDescent.
|
|
82
|
-
- [
|
|
103
|
+
- [FAISS](https://github.com/facebookresearch/faiss): All FAISS indexes are supported:
|
|
104
|
+
- `flat`: Exact search.
|
|
105
|
+
- `ivf`: Inverted file search.
|
|
106
|
+
- `hnsw`: Hierarchical Navigable Small World Graph.
|
|
107
|
+
- `lsh`: Locality Sensitive Hashing.
|
|
108
|
+
- `scalar`: Scalar quantizer.
|
|
109
|
+
- `pq`: Product Quantizer.
|
|
110
|
+
- `ivf_scalar`: Inverted file search with scalar quantizer.
|
|
111
|
+
- `ivfpq`: Inverted file search with product quantizer.
|
|
112
|
+
- `ivfpqr`: Inverted file search with product quantizer and refinement.
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
83
116
|
|
|
84
117
|
NOTE: the ANN backends do not support dynamic deletion. To delete items, you need to recreate the index. Insertion is supported in the following backends: `FAISS`, `HNSW`, and `Usearch`. The `BASIC` backend supports both insertion and deletion.
|
|
85
118
|
|
|
@@ -108,87 +141,22 @@ NOTE: the ANN backends do not support dynamic deletion. To delete items, you nee
|
|
|
108
141
|
| | `expansion_search` | Number of candidates considered during search. | `64` |
|
|
109
142
|
|
|
110
143
|
|
|
144
|
+
## Installation
|
|
145
|
+
The following installation options are available:
|
|
146
|
+
```bash
|
|
147
|
+
# Install the base package
|
|
148
|
+
pip install vicinity
|
|
111
149
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
<details>
|
|
115
|
-
<summary> Creating a Vector Store
|
|
116
|
-
</summary>
|
|
117
|
-
<br>
|
|
118
|
-
|
|
119
|
-
You can create a Vicinity instance by providing items and their corresponding vectors:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
```python
|
|
123
|
-
from vicinity import Vicinity
|
|
124
|
-
import numpy as np
|
|
125
|
-
|
|
126
|
-
items = ["triforce", "master sword", "hylian shield", "boomerang", "hookshot"]
|
|
127
|
-
vectors = np.random.rand(len(items), 128)
|
|
128
|
-
|
|
129
|
-
vicinity = Vicinity.from_vectors_and_items(vectors=vectors, items=items)
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
</details>
|
|
133
|
-
|
|
134
|
-
<details>
|
|
135
|
-
<summary> Querying
|
|
136
|
-
</summary>
|
|
137
|
-
<br>
|
|
138
|
-
|
|
139
|
-
Find the k nearest neighbors for a given vector:
|
|
140
|
-
|
|
141
|
-
```python
|
|
142
|
-
query_vector = np.random.rand(128)
|
|
143
|
-
results = vicinity.query([query_vector], k=3)
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
Find all neighbors within a given threshold:
|
|
147
|
-
|
|
148
|
-
```python
|
|
149
|
-
query_vector = np.random.rand(128)
|
|
150
|
-
results = vicinity.query_threshold([query_vector], threshold=0.9)
|
|
151
|
-
```
|
|
152
|
-
</details>
|
|
153
|
-
|
|
154
|
-
<details>
|
|
155
|
-
|
|
156
|
-
<summary> Inserting and Deleting Items
|
|
157
|
-
</summary>
|
|
158
|
-
<br>
|
|
159
|
-
|
|
160
|
-
Insert new items:
|
|
161
|
-
|
|
162
|
-
```python
|
|
163
|
-
new_items = ["ocarina", "bow"]
|
|
164
|
-
new_vectors = np.random.rand(2, 128)
|
|
165
|
-
vicinity.insert(new_items, new_vectors)
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Delete items:
|
|
169
|
-
|
|
170
|
-
```python
|
|
171
|
-
vicinity.delete(["hookshot"])
|
|
172
|
-
```
|
|
173
|
-
</details>
|
|
174
|
-
|
|
175
|
-
<details>
|
|
176
|
-
<summary> Saving and Loading
|
|
177
|
-
</summary>
|
|
178
|
-
<br>
|
|
179
|
-
|
|
180
|
-
Save the vector store:
|
|
181
|
-
|
|
182
|
-
```python
|
|
183
|
-
vicinity.save('my_vector_store')
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
Load the vector store:
|
|
150
|
+
# Install all backends
|
|
151
|
+
pip install vicinity[all]
|
|
187
152
|
|
|
188
|
-
|
|
189
|
-
|
|
153
|
+
# Install specific backends
|
|
154
|
+
pip install vicinity[annoy]
|
|
155
|
+
pip install vicinity[faiss]
|
|
156
|
+
pip install vicinity[hnsw]
|
|
157
|
+
pip install vicinity[pynndescent]
|
|
158
|
+
pip install vicinity[usearch]
|
|
190
159
|
```
|
|
191
|
-
</details>
|
|
192
160
|
|
|
193
161
|
## License
|
|
194
162
|
|
|
@@ -52,6 +52,16 @@ pynndescent = [
|
|
|
52
52
|
annoy = ["annoy"]
|
|
53
53
|
faiss = ["faiss-cpu"]
|
|
54
54
|
usearch = ["usearch"]
|
|
55
|
+
all = [
|
|
56
|
+
"hnswlib",
|
|
57
|
+
"pynndescent>=0.5.10",
|
|
58
|
+
"numba>=0.59.0",
|
|
59
|
+
"llvmlite>=0.42.0",
|
|
60
|
+
"numpy>=1.24.0",
|
|
61
|
+
"annoy",
|
|
62
|
+
"faiss-cpu",
|
|
63
|
+
"usearch"
|
|
64
|
+
]
|
|
55
65
|
|
|
56
66
|
[project.urls]
|
|
57
67
|
"Homepage" = "https://github.com/MinishLab"
|
|
@@ -220,3 +220,23 @@ def test_vicinity_delete_and_query(vicinity_instance: Vicinity, items: list[str]
|
|
|
220
220
|
|
|
221
221
|
# Check that the queried item is in the results
|
|
222
222
|
assert "item3" in returned_items
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def test_vicinity_evaluate(vicinity_instance: Vicinity, vectors: np.ndarray) -> None:
|
|
226
|
+
"""
|
|
227
|
+
Test the evaluate method of the Vicinity instance.
|
|
228
|
+
|
|
229
|
+
:param vicinity_instance: A Vicinity instance.
|
|
230
|
+
:param vectors: The full dataset vectors used to build the index.
|
|
231
|
+
"""
|
|
232
|
+
query_vectors = vectors[:10]
|
|
233
|
+
qps, recall = vicinity_instance.evaluate(vectors, query_vectors)
|
|
234
|
+
|
|
235
|
+
# Ensure the QPS and recall values are within valid ranges
|
|
236
|
+
assert qps > 0
|
|
237
|
+
assert 0 <= recall <= 1
|
|
238
|
+
|
|
239
|
+
# Test with an unsupported metric
|
|
240
|
+
vicinity_instance.backend.arguments.metric = "manhattan"
|
|
241
|
+
with pytest.raises(ValueError):
|
|
242
|
+
vicinity_instance.evaluate(vectors, query_vectors)
|
|
@@ -1087,7 +1087,7 @@ wheels = [
|
|
|
1087
1087
|
|
|
1088
1088
|
[[package]]
|
|
1089
1089
|
name = "vicinity"
|
|
1090
|
-
version = "0.
|
|
1090
|
+
version = "0.3.0"
|
|
1091
1091
|
source = { editable = "." }
|
|
1092
1092
|
dependencies = [
|
|
1093
1093
|
{ name = "numpy" },
|
|
@@ -1096,6 +1096,16 @@ dependencies = [
|
|
|
1096
1096
|
]
|
|
1097
1097
|
|
|
1098
1098
|
[package.optional-dependencies]
|
|
1099
|
+
all = [
|
|
1100
|
+
{ name = "annoy" },
|
|
1101
|
+
{ name = "faiss-cpu" },
|
|
1102
|
+
{ name = "hnswlib" },
|
|
1103
|
+
{ name = "llvmlite" },
|
|
1104
|
+
{ name = "numba" },
|
|
1105
|
+
{ name = "numpy" },
|
|
1106
|
+
{ name = "pynndescent" },
|
|
1107
|
+
{ name = "usearch" },
|
|
1108
|
+
]
|
|
1099
1109
|
annoy = [
|
|
1100
1110
|
{ name = "annoy" },
|
|
1101
1111
|
]
|
|
@@ -1127,24 +1137,32 @@ usearch = [
|
|
|
1127
1137
|
|
|
1128
1138
|
[package.metadata]
|
|
1129
1139
|
requires-dist = [
|
|
1140
|
+
{ name = "annoy", marker = "extra == 'all'" },
|
|
1130
1141
|
{ name = "annoy", marker = "extra == 'annoy'" },
|
|
1131
1142
|
{ name = "black", marker = "extra == 'dev'" },
|
|
1143
|
+
{ name = "faiss-cpu", marker = "extra == 'all'" },
|
|
1132
1144
|
{ name = "faiss-cpu", marker = "extra == 'faiss'" },
|
|
1145
|
+
{ name = "hnswlib", marker = "extra == 'all'" },
|
|
1133
1146
|
{ name = "hnswlib", marker = "extra == 'hnsw'" },
|
|
1134
1147
|
{ name = "ipython", marker = "extra == 'dev'" },
|
|
1148
|
+
{ name = "llvmlite", marker = "extra == 'all'", specifier = ">=0.42.0" },
|
|
1135
1149
|
{ name = "llvmlite", marker = "extra == 'pynndescent'", specifier = ">=0.42.0" },
|
|
1136
1150
|
{ name = "mypy", marker = "extra == 'dev'" },
|
|
1151
|
+
{ name = "numba", marker = "extra == 'all'", specifier = ">=0.59.0" },
|
|
1137
1152
|
{ name = "numba", marker = "extra == 'pynndescent'", specifier = ">=0.59.0" },
|
|
1138
1153
|
{ name = "numpy" },
|
|
1154
|
+
{ name = "numpy", marker = "extra == 'all'", specifier = ">=1.24.0" },
|
|
1139
1155
|
{ name = "numpy", marker = "extra == 'pynndescent'", specifier = ">=1.24.0" },
|
|
1140
1156
|
{ name = "orjson" },
|
|
1141
1157
|
{ name = "pre-commit", marker = "extra == 'dev'" },
|
|
1158
|
+
{ name = "pynndescent", marker = "extra == 'all'", specifier = ">=0.5.10" },
|
|
1142
1159
|
{ name = "pynndescent", marker = "extra == 'pynndescent'", specifier = ">=0.5.10" },
|
|
1143
1160
|
{ name = "pytest", marker = "extra == 'dev'" },
|
|
1144
1161
|
{ name = "pytest-coverage", marker = "extra == 'dev'" },
|
|
1145
1162
|
{ name = "ruff", marker = "extra == 'dev'" },
|
|
1146
1163
|
{ name = "setuptools", marker = "extra == 'dev'" },
|
|
1147
1164
|
{ name = "tqdm" },
|
|
1165
|
+
{ name = "usearch", marker = "extra == 'all'" },
|
|
1148
1166
|
{ name = "usearch", marker = "extra == 'usearch'" },
|
|
1149
1167
|
]
|
|
1150
1168
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""Small vector store."""
|
|
2
|
+
|
|
3
|
+
from vicinity.datatypes import Backend
|
|
4
|
+
from vicinity.utils import Metric, normalize
|
|
5
|
+
from vicinity.version import __version__
|
|
6
|
+
from vicinity.vicinity import Vicinity
|
|
7
|
+
|
|
8
|
+
__all__ = ["Backend", "Metric", "Vicinity", "normalize", "__version__"]
|