fastembed-gpu 0.3.3__tar.gz → 0.3.5__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 (42) hide show
  1. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/PKG-INFO +10 -9
  2. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/README.md +9 -9
  3. fastembed_gpu-0.3.5/fastembed/common/__init__.py +3 -0
  4. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/common/model_management.py +43 -37
  5. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/common/preprocessor_utils.py +11 -5
  6. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/common/types.py +3 -1
  7. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/image_embedding.py +2 -2
  8. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/onnx_embedding.py +22 -2
  9. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/onnx_image_model.py +12 -7
  10. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/late_interaction/colbert.py +11 -1
  11. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/bm25.py +44 -9
  12. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/bm42.py +1 -0
  13. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/sparse_text_embedding.py +10 -7
  14. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/splade_pp.py +0 -12
  15. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/text/clip_embedding.py +1 -1
  16. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/text/e5_onnx_embedding.py +2 -2
  17. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/text/onnx_embedding.py +14 -44
  18. fastembed_gpu-0.3.5/fastembed/text/pooled_embedding.py +87 -0
  19. fastembed_gpu-0.3.3/fastembed/text/jina_onnx_embedding.py → fastembed_gpu-0.3.5/fastembed/text/pooled_normalized_embedding.py +29 -19
  20. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/text/text_embedding.py +4 -4
  21. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/pyproject.toml +1 -1
  22. fastembed_gpu-0.3.3/fastembed/common/__init__.py +0 -3
  23. fastembed_gpu-0.3.3/fastembed/text/mini_lm_embedding.py +0 -58
  24. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/LICENSE +0 -0
  25. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/__init__.py +0 -0
  26. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/common/onnx_model.py +0 -0
  27. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/common/utils.py +0 -0
  28. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/embedding.py +0 -0
  29. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/__init__.py +0 -0
  30. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/image_embedding_base.py +0 -0
  31. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/transform/functional.py +0 -0
  32. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/transform/operators.py +0 -0
  33. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/late_interaction/__init__.py +0 -0
  34. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/late_interaction/late_interaction_embedding_base.py +0 -0
  35. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/late_interaction/late_interaction_text_embedding.py +0 -0
  36. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/parallel_processor.py +0 -0
  37. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/__init__.py +0 -0
  38. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/sparse_embedding_base.py +0 -0
  39. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/utils/tokenizer.py +0 -0
  40. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/text/__init__.py +0 -0
  41. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/text/onnx_text_model.py +0 -0
  42. {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/text/text_embedding_base.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastembed-gpu
3
- Version: 0.3.3
3
+ Version: 0.3.5
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
@@ -40,9 +40,9 @@ The default text embedding (`TextEmbedding`) model is Flag Embedding, presented
40
40
 
41
41
  1. Light: FastEmbed is a lightweight library with few external dependencies. We don't require a GPU and don't download GBs of PyTorch dependencies, and instead use the ONNX Runtime. This makes it a great candidate for serverless runtimes like AWS Lambda.
42
42
 
43
- 2. Fast: FastEmbed is designed for speed. We use the ONNX Runtime, which is faster than PyTorch. We also use data-parallelism for encoding large datasets.
43
+ 2. Fast: FastEmbed is designed for speed. We use the ONNX Runtime, which is faster than PyTorch. We also use data parallelism for encoding large datasets.
44
44
 
45
- 3. Accurate: FastEmbed is better than OpenAI Ada-002. We also [supported](https://qdrant.github.io/fastembed/examples/Supported_Models/) an ever expanding set of models, including a few multilingual models.
45
+ 3. Accurate: FastEmbed is better than OpenAI Ada-002. We also [support](https://qdrant.github.io/fastembed/examples/Supported_Models/) an ever-expanding set of models, including a few multilingual models.
46
46
 
47
47
  ## 🚀 Installation
48
48
 
@@ -86,7 +86,7 @@ The list of all the available models can be found [here](https://qdrant.github.i
86
86
  from fastembed import TextEmbedding
87
87
 
88
88
  model = TextEmbedding(model_name="BAAI/bge-small-en-v1.5")
89
- embeddings = list(embedding_model.embed(documents))
89
+ embeddings = list(model.embed(documents))
90
90
 
91
91
  # [
92
92
  # array([-0.1115, 0.0097, 0.0052, 0.0195, ...], dtype=float32),
@@ -105,7 +105,7 @@ embeddings = list(embedding_model.embed(documents))
105
105
  from fastembed import SparseTextEmbedding
106
106
 
107
107
  model = SparseTextEmbedding(model_name="prithivida/Splade_PP_en_v1")
108
- embeddings = list(embedding_model.embed(documents))
108
+ embeddings = list(model.embed(documents))
109
109
 
110
110
  # [
111
111
  # SparseEmbedding(indices=[ 17, 123, 919, ... ], values=[0.71, 0.22, 0.39, ...]),
@@ -120,7 +120,7 @@ embeddings = list(embedding_model.embed(documents))
120
120
  from fastembed import SparseTextEmbedding
121
121
 
122
122
  model = SparseTextEmbedding(model_name="Qdrant/bm42-all-minilm-l6-v2-attentions")
123
- embeddings = list(embedding_model.embed(documents))
123
+ embeddings = list(model.embed(documents))
124
124
 
125
125
  # [
126
126
  # SparseEmbedding(indices=[ 17, 123, 919, ... ], values=[0.71, 0.22, 0.39, ...]),
@@ -136,7 +136,7 @@ embeddings = list(embedding_model.embed(documents))
136
136
  from fastembed import LateInteractionTextEmbedding
137
137
 
138
138
  model = LateInteractionTextEmbedding(model_name="colbert-ir/colbertv2.0")
139
- embeddings = list(embedding_model.embed(documents))
139
+ embeddings = list(model.embed(documents))
140
140
 
141
141
  # [
142
142
  # array([
@@ -161,7 +161,7 @@ images = [
161
161
  ]
162
162
 
163
163
  model = ImageEmbedding(model_name="Qdrant/clip-ViT-B-32-vision")
164
- embeddings = list(embedding_model.embed(images))
164
+ embeddings = list(model.embed(images))
165
165
 
166
166
  # [
167
167
  # array([-0.1115, 0.0097, 0.0052, 0.0195, ...], dtype=float32),
@@ -179,7 +179,7 @@ It requires installation of the `fastembed-gpu` package.
179
179
  pip install fastembed-gpu
180
180
  ```
181
181
 
182
- Check our [example](https://qdrant.github.io/fastembed/examples/FastEmbed_GPU/) for the detailed instructions and CUDA 12.x support.
182
+ Check our [example](https://qdrant.github.io/fastembed/examples/FastEmbed_GPU/) for detailed instructions and CUDA 12.x support.
183
183
 
184
184
  ```python
185
185
  from fastembed import TextEmbedding
@@ -242,3 +242,4 @@ search_result = client.query(
242
242
  )
243
243
  print(search_result)
244
244
  ```
245
+
@@ -8,9 +8,9 @@ The default text embedding (`TextEmbedding`) model is Flag Embedding, presented
8
8
 
9
9
  1. Light: FastEmbed is a lightweight library with few external dependencies. We don't require a GPU and don't download GBs of PyTorch dependencies, and instead use the ONNX Runtime. This makes it a great candidate for serverless runtimes like AWS Lambda.
10
10
 
11
- 2. Fast: FastEmbed is designed for speed. We use the ONNX Runtime, which is faster than PyTorch. We also use data-parallelism for encoding large datasets.
11
+ 2. Fast: FastEmbed is designed for speed. We use the ONNX Runtime, which is faster than PyTorch. We also use data parallelism for encoding large datasets.
12
12
 
13
- 3. Accurate: FastEmbed is better than OpenAI Ada-002. We also [supported](https://qdrant.github.io/fastembed/examples/Supported_Models/) an ever expanding set of models, including a few multilingual models.
13
+ 3. Accurate: FastEmbed is better than OpenAI Ada-002. We also [support](https://qdrant.github.io/fastembed/examples/Supported_Models/) an ever-expanding set of models, including a few multilingual models.
14
14
 
15
15
  ## 🚀 Installation
16
16
 
@@ -54,7 +54,7 @@ The list of all the available models can be found [here](https://qdrant.github.i
54
54
  from fastembed import TextEmbedding
55
55
 
56
56
  model = TextEmbedding(model_name="BAAI/bge-small-en-v1.5")
57
- embeddings = list(embedding_model.embed(documents))
57
+ embeddings = list(model.embed(documents))
58
58
 
59
59
  # [
60
60
  # array([-0.1115, 0.0097, 0.0052, 0.0195, ...], dtype=float32),
@@ -73,7 +73,7 @@ embeddings = list(embedding_model.embed(documents))
73
73
  from fastembed import SparseTextEmbedding
74
74
 
75
75
  model = SparseTextEmbedding(model_name="prithivida/Splade_PP_en_v1")
76
- embeddings = list(embedding_model.embed(documents))
76
+ embeddings = list(model.embed(documents))
77
77
 
78
78
  # [
79
79
  # SparseEmbedding(indices=[ 17, 123, 919, ... ], values=[0.71, 0.22, 0.39, ...]),
@@ -88,7 +88,7 @@ embeddings = list(embedding_model.embed(documents))
88
88
  from fastembed import SparseTextEmbedding
89
89
 
90
90
  model = SparseTextEmbedding(model_name="Qdrant/bm42-all-minilm-l6-v2-attentions")
91
- embeddings = list(embedding_model.embed(documents))
91
+ embeddings = list(model.embed(documents))
92
92
 
93
93
  # [
94
94
  # SparseEmbedding(indices=[ 17, 123, 919, ... ], values=[0.71, 0.22, 0.39, ...]),
@@ -104,7 +104,7 @@ embeddings = list(embedding_model.embed(documents))
104
104
  from fastembed import LateInteractionTextEmbedding
105
105
 
106
106
  model = LateInteractionTextEmbedding(model_name="colbert-ir/colbertv2.0")
107
- embeddings = list(embedding_model.embed(documents))
107
+ embeddings = list(model.embed(documents))
108
108
 
109
109
  # [
110
110
  # array([
@@ -129,7 +129,7 @@ images = [
129
129
  ]
130
130
 
131
131
  model = ImageEmbedding(model_name="Qdrant/clip-ViT-B-32-vision")
132
- embeddings = list(embedding_model.embed(images))
132
+ embeddings = list(model.embed(images))
133
133
 
134
134
  # [
135
135
  # array([-0.1115, 0.0097, 0.0052, 0.0195, ...], dtype=float32),
@@ -147,7 +147,7 @@ It requires installation of the `fastembed-gpu` package.
147
147
  pip install fastembed-gpu
148
148
  ```
149
149
 
150
- Check our [example](https://qdrant.github.io/fastembed/examples/FastEmbed_GPU/) for the detailed instructions and CUDA 12.x support.
150
+ Check our [example](https://qdrant.github.io/fastembed/examples/FastEmbed_GPU/) for detailed instructions and CUDA 12.x support.
151
151
 
152
152
  ```python
153
153
  from fastembed import TextEmbedding
@@ -209,4 +209,4 @@ search_result = client.query(
209
209
  query_text="This is a query document"
210
210
  )
211
211
  print(search_result)
212
- ```
212
+ ```
@@ -0,0 +1,3 @@
1
+ from fastembed.common.types import ImageInput, OnnxProvider, PathInput, PilInput
2
+
3
+ __all__ = ["OnnxProvider", "ImageInput", "PathInput", "PilInput"]
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import time
2
3
  import shutil
3
4
  import tarfile
4
5
  from pathlib import Path
@@ -42,9 +43,7 @@ class ModelManagement:
42
43
  raise ValueError(f"Model {model_name} is not supported in {cls.__name__}.")
43
44
 
44
45
  @classmethod
45
- def download_file_from_gcs(
46
- cls, url: str, output_path: str, show_progress: bool = True
47
- ) -> str:
46
+ def download_file_from_gcs(cls, url: str, output_path: str, show_progress: bool = True) -> str:
48
47
  """
49
48
  Downloads a file from Google Cloud Storage.
50
49
 
@@ -73,9 +72,7 @@ class ModelManagement:
73
72
 
74
73
  # Warn if the total size is zero
75
74
  if total_size_in_bytes == 0:
76
- print(
77
- f"Warning: Content-length header is missing or zero in the response from {url}."
78
- )
75
+ print(f"Warning: Content-length header is missing or zero in the response from {url}.")
79
76
 
80
77
  show_progress = total_size_in_bytes and show_progress
81
78
 
@@ -151,7 +148,9 @@ class ModelManagement:
151
148
  # Open the tar.gz file
152
149
  with tarfile.open(targz_path, "r:gz") as tar:
153
150
  # Extract all files into the cache directory
154
- tar.extractall(path=cache_dir)
151
+ tar.extractall(
152
+ path=cache_dir,
153
+ )
155
154
  except tarfile.TarError as e:
156
155
  # If any error occurs while opening or extracting the tar.gz file,
157
156
  # delete the cache directory (if it was created in this function)
@@ -163,9 +162,7 @@ class ModelManagement:
163
162
  return cache_dir
164
163
 
165
164
  @classmethod
166
- def retrieve_model_gcs(
167
- cls, model_name: str, source_url: str, cache_dir: str
168
- ) -> Path:
165
+ def retrieve_model_gcs(cls, model_name: str, source_url: str, cache_dir: str) -> Path:
169
166
  fast_model_name = f"fast-{model_name.split('/')[-1]}"
170
167
 
171
168
  cache_tmp_dir = Path(cache_dir) / "tmp"
@@ -191,12 +188,8 @@ class ModelManagement:
191
188
  output_path=str(model_tar_gz),
192
189
  )
193
190
 
194
- cls.decompress_to_cache(
195
- targz_path=str(model_tar_gz), cache_dir=str(cache_tmp_dir)
196
- )
197
- assert (
198
- model_tmp_dir.exists()
199
- ), f"Could not find {model_tmp_dir} in {cache_tmp_dir}"
191
+ cls.decompress_to_cache(targz_path=str(model_tar_gz), cache_dir=str(cache_tmp_dir))
192
+ assert model_tmp_dir.exists(), f"Could not find {model_tmp_dir} in {cache_tmp_dir}"
200
193
 
201
194
  model_tar_gz.unlink()
202
195
  # Rename from tmp to final name is atomic
@@ -205,7 +198,7 @@ class ModelManagement:
205
198
  return model_dir
206
199
 
207
200
  @classmethod
208
- def download_model(cls, model: Dict[str, Any], cache_dir: Path, **kwargs) -> Path:
201
+ def download_model(cls, model: Dict[str, Any], cache_dir: Path, retries=3, **kwargs) -> Path:
209
202
  """
210
203
  Downloads a model from HuggingFace Hub or Google Cloud Storage.
211
204
 
@@ -225,6 +218,7 @@ class ModelManagement:
225
218
  }
226
219
  ```
227
220
  cache_dir (str): The path to the cache directory.
221
+ retries: (int): The number of times to retry (including the first attempt)
228
222
 
229
223
  Returns:
230
224
  Path: The path to the downloaded model directory.
@@ -233,26 +227,38 @@ class ModelManagement:
233
227
  hf_source = model.get("sources", {}).get("hf")
234
228
  url_source = model.get("sources", {}).get("url")
235
229
 
236
- if hf_source:
237
- extra_patterns = [model["model_file"]]
238
- extra_patterns.extend(model.get("additional_files", []))
239
-
240
- try:
241
- return Path(
242
- cls.download_files_from_huggingface(
243
- hf_source,
244
- cache_dir=str(cache_dir),
245
- extra_patterns=extra_patterns,
246
- local_files_only=kwargs.get("local_files_only", False),
230
+ sleep = 3.0
231
+ while retries > 0:
232
+ retries -= 1
233
+
234
+ if hf_source:
235
+ extra_patterns = [model["model_file"]]
236
+ extra_patterns.extend(model.get("additional_files", []))
237
+
238
+ try:
239
+ return Path(
240
+ cls.download_files_from_huggingface(
241
+ hf_source,
242
+ cache_dir=str(cache_dir),
243
+ extra_patterns=extra_patterns,
244
+ local_files_only=kwargs.get("local_files_only", False),
245
+ )
247
246
  )
248
- )
249
- except (EnvironmentError, RepositoryNotFoundError, ValueError) as e:
250
- logger.error(
251
- f"Could not download model from HuggingFace: {e}"
252
- "Falling back to other sources."
253
- )
254
-
255
- if url_source:
256
- return cls.retrieve_model_gcs(model["model"], url_source, str(cache_dir))
247
+ except (EnvironmentError, RepositoryNotFoundError, ValueError) as e:
248
+ logger.error(
249
+ f"Could not download model from HuggingFace: {e} "
250
+ "Falling back to other sources."
251
+ )
252
+ if url_source:
253
+ try:
254
+ return cls.retrieve_model_gcs(model["model"], url_source, str(cache_dir))
255
+ except Exception:
256
+ logger.error(f"Could not download model from url: {url_source}")
257
+
258
+ logger.error(
259
+ f"Could not download model from either source, sleeping for {sleep} seconds, {retries} retries left."
260
+ )
261
+ time.sleep(sleep)
262
+ sleep *= 3
257
263
 
258
264
  raise ValueError(f"Could not download model {model['model']} from any source.")
@@ -1,7 +1,6 @@
1
1
  import json
2
2
  from pathlib import Path
3
3
  from typing import Tuple
4
-
5
4
  from tokenizers import AddedToken, Tokenizer
6
5
 
7
6
  from fastembed.image.transform.operators import Compose
@@ -18,7 +17,7 @@ def load_special_tokens(model_dir: Path) -> dict:
18
17
  return tokens_map
19
18
 
20
19
 
21
- def load_tokenizer(model_dir: Path, max_length: int = 512) -> Tuple[Tokenizer, dict]:
20
+ def load_tokenizer(model_dir: Path) -> Tuple[Tokenizer, dict]:
22
21
  config_path = model_dir / "config.json"
23
22
  if not config_path.exists():
24
23
  raise ValueError(f"Could not find config.json in {model_dir}")
@@ -36,13 +35,20 @@ def load_tokenizer(model_dir: Path, max_length: int = 512) -> Tuple[Tokenizer, d
36
35
 
37
36
  with open(str(tokenizer_config_path)) as tokenizer_config_file:
38
37
  tokenizer_config = json.load(tokenizer_config_file)
38
+ assert (
39
+ "model_max_length" in tokenizer_config or "max_length" in tokenizer_config
40
+ ), "Models without model_max_length or max_length are not supported."
41
+ if "model_max_length" not in tokenizer_config:
42
+ max_context = tokenizer_config["max_length"]
43
+ elif "max_length" not in tokenizer_config:
44
+ max_context = tokenizer_config["model_max_length"]
45
+ else:
46
+ max_context = min(tokenizer_config["model_max_length"], tokenizer_config["max_length"])
39
47
 
40
48
  tokens_map = load_special_tokens(model_dir)
41
49
 
42
50
  tokenizer = Tokenizer.from_file(str(tokenizer_path))
43
- tokenizer.enable_truncation(
44
- max_length=min(tokenizer_config["model_max_length"], max_length)
45
- )
51
+ tokenizer.enable_truncation(max_length=max_context)
46
52
  tokenizer.enable_padding(
47
53
  pad_id=config.get("pad_token_id", 0), pad_token=tokenizer_config["pad_token"]
48
54
  )
@@ -1,5 +1,6 @@
1
1
  import os
2
2
  import sys
3
+ from PIL import Image
3
4
  from typing import Any, Dict, Iterable, Tuple, Union
4
5
 
5
6
  if sys.version_info >= (3, 10):
@@ -9,6 +10,7 @@ else:
9
10
 
10
11
 
11
12
  PathInput: TypeAlias = Union[str, os.PathLike]
12
- ImageInput: TypeAlias = Union[PathInput, Iterable[PathInput]]
13
+ PilInput: TypeAlias = Union[Image.Image, Iterable[Image.Image]]
14
+ ImageInput: TypeAlias = Union[PathInput, Iterable[PathInput], PilInput]
13
15
 
14
16
  OnnxProvider: TypeAlias = Union[str, Tuple[str, Dict[Any, Any]]]
@@ -65,8 +65,8 @@ class ImageEmbedding(ImageEmbeddingBase):
65
65
  return
66
66
 
67
67
  raise ValueError(
68
- f"Model {model_name} is not supported in TextEmbedding."
69
- "Please check the supported models using `TextEmbedding.list_supported_models()`"
68
+ f"Model {model_name} is not supported in ImageEmbedding."
69
+ "Please check the supported models using `ImageEmbedding.list_supported_models()`"
70
70
  )
71
71
 
72
72
  def embed(
@@ -12,7 +12,7 @@ supported_onnx_models = [
12
12
  {
13
13
  "model": "Qdrant/clip-ViT-B-32-vision",
14
14
  "dim": 512,
15
- "description": "CLIP vision encoder based on ViT-B/32",
15
+ "description": "Image embeddings, Multimodal (text&image), 2021 year",
16
16
  "size_in_GB": 0.34,
17
17
  "sources": {
18
18
  "hf": "Qdrant/clip-ViT-B-32-vision",
@@ -22,13 +22,33 @@ supported_onnx_models = [
22
22
  {
23
23
  "model": "Qdrant/resnet50-onnx",
24
24
  "dim": 2048,
25
- "description": "ResNet-50 from `Deep Residual Learning for Image Recognition <https://arxiv.org/abs/1512.03385>`__.",
25
+ "description": "Image embeddings, Unimodal (image), 2016 year",
26
26
  "size_in_GB": 0.1,
27
27
  "sources": {
28
28
  "hf": "Qdrant/resnet50-onnx",
29
29
  },
30
30
  "model_file": "model.onnx",
31
31
  },
32
+ {
33
+ "model": "Qdrant/Unicom-ViT-B-16",
34
+ "dim": 768,
35
+ "description": "Image embeddings (more detailed than Unicom-ViT-B-32), Multimodal (text&image), 2023 year",
36
+ "size_in_GB": 0.82,
37
+ "sources": {
38
+ "hf": "Qdrant/Unicom-ViT-B-16",
39
+ },
40
+ "model_file": "model.onnx",
41
+ },
42
+ {
43
+ "model": "Qdrant/Unicom-ViT-B-32",
44
+ "dim": 512,
45
+ "description": "Image embeddings, Multimodal (text&image), 2023 year",
46
+ "size_in_GB": 0.48,
47
+ "sources": {
48
+ "hf": "Qdrant/Unicom-ViT-B-32",
49
+ },
50
+ "model_file": "model.onnx",
51
+ },
32
52
  ]
33
53
 
34
54
 
@@ -7,7 +7,7 @@ from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Type
7
7
  import numpy as np
8
8
  from PIL import Image
9
9
 
10
- from fastembed.common import ImageInput, OnnxProvider, PathInput
10
+ from fastembed.common import ImageInput, OnnxProvider
11
11
  from fastembed.common.onnx_model import EmbeddingWorker, OnnxModel, OnnxOutputContext, T
12
12
  from fastembed.common.preprocessor_utils import load_preprocessor
13
13
  from fastembed.common.utils import iter_batch
@@ -54,9 +54,12 @@ class OnnxImageModel(OnnxModel[T]):
54
54
  def _build_onnx_input(self, encoded: np.ndarray) -> Dict[str, np.ndarray]:
55
55
  return {node.name: encoded for node in self.model.get_inputs()}
56
56
 
57
- def onnx_embed(self, images: List[PathInput], **kwargs) -> OnnxOutputContext:
57
+ def onnx_embed(self, images: List[ImageInput], **kwargs) -> OnnxOutputContext:
58
58
  with contextlib.ExitStack():
59
- image_files = [Image.open(image) for image in images]
59
+ image_files = [
60
+ Image.open(image) if not isinstance(image, Image.Image) else image
61
+ for image in images
62
+ ]
60
63
  encoded = self.processor(image_files)
61
64
  onnx_input = self._build_onnx_input(encoded)
62
65
  onnx_input = self._preprocess_onnx_input(onnx_input)
@@ -75,7 +78,11 @@ class OnnxImageModel(OnnxModel[T]):
75
78
  ) -> Iterable[T]:
76
79
  is_small = False
77
80
 
78
- if isinstance(images, str) or isinstance(images, Path):
81
+ if (
82
+ isinstance(images, str)
83
+ or isinstance(images, Path)
84
+ or (isinstance(images, Image.Image))
85
+ ):
79
86
  images = [images]
80
87
  is_small = True
81
88
 
@@ -90,9 +97,7 @@ class OnnxImageModel(OnnxModel[T]):
90
97
  for batch in iter_batch(images, batch_size):
91
98
  yield from self._post_process_onnx_output(self.onnx_embed(batch))
92
99
  else:
93
- start_method = (
94
- "forkserver" if "forkserver" in get_all_start_methods() else "spawn"
95
- )
100
+ start_method = "forkserver" if "forkserver" in get_all_start_methods() else "spawn"
96
101
  params = {"model_name": model_name, "cache_dir": cache_dir, **kwargs}
97
102
  pool = ParallelWorkerPool(
98
103
  parallel, self._get_worker_class(), start_method=start_method
@@ -22,7 +22,17 @@ supported_colbert_models = [
22
22
  "hf": "colbert-ir/colbertv2.0",
23
23
  },
24
24
  "model_file": "model.onnx",
25
- }
25
+ },
26
+ {
27
+ "model": "answerdotai/answerai-colbert-small-v1",
28
+ "dim": 96,
29
+ "description": "Text embeddings, Unimodal (text), Multilingual (~100 languages), 512 input tokens truncation, 2024 year",
30
+ "size_in_GB": 0.13,
31
+ "sources": {
32
+ "hf": "answerdotai/answerai-colbert-small-v1",
33
+ },
34
+ "model_file": "vespa_colbert.onnx",
35
+ },
26
36
  ]
27
37
 
28
38
 
@@ -17,6 +17,38 @@ from fastembed.sparse.sparse_embedding_base import (
17
17
  )
18
18
  from fastembed.sparse.utils.tokenizer import WordTokenizer
19
19
 
20
+ supported_languages = [
21
+ "arabic",
22
+ "azerbaijani",
23
+ "basque",
24
+ "bengali",
25
+ "catalan",
26
+ "chinese",
27
+ "danish",
28
+ "dutch",
29
+ "english",
30
+ "finnish",
31
+ "french",
32
+ "german",
33
+ "greek",
34
+ "hebrew",
35
+ "hinglish",
36
+ "hungarian",
37
+ "indonesian",
38
+ "italian",
39
+ "kazakh",
40
+ "nepali",
41
+ "norwegian",
42
+ "portuguese",
43
+ "romanian",
44
+ "russian",
45
+ "slovene",
46
+ "spanish",
47
+ "swedish",
48
+ "tajik",
49
+ "turkish",
50
+ ]
51
+
20
52
  supported_bm25_models = [
21
53
  {
22
54
  "model": "Qdrant/bm25",
@@ -26,14 +58,11 @@ supported_bm25_models = [
26
58
  "hf": "Qdrant/bm25",
27
59
  },
28
60
  "model_file": "mock.file", # bm25 does not require a model, so we just use a mock
29
- "additional_files": ["stopwords.txt"],
61
+ "additional_files": [f"{lang}.txt" for lang in supported_languages],
62
+ "requires_idf": True,
30
63
  },
31
64
  ]
32
65
 
33
- MODEL_TO_LANGUAGE = {
34
- "Qdrant/bm25": "english",
35
- }
36
-
37
66
 
38
67
  class Bm25(SparseTextEmbeddingBase):
39
68
  """Implements traditional BM25 in a form of sparse embeddings.
@@ -70,10 +99,16 @@ class Bm25(SparseTextEmbeddingBase):
70
99
  k: float = 1.2,
71
100
  b: float = 0.75,
72
101
  avg_len: float = 256.0,
102
+ language: str = "english",
73
103
  **kwargs,
74
104
  ):
75
105
  super().__init__(model_name, cache_dir, **kwargs)
76
106
 
107
+ if language not in supported_languages:
108
+ raise ValueError(f"{language} language is not supported")
109
+ else:
110
+ self.language = language
111
+
77
112
  self.k = k
78
113
  self.b = b
79
114
  self.avg_len = avg_len
@@ -86,8 +121,8 @@ class Bm25(SparseTextEmbeddingBase):
86
121
  )
87
122
 
88
123
  self.punctuation = set(string.punctuation)
89
- self.stopwords = set(self._load_stopwords(model_dir))
90
- self.stemmer = get_stemmer(MODEL_TO_LANGUAGE[model_name])
124
+ self.stopwords = set(self._load_stopwords(model_dir, self.language))
125
+ self.stemmer = get_stemmer(language)
91
126
  self.tokenizer = WordTokenizer
92
127
 
93
128
  @classmethod
@@ -100,8 +135,8 @@ class Bm25(SparseTextEmbeddingBase):
100
135
  return supported_bm25_models
101
136
 
102
137
  @classmethod
103
- def _load_stopwords(cls, model_dir: Path) -> List[str]:
104
- stopwords_path = model_dir / "stopwords.txt"
138
+ def _load_stopwords(cls, model_dir: Path, language: str) -> List[str]:
139
+ stopwords_path = model_dir / f"{language}.txt"
105
140
  if not stopwords_path.exists():
106
141
  return []
107
142
 
@@ -27,6 +27,7 @@ supported_bm42_models = [
27
27
  },
28
28
  "model_file": "model.onnx",
29
29
  "additional_files": ["stopwords.txt"],
30
+ "requires_idf": True,
30
31
  },
31
32
  ]
32
33
 
@@ -8,6 +8,7 @@ from fastembed.sparse.sparse_embedding_base import (
8
8
  SparseTextEmbeddingBase,
9
9
  )
10
10
  from fastembed.sparse.splade_pp import SpladePP
11
+ import warnings
11
12
 
12
13
 
13
14
  class SparseTextEmbedding(SparseTextEmbeddingBase):
@@ -50,13 +51,17 @@ class SparseTextEmbedding(SparseTextEmbeddingBase):
50
51
  **kwargs,
51
52
  ):
52
53
  super().__init__(model_name, cache_dir, threads, **kwargs)
54
+ if model_name == "prithvida/Splade_PP_en_v1":
55
+ warnings.warn(
56
+ "The right spelling is prithivida/Splade_PP_en_v1. "
57
+ "Support of this name will be removed soon, please fix the model_name",
58
+ DeprecationWarning,
59
+ )
60
+ model_name = "prithivida/Splade_PP_en_v1"
53
61
 
54
62
  for EMBEDDING_MODEL_TYPE in self.EMBEDDINGS_REGISTRY:
55
63
  supported_models = EMBEDDING_MODEL_TYPE.list_supported_models()
56
- if any(
57
- model_name.lower() == model["model"].lower()
58
- for model in supported_models
59
- ):
64
+ if any(model_name.lower() == model["model"].lower() for model in supported_models):
60
65
  self.model = EMBEDDING_MODEL_TYPE(
61
66
  model_name,
62
67
  cache_dir,
@@ -95,9 +100,7 @@ class SparseTextEmbedding(SparseTextEmbeddingBase):
95
100
  """
96
101
  yield from self.model.embed(documents, batch_size, parallel, **kwargs)
97
102
 
98
- def query_embed(
99
- self, query: Union[str, Iterable[str]], **kwargs
100
- ) -> Iterable[SparseEmbedding]:
103
+ def query_embed(self, query: Union[str, Iterable[str]], **kwargs) -> Iterable[SparseEmbedding]:
101
104
  """
102
105
  Embeds queries
103
106
 
@@ -1,7 +1,6 @@
1
1
  from typing import Any, Dict, Iterable, List, Optional, Sequence, Type, Union
2
2
 
3
3
  import numpy as np
4
-
5
4
  from fastembed.common import OnnxProvider
6
5
  from fastembed.common.onnx_model import OnnxOutputContext
7
6
  from fastembed.common.utils import define_cache_dir
@@ -12,16 +11,6 @@ from fastembed.sparse.sparse_embedding_base import (
12
11
  from fastembed.text.onnx_text_model import OnnxTextModel, TextEmbeddingWorker
13
12
 
14
13
  supported_splade_models = [
15
- {
16
- "model": "prithvida/Splade_PP_en_v1",
17
- "vocab_size": 30522,
18
- "description": "Misspelled version of the model. Retained for backward compatibility. Independent Implementation of SPLADE++ Model for English",
19
- "size_in_GB": 0.532,
20
- "sources": {
21
- "hf": "Qdrant/SPLADE_PP_en_v1",
22
- },
23
- "model_file": "model.onnx",
24
- },
25
14
  {
26
15
  "model": "prithivida/Splade_PP_en_v1",
27
16
  "vocab_size": 30522,
@@ -78,7 +67,6 @@ class SpladePP(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
78
67
  Raises:
79
68
  ValueError: If the model_name is not in the format <org>/<model> e.g. BAAI/bge-base-en.
80
69
  """
81
-
82
70
  super().__init__(model_name, cache_dir, threads, **kwargs)
83
71
 
84
72
  model_description = self._get_model_description(model_name)
@@ -10,7 +10,7 @@ supported_clip_models = [
10
10
  {
11
11
  "model": "Qdrant/clip-ViT-B-32-text",
12
12
  "dim": 512,
13
- "description": "CLIP text encoder",
13
+ "description": "Text embeddings, Multimodal (text&image), English, 77 input tokens truncation, Prefixes for queries/documents: not necessary, 2021 year",
14
14
  "size_in_GB": 0.25,
15
15
  "sources": {
16
16
  "hf": "Qdrant/clip-ViT-B-32-text",
@@ -9,7 +9,7 @@ supported_multilingual_e5_models = [
9
9
  {
10
10
  "model": "intfloat/multilingual-e5-large",
11
11
  "dim": 1024,
12
- "description": "Multilingual model, e5-large. Recommend using this model for non-English languages",
12
+ "description": "Text embeddings, Unimodal (text), Multilingual (~100 languages), 512 input tokens truncation, Prefixes for queries/documents: necessary, 2024 year",
13
13
  "size_in_GB": 2.24,
14
14
  "sources": {
15
15
  "url": "https://storage.googleapis.com/qdrant-fastembed/fast-multilingual-e5-large.tar.gz",
@@ -21,7 +21,7 @@ supported_multilingual_e5_models = [
21
21
  {
22
22
  "model": "sentence-transformers/paraphrase-multilingual-mpnet-base-v2",
23
23
  "dim": 768,
24
- "description": "Sentence-transformers model for tasks like clustering or semantic search",
24
+ "description": "Text embeddings, Unimodal (text), Multilingual (~50 languages), 384 input tokens truncation, Prefixes for queries/documents: not necessary, 2021 year",
25
25
  "size_in_GB": 1.00,
26
26
  "sources": {
27
27
  "hf": "xenova/paraphrase-multilingual-mpnet-base-v2",
@@ -12,7 +12,7 @@ supported_onnx_models = [
12
12
  {
13
13
  "model": "BAAI/bge-base-en",
14
14
  "dim": 768,
15
- "description": "Base English model",
15
+ "description": "Text embeddings, Unimodal (text), English, 512 input tokens truncation, Prefixes for queries/documents: necessary, 2023 year",
16
16
  "size_in_GB": 0.42,
17
17
  "sources": {
18
18
  "url": "https://storage.googleapis.com/qdrant-fastembed/fast-bge-base-en.tar.gz",
@@ -22,7 +22,7 @@ supported_onnx_models = [
22
22
  {
23
23
  "model": "BAAI/bge-base-en-v1.5",
24
24
  "dim": 768,
25
- "description": "Base English model, v1.5",
25
+ "description": "Text embeddings, Unimodal (text), English, 512 input tokens truncation, Prefixes for queries/documents: not so necessary, 2023 year",
26
26
  "size_in_GB": 0.21,
27
27
  "sources": {
28
28
  "url": "https://storage.googleapis.com/qdrant-fastembed/fast-bge-base-en-v1.5.tar.gz",
@@ -33,7 +33,7 @@ supported_onnx_models = [
33
33
  {
34
34
  "model": "BAAI/bge-large-en-v1.5",
35
35
  "dim": 1024,
36
- "description": "Large English model, v1.5",
36
+ "description": "Text embeddings, Unimodal (text), English, 512 input tokens truncation, Prefixes for queries/documents: not so necessary, 2023 year",
37
37
  "size_in_GB": 1.20,
38
38
  "sources": {
39
39
  "hf": "qdrant/bge-large-en-v1.5-onnx",
@@ -43,7 +43,7 @@ supported_onnx_models = [
43
43
  {
44
44
  "model": "BAAI/bge-small-en",
45
45
  "dim": 384,
46
- "description": "Fast English model",
46
+ "description": "Text embeddings, Unimodal (text), English, 512 input tokens truncation, Prefixes for queries/documents: necessary, 2023 year",
47
47
  "size_in_GB": 0.13,
48
48
  "sources": {
49
49
  "url": "https://storage.googleapis.com/qdrant-fastembed/BAAI-bge-small-en.tar.gz",
@@ -53,7 +53,7 @@ supported_onnx_models = [
53
53
  {
54
54
  "model": "BAAI/bge-small-en-v1.5",
55
55
  "dim": 384,
56
- "description": "Fast and Default English model",
56
+ "description": "Text embeddings, Unimodal (text), English, 512 input tokens truncation, Prefixes for queries/documents: not so necessary, 2023 year",
57
57
  "size_in_GB": 0.067,
58
58
  "sources": {
59
59
  "hf": "qdrant/bge-small-en-v1.5-onnx-q",
@@ -63,7 +63,7 @@ supported_onnx_models = [
63
63
  {
64
64
  "model": "BAAI/bge-small-zh-v1.5",
65
65
  "dim": 512,
66
- "description": "Fast and recommended Chinese model",
66
+ "description": "Text embeddings, Unimodal (text), Chinese, 512 input tokens truncation, Prefixes for queries/documents: not so necessary, 2023 year",
67
67
  "size_in_GB": 0.09,
68
68
  "sources": {
69
69
  "url": "https://storage.googleapis.com/qdrant-fastembed/fast-bge-small-zh-v1.5.tar.gz",
@@ -73,47 +73,17 @@ supported_onnx_models = [
73
73
  {
74
74
  "model": "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
75
75
  "dim": 384,
76
- "description": "Sentence Transformer model, paraphrase-multilingual-MiniLM-L12-v2",
76
+ "description": "Text embeddings, Unimodal (text), Multilingual (~50 languages), 512 input tokens truncation, Prefixes for queries/documents: not necessary, 2019 year",
77
77
  "size_in_GB": 0.22,
78
78
  "sources": {
79
79
  "hf": "qdrant/paraphrase-multilingual-MiniLM-L12-v2-onnx-Q",
80
80
  },
81
81
  "model_file": "model_optimized.onnx",
82
82
  },
83
- {
84
- "model": "nomic-ai/nomic-embed-text-v1",
85
- "dim": 768,
86
- "description": "8192 context length english model",
87
- "size_in_GB": 0.52,
88
- "sources": {
89
- "hf": "nomic-ai/nomic-embed-text-v1",
90
- },
91
- "model_file": "onnx/model.onnx",
92
- },
93
- {
94
- "model": "nomic-ai/nomic-embed-text-v1.5",
95
- "dim": 768,
96
- "description": "8192 context length english model",
97
- "size_in_GB": 0.52,
98
- "sources": {
99
- "hf": "nomic-ai/nomic-embed-text-v1.5",
100
- },
101
- "model_file": "onnx/model.onnx",
102
- },
103
- {
104
- "model": "nomic-ai/nomic-embed-text-v1.5-Q",
105
- "dim": 768,
106
- "description": "Quantized 8192 context length english model",
107
- "size_in_GB": 0.13,
108
- "sources": {
109
- "hf": "nomic-ai/nomic-embed-text-v1.5",
110
- },
111
- "model_file": "onnx/model_quantized.onnx",
112
- },
113
83
  {
114
84
  "model": "thenlper/gte-large",
115
85
  "dim": 1024,
116
- "description": "Large general text embeddings model",
86
+ "description": "Text embeddings, Unimodal (text), English, 512 input tokens truncation, Prefixes for queries/documents: not necessary, 2023 year",
117
87
  "size_in_GB": 1.20,
118
88
  "sources": {
119
89
  "hf": "qdrant/gte-large-onnx",
@@ -123,7 +93,7 @@ supported_onnx_models = [
123
93
  {
124
94
  "model": "mixedbread-ai/mxbai-embed-large-v1",
125
95
  "dim": 1024,
126
- "description": "MixedBread Base sentence embedding model, does well on MTEB",
96
+ "description": "Text embeddings, Unimodal (text), English, 512 input tokens truncation, Prefixes for queries/documents: necessary, 2024 year",
127
97
  "size_in_GB": 0.64,
128
98
  "sources": {
129
99
  "hf": "mixedbread-ai/mxbai-embed-large-v1",
@@ -133,7 +103,7 @@ supported_onnx_models = [
133
103
  {
134
104
  "model": "snowflake/snowflake-arctic-embed-xs",
135
105
  "dim": 384,
136
- "description": "Based on all-MiniLM-L6-v2 model with only 22m parameters, ideal for latency/TCO budgets.",
106
+ "description": "Text embeddings, Unimodal (text), English, 512 input tokens truncation, Prefixes for queries/documents: necessary, 2024 year",
137
107
  "size_in_GB": 0.09,
138
108
  "sources": {
139
109
  "hf": "snowflake/snowflake-arctic-embed-xs",
@@ -143,7 +113,7 @@ supported_onnx_models = [
143
113
  {
144
114
  "model": "snowflake/snowflake-arctic-embed-s",
145
115
  "dim": 384,
146
- "description": "Based on infloat/e5-small-unsupervised, does not trade off retrieval accuracy for its small size.",
116
+ "description": "Text embeddings, Unimodal (text), English, 512 input tokens truncation, Prefixes for queries/documents: necessary, 2024 year",
147
117
  "size_in_GB": 0.13,
148
118
  "sources": {
149
119
  "hf": "snowflake/snowflake-arctic-embed-s",
@@ -153,7 +123,7 @@ supported_onnx_models = [
153
123
  {
154
124
  "model": "snowflake/snowflake-arctic-embed-m",
155
125
  "dim": 768,
156
- "description": "Based on intfloat/e5-base-unsupervised model, provides the best retrieval without slowing down inference.",
126
+ "description": "Text embeddings, Unimodal (text), English, 512 input tokens truncation, Prefixes for queries/documents: necessary, 2024 year",
157
127
  "size_in_GB": 0.43,
158
128
  "sources": {
159
129
  "hf": "Snowflake/snowflake-arctic-embed-m",
@@ -163,7 +133,7 @@ supported_onnx_models = [
163
133
  {
164
134
  "model": "snowflake/snowflake-arctic-embed-m-long",
165
135
  "dim": 768,
166
- "description": "Based on nomic-ai/nomic-embed-text-v1-unsupervised model, 8192 context-length model",
136
+ "description": "Text embeddings, Unimodal (text), English, 2048 input tokens truncation, Prefixes for queries/documents: necessary, 2024 year",
167
137
  "size_in_GB": 0.54,
168
138
  "sources": {
169
139
  "hf": "snowflake/snowflake-arctic-embed-m-long",
@@ -173,7 +143,7 @@ supported_onnx_models = [
173
143
  {
174
144
  "model": "snowflake/snowflake-arctic-embed-l",
175
145
  "dim": 1024,
176
- "description": "Based on intfloat/e5-large-unsupervised, large model for most accurate retrieval.",
146
+ "description": "Text embeddings, Unimodal (text), English, 512 input tokens truncation, Prefixes for queries/documents: necessary, 2024 year",
177
147
  "size_in_GB": 1.02,
178
148
  "sources": {
179
149
  "hf": "snowflake/snowflake-arctic-embed-l",
@@ -0,0 +1,87 @@
1
+ from typing import Any, Dict, Iterable, List, Type
2
+
3
+ import numpy as np
4
+
5
+ from fastembed.common.onnx_model import OnnxOutputContext
6
+ from fastembed.common.utils import normalize
7
+ from fastembed.text.onnx_embedding import OnnxTextEmbedding, OnnxTextEmbeddingWorker
8
+ from fastembed.text.onnx_text_model import TextEmbeddingWorker
9
+
10
+ supported_pooled_models = [
11
+ {
12
+ "model": "nomic-ai/nomic-embed-text-v1.5",
13
+ "dim": 768,
14
+ "description": "Text embeddings, Multimodal (text, image), English, 8192 input tokens truncation, Prefixes for queries/documents: necessary, 2024 year",
15
+ "size_in_GB": 0.52,
16
+ "sources": {
17
+ "hf": "nomic-ai/nomic-embed-text-v1.5",
18
+ },
19
+ "model_file": "onnx/model.onnx",
20
+ },
21
+ {
22
+ "model": "nomic-ai/nomic-embed-text-v1.5-Q",
23
+ "dim": 768,
24
+ "description": "Text embeddings, Multimodal (text, image), English, 8192 input tokens truncation, Prefixes for queries/documents: necessary, 2024 year",
25
+ "size_in_GB": 0.13,
26
+ "sources": {
27
+ "hf": "nomic-ai/nomic-embed-text-v1.5",
28
+ },
29
+ "model_file": "onnx/model_quantized.onnx",
30
+ },
31
+ {
32
+ "model": "nomic-ai/nomic-embed-text-v1",
33
+ "dim": 768,
34
+ "description": "Text embeddings, Multimodal (text, image), English, 8192 input tokens truncation, Prefixes for queries/documents: necessary, 2024 year",
35
+ "size_in_GB": 0.52,
36
+ "sources": {
37
+ "hf": "nomic-ai/nomic-embed-text-v1",
38
+ },
39
+ "model_file": "onnx/model.onnx",
40
+ },
41
+ ]
42
+
43
+
44
+ class PooledEmbedding(OnnxTextEmbedding):
45
+ @classmethod
46
+ def _get_worker_class(cls) -> Type[TextEmbeddingWorker]:
47
+ return PooledEmbeddingWorker
48
+
49
+ @classmethod
50
+ def mean_pooling(
51
+ cls, model_output: np.ndarray, attention_mask: np.ndarray
52
+ ) -> np.ndarray:
53
+ token_embeddings = model_output
54
+ input_mask_expanded = np.expand_dims(attention_mask, axis=-1)
55
+ input_mask_expanded = np.tile(
56
+ input_mask_expanded, (1, 1, token_embeddings.shape[-1])
57
+ )
58
+ input_mask_expanded = input_mask_expanded.astype(float)
59
+ sum_embeddings = np.sum(token_embeddings * input_mask_expanded, axis=1)
60
+ sum_mask = np.sum(input_mask_expanded, axis=1)
61
+ pooled_embeddings = sum_embeddings / np.maximum(sum_mask, 1e-9)
62
+ return pooled_embeddings
63
+
64
+ @classmethod
65
+ def list_supported_models(cls) -> List[Dict[str, Any]]:
66
+ """Lists the supported models.
67
+
68
+ Returns:
69
+ List[Dict[str, Any]]: A list of dictionaries containing the model information.
70
+ """
71
+ return supported_pooled_models
72
+
73
+ def _post_process_onnx_output(
74
+ self, output: OnnxOutputContext
75
+ ) -> Iterable[np.ndarray]:
76
+ embeddings = output.model_output
77
+ attn_mask = output.attention_mask
78
+ return self.mean_pooling(embeddings, attn_mask).astype(np.float32)
79
+
80
+
81
+ class PooledEmbeddingWorker(OnnxTextEmbeddingWorker):
82
+ def init_embedding(
83
+ self, model_name: str, cache_dir: str, **kwargs
84
+ ) -> OnnxTextEmbedding:
85
+ return PooledEmbedding(
86
+ model_name=model_name, cache_dir=cache_dir, threads=1, **kwargs
87
+ )
@@ -6,12 +6,24 @@ from fastembed.common.onnx_model import OnnxOutputContext
6
6
  from fastembed.common.utils import normalize
7
7
  from fastembed.text.onnx_embedding import OnnxTextEmbedding, OnnxTextEmbeddingWorker
8
8
  from fastembed.text.onnx_text_model import TextEmbeddingWorker
9
+ from fastembed.text.pooled_embedding import PooledEmbedding
9
10
 
10
- supported_jina_models = [
11
+ supported_pooled_normalized_models = [
12
+ {
13
+ "model": "sentence-transformers/all-MiniLM-L6-v2",
14
+ "dim": 384,
15
+ "description": "Text embeddings, Unimodal (text), English, 256 input tokens truncation, Prefixes for queries/documents: not necessary, 2021 year",
16
+ "size_in_GB": 0.09,
17
+ "sources": {
18
+ "url": "https://storage.googleapis.com/qdrant-fastembed/sentence-transformers-all-MiniLM-L6-v2.tar.gz",
19
+ "hf": "qdrant/all-MiniLM-L6-v2-onnx",
20
+ },
21
+ "model_file": "model.onnx",
22
+ },
11
23
  {
12
24
  "model": "jinaai/jina-embeddings-v2-base-en",
13
25
  "dim": 768,
14
- "description": "English embedding model supporting 8192 sequence length",
26
+ "description": "Text embeddings, Unimodal (text), English, 8192 input tokens truncation, Prefixes for queries/documents: not necessary, 2023 year",
15
27
  "size_in_GB": 0.52,
16
28
  "sources": {"hf": "xenova/jina-embeddings-v2-base-en"},
17
29
  "model_file": "onnx/model.onnx",
@@ -19,7 +31,7 @@ supported_jina_models = [
19
31
  {
20
32
  "model": "jinaai/jina-embeddings-v2-small-en",
21
33
  "dim": 512,
22
- "description": "English embedding model supporting 8192 sequence length",
34
+ "description": "Text embeddings, Unimodal (text), English, 8192 input tokens truncation, Prefixes for queries/documents: not necessary, 2023 year",
23
35
  "size_in_GB": 0.12,
24
36
  "sources": {"hf": "xenova/jina-embeddings-v2-small-en"},
25
37
  "model_file": "onnx/model.onnx",
@@ -27,28 +39,26 @@ supported_jina_models = [
27
39
  {
28
40
  "model": "jinaai/jina-embeddings-v2-base-de",
29
41
  "dim": 768,
30
- "description": "German embedding model supporting 8192 sequence length",
42
+ "description": "Text embeddings, Unimodal (text), Multilingual (German, English), 8192 input tokens truncation, Prefixes for queries/documents: not necessary, 2024 year",
31
43
  "size_in_GB": 0.32,
32
44
  "sources": {"hf": "jinaai/jina-embeddings-v2-base-de"},
33
45
  "model_file": "onnx/model_fp16.onnx",
34
46
  },
47
+ {
48
+ "model": "jinaai/jina-embeddings-v2-base-code",
49
+ "dim": 768,
50
+ "description": "Text embeddings, Unimodal (text), Multilingual (English, 30 programming languages), 8192 input tokens truncation, Prefixes for queries/documents: not necessary, 2024 year",
51
+ "size_in_GB": 0.64,
52
+ "sources": {"hf": "jinaai/jina-embeddings-v2-base-code"},
53
+ "model_file": "onnx/model.onnx",
54
+ },
35
55
  ]
36
56
 
37
57
 
38
- class JinaOnnxEmbedding(OnnxTextEmbedding):
58
+ class PooledNormalizedEmbedding(PooledEmbedding):
39
59
  @classmethod
40
60
  def _get_worker_class(cls) -> Type[TextEmbeddingWorker]:
41
- return JinaEmbeddingWorker
42
-
43
- @classmethod
44
- def mean_pooling(cls, model_output, attention_mask) -> np.ndarray:
45
- token_embeddings = model_output
46
- input_mask_expanded = (np.expand_dims(attention_mask, axis=-1)).astype(float)
47
-
48
- sum_embeddings = np.sum(token_embeddings * input_mask_expanded, axis=1)
49
- mask_sum = np.clip(np.sum(input_mask_expanded, axis=1), a_min=1e-9, a_max=None)
50
-
51
- return sum_embeddings / mask_sum
61
+ return PooledNormalizedEmbeddingWorker
52
62
 
53
63
  @classmethod
54
64
  def list_supported_models(cls) -> List[Dict[str, Any]]:
@@ -57,7 +67,7 @@ class JinaOnnxEmbedding(OnnxTextEmbedding):
57
67
  Returns:
58
68
  List[Dict[str, Any]]: A list of dictionaries containing the model information.
59
69
  """
60
- return supported_jina_models
70
+ return supported_pooled_normalized_models
61
71
 
62
72
  def _post_process_onnx_output(
63
73
  self, output: OnnxOutputContext
@@ -67,10 +77,10 @@ class JinaOnnxEmbedding(OnnxTextEmbedding):
67
77
  return normalize(self.mean_pooling(embeddings, attn_mask)).astype(np.float32)
68
78
 
69
79
 
70
- class JinaEmbeddingWorker(OnnxTextEmbeddingWorker):
80
+ class PooledNormalizedEmbeddingWorker(OnnxTextEmbeddingWorker):
71
81
  def init_embedding(
72
82
  self, model_name: str, cache_dir: str, **kwargs
73
83
  ) -> OnnxTextEmbedding:
74
- return JinaOnnxEmbedding(
84
+ return PooledNormalizedEmbedding(
75
85
  model_name=model_name, cache_dir=cache_dir, threads=1, **kwargs
76
86
  )
@@ -5,8 +5,8 @@ import numpy as np
5
5
  from fastembed.common import OnnxProvider
6
6
  from fastembed.text.clip_embedding import CLIPOnnxEmbedding
7
7
  from fastembed.text.e5_onnx_embedding import E5OnnxEmbedding
8
- from fastembed.text.jina_onnx_embedding import JinaOnnxEmbedding
9
- from fastembed.text.mini_lm_embedding import MiniLMOnnxEmbedding
8
+ from fastembed.text.pooled_normalized_embedding import PooledNormalizedEmbedding
9
+ from fastembed.text.pooled_embedding import PooledEmbedding
10
10
  from fastembed.text.onnx_embedding import OnnxTextEmbedding
11
11
  from fastembed.text.text_embedding_base import TextEmbeddingBase
12
12
 
@@ -15,9 +15,9 @@ class TextEmbedding(TextEmbeddingBase):
15
15
  EMBEDDINGS_REGISTRY: List[Type[TextEmbeddingBase]] = [
16
16
  OnnxTextEmbedding,
17
17
  E5OnnxEmbedding,
18
- JinaOnnxEmbedding,
19
18
  CLIPOnnxEmbedding,
20
- MiniLMOnnxEmbedding,
19
+ PooledNormalizedEmbedding,
20
+ PooledEmbedding,
21
21
  ]
22
22
 
23
23
  @classmethod
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "fastembed-gpu"
3
- version = "0.3.3"
3
+ version = "0.3.5"
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"
@@ -1,3 +0,0 @@
1
- from fastembed.common.types import ImageInput, OnnxProvider, PathInput
2
-
3
- __all__ = ["OnnxProvider", "ImageInput", "PathInput"]
@@ -1,58 +0,0 @@
1
- from typing import Any, Dict, Iterable, List, Type
2
-
3
- import numpy as np
4
-
5
- from fastembed.common.onnx_model import OnnxOutputContext
6
- from fastembed.common.utils import normalize
7
- from fastembed.text.onnx_embedding import OnnxTextEmbedding, OnnxTextEmbeddingWorker
8
- from fastembed.text.onnx_text_model import TextEmbeddingWorker
9
-
10
- supported_mini_lm_models = [
11
- {
12
- "model": "sentence-transformers/all-MiniLM-L6-v2",
13
- "dim": 384,
14
- "description": "Sentence Transformer model, MiniLM-L6-v2",
15
- "size_in_GB": 0.09,
16
- "sources": {
17
- "url": "https://storage.googleapis.com/qdrant-fastembed/sentence-transformers-all-MiniLM-L6-v2.tar.gz",
18
- "hf": "qdrant/all-MiniLM-L6-v2-onnx",
19
- },
20
- "model_file": "model.onnx",
21
- }
22
- ]
23
-
24
-
25
- class MiniLMOnnxEmbedding(OnnxTextEmbedding):
26
- @classmethod
27
- def _get_worker_class(cls) -> Type[TextEmbeddingWorker]:
28
- return MiniLMEmbeddingWorker
29
-
30
- @classmethod
31
- def mean_pooling(cls, model_output: np.ndarray, attention_mask: np.ndarray) -> np.ndarray:
32
- token_embeddings = model_output
33
- input_mask_expanded = np.expand_dims(attention_mask, axis=-1)
34
- input_mask_expanded = np.tile(input_mask_expanded, (1, 1, token_embeddings.shape[-1]))
35
- input_mask_expanded = input_mask_expanded.astype(float)
36
- sum_embeddings = np.sum(token_embeddings * input_mask_expanded, axis=1)
37
- sum_mask = np.sum(input_mask_expanded, axis=1)
38
- pooled_embeddings = sum_embeddings / np.maximum(sum_mask, 1e-9)
39
- return pooled_embeddings
40
-
41
- @classmethod
42
- def list_supported_models(cls) -> List[Dict[str, Any]]:
43
- """Lists the supported models.
44
-
45
- Returns:
46
- List[Dict[str, Any]]: A list of dictionaries containing the model information.
47
- """
48
- return supported_mini_lm_models
49
-
50
- def _post_process_onnx_output(self, output: OnnxOutputContext) -> Iterable[np.ndarray]:
51
- embeddings = output.model_output
52
- attn_mask = output.attention_mask
53
- return normalize(self.mean_pooling(embeddings, attn_mask)).astype(np.float32)
54
-
55
-
56
- class MiniLMEmbeddingWorker(OnnxTextEmbeddingWorker):
57
- def init_embedding(self, model_name: str, cache_dir: str, **kwargs) -> OnnxTextEmbedding:
58
- return MiniLMOnnxEmbedding(model_name=model_name, cache_dir=cache_dir, threads=1, **kwargs)
File without changes