usearch 0.11.0 → 0.11.1
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/Cargo.toml +1 -1
- package/VERSION +1 -1
- package/conanfile.py +1 -1
- package/package.json +1 -1
- package/python/usearch/client.py +8 -9
- package/python/usearch/index.py +13 -5
- package/python/usearch/server.py +6 -16
package/Cargo.toml
CHANGED
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.11.
|
|
1
|
+
0.11.1
|
package/conanfile.py
CHANGED
|
@@ -4,7 +4,7 @@ from conans import ConanFile
|
|
|
4
4
|
class USearchConan(ConanFile):
|
|
5
5
|
|
|
6
6
|
name = 'USearch'
|
|
7
|
-
version = '0.11.
|
|
7
|
+
version = '0.11.1'
|
|
8
8
|
license = 'Apache 2.0'
|
|
9
9
|
url = 'https://github.com/unum-cloud/usearch'
|
|
10
10
|
description = 'Smaller & Faster Single-File Vector Search Engine from Unum'
|
package/package.json
CHANGED
package/python/usearch/client.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
from typing import Union, Optional
|
|
1
|
+
from typing import Union, Optional, List
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
from ucall.client import Client
|
|
5
5
|
|
|
6
|
+
from usearch.index import Matches
|
|
7
|
+
|
|
6
8
|
|
|
7
9
|
def _vector_to_ascii(vector: np.ndarray) -> Optional[str]:
|
|
8
10
|
if vector.dtype != np.int8 and vector.dtype != np.uint8 and vector.dtype != np.byte:
|
|
@@ -18,9 +20,6 @@ def _vector_to_ascii(vector: np.ndarray) -> Optional[str]:
|
|
|
18
20
|
return ascii
|
|
19
21
|
|
|
20
22
|
|
|
21
|
-
Triplet = tuple[np.ndarray, np.ndarray, np.ndarray]
|
|
22
|
-
|
|
23
|
-
|
|
24
23
|
class IndexClient:
|
|
25
24
|
|
|
26
25
|
def __init__(
|
|
@@ -53,8 +52,8 @@ class IndexClient:
|
|
|
53
52
|
else:
|
|
54
53
|
return self.add_many(labels, vectors)
|
|
55
54
|
|
|
56
|
-
def search_one(self, vector: np.ndarray, count: int) ->
|
|
57
|
-
matches:
|
|
55
|
+
def search_one(self, vector: np.ndarray, count: int) -> Matches:
|
|
56
|
+
matches: List[dict] = []
|
|
58
57
|
vector = vector.flatten()
|
|
59
58
|
ascii = _vector_to_ascii(vector)
|
|
60
59
|
if ascii:
|
|
@@ -75,9 +74,9 @@ class IndexClient:
|
|
|
75
74
|
|
|
76
75
|
return labels, distances, counts
|
|
77
76
|
|
|
78
|
-
def search_many(self, vectors: np.ndarray, count: int) ->
|
|
77
|
+
def search_many(self, vectors: np.ndarray, count: int) -> Matches:
|
|
79
78
|
batch_size: int = vectors.shape[0]
|
|
80
|
-
list_of_matches:
|
|
79
|
+
list_of_matches: List[List[dict]] = self.client.search_many(
|
|
81
80
|
vectors=vectors, count=count)
|
|
82
81
|
|
|
83
82
|
labels = np.array((batch_size, count), dtype=np.uint32)
|
|
@@ -91,7 +90,7 @@ class IndexClient:
|
|
|
91
90
|
|
|
92
91
|
return labels, distances, counts
|
|
93
92
|
|
|
94
|
-
def search(self, vectors: np.ndarray, count: int) ->
|
|
93
|
+
def search(self, vectors: np.ndarray, count: int) -> Matches:
|
|
95
94
|
if vectors.ndim == 1 or (vectors.ndim == 2 and vectors.shape[0] == 1):
|
|
96
95
|
return self.search_one(vectors, count)
|
|
97
96
|
else:
|
package/python/usearch/index.py
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# into the primary `Index` class, connecting USearch with Numba.
|
|
5
5
|
import os
|
|
6
6
|
from math import sqrt
|
|
7
|
-
from typing import Optional, Callable, Union
|
|
7
|
+
from typing import Optional, Callable, Union, NamedTuple, List
|
|
8
8
|
|
|
9
9
|
import numpy as np
|
|
10
10
|
|
|
@@ -13,12 +13,17 @@ from usearch.compiled import SetsIndex as _CompiledSetsIndex
|
|
|
13
13
|
from usearch.compiled import HashIndex as _CompiledHashIndex
|
|
14
14
|
from usearch.compiled import DEFAULT_CONNECTIVITY, DEFAULT_EXPANSION_ADD, DEFAULT_EXPANSION_SEARCH
|
|
15
15
|
|
|
16
|
-
Triplet = tuple[np.ndarray, np.ndarray, np.ndarray]
|
|
17
16
|
SetsIndex = _CompiledSetsIndex
|
|
18
17
|
HashIndex = _CompiledHashIndex
|
|
19
18
|
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
class Matches(NamedTuple):
|
|
21
|
+
labels: np.ndarray
|
|
22
|
+
distances: np.ndarray
|
|
23
|
+
counts: np.ndarray
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def list_matches(results: Matches, row: int) -> List[dict]:
|
|
22
27
|
|
|
23
28
|
count = results[2][row]
|
|
24
29
|
labels = results[0][row, :count]
|
|
@@ -236,8 +241,11 @@ class Index:
|
|
|
236
241
|
|
|
237
242
|
def search(
|
|
238
243
|
self, vectors, k: int = 10, *,
|
|
239
|
-
threads: int = 0, exact: bool = False) ->
|
|
240
|
-
|
|
244
|
+
threads: int = 0, exact: bool = False) -> Matches:
|
|
245
|
+
tuple_ = self._compiled.search(
|
|
246
|
+
vectors, k,
|
|
247
|
+
exact=exact, threads=threads)
|
|
248
|
+
return Matches(*tuple_)
|
|
241
249
|
|
|
242
250
|
def __len__(self) -> int:
|
|
243
251
|
return len(self._compiled)
|
package/python/usearch/server.py
CHANGED
|
@@ -4,20 +4,10 @@
|
|
|
4
4
|
import os
|
|
5
5
|
import argparse
|
|
6
6
|
import numpy as np
|
|
7
|
+
from typing import List
|
|
7
8
|
|
|
8
9
|
from ucall.rich_posix import Server
|
|
9
|
-
from usearch.index import Index
|
|
10
|
-
|
|
11
|
-
Triplet = tuple[np.ndarray, np.ndarray, np.ndarray]
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def _results_to_json(results: Triplet, row: int) -> list[dict]:
|
|
15
|
-
|
|
16
|
-
count = results[2][row]
|
|
17
|
-
labels = results[0][row, :count]
|
|
18
|
-
distances = results[1][row, :count]
|
|
19
|
-
return [{'label': int(label), 'distance': float(distance)}
|
|
20
|
-
for label, distance in zip(labels, distances)]
|
|
10
|
+
from usearch.index import Index, list_matches
|
|
21
11
|
|
|
22
12
|
|
|
23
13
|
def _ascii_to_vector(string: str) -> np.ndarray:
|
|
@@ -78,16 +68,16 @@ def serve(
|
|
|
78
68
|
index.add(labels, vectors, threads=threads)
|
|
79
69
|
|
|
80
70
|
@server
|
|
81
|
-
def search_one(vector: np.ndarray, count: int) ->
|
|
71
|
+
def search_one(vector: np.ndarray, count: int) -> List[dict]:
|
|
82
72
|
print('search', vector, count)
|
|
83
73
|
vectors = vector.reshape(vector.shape[0], 1)
|
|
84
74
|
results = index.search(vectors, count)
|
|
85
|
-
return
|
|
75
|
+
return list_matches(results, 0)
|
|
86
76
|
|
|
87
77
|
@server
|
|
88
|
-
def search_many(vectors: np.ndarray, count: int) ->
|
|
78
|
+
def search_many(vectors: np.ndarray, count: int) -> List[List[dict]]:
|
|
89
79
|
results = index.search(vectors, count)
|
|
90
|
-
return [
|
|
80
|
+
return [list_matches(results, i) for i in range(vectors.shape[0])]
|
|
91
81
|
|
|
92
82
|
@server
|
|
93
83
|
def add_ascii(label: int, string: str):
|