Skip to content

Commit c12d64f

Browse files
authored
feat: Add configurable ANN backends (#67)
* Added support for custom ANN backends * Added kwargs support for vicinity * Added kwargs support for vicinity * Bumped version
1 parent 46ae1f1 commit c12d64f

6 files changed

Lines changed: 858 additions & 817 deletions

File tree

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,35 @@ deduplicated_texts = semhash.self_deduplicate()
318318

319319
</details>
320320

321+
322+
323+
324+
<details>
325+
<summary> Using custom ANN backends </summary>
326+
<br>
327+
328+
The following code snippet shows how to use a custom ANN backend and custom args with SemHash:
329+
330+
```python
331+
from datasets import load_dataset
332+
from semhash import SemHash
333+
from vicinity import Backend
334+
335+
# Load a dataset to deduplicate
336+
texts = load_dataset("ag_news", split="train")["text"]
337+
338+
# Initialize a SemHash with the model and custom ann backend and custom args
339+
semhash = SemHash.from_records(records=texts, ann_backend=Backend.FAISS, nlist=50)
340+
341+
# Deduplicate the texts
342+
deduplicated_texts = semhash.self_deduplicate()
343+
```
344+
345+
For the full list of supported ANN backends and args, see the [Vicinity docs](https://github.com/MinishLab/vicinity/tree/main?tab=readme-ov-file#supported-backends).
346+
347+
</details>
348+
349+
321350
<details>
322351
<summary> Using Pandas DataFrames </summary>
323352
<br>

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ classifiers = [
2424

2525
dependencies = [
2626
"model2vec>=0.3.4",
27-
"vicinity[usearch]>=0.4.0",
27+
"vicinity[usearch]>=0.4.3",
2828
"frozendict",
2929
]
3030

semhash/index.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
from typing import Any
4+
35
import numpy as np
46
from vicinity import Backend
57
from vicinity.backends import AbstractBackend, get_backend_class
@@ -27,17 +29,21 @@ def __init__(self, vectors: np.ndarray, items: list[DictItem], backend: Abstract
2729
self.vectors = vectors
2830

2931
@classmethod
30-
def from_vectors_and_items(cls, vectors: np.ndarray, items: list[DictItem], backend_type: Backend) -> Index:
32+
def from_vectors_and_items(
33+
cls, vectors: np.ndarray, items: list[DictItem], backend_type: Backend | str, **kwargs: Any
34+
) -> Index:
3135
"""
3236
Load the index from vectors and items.
3337
3438
:param vectors: The vectors of the items.
3539
:param items: The items in the index.
3640
:param backend_type: The type of backend to use.
41+
:param **kwargs: Additional arguments to pass to the backend.
3742
:return: The index.
3843
"""
3944
backend_class = get_backend_class(backend_type)
40-
backend = backend_class.from_vectors(vectors)
45+
arguments = backend_class.argument_class(**kwargs)
46+
backend = backend_class.from_vectors(vectors, **arguments.dict())
4147

4248
return cls(vectors, items, backend)
4349

semhash/semhash.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from collections import defaultdict
44
from math import ceil
5-
from typing import Generic, Literal, Sequence
5+
from typing import Any, Generic, Literal, Sequence
66

77
import numpy as np
88
from frozendict import frozendict
@@ -102,6 +102,8 @@ def from_records(
102102
columns: Sequence[str] | None = None,
103103
use_ann: bool = True,
104104
model: Encoder | None = None,
105+
ann_backend: Backend | str = Backend.USEARCH,
106+
**kwargs: Any,
105107
) -> SemHash:
106108
"""
107109
Initialize a SemHash instance from records.
@@ -112,6 +114,8 @@ def from_records(
112114
:param columns: Columns to featurize if records are dictionaries.
113115
:param use_ann: Whether to use approximate nearest neighbors (True) or basic search (False). Default is True.
114116
:param model: (Optional) An Encoder model. If None, the default model is used (minishlab/potion-base-8M).
117+
:param ann_backend: (Optional) The ANN backend to use if use_ann is True. Defaults to Backend.USEARCH.
118+
:param **kwargs: Any additional keyword arguments to pass to the Vicinity index.
115119
:return: A SemHash instance with a fitted vicinity index.
116120
:raises ValueError: If columns are not provided for dictionary records.
117121
"""
@@ -151,11 +155,12 @@ def from_records(
151155
embeddings = cls._featurize(deduplicated_records, columns, model)
152156

153157
# Build the Vicinity index
154-
backend = Backend.USEARCH if use_ann else Backend.BASIC
158+
backend = ann_backend if use_ann else Backend.BASIC
155159
index = Index.from_vectors_and_items(
156160
vectors=embeddings,
157161
items=items,
158162
backend_type=backend,
163+
**kwargs,
159164
)
160165

161166
return cls(index=index, columns=columns, model=model, was_string=was_string)

semhash/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__version_triple__ = (0, 3, 1)
1+
__version_triple__ = (0, 3, 2)
22
__version__ = ".".join(map(str, __version_triple__))

0 commit comments

Comments
 (0)