fastembed 0.2.6__tar.gz → 0.2.7__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 (24) hide show
  1. {fastembed-0.2.6 → fastembed-0.2.7}/PKG-INFO +34 -10
  2. {fastembed-0.2.6 → fastembed-0.2.7}/README.md +33 -8
  3. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/__init__.py +6 -1
  4. fastembed-0.2.7/fastembed/common/__init__.py +3 -0
  5. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/common/model_management.py +30 -21
  6. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/common/onnx_model.py +35 -6
  7. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/sparse/sparse_embedding_base.py +1 -0
  8. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/sparse/sparse_text_embedding.py +6 -2
  9. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/sparse/splade_pp.py +17 -9
  10. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/text/e5_onnx_embedding.py +3 -0
  11. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/text/jina_onnx_embedding.py +2 -0
  12. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/text/onnx_embedding.py +87 -34
  13. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/text/text_embedding.py +6 -2
  14. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/text/text_embedding_base.py +1 -0
  15. {fastembed-0.2.6 → fastembed-0.2.7}/pyproject.toml +2 -2
  16. fastembed-0.2.6/fastembed/image/__init__.py +0 -0
  17. {fastembed-0.2.6 → fastembed-0.2.7}/LICENSE +0 -0
  18. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/common/models.py +0 -0
  19. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/common/utils.py +0 -0
  20. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/embedding.py +0 -0
  21. {fastembed-0.2.6/fastembed/common → fastembed-0.2.7/fastembed/image}/__init__.py +0 -0
  22. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/parallel_processor.py +0 -0
  23. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/sparse/__init__.py +0 -0
  24. {fastembed-0.2.6 → fastembed-0.2.7}/fastembed/text/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastembed
3
- Version: 0.2.6
3
+ Version: 0.2.7
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
@@ -22,7 +22,7 @@ Requires-Dist: numpy (>=1.26) ; python_version >= "3.12"
22
22
  Requires-Dist: onnx (>=1.15.0,<2.0.0)
23
23
  Requires-Dist: onnxruntime (>=1.17.0,<2.0.0)
24
24
  Requires-Dist: requests (>=2.31,<3.0)
25
- Requires-Dist: tokenizers (>=0.15.1,<0.16.0)
25
+ Requires-Dist: tokenizers (>=0.15,<0.16)
26
26
  Requires-Dist: tqdm (>=4.66,<5.0)
27
27
  Project-URL: Repository, https://github.com/qdrant/fastembed
28
28
  Description-Content-Type: text/markdown
@@ -31,7 +31,7 @@ Description-Content-Type: text/markdown
31
31
 
32
32
  FastEmbed is a lightweight, fast, Python library built for embedding generation. We [support popular text models](https://qdrant.github.io/fastembed/examples/Supported_Models/). Please [open a GitHub issue](https://github.com/qdrant/fastembed/issues/new) if you want us to add a new model.
33
33
 
34
- The default text embedding (`TextEmbedding`) model is Flag Embedding, presented in the [MTEB](https://huggingface.co/spaces/mteb/leaderboard) leaderboard. It supports "query" and "passage" prefixes for the input text. Here is an example for [Retrieval Embedding Generation](https://qdrant.github.io/fastembed/examples/Retrieval_with_FastEmbed/) and how to use [FastEmbed with Qdrant](https://qdrant.github.io/fastembed/examples/Usage_With_Qdrant/).
34
+ The default text embedding (`TextEmbedding`) model is Flag Embedding, presented in the [MTEB](https://huggingface.co/spaces/mteb/leaderboard) leaderboard. It supports "query" and "passage" prefixes for the input text. Here is an example for [Retrieval Embedding Generation](https://qdrant.github.io/fastembed/qdrant/Retrieval_with_FastEmbed/) and how to use [FastEmbed with Qdrant](https://qdrant.github.io/fastembed/qdrant/Usage_With_Qdrant/).
35
35
 
36
36
  ## 📈 Why FastEmbed?
37
37
 
@@ -43,12 +43,18 @@ The default text embedding (`TextEmbedding`) model is Flag Embedding, presented
43
43
 
44
44
  ## 🚀 Installation
45
45
 
46
- To install the FastEmbed library, pip works:
46
+ To install the FastEmbed library, pip works best. You can install it with or without GPU support:
47
47
 
48
48
  ```bash
49
49
  pip install fastembed
50
50
  ```
51
51
 
52
+ ### ⚡️ With GPU
53
+
54
+ ```bash
55
+ pip install fastembed-gpu
56
+ ```
57
+
52
58
  ## 📖 Quickstart
53
59
 
54
60
  ```python
@@ -71,6 +77,23 @@ embeddings_list = list(embedding_model.embed(documents))
71
77
  len(embeddings_list[0]) # Vector of 384 dimensions
72
78
  ```
73
79
 
80
+ ### ⚡️ FastEmbed on a GPU
81
+
82
+ FastEmbed supports running on GPU devices. It requires installation of the `fastembed-gpu` package.
83
+ Make sure not to have the `fastembed` package installed, as it might interfere with the `fastembed-gpu` package.
84
+
85
+ ```bash
86
+ pip install fastembed-gpu
87
+ ```
88
+
89
+ ```python
90
+ from fastembed import TextEmbedding
91
+
92
+ embedding_model = TextEmbedding(model_name="BAAI/bge-small-en-v1.5", providers=["CUDAExecutionProvider"])
93
+ print("The model BAAI/bge-small-en-v1.5 is ready to use on a GPU.")
94
+
95
+ ```
96
+
74
97
  ## Usage with Qdrant
75
98
 
76
99
  Installation with Qdrant Client in Python:
@@ -79,7 +102,13 @@ Installation with Qdrant Client in Python:
79
102
  pip install qdrant-client[fastembed]
80
103
  ```
81
104
 
82
- You might have to use ```pip install 'qdrant-client[fastembed]'``` on zsh.
105
+ or
106
+
107
+ ```bash
108
+ pip install qdrant-client[fastembed-gpu]
109
+ ```
110
+
111
+ You might have to use quotes ```pip install 'qdrant-client[fastembed]'``` on zsh.
83
112
 
84
113
  ```python
85
114
  from qdrant_client import QdrantClient
@@ -115,8 +144,3 @@ search_result = client.query(
115
144
  )
116
145
  print(search_result)
117
146
  ```
118
-
119
- #### Similar Work
120
-
121
- Ilyas M. wrote about using [FlagEmbeddings with Optimum](https://twitter.com/IlysMoutawwakil/status/1705215192425288017) over CUDA.
122
-
@@ -2,7 +2,7 @@
2
2
 
3
3
  FastEmbed is a lightweight, fast, Python library built for embedding generation. We [support popular text models](https://qdrant.github.io/fastembed/examples/Supported_Models/). Please [open a GitHub issue](https://github.com/qdrant/fastembed/issues/new) if you want us to add a new model.
4
4
 
5
- The default text embedding (`TextEmbedding`) model is Flag Embedding, presented in the [MTEB](https://huggingface.co/spaces/mteb/leaderboard) leaderboard. It supports "query" and "passage" prefixes for the input text. Here is an example for [Retrieval Embedding Generation](https://qdrant.github.io/fastembed/examples/Retrieval_with_FastEmbed/) and how to use [FastEmbed with Qdrant](https://qdrant.github.io/fastembed/examples/Usage_With_Qdrant/).
5
+ The default text embedding (`TextEmbedding`) model is Flag Embedding, presented in the [MTEB](https://huggingface.co/spaces/mteb/leaderboard) leaderboard. It supports "query" and "passage" prefixes for the input text. Here is an example for [Retrieval Embedding Generation](https://qdrant.github.io/fastembed/qdrant/Retrieval_with_FastEmbed/) and how to use [FastEmbed with Qdrant](https://qdrant.github.io/fastembed/qdrant/Usage_With_Qdrant/).
6
6
 
7
7
  ## 📈 Why FastEmbed?
8
8
 
@@ -14,12 +14,18 @@ The default text embedding (`TextEmbedding`) model is Flag Embedding, presented
14
14
 
15
15
  ## 🚀 Installation
16
16
 
17
- To install the FastEmbed library, pip works:
17
+ To install the FastEmbed library, pip works best. You can install it with or without GPU support:
18
18
 
19
19
  ```bash
20
20
  pip install fastembed
21
21
  ```
22
22
 
23
+ ### ⚡️ With GPU
24
+
25
+ ```bash
26
+ pip install fastembed-gpu
27
+ ```
28
+
23
29
  ## 📖 Quickstart
24
30
 
25
31
  ```python
@@ -42,6 +48,23 @@ embeddings_list = list(embedding_model.embed(documents))
42
48
  len(embeddings_list[0]) # Vector of 384 dimensions
43
49
  ```
44
50
 
51
+ ### ⚡️ FastEmbed on a GPU
52
+
53
+ FastEmbed supports running on GPU devices. It requires installation of the `fastembed-gpu` package.
54
+ Make sure not to have the `fastembed` package installed, as it might interfere with the `fastembed-gpu` package.
55
+
56
+ ```bash
57
+ pip install fastembed-gpu
58
+ ```
59
+
60
+ ```python
61
+ from fastembed import TextEmbedding
62
+
63
+ embedding_model = TextEmbedding(model_name="BAAI/bge-small-en-v1.5", providers=["CUDAExecutionProvider"])
64
+ print("The model BAAI/bge-small-en-v1.5 is ready to use on a GPU.")
65
+
66
+ ```
67
+
45
68
  ## Usage with Qdrant
46
69
 
47
70
  Installation with Qdrant Client in Python:
@@ -50,7 +73,13 @@ Installation with Qdrant Client in Python:
50
73
  pip install qdrant-client[fastembed]
51
74
  ```
52
75
 
53
- You might have to use ```pip install 'qdrant-client[fastembed]'``` on zsh.
76
+ or
77
+
78
+ ```bash
79
+ pip install qdrant-client[fastembed-gpu]
80
+ ```
81
+
82
+ You might have to use quotes ```pip install 'qdrant-client[fastembed]'``` on zsh.
54
83
 
55
84
  ```python
56
85
  from qdrant_client import QdrantClient
@@ -85,8 +114,4 @@ search_result = client.query(
85
114
  query_text="This is a query document"
86
115
  )
87
116
  print(search_result)
88
- ```
89
-
90
- #### Similar Work
91
-
92
- Ilyas M. wrote about using [FlagEmbeddings with Optimum](https://twitter.com/IlysMoutawwakil/status/1705215192425288017) over CUDA.
117
+ ```
@@ -3,5 +3,10 @@ import importlib.metadata
3
3
  from fastembed.text import TextEmbedding
4
4
  from fastembed.sparse import SparseTextEmbedding, SparseEmbedding
5
5
 
6
- __version__ = importlib.metadata.version("fastembed")
6
+ try:
7
+ version = importlib.metadata.version("fastembed")
8
+ except importlib.metadata.PackageNotFoundError as _:
9
+ version = importlib.metadata.version("fastembed-gpu")
10
+
11
+ __version__ = version
7
12
  __all__ = ["TextEmbedding", "SparseTextEmbedding", "SparseEmbedding"]
@@ -0,0 +1,3 @@
1
+ from fastembed.common.onnx_model import OnnxProvider
2
+
3
+ __all__ = ["OnnxProvider"]
@@ -11,23 +11,6 @@ from tqdm import tqdm
11
11
  from loguru import logger
12
12
 
13
13
 
14
- def locate_model_file(model_dir: Path, file_names: List[str]) -> Path:
15
- """
16
- Find model path for both TransformerJS style `onnx` subdirectory structure and direct model weights structure used
17
- by Optimum and Qdrant
18
- """
19
- if not model_dir.is_dir():
20
- raise ValueError(f"Provided model path '{model_dir}' is not a directory.")
21
-
22
- for file_name in file_names:
23
- file_paths = [path for path in model_dir.rglob(file_name) if path.is_file()]
24
-
25
- if file_paths:
26
- return file_paths[0]
27
-
28
- raise ValueError(f"Could not find either of {', '.join(file_names)} in {model_dir}")
29
-
30
-
31
14
  class ModelManagement:
32
15
  @classmethod
33
16
  def list_supported_models(cls) -> List[Dict[str, Any]]:
@@ -104,21 +87,36 @@ class ModelManagement:
104
87
 
105
88
  @classmethod
106
89
  def download_files_from_huggingface(
107
- cls, hf_source_repo: str, cache_dir: Optional[str] = None
90
+ cls,
91
+ hf_source_repo: str,
92
+ cache_dir: Optional[str] = None,
93
+ extra_patterns: Optional[List[str]] = None,
94
+ **kwargs,
108
95
  ) -> str:
109
96
  """
110
97
  Downloads a model from HuggingFace Hub.
111
98
  Args:
112
99
  hf_source_repo (str): Name of the model on HuggingFace Hub, e.g. "qdrant/all-MiniLM-L6-v2-onnx".
113
100
  cache_dir (Optional[str]): The path to the cache directory.
101
+ extra_patterns (Optional[List[str]]): extra patterns to allow in the snapshot download, typically
102
+ includes the required model files.
114
103
  Returns:
115
104
  Path: The path to the model directory.
116
105
  """
106
+ allow_patterns = [
107
+ "config.json",
108
+ "tokenizer.json",
109
+ "tokenizer_config.json",
110
+ "special_tokens_map.json",
111
+ ]
112
+ if extra_patterns is not None:
113
+ allow_patterns.extend(extra_patterns)
117
114
 
118
115
  return snapshot_download(
119
116
  repo_id=hf_source_repo,
120
- ignore_patterns=["model.safetensors", "pytorch_model.bin"],
117
+ allow_patterns=allow_patterns,
121
118
  cache_dir=cache_dir,
119
+ local_files_only=kwargs.get("local_files_only", False),
122
120
  )
123
121
 
124
122
  @classmethod
@@ -175,6 +173,9 @@ class ModelManagement:
175
173
 
176
174
  model_tar_gz = Path(cache_dir) / f"{fast_model_name}.tar.gz"
177
175
 
176
+ if model_tar_gz.exists():
177
+ model_tar_gz.unlink()
178
+
178
179
  cls.download_file_from_gcs(
179
180
  source_url,
180
181
  output_path=str(model_tar_gz),
@@ -190,7 +191,7 @@ class ModelManagement:
190
191
  return model_dir
191
192
 
192
193
  @classmethod
193
- def download_model(cls, model: Dict[str, Any], cache_dir: Path) -> Path:
194
+ def download_model(cls, model: Dict[str, Any], cache_dir: Path, **kwargs) -> Path:
194
195
  """
195
196
  Downloads a model from HuggingFace Hub or Google Cloud Storage.
196
197
 
@@ -219,9 +220,17 @@ class ModelManagement:
219
220
  url_source = model.get("sources", {}).get("url")
220
221
 
221
222
  if hf_source:
223
+ extra_patterns = [model["model_file"]]
224
+ extra_patterns.extend(model.get("additional_files", []))
225
+
222
226
  try:
223
227
  return Path(
224
- cls.download_files_from_huggingface(hf_source, cache_dir=str(cache_dir))
228
+ cls.download_files_from_huggingface(
229
+ hf_source,
230
+ cache_dir=str(cache_dir),
231
+ extra_patterns=extra_patterns,
232
+ local_files_only=kwargs.get("local_files_only", False),
233
+ )
225
234
  )
226
235
  except (EnvironmentError, RepositoryNotFoundError, ValueError) as e:
227
236
  logger.error(
@@ -1,19 +1,33 @@
1
1
  import os
2
2
  from multiprocessing import get_all_start_methods
3
3
  from pathlib import Path
4
- from typing import Any, Dict, Generic, Iterable, List, Optional, Tuple, Type, TypeVar, Union
4
+ from typing import (
5
+ Any,
6
+ Dict,
7
+ Generic,
8
+ Iterable,
9
+ List,
10
+ Optional,
11
+ Tuple,
12
+ Type,
13
+ TypeVar,
14
+ Union,
15
+ Sequence,
16
+ )
5
17
 
6
18
  import numpy as np
7
19
  import onnxruntime as ort
8
20
 
9
- from fastembed.common.model_management import locate_model_file
10
21
  from fastembed.common.models import load_tokenizer
11
22
  from fastembed.common.utils import iter_batch
12
23
  from fastembed.parallel_processor import ParallelWorkerPool, Worker
13
24
 
25
+
14
26
  # Holds type of the embedding result
15
27
  T = TypeVar("T")
16
28
 
29
+ OnnxProvider = Union[str, Tuple[str, Dict[Any, Any]]]
30
+
17
31
 
18
32
  class OnnxModel(Generic[T]):
19
33
  @classmethod
@@ -34,11 +48,26 @@ class OnnxModel(Generic[T]):
34
48
  """
35
49
  return onnx_input
36
50
 
37
- def load_onnx_model(self, model_dir: Path, threads: Optional[int], max_length: int) -> None:
38
- model_path = locate_model_file(model_dir, ["model.onnx", "model_optimized.onnx"])
51
+ def load_onnx_model(
52
+ self,
53
+ model_dir: Path,
54
+ model_file: str,
55
+ threads: Optional[int],
56
+ providers: Optional[Sequence[OnnxProvider]] = None,
57
+ ) -> None:
58
+ model_path = model_dir / model_file
39
59
 
40
60
  # List of Execution Providers: https://onnxruntime.ai/docs/execution-providers
41
- onnx_providers = ["CPUExecutionProvider"]
61
+
62
+ onnx_providers = ["CPUExecutionProvider"] if providers is None else list(providers)
63
+ available_providers = ort.get_available_providers()
64
+ for provider in onnx_providers:
65
+ # check providers available
66
+ provider_name = provider if isinstance(provider, str) else provider[0]
67
+ if provider_name not in available_providers:
68
+ raise ValueError(
69
+ f"Provider {provider_name} is not available. Available providers: {available_providers}"
70
+ )
42
71
 
43
72
  so = ort.SessionOptions()
44
73
  so.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
@@ -47,7 +76,7 @@ class OnnxModel(Generic[T]):
47
76
  so.intra_op_num_threads = threads
48
77
  so.inter_op_num_threads = threads
49
78
 
50
- self.tokenizer = load_tokenizer(model_dir=model_dir, max_length=max_length)
79
+ self.tokenizer = load_tokenizer(model_dir=model_dir)
51
80
  self.model = ort.InferenceSession(
52
81
  str(model_path), providers=onnx_providers, sess_options=so
53
82
  )
@@ -32,6 +32,7 @@ class SparseTextEmbeddingBase(ModelManagement):
32
32
  self.model_name = model_name
33
33
  self.cache_dir = cache_dir
34
34
  self.threads = threads
35
+ self._local_files_only = kwargs.pop("local_files_only", False)
35
36
 
36
37
  def embed(
37
38
  self,
@@ -1,5 +1,6 @@
1
- from typing import List, Type, Dict, Any, Union, Iterable, Optional
1
+ from typing import List, Type, Dict, Any, Union, Iterable, Optional, Sequence
2
2
 
3
+ from fastembed.common import OnnxProvider
3
4
  from fastembed.sparse.sparse_embedding_base import SparseTextEmbeddingBase, SparseEmbedding
4
5
  from fastembed.sparse.splade_pp import SpladePP
5
6
 
@@ -42,6 +43,7 @@ class SparseTextEmbedding(SparseTextEmbeddingBase):
42
43
  model_name: str,
43
44
  cache_dir: Optional[str] = None,
44
45
  threads: Optional[int] = None,
46
+ providers: Optional[Sequence[OnnxProvider]] = None,
45
47
  **kwargs,
46
48
  ):
47
49
  super().__init__(model_name, cache_dir, threads, **kwargs)
@@ -49,7 +51,9 @@ class SparseTextEmbedding(SparseTextEmbeddingBase):
49
51
  for EMBEDDING_MODEL_TYPE in self.EMBEDDINGS_REGISTRY:
50
52
  supported_models = EMBEDDING_MODEL_TYPE.list_supported_models()
51
53
  if any(model_name.lower() == model["model"].lower() for model in supported_models):
52
- self.model = EMBEDDING_MODEL_TYPE(model_name, cache_dir, threads, **kwargs)
54
+ self.model = EMBEDDING_MODEL_TYPE(
55
+ model_name, cache_dir, threads, providers=providers, **kwargs
56
+ )
53
57
  return
54
58
 
55
59
  raise ValueError(
@@ -1,8 +1,8 @@
1
- from typing import Any, Dict, Iterable, List, Optional, Tuple, Union, Type
1
+ from typing import Any, Dict, Iterable, List, Optional, Tuple, Union, Type, Sequence
2
2
 
3
3
  import numpy as np
4
4
 
5
- from fastembed.common.onnx_model import EmbeddingWorker, OnnxModel
5
+ from fastembed.common.onnx_model import EmbeddingWorker, OnnxModel, OnnxProvider
6
6
  from fastembed.common.utils import define_cache_dir
7
7
  from fastembed.sparse.sparse_embedding_base import SparseEmbedding, SparseTextEmbeddingBase
8
8
 
@@ -15,6 +15,7 @@ supported_splade_models = [
15
15
  "sources": {
16
16
  "hf": "Qdrant/SPLADE_PP_en_v1",
17
17
  },
18
+ "model_file": "model.onnx",
18
19
  },
19
20
  {
20
21
  "model": "prithivida/Splade_PP_en_v1",
@@ -24,6 +25,7 @@ supported_splade_models = [
24
25
  "sources": {
25
26
  "hf": "Qdrant/SPLADE_PP_en_v1",
26
27
  },
28
+ "model_file": "model.onnx",
27
29
  },
28
30
  ]
29
31
 
@@ -61,6 +63,7 @@ class SpladePP(SparseTextEmbeddingBase, OnnxModel[SparseEmbedding]):
61
63
  model_name: str,
62
64
  cache_dir: Optional[str] = None,
63
65
  threads: Optional[int] = None,
66
+ providers: Optional[Sequence[OnnxProvider]] = None,
64
67
  **kwargs,
65
68
  ):
66
69
  """
@@ -77,14 +80,19 @@ class SpladePP(SparseTextEmbeddingBase, OnnxModel[SparseEmbedding]):
77
80
 
78
81
  super().__init__(model_name, cache_dir, threads, **kwargs)
79
82
 
80
- self.model_name = model_name
81
- self._model_description = self._get_model_description(model_name)
83
+ model_description = self._get_model_description(model_name)
84
+ cache_dir = define_cache_dir(cache_dir)
82
85
 
83
- self._cache_dir = define_cache_dir(cache_dir)
84
- self._model_dir = self.download_model(self._model_description, self._cache_dir)
85
- self._max_length = 512
86
+ model_dir = self.download_model(
87
+ model_description, cache_dir, local_files_only=self._local_files_only
88
+ )
86
89
 
87
- self.load_onnx_model(self._model_dir, self.threads, self._max_length)
90
+ self.load_onnx_model(
91
+ model_dir=model_dir,
92
+ model_file=model_description["model_file"],
93
+ threads=threads,
94
+ providers=providers,
95
+ )
88
96
 
89
97
  def embed(
90
98
  self,
@@ -110,7 +118,7 @@ class SpladePP(SparseTextEmbeddingBase, OnnxModel[SparseEmbedding]):
110
118
  """
111
119
  yield from self._embed_documents(
112
120
  model_name=self.model_name,
113
- cache_dir=str(self._cache_dir),
121
+ cache_dir=str(self.cache_dir),
114
122
  documents=documents,
115
123
  batch_size=batch_size,
116
124
  parallel=parallel,
@@ -15,6 +15,8 @@ supported_multilingual_e5_models = [
15
15
  "url": "https://storage.googleapis.com/qdrant-fastembed/fast-multilingual-e5-large.tar.gz",
16
16
  "hf": "qdrant/multilingual-e5-large-onnx",
17
17
  },
18
+ "model_file": "model.onnx",
19
+ "additional_files": ["model.onnx_data"],
18
20
  },
19
21
  {
20
22
  "model": "sentence-transformers/paraphrase-multilingual-mpnet-base-v2",
@@ -24,6 +26,7 @@ supported_multilingual_e5_models = [
24
26
  "sources": {
25
27
  "hf": "xenova/paraphrase-multilingual-mpnet-base-v2",
26
28
  },
29
+ "model_file": "onnx/model.onnx",
27
30
  },
28
31
  ]
29
32
 
@@ -13,6 +13,7 @@ supported_jina_models = [
13
13
  "description": "English embedding model supporting 8192 sequence length",
14
14
  "size_in_GB": 0.52,
15
15
  "sources": {"hf": "xenova/jina-embeddings-v2-base-en"},
16
+ "model_file": "onnx/model.onnx",
16
17
  },
17
18
  {
18
19
  "model": "jinaai/jina-embeddings-v2-small-en",
@@ -20,6 +21,7 @@ supported_jina_models = [
20
21
  "description": "English embedding model supporting 8192 sequence length",
21
22
  "size_in_GB": 0.12,
22
23
  "sources": {"hf": "xenova/jina-embeddings-v2-small-en"},
24
+ "model_file": "onnx/model.onnx",
23
25
  },
24
26
  ]
25
27
 
@@ -1,8 +1,8 @@
1
- from typing import Dict, Optional, Tuple, Union, Iterable, Type, List, Any
1
+ from typing import Dict, Optional, Tuple, Union, Iterable, Type, List, Any, Sequence
2
2
 
3
3
  import numpy as np
4
4
 
5
- from fastembed.common.onnx_model import OnnxModel, EmbeddingWorker
5
+ from fastembed.common.onnx_model import OnnxModel, EmbeddingWorker, OnnxProvider
6
6
  from fastembed.common.models import normalize
7
7
  from fastembed.common.utils import define_cache_dir
8
8
  from fastembed.text.text_embedding_base import TextEmbeddingBase
@@ -16,6 +16,7 @@ supported_onnx_models = [
16
16
  "sources": {
17
17
  "url": "https://storage.googleapis.com/qdrant-fastembed/fast-bge-base-en.tar.gz",
18
18
  },
19
+ "model_file": "model_optimized.onnx",
19
20
  },
20
21
  {
21
22
  "model": "BAAI/bge-base-en-v1.5",
@@ -26,6 +27,7 @@ supported_onnx_models = [
26
27
  "url": "https://storage.googleapis.com/qdrant-fastembed/fast-bge-base-en-v1.5.tar.gz",
27
28
  "hf": "qdrant/bge-base-en-v1.5-onnx-q",
28
29
  },
30
+ "model_file": "model_optimized.onnx",
29
31
  },
30
32
  {
31
33
  "model": "BAAI/bge-large-en-v1.5",
@@ -35,6 +37,7 @@ supported_onnx_models = [
35
37
  "sources": {
36
38
  "hf": "qdrant/bge-large-en-v1.5-onnx",
37
39
  },
40
+ "model_file": "model.onnx",
38
41
  },
39
42
  {
40
43
  "model": "BAAI/bge-small-en",
@@ -44,18 +47,8 @@ supported_onnx_models = [
44
47
  "sources": {
45
48
  "url": "https://storage.googleapis.com/qdrant-fastembed/BAAI-bge-small-en.tar.gz",
46
49
  },
50
+ "model_file": "model_optimized.onnx",
47
51
  },
48
- # {
49
- # "model": "BAAI/bge-small-en",
50
- # "dim": 384,
51
- # "description": "Fast English model",
52
- # "size_in_GB": 0.2,
53
- # "hf_sources": [],
54
- # "compressed_url_sources": [
55
- # "https://storage.googleapis.com/qdrant-fastembed/fast-bge-small-en.tar.gz",
56
- # "https://storage.googleapis.com/qdrant-fastembed/BAAI-bge-small-en.tar.gz"
57
- # ]
58
- # },
59
52
  {
60
53
  "model": "BAAI/bge-small-en-v1.5",
61
54
  "dim": 384,
@@ -64,6 +57,7 @@ supported_onnx_models = [
64
57
  "sources": {
65
58
  "hf": "qdrant/bge-small-en-v1.5-onnx-q",
66
59
  },
60
+ "model_file": "model_optimized.onnx",
67
61
  },
68
62
  {
69
63
  "model": "BAAI/bge-small-zh-v1.5",
@@ -73,6 +67,7 @@ supported_onnx_models = [
73
67
  "sources": {
74
68
  "url": "https://storage.googleapis.com/qdrant-fastembed/fast-bge-small-zh-v1.5.tar.gz",
75
69
  },
70
+ "model_file": "model_optimized.onnx",
76
71
  },
77
72
  {
78
73
  "model": "sentence-transformers/all-MiniLM-L6-v2",
@@ -83,6 +78,7 @@ supported_onnx_models = [
83
78
  "url": "https://storage.googleapis.com/qdrant-fastembed/sentence-transformers-all-MiniLM-L6-v2.tar.gz",
84
79
  "hf": "qdrant/all-MiniLM-L6-v2-onnx",
85
80
  },
81
+ "model_file": "model.onnx",
86
82
  },
87
83
  {
88
84
  "model": "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
@@ -92,6 +88,7 @@ supported_onnx_models = [
92
88
  "sources": {
93
89
  "hf": "qdrant/paraphrase-multilingual-MiniLM-L12-v2-onnx-Q",
94
90
  },
91
+ "model_file": "model_optimized.onnx",
95
92
  },
96
93
  {
97
94
  "model": "nomic-ai/nomic-embed-text-v1",
@@ -101,6 +98,7 @@ supported_onnx_models = [
101
98
  "sources": {
102
99
  "hf": "nomic-ai/nomic-embed-text-v1",
103
100
  },
101
+ "model_file": "onnx/model.onnx",
104
102
  },
105
103
  {
106
104
  "model": "nomic-ai/nomic-embed-text-v1.5",
@@ -110,6 +108,17 @@ supported_onnx_models = [
110
108
  "sources": {
111
109
  "hf": "nomic-ai/nomic-embed-text-v1.5",
112
110
  },
111
+ "model_file": "onnx/model.onnx",
112
+ },
113
+ {
114
+ "model": "nomic-ai/nomic-embed-text-v1.5-Q",
115
+ "dim": 768,
116
+ "description": "Quantized 8192 context length english model",
117
+ "size_in_GB": 0.13,
118
+ "sources": {
119
+ "hf": "nomic-ai/nomic-embed-text-v1.5",
120
+ },
121
+ "model_file": "onnx/model_quantized.onnx",
113
122
  },
114
123
  {
115
124
  "model": "thenlper/gte-large",
@@ -119,20 +128,8 @@ supported_onnx_models = [
119
128
  "sources": {
120
129
  "hf": "qdrant/gte-large-onnx",
121
130
  },
131
+ "model_file": "model.onnx",
122
132
  },
123
- # {
124
- # "model": "sentence-transformers/all-MiniLM-L6-v2",
125
- # "dim": 384,
126
- # "description": "Sentence Transformer model, MiniLM-L6-v2",
127
- # "size_in_GB": 0.09,
128
- # "hf_sources": [
129
- # "qdrant/all-MiniLM-L6-v2-onnx"
130
- # ],
131
- # "compressed_url_sources": [
132
- # "https://storage.googleapis.com/qdrant-fastembed/fast-all-MiniLM-L6-v2.tar.gz",
133
- # "https://storage.googleapis.com/qdrant-fastembed/sentence-transformers-all-MiniLM-L6-v2.tar.gz"
134
- # ]
135
- # }
136
133
  {
137
134
  "model": "mixedbread-ai/mxbai-embed-large-v1",
138
135
  "dim": 1024,
@@ -141,6 +138,57 @@ supported_onnx_models = [
141
138
  "sources": {
142
139
  "hf": "mixedbread-ai/mxbai-embed-large-v1",
143
140
  },
141
+ "model_file": "onnx/model.onnx",
142
+ },
143
+ {
144
+ "model": "snowflake/snowflake-arctic-embed-xs",
145
+ "dim": 384,
146
+ "description": "Based on all-MiniLM-L6-v2 model with only 22m parameters, ideal for latency/TCO budgets.",
147
+ "size_in_GB": 0.09,
148
+ "sources": {
149
+ "hf": "snowflake/snowflake-arctic-embed-xs",
150
+ },
151
+ "model_file": "onnx/model.onnx",
152
+ },
153
+ {
154
+ "model": "snowflake/snowflake-arctic-embed-s",
155
+ "dim": 384,
156
+ "description": "Based on infloat/e5-small-unsupervised, does not trade off retrieval accuracy for its small size.",
157
+ "size_in_GB": 0.13,
158
+ "sources": {
159
+ "hf": "snowflake/snowflake-arctic-embed-s",
160
+ },
161
+ "model_file": "onnx/model.onnx",
162
+ },
163
+ {
164
+ "model": "snowflake/snowflake-arctic-embed-m",
165
+ "dim": 768,
166
+ "description": "Based on intfloat/e5-base-unsupervised model, provides the best retrieval without slowing down inference.",
167
+ "size_in_GB": 0.43,
168
+ "sources": {
169
+ "hf": "Snowflake/snowflake-arctic-embed-m",
170
+ },
171
+ "model_file": "onnx/model.onnx",
172
+ },
173
+ {
174
+ "model": "snowflake/snowflake-arctic-embed-m-long",
175
+ "dim": 768,
176
+ "description": "Based on nomic-ai/nomic-embed-text-v1-unsupervised model, 8192 context-length model",
177
+ "size_in_GB": 0.54,
178
+ "sources": {
179
+ "hf": "snowflake/snowflake-arctic-embed-m-long",
180
+ },
181
+ "model_file": "onnx/model.onnx",
182
+ },
183
+ {
184
+ "model": "snowflake/snowflake-arctic-embed-l",
185
+ "dim": 1024,
186
+ "description": "Based on intfloat/e5-large-unsupervised, large model for most accurate retrieval.",
187
+ "size_in_GB": 1.02,
188
+ "sources": {
189
+ "hf": "snowflake/snowflake-arctic-embed-l",
190
+ },
191
+ "model_file": "onnx/model.onnx",
144
192
  },
145
193
  ]
146
194
 
@@ -163,6 +211,7 @@ class OnnxTextEmbedding(TextEmbeddingBase, OnnxModel[np.ndarray]):
163
211
  model_name: str = "BAAI/bge-small-en-v1.5",
164
212
  cache_dir: Optional[str] = None,
165
213
  threads: Optional[int] = None,
214
+ providers: Optional[Sequence[OnnxProvider]] = None,
166
215
  **kwargs,
167
216
  ):
168
217
  """
@@ -179,14 +228,18 @@ class OnnxTextEmbedding(TextEmbeddingBase, OnnxModel[np.ndarray]):
179
228
 
180
229
  super().__init__(model_name, cache_dir, threads, **kwargs)
181
230
 
182
- self.model_name = model_name
183
- self._model_description = self._get_model_description(model_name)
184
-
185
- self._cache_dir = define_cache_dir(cache_dir)
186
- self._model_dir = self.download_model(self._model_description, self._cache_dir)
187
- self._max_length = 512
231
+ model_description = self._get_model_description(model_name)
232
+ cache_dir = define_cache_dir(cache_dir)
233
+ model_dir = self.download_model(
234
+ model_description, cache_dir, local_files_only=self._local_files_only
235
+ )
188
236
 
189
- self.load_onnx_model(self._model_dir, self.threads, self._max_length)
237
+ self.load_onnx_model(
238
+ model_dir=model_dir,
239
+ model_file=model_description["model_file"],
240
+ threads=threads,
241
+ providers=providers,
242
+ )
190
243
 
191
244
  def embed(
192
245
  self,
@@ -212,7 +265,7 @@ class OnnxTextEmbedding(TextEmbeddingBase, OnnxModel[np.ndarray]):
212
265
  """
213
266
  yield from self._embed_documents(
214
267
  model_name=self.model_name,
215
- cache_dir=str(self._cache_dir),
268
+ cache_dir=str(self.cache_dir),
216
269
  documents=documents,
217
270
  batch_size=batch_size,
218
271
  parallel=parallel,
@@ -1,7 +1,8 @@
1
- from typing import Any, Dict, Iterable, List, Optional, Type, Union
1
+ from typing import Any, Dict, Iterable, List, Optional, Type, Union, Sequence
2
2
 
3
3
  import numpy as np
4
4
 
5
+ from fastembed.common import OnnxProvider
5
6
  from fastembed.text.e5_onnx_embedding import E5OnnxEmbedding
6
7
  from fastembed.text.jina_onnx_embedding import JinaOnnxEmbedding
7
8
  from fastembed.text.onnx_embedding import OnnxTextEmbedding
@@ -49,6 +50,7 @@ class TextEmbedding(TextEmbeddingBase):
49
50
  model_name: str = "BAAI/bge-small-en-v1.5",
50
51
  cache_dir: Optional[str] = None,
51
52
  threads: Optional[int] = None,
53
+ providers: Optional[Sequence[OnnxProvider]] = None,
52
54
  **kwargs,
53
55
  ):
54
56
  super().__init__(model_name, cache_dir, threads, **kwargs)
@@ -56,7 +58,9 @@ class TextEmbedding(TextEmbeddingBase):
56
58
  for EMBEDDING_MODEL_TYPE in self.EMBEDDINGS_REGISTRY:
57
59
  supported_models = EMBEDDING_MODEL_TYPE.list_supported_models()
58
60
  if any(model_name.lower() == model["model"].lower() for model in supported_models):
59
- self.model = EMBEDDING_MODEL_TYPE(model_name, cache_dir, threads, **kwargs)
61
+ self.model = EMBEDDING_MODEL_TYPE(
62
+ model_name, cache_dir, threads, providers=providers, **kwargs
63
+ )
60
64
  return
61
65
 
62
66
  raise ValueError(
@@ -16,6 +16,7 @@ class TextEmbeddingBase(ModelManagement):
16
16
  self.model_name = model_name
17
17
  self.cache_dir = cache_dir
18
18
  self.threads = threads
19
+ self._local_files_only = kwargs.pop("local_files_only", False)
19
20
 
20
21
  def embed(
21
22
  self,
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "fastembed"
3
- version = "0.2.6"
3
+ version = "0.2.7"
4
4
  description = "Fast, light, accurate library built for retrieval embedding generation"
5
5
  authors = ["NirantK <nirant.bits@gmail.com>"]
6
6
  license = "Apache License"
@@ -16,7 +16,7 @@ onnx = "^1.15.0"
16
16
  onnxruntime = "^1.17.0"
17
17
  tqdm = "^4.66"
18
18
  requests = "^2.31"
19
- tokenizers = "^0.15.1"
19
+ tokenizers = "^0.15"
20
20
  huggingface-hub = "^0.20"
21
21
  loguru = "^0.7.2"
22
22
  numpy = [
File without changes
File without changes