fastembed-gpu 0.4.0__tar.gz → 0.4.2__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 (47) hide show
  1. fastembed_gpu-0.4.2/NOTICE +14 -0
  2. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/PKG-INFO +21 -6
  3. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/README.md +15 -0
  4. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/common/onnx_model.py +1 -11
  5. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/late_interaction/colbert.py +11 -15
  6. fastembed_gpu-0.4.2/fastembed/late_interaction/jina_colbert.py +62 -0
  7. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/late_interaction/late_interaction_text_embedding.py +2 -3
  8. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/parallel_processor.py +1 -1
  9. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/rerank/cross_encoder/onnx_text_cross_encoder.py +30 -0
  10. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/rerank/cross_encoder/onnx_text_model.py +4 -4
  11. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/sparse/bm25.py +3 -4
  12. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/sparse/bm42.py +4 -4
  13. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/sparse/utils/tokenizer.py +1 -0
  14. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/pyproject.toml +6 -6
  15. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/LICENSE +0 -0
  16. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/__init__.py +0 -0
  17. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/common/__init__.py +0 -0
  18. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/common/model_management.py +0 -0
  19. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/common/preprocessor_utils.py +0 -0
  20. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/common/types.py +0 -0
  21. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/common/utils.py +0 -0
  22. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/embedding.py +0 -0
  23. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/image/__init__.py +0 -0
  24. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/image/image_embedding.py +0 -0
  25. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/image/image_embedding_base.py +0 -0
  26. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/image/onnx_embedding.py +0 -0
  27. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/image/onnx_image_model.py +0 -0
  28. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/image/transform/functional.py +0 -0
  29. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/image/transform/operators.py +0 -0
  30. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/late_interaction/__init__.py +0 -0
  31. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/late_interaction/late_interaction_embedding_base.py +0 -0
  32. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/rerank/cross_encoder/__init__.py +0 -0
  33. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/rerank/cross_encoder/text_cross_encoder.py +0 -0
  34. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/rerank/cross_encoder/text_cross_encoder_base.py +0 -0
  35. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/sparse/__init__.py +0 -0
  36. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/sparse/sparse_embedding_base.py +0 -0
  37. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/sparse/sparse_text_embedding.py +0 -0
  38. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/sparse/splade_pp.py +0 -0
  39. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/text/__init__.py +0 -0
  40. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/text/clip_embedding.py +0 -0
  41. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/text/e5_onnx_embedding.py +0 -0
  42. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/text/onnx_embedding.py +0 -0
  43. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/text/onnx_text_model.py +0 -0
  44. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/text/pooled_embedding.py +0 -0
  45. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/text/pooled_normalized_embedding.py +0 -0
  46. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/text/text_embedding.py +0 -0
  47. {fastembed_gpu-0.4.0 → fastembed_gpu-0.4.2}/fastembed/text/text_embedding_base.py +0 -0
@@ -0,0 +1,14 @@
1
+ Copyright 2024 Qdrant
2
+
3
+ This product includes software developed by Qdrant
4
+
5
+ This distribution includes the following Jina AI models, each with its respective license:
6
+ - jinaai/jina-colbert-v2
7
+ - License: cc-by-nc-4.0
8
+ - jinaai/jina-reranker-v2-base-multilingual
9
+ - License: cc-by-nc-4.0
10
+
11
+ These models are developed by Jina (https://jina.ai/) and are subject to Jina AI's licensing terms.
12
+
13
+ Additional Notes:
14
+ This project also includes third-party libraries with their respective licenses. Please refer to the documentation of each library for details regarding its usage and licensing terms.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastembed-gpu
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Fast, light, accurate library built for retrieval embedding generation
5
5
  Home-page: https://github.com/qdrant/fastembed
6
6
  License: Apache License
@@ -15,16 +15,16 @@ Classifier: Programming Language :: Python :: 3.9
15
15
  Classifier: Programming Language :: Python :: 3.10
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
- Requires-Dist: PyStemmer (>=2.2.0,<3.0.0)
19
18
  Requires-Dist: huggingface-hub (>=0.20,<1.0)
20
19
  Requires-Dist: loguru (>=0.7.2,<0.8.0)
21
20
  Requires-Dist: mmh3 (>=4.1.0,<5.0.0)
22
- Requires-Dist: numpy (>=1.21,<2) ; python_version < "3.12"
23
- Requires-Dist: numpy (>=1.26,<2) ; python_version >= "3.12"
24
- Requires-Dist: onnxruntime-gpu (>=1.17.0,<2.0.0)
21
+ Requires-Dist: numpy (>=1.21) ; python_version < "3.12"
22
+ Requires-Dist: numpy (>=1.26) ; python_version >= "3.12"
23
+ Requires-Dist: onnx (>=1.15.0,<2.0.0)
24
+ Requires-Dist: onnxruntime-gpu (>=1.17.0,<1.20.0)
25
25
  Requires-Dist: pillow (>=10.3.0,<11.0.0)
26
+ Requires-Dist: py-rust-stemmers (>=0.1.0,<0.2.0)
26
27
  Requires-Dist: requests (>=2.31,<3.0)
27
- Requires-Dist: snowballstemmer (>=2.2.0,<3.0.0)
28
28
  Requires-Dist: tokenizers (>=0.15,<1.0)
29
29
  Requires-Dist: tqdm (>=4.66,<5.0)
30
30
  Project-URL: Repository, https://github.com/qdrant/fastembed
@@ -169,6 +169,21 @@ embeddings = list(model.embed(images))
169
169
  # ]
170
170
  ```
171
171
 
172
+ ### 🔄 Rerankers
173
+ ```python
174
+ from typing import List
175
+ from fastembed.rerank.cross_encoder import TextCrossEncoder
176
+
177
+ query = "Who is maintaining Qdrant?"
178
+ documents: List[str] = [
179
+ "This is built to be faster and lighter than other embedding libraries e.g. Transformers, Sentence-Transformers, etc.",
180
+ "fastembed is supported by and maintained by Qdrant.",
181
+ ]
182
+ encoder = TextCrossEncoder(model_name="Xenova/ms-marco-MiniLM-L-6-v2")
183
+ scores = list(encoder.rerank(query, documents))
184
+
185
+ # [-11.48061752319336, 5.472434997558594]
186
+ ```
172
187
 
173
188
  ## ⚡️ FastEmbed on a GPU
174
189
 
@@ -137,6 +137,21 @@ embeddings = list(model.embed(images))
137
137
  # ]
138
138
  ```
139
139
 
140
+ ### 🔄 Rerankers
141
+ ```python
142
+ from typing import List
143
+ from fastembed.rerank.cross_encoder import TextCrossEncoder
144
+
145
+ query = "Who is maintaining Qdrant?"
146
+ documents: List[str] = [
147
+ "This is built to be faster and lighter than other embedding libraries e.g. Transformers, Sentence-Transformers, etc.",
148
+ "fastembed is supported by and maintained by Qdrant.",
149
+ ]
150
+ encoder = TextCrossEncoder(model_name="Xenova/ms-marco-MiniLM-L-6-v2")
151
+ scores = list(encoder.rerank(query, documents))
152
+
153
+ # [-11.48061752319336, 5.472434997558594]
154
+ ```
140
155
 
141
156
  ## ⚡️ FastEmbed on a GPU
142
157
 
@@ -1,17 +1,7 @@
1
1
  import warnings
2
2
  from dataclasses import dataclass
3
3
  from pathlib import Path
4
- from typing import (
5
- Any,
6
- Dict,
7
- Generic,
8
- Iterable,
9
- Optional,
10
- Sequence,
11
- Tuple,
12
- Type,
13
- TypeVar,
14
- )
4
+ from typing import Any, Dict, Generic, Iterable, Optional, Sequence, Tuple, Type, TypeVar
15
5
 
16
6
  import numpy as np
17
7
  import onnxruntime as ort
@@ -12,6 +12,7 @@ from fastembed.late_interaction.late_interaction_embedding_base import (
12
12
  )
13
13
  from fastembed.text.onnx_text_model import OnnxTextModel, TextEmbeddingWorker
14
14
 
15
+
15
16
  supported_colbert_models = [
16
17
  {
17
18
  "model": "colbert-ir/colbertv2.0",
@@ -41,7 +42,7 @@ supported_colbert_models = [
41
42
  class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[np.ndarray]):
42
43
  QUERY_MARKER_TOKEN_ID = 1
43
44
  DOCUMENT_MARKER_TOKEN_ID = 2
44
- MIN_QUERY_LENGTH = 32
45
+ MIN_QUERY_LENGTH = 31 # it's 32, we add one additional special token in the beginning
45
46
  MASK_TOKEN = "[MASK]"
46
47
 
47
48
  def _post_process_onnx_output(
@@ -67,15 +68,14 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[np.ndarray]):
67
68
  return output.model_output.astype(np.float32)
68
69
 
69
70
  def _preprocess_onnx_input(
70
- self, onnx_input: Dict[str, np.ndarray], is_doc: bool = True
71
+ self, onnx_input: Dict[str, np.ndarray], is_doc: bool = True, **kwargs: Any
71
72
  ) -> Dict[str, np.ndarray]:
72
- if is_doc:
73
- onnx_input["input_ids"][:, 1] = self.DOCUMENT_MARKER_TOKEN_ID
74
- else:
75
- onnx_input["input_ids"][:, 1] = self.QUERY_MARKER_TOKEN_ID
73
+ marker_token = self.DOCUMENT_MARKER_TOKEN_ID if is_doc else self.QUERY_MARKER_TOKEN_ID
74
+ onnx_input["input_ids"] = np.insert(onnx_input["input_ids"], 1, marker_token, axis=1)
75
+ onnx_input["attention_mask"] = np.insert(onnx_input["attention_mask"], 1, 1, axis=1)
76
76
  return onnx_input
77
77
 
78
- def tokenize(self, documents: List[str], is_doc: bool = True) -> List[Encoding]:
78
+ def tokenize(self, documents: List[str], is_doc: bool = True, **kwargs: Any) -> List[Encoding]:
79
79
  return (
80
80
  self._tokenize_documents(documents=documents)
81
81
  if is_doc
@@ -83,9 +83,7 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[np.ndarray]):
83
83
  )
84
84
 
85
85
  def _tokenize_query(self, query: str) -> List[Encoding]:
86
- # ". " is added to a query to be replaced with a special query token
87
- query = [f". {query}"]
88
- encoded = self.tokenizer.encode_batch(query)
86
+ encoded = self.tokenizer.encode_batch([query])
89
87
  # colbert authors recommend to pad queries with [MASK] tokens for query augmentation to improve performance
90
88
  if len(encoded[0].ids) < self.MIN_QUERY_LENGTH:
91
89
  prev_padding = None
@@ -96,7 +94,7 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[np.ndarray]):
96
94
  pad_id=self.mask_token_id,
97
95
  length=self.MIN_QUERY_LENGTH,
98
96
  )
99
- encoded = self.tokenizer.encode_batch(query)
97
+ encoded = self.tokenizer.encode_batch([query])
100
98
  if prev_padding is None:
101
99
  self.tokenizer.no_padding()
102
100
  else:
@@ -104,8 +102,6 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[np.ndarray]):
104
102
  return encoded
105
103
 
106
104
  def _tokenize_documents(self, documents: List[str]) -> List[Encoding]:
107
- # ". " is added to a document to be replaced with a special document token
108
- documents = [". " + doc for doc in documents]
109
105
  encoded = self.tokenizer.encode_batch(documents)
110
106
  return encoded
111
107
 
@@ -189,7 +185,7 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[np.ndarray]):
189
185
  cuda=self.cuda,
190
186
  device_id=self.device_id,
191
187
  )
192
- self.mask_token_id = self.special_token_to_id["[MASK]"]
188
+ self.mask_token_id = self.special_token_to_id[self.MASK_TOKEN]
193
189
  self.pad_token_id = self.tokenizer.padding["pad_id"]
194
190
  self.skip_list = {
195
191
  self.tokenizer.encode(symbol, add_special_tokens=False).ids[0]
@@ -230,7 +226,7 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[np.ndarray]):
230
226
  **kwargs,
231
227
  )
232
228
 
233
- def query_embed(self, query: Union[str, List[str]], **kwargs) -> Iterable[np.ndarray]:
229
+ def query_embed(self, query: Union[str, Iterable[str]], **kwargs) -> Iterable[np.ndarray]:
234
230
  if isinstance(query, str):
235
231
  query = [query]
236
232
 
@@ -0,0 +1,62 @@
1
+ from typing import Any, Dict, List, Type
2
+
3
+ import numpy as np
4
+
5
+ from fastembed.late_interaction.colbert import Colbert
6
+ from fastembed.text.onnx_text_model import TextEmbeddingWorker
7
+
8
+
9
+ supported_jina_colbert_models = [
10
+ {
11
+ "model": "jinaai/jina-colbert-v2",
12
+ "dim": 128,
13
+ "description": "New model that expands capabilities of colbert-v1 with multilingual and context length of 8192, 2024 year",
14
+ "license": "cc-by-nc-4.0",
15
+ "size_in_GB": 2.24,
16
+ "sources": {
17
+ "hf": "jinaai/jina-colbert-v2",
18
+ },
19
+ "model_file": "onnx/model.onnx",
20
+ "additional_files": ["onnx/model.onnx_data"],
21
+ },
22
+ ]
23
+
24
+
25
+ class JinaColbert(Colbert):
26
+ QUERY_MARKER_TOKEN_ID = 250002
27
+ DOCUMENT_MARKER_TOKEN_ID = 250003
28
+ MIN_QUERY_LENGTH = 31 # it's 32, we add one additional special token in the beginning
29
+ MASK_TOKEN = "<mask>"
30
+
31
+ @classmethod
32
+ def _get_worker_class(cls) -> Type[TextEmbeddingWorker]:
33
+ return JinaColbertEmbeddingWorker
34
+
35
+ @classmethod
36
+ def list_supported_models(cls) -> List[Dict[str, Any]]:
37
+ """Lists the supported models.
38
+
39
+ Returns:
40
+ List[Dict[str, Any]]: A list of dictionaries containing the model information.
41
+ """
42
+ return supported_jina_colbert_models
43
+
44
+ def _preprocess_onnx_input(
45
+ self, onnx_input: Dict[str, np.ndarray], is_doc: bool = True, **kwargs: Any
46
+ ) -> Dict[str, np.ndarray]:
47
+ onnx_input = super()._preprocess_onnx_input(onnx_input, is_doc)
48
+
49
+ # the attention mask for jina-colbert-v2 is always 1 in queries
50
+ if not is_doc:
51
+ onnx_input["attention_mask"][:] = 1
52
+ return onnx_input
53
+
54
+
55
+ class JinaColbertEmbeddingWorker(TextEmbeddingWorker):
56
+ def init_embedding(self, model_name: str, cache_dir: str, **kwargs) -> JinaColbert:
57
+ return JinaColbert(
58
+ model_name=model_name,
59
+ cache_dir=cache_dir,
60
+ threads=1,
61
+ **kwargs,
62
+ )
@@ -4,15 +4,14 @@ import numpy as np
4
4
 
5
5
  from fastembed.common import OnnxProvider
6
6
  from fastembed.late_interaction.colbert import Colbert
7
+ from fastembed.late_interaction.jina_colbert import JinaColbert
7
8
  from fastembed.late_interaction.late_interaction_embedding_base import (
8
9
  LateInteractionTextEmbeddingBase,
9
10
  )
10
11
 
11
12
 
12
13
  class LateInteractionTextEmbedding(LateInteractionTextEmbeddingBase):
13
- EMBEDDINGS_REGISTRY: List[Type[LateInteractionTextEmbeddingBase]] = [
14
- Colbert,
15
- ]
14
+ EMBEDDINGS_REGISTRY: List[Type[LateInteractionTextEmbeddingBase]] = [Colbert, JinaColbert]
16
15
 
17
16
  @classmethod
18
17
  def list_supported_models(cls) -> List[Dict[str, Any]]:
@@ -24,7 +24,7 @@ class QueueSignals(str, Enum):
24
24
 
25
25
  class Worker:
26
26
  @classmethod
27
- def start(cls, **kwargs: Any) -> "Worker":
27
+ def start(cls, *args: Any, **kwargs: Any) -> "Worker":
28
28
  raise NotImplementedError()
29
29
 
30
30
  def process(self, items: Iterable[Tuple[int, Any]]) -> Iterable[Tuple[int, Any]]:
@@ -38,6 +38,36 @@ supported_onnx_models = [
38
38
  "description": "BGE reranker base model for cross-encoder re-ranking.",
39
39
  "license": "mit",
40
40
  },
41
+ {
42
+ "model": "jinaai/jina-reranker-v1-tiny-en",
43
+ "size_in_GB": 0.13,
44
+ "sources": {
45
+ "hf": "jinaai/jina-reranker-v1-tiny-en",
46
+ },
47
+ "model_file": "onnx/model.onnx",
48
+ "description": "Designed for blazing-fast re-ranking with 8K context length and fewer parameters than jina-reranker-v1-turbo-en.",
49
+ "license": "apache-2.0",
50
+ },
51
+ {
52
+ "model": "jinaai/jina-reranker-v1-turbo-en",
53
+ "size_in_GB": 0.15,
54
+ "sources": {
55
+ "hf": "jinaai/jina-reranker-v1-turbo-en",
56
+ },
57
+ "model_file": "onnx/model.onnx",
58
+ "description": "Designed for blazing-fast re-ranking with 8K context length.",
59
+ "license": "apache-2.0",
60
+ },
61
+ {
62
+ "model": "jinaai/jina-reranker-v2-base-multilingual",
63
+ "size_in_GB": 1.11,
64
+ "sources": {
65
+ "hf": "jinaai/jina-reranker-v2-base-multilingual",
66
+ },
67
+ "model_file": "onnx/model.onnx",
68
+ "description": "A multi-lingual reranker model for cross-encoder re-ranking with 1K context length and sliding window",
69
+ "license": "cc-by-nc-4.0",
70
+ },
41
71
  ]
42
72
 
43
73
 
@@ -4,7 +4,7 @@ from pathlib import Path
4
4
  import numpy as np
5
5
  from tokenizers import Encoding
6
6
 
7
- from fastembed.common.onnx_model import OnnxModel, OnnxProvider
7
+ from fastembed.common.onnx_model import OnnxModel, OnnxProvider, OnnxOutputContext
8
8
  from fastembed.common.preprocessor_utils import load_tokenizer
9
9
  from fastembed.common.utils import iter_batch
10
10
 
@@ -34,7 +34,7 @@ class OnnxCrossEncoderModel(OnnxModel):
34
34
  def tokenize(self, query: str, documents: List[str], **kwargs) -> List[Encoding]:
35
35
  return self.tokenizer.encode_batch([(query, doc) for doc in documents])
36
36
 
37
- def onnx_embed(self, query: str, documents: List[str], **kwargs) -> List[float]:
37
+ def onnx_embed(self, query: str, documents: List[str], **kwargs) -> OnnxOutputContext:
38
38
  tokenized_input = self.tokenize(query, documents, **kwargs)
39
39
 
40
40
  inputs = {
@@ -51,7 +51,7 @@ class OnnxCrossEncoderModel(OnnxModel):
51
51
 
52
52
  onnx_input = self._preprocess_onnx_input(inputs, **kwargs)
53
53
  outputs = self.model.run(self.ONNX_OUTPUT_NAMES, onnx_input)
54
- return outputs[0][:, 0].tolist()
54
+ return OnnxOutputContext(model_output=outputs[0][:, 0].tolist())
55
55
 
56
56
  def _rerank_documents(
57
57
  self, query: str, documents: Iterable[str], batch_size: int, **kwargs
@@ -59,7 +59,7 @@ class OnnxCrossEncoderModel(OnnxModel):
59
59
  if not hasattr(self, "model") or self.model is None:
60
60
  self.load_onnx_model()
61
61
  for batch in iter_batch(documents, batch_size):
62
- yield from self.onnx_embed(query, batch, **kwargs)
62
+ yield from self.onnx_embed(query, batch, **kwargs).model_output
63
63
 
64
64
  def _preprocess_onnx_input(
65
65
  self, onnx_input: Dict[str, np.ndarray], **kwargs
@@ -6,8 +6,7 @@ from typing import Any, Dict, Iterable, List, Optional, Tuple, Type, Union
6
6
 
7
7
  import mmh3
8
8
  import numpy as np
9
- from snowballstemmer import stemmer as get_stemmer
10
-
9
+ from py_rust_stemmers import SnowballStemmer
11
10
  from fastembed.common.utils import (
12
11
  define_cache_dir,
13
12
  iter_batch,
@@ -130,7 +129,7 @@ class Bm25(SparseTextEmbeddingBase):
130
129
  self.punctuation = set(get_all_punctuation())
131
130
  self.stopwords = set(self._load_stopwords(self._model_dir, self.language))
132
131
 
133
- self.stemmer = get_stemmer(language)
132
+ self.stemmer = SnowballStemmer(language)
134
133
  self.tokenizer = SimpleTokenizer
135
134
 
136
135
  @classmethod
@@ -235,7 +234,7 @@ class Bm25(SparseTextEmbeddingBase):
235
234
  if len(token) > self.token_max_length:
236
235
  continue
237
236
 
238
- stemmed_token = self.stemmer.stemWord(token.lower())
237
+ stemmed_token = self.stemmer.stem_word(token.lower())
239
238
 
240
239
  if stemmed_token:
241
240
  stemmed_tokens.append(stemmed_token)
@@ -5,7 +5,7 @@ from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Type, U
5
5
 
6
6
  import mmh3
7
7
  import numpy as np
8
- from snowballstemmer import stemmer as get_stemmer
8
+ from py_rust_stemmers import SnowballStemmer
9
9
 
10
10
  from fastembed.common import OnnxProvider
11
11
  from fastembed.common.onnx_model import OnnxOutputContext
@@ -119,8 +119,8 @@ class Bm42(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
119
119
  self.special_tokens = set()
120
120
  self.special_tokens_ids = set()
121
121
  self.punctuation = set(string.punctuation)
122
- self.stopwords = set()
123
- self.stemmer = get_stemmer(MODEL_TO_LANGUAGE[model_name])
122
+ self.stopwords = set(self._load_stopwords(self._model_dir))
123
+ self.stemmer = SnowballStemmer(MODEL_TO_LANGUAGE[model_name])
124
124
  self.alpha = alpha
125
125
 
126
126
  if not self.lazy_load:
@@ -152,7 +152,7 @@ class Bm42(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
152
152
  def _stem_pair_tokens(self, tokens: List[Tuple[str, Any]]) -> List[Tuple[str, Any]]:
153
153
  result = []
154
154
  for token, value in tokens:
155
- processed_token = self.stemmer.stemWord(token)
155
+ processed_token = self.stemmer.stem_word(token)
156
156
  result.append((processed_token, value))
157
157
  return result
158
158
 
@@ -5,6 +5,7 @@ from typing import List
5
5
 
6
6
 
7
7
  class SimpleTokenizer:
8
+ @staticmethod
8
9
  def tokenize(text: str) -> List[str]:
9
10
  text = re.sub(r"[^\w]", " ", text.lower())
10
11
  text = re.sub(r"\s+", " ", text)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "fastembed-gpu"
3
- version = "0.4.0"
3
+ version = "0.4.2"
4
4
  description = "Fast, light, accurate library built for retrieval embedding generation"
5
5
  authors = ["Qdrant Team <info@qdrant.tech>", "NirantK <nirant.bits@gmail.com>"]
6
6
  license = "Apache License"
@@ -12,20 +12,20 @@ keywords = ["vector", "embedding", "neural", "search", "qdrant", "sentence-trans
12
12
 
13
13
  [tool.poetry.dependencies]
14
14
  python = ">=3.8.0,<3.13"
15
- onnxruntime-gpu = "^1.17.0"
15
+ onnx = "^1.15.0"
16
+ onnxruntime-gpu = ">=1.17.0,<1.20.0"
16
17
  tqdm = "^4.66"
17
18
  requests = "^2.31"
18
19
  tokenizers = ">=0.15,<1.0"
19
20
  huggingface-hub = ">=0.20,<1.0"
20
21
  loguru = "^0.7.2"
21
22
  numpy = [
22
- { version = ">=1.21, <2", python = "<3.12" },
23
- { version = ">=1.26, <2", python = ">=3.12" }
23
+ { version = ">=1.21", python = "<3.12" },
24
+ { version = ">=1.26", python = ">=3.12" }
24
25
  ]
25
26
  pillow = "^10.3.0"
26
- snowballstemmer = "^2.2.0"
27
- PyStemmer = "^2.2.0"
28
27
  mmh3 = "^4.1.0"
28
+ py-rust-stemmers = "^0.1.0"
29
29
 
30
30
  [tool.poetry.group.dev.dependencies]
31
31
  pytest = "^7.4.2"
File without changes