vicinity 0.2.0__tar.gz → 0.3.0__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.
Files changed (38) hide show
  1. {vicinity-0.2.0 → vicinity-0.3.0}/Makefile +1 -1
  2. vicinity-0.3.0/PKG-INFO +243 -0
  3. vicinity-0.3.0/README.md +164 -0
  4. {vicinity-0.2.0 → vicinity-0.3.0}/pyproject.toml +11 -0
  5. {vicinity-0.2.0 → vicinity-0.3.0}/tests/conftest.py +2 -0
  6. {vicinity-0.2.0 → vicinity-0.3.0}/tests/test_vicinity.py +56 -9
  7. {vicinity-0.2.0 → vicinity-0.3.0}/uv.lock +234 -42
  8. vicinity-0.3.0/vicinity/__init__.py +8 -0
  9. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity/backends/__init__.py +8 -1
  10. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity/backends/annoy.py +28 -24
  11. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity/backends/base.py +7 -0
  12. vicinity-0.3.0/vicinity/backends/basic.py +218 -0
  13. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity/backends/faiss.py +35 -66
  14. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity/backends/hnsw.py +20 -8
  15. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity/backends/pynndescent.py +23 -14
  16. vicinity-0.3.0/vicinity/backends/usearch.py +136 -0
  17. vicinity-0.3.0/vicinity/datatypes.py +24 -0
  18. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity/utils.py +42 -1
  19. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity/version.py +1 -1
  20. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity/vicinity.py +83 -6
  21. vicinity-0.3.0/vicinity.egg-info/PKG-INFO +243 -0
  22. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity.egg-info/SOURCES.txt +2 -1
  23. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity.egg-info/requires.txt +13 -0
  24. vicinity-0.2.0/PKG-INFO +0 -254
  25. vicinity-0.2.0/README.md +0 -186
  26. vicinity-0.2.0/vicinity/__init__.py +0 -7
  27. vicinity-0.2.0/vicinity/backends/basic.py +0 -149
  28. vicinity-0.2.0/vicinity/datatypes.py +0 -23
  29. vicinity-0.2.0/vicinity.egg-info/PKG-INFO +0 -254
  30. {vicinity-0.2.0 → vicinity-0.3.0}/.github/workflows/ci.yaml +0 -0
  31. {vicinity-0.2.0 → vicinity-0.3.0}/.gitignore +0 -0
  32. {vicinity-0.2.0 → vicinity-0.3.0}/.pre-commit-config.yaml +0 -0
  33. {vicinity-0.2.0 → vicinity-0.3.0}/LICENSE +0 -0
  34. {vicinity-0.2.0 → vicinity-0.3.0}/setup.cfg +0 -0
  35. {vicinity-0.2.0 → vicinity-0.3.0}/tests/test_utils.py +0 -0
  36. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity/py.typed +0 -0
  37. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity.egg-info/dependency_links.txt +0 -0
  38. {vicinity-0.2.0 → vicinity-0.3.0}/vicinity.egg-info/top_level.txt +0 -0
@@ -9,7 +9,7 @@ install: venv
9
9
  uv run pre-commit install
10
10
 
11
11
  install-no-pre-commit:
12
- uv pip install ".[dev,hnsw,pynndescent,annoy,faiss]"
12
+ uv pip install ".[dev,hnsw,pynndescent,annoy,faiss,usearch]"
13
13
 
14
14
  install-base:
15
15
  uv sync --extra dev
@@ -0,0 +1,243 @@
1
+ Metadata-Version: 2.1
2
+ Name: vicinity
3
+ Version: 0.3.0
4
+ Summary: Lightweight Nearest Neighbors with Flexible Backends
5
+ Author-email: Stéphan Tulkens <stephantul@gmail.com>, Thomas van Dongen <thomas123@live.nl>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2024 The Minish Lab
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/MinishLab
29
+ Project-URL: Bug Reports, https://github.com/MinishLab/vicinity/issues
30
+ Project-URL: Source, https://github.com/MinishLab/vicinity
31
+ Classifier: Development Status :: 4 - Beta
32
+ Classifier: Intended Audience :: Developers
33
+ Classifier: Intended Audience :: Science/Research
34
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
35
+ Classifier: Topic :: Software Development :: Libraries
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Programming Language :: Python :: 3 :: Only
38
+ Classifier: Programming Language :: Python :: 3.9
39
+ Classifier: Programming Language :: Python :: 3.10
40
+ Classifier: Programming Language :: Python :: 3.11
41
+ Classifier: Programming Language :: Python :: 3.12
42
+ Requires-Python: >=3.9
43
+ Description-Content-Type: text/markdown
44
+ License-File: LICENSE
45
+ Requires-Dist: numpy
46
+ Requires-Dist: orjson
47
+ Requires-Dist: tqdm
48
+ Provides-Extra: dev
49
+ Requires-Dist: black; extra == "dev"
50
+ Requires-Dist: ipython; extra == "dev"
51
+ Requires-Dist: mypy; extra == "dev"
52
+ Requires-Dist: pre-commit; extra == "dev"
53
+ Requires-Dist: pytest; extra == "dev"
54
+ Requires-Dist: pytest-coverage; extra == "dev"
55
+ Requires-Dist: ruff; extra == "dev"
56
+ Requires-Dist: setuptools; extra == "dev"
57
+ Provides-Extra: hnsw
58
+ Requires-Dist: hnswlib; extra == "hnsw"
59
+ Provides-Extra: pynndescent
60
+ Requires-Dist: pynndescent>=0.5.10; extra == "pynndescent"
61
+ Requires-Dist: numba>=0.59.0; extra == "pynndescent"
62
+ Requires-Dist: llvmlite>=0.42.0; extra == "pynndescent"
63
+ Requires-Dist: numpy>=1.24.0; extra == "pynndescent"
64
+ Provides-Extra: annoy
65
+ Requires-Dist: annoy; extra == "annoy"
66
+ Provides-Extra: faiss
67
+ Requires-Dist: faiss-cpu; extra == "faiss"
68
+ Provides-Extra: usearch
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"
79
+
80
+ <div align="center">
81
+
82
+ # Vicinity: Lightweight Nearest Neighbors
83
+
84
+ </div>
85
+
86
+
87
+ <div align="center">
88
+ <h2>
89
+ <a href="https://pypi.org/project/vicinity/"><img src="https://img.shields.io/pypi/v/vicinity?color=%23007ec6&label=pypi%20package" alt="Package version"></a>
90
+ <a href="https://pypi.org/project/vicinity/"><img src="https://img.shields.io/pypi/pyversions/vicinity" alt="Supported Python versions"></a>
91
+ <a href="https://pepy.tech/project/vicinity">
92
+ <img src="https://static.pepy.tech/badge/vicinity" alt="Downloads">
93
+ </a>
94
+ <a href="https://app.codecov.io/gh/MinishLab/vicinity">
95
+ <img src="https://codecov.io/gh/MinishLab/vicinity/graph/badge.svg?token=0MQ2945OZL" alt="Codecov">
96
+ </a>
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>
98
+ </h2>
99
+
100
+ [Quickstart](#quickstart) •
101
+ [Main Features](#main-features) •
102
+ [Supported Backends](#supported-backends) •
103
+ [Installation](#installation)
104
+
105
+ </div>
106
+
107
+
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?
111
+
112
+
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.
114
+
115
+ ## Quickstart
116
+
117
+ Install the package with:
118
+ ```bash
119
+ pip install vicinity
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
+ ```
125
+
126
+
127
+ The following code snippet demonstrates how to use Vicinity for nearest neighbor search:
128
+ ```python
129
+ import numpy as np
130
+ from vicinity import Vicinity
131
+ from vicinity.datatypes import Backend, Metric
132
+
133
+ # Create some dummy data
134
+ items = ["triforce", "master sword", "hylian shield", "boomerang", "hookshot"]
135
+ vectors = np.random.rand(len(items), 128)
136
+
137
+ # Initialize the Vicinity instance (using the basic backend and cosine metric)
138
+ vicinity = Vicinity.from_vectors_and_items(vectors=vectors, items=items, backend_type=Backend.BASIC, metric=Metric.COSINE)
139
+
140
+ # Create a query vector
141
+ query_vector = np.random.rand(128)
142
+
143
+ # Query for nearest neighbors with a top-k search
144
+ results = vicinity.query([query_vector], k=3)
145
+
146
+ # Query for nearest neighbors with a threshold search
147
+ results = vicinity.query_threshold([query_vector], threshold=0.9)
148
+ ```
149
+
150
+ Saving and loading a vector store:
151
+ ```python
152
+ vicinity.save('my_vector_store')
153
+ vicinity = Vicinity.load('my_vector_store')
154
+ ```
155
+
156
+ Evaluating a backend:
157
+ ```python
158
+ # Use the first 1000 vectors as query vectors
159
+ query_vectors = vectors[:1000]
160
+
161
+ # Evaluate the Vicinity instance by measuring the queries per second and recall
162
+ qps, recall = vicinity.evaluate(
163
+ full_vectors=vectors,
164
+ query_vectors=query_vectors,
165
+ )
166
+ ```
167
+
168
+ ## Main Features
169
+ Vicinity provides the following features:
170
+ - Lightweight: Minimal dependencies and fast performance.
171
+ - Flexible Backend Support: Use different backends for vector storage and search.
172
+ - Serialization: Save and load vector stores for persistence.
173
+ - Evaluation: Easily evaluate the performance of different backends.
174
+ - Easy to Use: Simple and intuitive API.
175
+
176
+ ## Supported Backends
177
+ The following backends are supported:
178
+ - `BASIC`: A simple (exact matching) flat index for vector storage and search.
179
+ - [HNSW](https://github.com/nmslib/hnswlib): Hierarchical Navigable Small World Graph (HNSW) for ANN search using hnswlib.
180
+ - [USEARCH](https://github.com/unum-cloud/usearch): ANN search using Usearch. This uses a highly optimized version of the HNSW algorithm.
181
+ - [ANNOY](https://github.com/spotify/annoy): "Approximate Nearest Neighbors Oh Yeah" for approximate nearest neighbor search.
182
+ - [PYNNDescent](https://github.com/lmcinnes/pynndescent): ANN search using PyNNDescent.
183
+ - [FAISS](https://github.com/facebookresearch/faiss): All FAISS indexes are supported:
184
+ - `flat`: Exact search.
185
+ - `ivf`: Inverted file search.
186
+ - `hnsw`: Hierarchical Navigable Small World Graph.
187
+ - `lsh`: Locality Sensitive Hashing.
188
+ - `scalar`: Scalar quantizer.
189
+ - `pq`: Product Quantizer.
190
+ - `ivf_scalar`: Inverted file search with scalar quantizer.
191
+ - `ivfpq`: Inverted file search with product quantizer.
192
+ - `ivfpqr`: Inverted file search with product quantizer and refinement.
193
+
194
+
195
+
196
+
197
+ 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.
198
+
199
+ ### Backend Parameters
200
+
201
+
202
+ | Backend | Parameter | Description | Default Value |
203
+ |-----------------|---------------------|-----------------------------------------------------------------------------------------------|---------------------|
204
+ | **Annoy** | `metric` | Similarity metric to use (`dot`, `euclidean`, `cosine`). | `"cosine"` |
205
+ | | `trees` | Number of trees to use for indexing. | `100` |
206
+ | | `length` | Optional length of the dataset. | `None` |
207
+ | **FAISS** | `metric` | Similarity metric to use (`cosine`, `l2`). | `"cosine"` |
208
+ | | `index_type` | Type of FAISS index (`flat`, `ivf`, `hnsw`, `lsh`, `scalar`, `pq`, `ivf_scalar`, `ivfpq`, `ivfpqr`). | `"hnsw"` |
209
+ | | `nlist` | Number of cells for IVF indexes. | `100` |
210
+ | | `m` | Number of subquantizers for PQ and HNSW indexes. | `8` |
211
+ | | `nbits` | Number of bits for LSH and PQ indexes. | `8` |
212
+ | | `refine_nbits` | Number of bits for the refinement stage in IVFPQR indexes. | `8` |
213
+ | **HNSW** | `metric` | Similarity space to use (`cosine`, `l2`). | `"cosine"` |
214
+ | | `ef_construction` | Size of the dynamic list during index construction. | `200` |
215
+ | | `m` | Number of connections per layer. | `16` |
216
+ | **PyNNDescent** | `metric` | Similarity metric to use (`cosine`, `euclidean`, `manhattan`). | `"cosine"` |
217
+ | | `n_neighbors` | Number of neighbors to use for search. | `15` |
218
+ | **Usearch** | `metric` | Similarity metric to use (`cos`, `ip`, `l2sq`, `hamming`, `tanimoto`). | `"cos"` |
219
+ | | `connectivity` | Number of connections per node in the graph. | `16` |
220
+ | | `expansion_add` | Number of candidates considered during graph construction. | `128` |
221
+ | | `expansion_search` | Number of candidates considered during search. | `64` |
222
+
223
+
224
+ ## Installation
225
+ The following installation options are available:
226
+ ```bash
227
+ # Install the base package
228
+ pip install vicinity
229
+
230
+ # Install all backends
231
+ pip install vicinity[all]
232
+
233
+ # Install specific backends
234
+ pip install vicinity[annoy]
235
+ pip install vicinity[faiss]
236
+ pip install vicinity[hnsw]
237
+ pip install vicinity[pynndescent]
238
+ pip install vicinity[usearch]
239
+ ```
240
+
241
+ ## License
242
+
243
+ MIT
@@ -0,0 +1,164 @@
1
+ <div align="center">
2
+
3
+ # Vicinity: Lightweight Nearest Neighbors
4
+
5
+ </div>
6
+
7
+
8
+ <div align="center">
9
+ <h2>
10
+ <a href="https://pypi.org/project/vicinity/"><img src="https://img.shields.io/pypi/v/vicinity?color=%23007ec6&label=pypi%20package" alt="Package version"></a>
11
+ <a href="https://pypi.org/project/vicinity/"><img src="https://img.shields.io/pypi/pyversions/vicinity" alt="Supported Python versions"></a>
12
+ <a href="https://pepy.tech/project/vicinity">
13
+ <img src="https://static.pepy.tech/badge/vicinity" alt="Downloads">
14
+ </a>
15
+ <a href="https://app.codecov.io/gh/MinishLab/vicinity">
16
+ <img src="https://codecov.io/gh/MinishLab/vicinity/graph/badge.svg?token=0MQ2945OZL" alt="Codecov">
17
+ </a>
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
+ </h2>
20
+
21
+ [Quickstart](#quickstart) •
22
+ [Main Features](#main-features) •
23
+ [Supported Backends](#supported-backends) •
24
+ [Installation](#installation)
25
+
26
+ </div>
27
+
28
+
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?
32
+
33
+
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.
35
+
36
+ ## Quickstart
37
+
38
+ Install the package with:
39
+ ```bash
40
+ pip install vicinity
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
+ ```
46
+
47
+
48
+ The following code snippet demonstrates how to use Vicinity for nearest neighbor search:
49
+ ```python
50
+ import numpy as np
51
+ from vicinity import Vicinity
52
+ from vicinity.datatypes import Backend, Metric
53
+
54
+ # Create some dummy data
55
+ items = ["triforce", "master sword", "hylian shield", "boomerang", "hookshot"]
56
+ vectors = np.random.rand(len(items), 128)
57
+
58
+ # Initialize the Vicinity instance (using the basic backend and cosine metric)
59
+ vicinity = Vicinity.from_vectors_and_items(vectors=vectors, items=items, backend_type=Backend.BASIC, metric=Metric.COSINE)
60
+
61
+ # Create a query vector
62
+ query_vector = np.random.rand(128)
63
+
64
+ # Query for nearest neighbors with a top-k search
65
+ results = vicinity.query([query_vector], k=3)
66
+
67
+ # Query for nearest neighbors with a threshold search
68
+ results = vicinity.query_threshold([query_vector], threshold=0.9)
69
+ ```
70
+
71
+ Saving and loading a vector store:
72
+ ```python
73
+ vicinity.save('my_vector_store')
74
+ vicinity = Vicinity.load('my_vector_store')
75
+ ```
76
+
77
+ Evaluating a backend:
78
+ ```python
79
+ # Use the first 1000 vectors as query vectors
80
+ query_vectors = vectors[:1000]
81
+
82
+ # Evaluate the Vicinity instance by measuring the queries per second and recall
83
+ qps, recall = vicinity.evaluate(
84
+ full_vectors=vectors,
85
+ query_vectors=query_vectors,
86
+ )
87
+ ```
88
+
89
+ ## Main Features
90
+ Vicinity provides the following features:
91
+ - Lightweight: Minimal dependencies and fast performance.
92
+ - Flexible Backend Support: Use different backends for vector storage and search.
93
+ - Serialization: Save and load vector stores for persistence.
94
+ - Evaluation: Easily evaluate the performance of different backends.
95
+ - Easy to Use: Simple and intuitive API.
96
+
97
+ ## Supported Backends
98
+ The following backends are supported:
99
+ - `BASIC`: A simple (exact matching) flat index for vector storage and search.
100
+ - [HNSW](https://github.com/nmslib/hnswlib): Hierarchical Navigable Small World Graph (HNSW) for ANN search using hnswlib.
101
+ - [USEARCH](https://github.com/unum-cloud/usearch): ANN search using Usearch. This uses a highly optimized version of the HNSW algorithm.
102
+ - [ANNOY](https://github.com/spotify/annoy): "Approximate Nearest Neighbors Oh Yeah" for approximate nearest neighbor search.
103
+ - [PYNNDescent](https://github.com/lmcinnes/pynndescent): ANN search using PyNNDescent.
104
+ - [FAISS](https://github.com/facebookresearch/faiss): All FAISS indexes are supported:
105
+ - `flat`: Exact search.
106
+ - `ivf`: Inverted file search.
107
+ - `hnsw`: Hierarchical Navigable Small World Graph.
108
+ - `lsh`: Locality Sensitive Hashing.
109
+ - `scalar`: Scalar quantizer.
110
+ - `pq`: Product Quantizer.
111
+ - `ivf_scalar`: Inverted file search with scalar quantizer.
112
+ - `ivfpq`: Inverted file search with product quantizer.
113
+ - `ivfpqr`: Inverted file search with product quantizer and refinement.
114
+
115
+
116
+
117
+
118
+ 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.
119
+
120
+ ### Backend Parameters
121
+
122
+
123
+ | Backend | Parameter | Description | Default Value |
124
+ |-----------------|---------------------|-----------------------------------------------------------------------------------------------|---------------------|
125
+ | **Annoy** | `metric` | Similarity metric to use (`dot`, `euclidean`, `cosine`). | `"cosine"` |
126
+ | | `trees` | Number of trees to use for indexing. | `100` |
127
+ | | `length` | Optional length of the dataset. | `None` |
128
+ | **FAISS** | `metric` | Similarity metric to use (`cosine`, `l2`). | `"cosine"` |
129
+ | | `index_type` | Type of FAISS index (`flat`, `ivf`, `hnsw`, `lsh`, `scalar`, `pq`, `ivf_scalar`, `ivfpq`, `ivfpqr`). | `"hnsw"` |
130
+ | | `nlist` | Number of cells for IVF indexes. | `100` |
131
+ | | `m` | Number of subquantizers for PQ and HNSW indexes. | `8` |
132
+ | | `nbits` | Number of bits for LSH and PQ indexes. | `8` |
133
+ | | `refine_nbits` | Number of bits for the refinement stage in IVFPQR indexes. | `8` |
134
+ | **HNSW** | `metric` | Similarity space to use (`cosine`, `l2`). | `"cosine"` |
135
+ | | `ef_construction` | Size of the dynamic list during index construction. | `200` |
136
+ | | `m` | Number of connections per layer. | `16` |
137
+ | **PyNNDescent** | `metric` | Similarity metric to use (`cosine`, `euclidean`, `manhattan`). | `"cosine"` |
138
+ | | `n_neighbors` | Number of neighbors to use for search. | `15` |
139
+ | **Usearch** | `metric` | Similarity metric to use (`cos`, `ip`, `l2sq`, `hamming`, `tanimoto`). | `"cos"` |
140
+ | | `connectivity` | Number of connections per node in the graph. | `16` |
141
+ | | `expansion_add` | Number of candidates considered during graph construction. | `128` |
142
+ | | `expansion_search` | Number of candidates considered during search. | `64` |
143
+
144
+
145
+ ## Installation
146
+ The following installation options are available:
147
+ ```bash
148
+ # Install the base package
149
+ pip install vicinity
150
+
151
+ # Install all backends
152
+ pip install vicinity[all]
153
+
154
+ # Install specific backends
155
+ pip install vicinity[annoy]
156
+ pip install vicinity[faiss]
157
+ pip install vicinity[hnsw]
158
+ pip install vicinity[pynndescent]
159
+ pip install vicinity[usearch]
160
+ ```
161
+
162
+ ## License
163
+
164
+ MIT
@@ -51,6 +51,17 @@ pynndescent = [
51
51
  ]
52
52
  annoy = ["annoy"]
53
53
  faiss = ["faiss-cpu"]
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
+ ]
54
65
 
55
66
  [project.urls]
56
67
  "Homepage" = "https://github.com/MinishLab"
@@ -34,8 +34,10 @@ BACKEND_PARAMS = [(Backend.FAISS, index_type) for index_type in _faiss_index_typ
34
34
  (Backend.HNSW, None),
35
35
  (Backend.ANNOY, None),
36
36
  (Backend.PYNNDESCENT, None),
37
+ (Backend.USEARCH, None),
37
38
  ]
38
39
 
40
+
39
41
  # Create human-readable ids for each backend type
40
42
  BACKEND_IDS = [f"{backend.name}-{index_type}" if index_type else backend.name for backend, index_type in BACKEND_PARAMS]
41
43
 
@@ -100,15 +100,8 @@ def test_vicinity_delete(vicinity_instance: Vicinity, items: list[str], vectors:
100
100
  :param items: List of item names.
101
101
  :param vectors: Array of vectors corresponding to items.
102
102
  """
103
- if vicinity_instance.backend.backend_type in {Backend.ANNOY, Backend.PYNNDESCENT}:
104
- # Skip delete for Annoy and Pynndescent backend
105
- return
106
-
107
- elif vicinity_instance.backend.backend_type == Backend.FAISS and vicinity_instance.backend.arguments.index_type in {
108
- "hnsw",
109
- "ivfpqr",
110
- }:
111
- # Skip delete test for FAISS index types that do not support deletion
103
+ if vicinity_instance.backend.backend_type != Backend.BASIC:
104
+ # Skip delete for non-basic backends
112
105
  return
113
106
 
114
107
  # Get the vector corresponding to "item2"
@@ -163,6 +156,9 @@ def test_vicinity_delete_nonexistent(vicinity_instance: Vicinity) -> None:
163
156
  :param vicinity_instance: A Vicinity instance.
164
157
  :raises ValueError: If deleting items that do not exist.
165
158
  """
159
+ if vicinity_instance.backend.backend_type != Backend.BASIC:
160
+ # Skip delete for non-basic backends
161
+ return
166
162
  with pytest.raises(ValueError):
167
163
  vicinity_instance.delete(["item10002"])
168
164
 
@@ -193,3 +189,54 @@ def test_vicinity_insert_wrong_dimension(vicinity_instance: Vicinity) -> None:
193
189
 
194
190
  with pytest.raises(ValueError):
195
191
  vicinity_instance.insert(new_item, new_vector)
192
+
193
+
194
+ def test_vicinity_delete_and_query(vicinity_instance: Vicinity, items: list[str], vectors: np.ndarray) -> None:
195
+ """
196
+ Test Vicinity's delete and query methods together to ensure that indices are correctly handled after deletions.
197
+
198
+ :param vicinity_instance: A Vicinity instance.
199
+ :param items: List of item names.
200
+ :param vectors: Array of vectors corresponding to items.
201
+ """
202
+ if vicinity_instance.backend.backend_type != Backend.BASIC:
203
+ # Skip delete for non-basic backends
204
+ return
205
+
206
+ # Delete some items from the Vicinity instance
207
+ items_to_delete = ["item2", "item4", "item6"]
208
+ vicinity_instance.delete(items_to_delete)
209
+
210
+ # Ensure the items are no longer in the items list
211
+ for item in items_to_delete:
212
+ assert item not in vicinity_instance.items
213
+
214
+ # Query using a vector of an item that wasn't deleted
215
+ item3_index = items.index("item3")
216
+ item3_vector = vectors[item3_index]
217
+
218
+ results = vicinity_instance.query(item3_vector, k=10)
219
+ returned_items = [item for item, _ in results[0]]
220
+
221
+ # Check that the queried item is in the results
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)