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.
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/PKG-INFO +10 -9
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/README.md +9 -9
- fastembed_gpu-0.3.5/fastembed/common/__init__.py +3 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/common/model_management.py +43 -37
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/common/preprocessor_utils.py +11 -5
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/common/types.py +3 -1
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/image_embedding.py +2 -2
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/onnx_embedding.py +22 -2
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/onnx_image_model.py +12 -7
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/late_interaction/colbert.py +11 -1
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/bm25.py +44 -9
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/bm42.py +1 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/sparse_text_embedding.py +10 -7
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/splade_pp.py +0 -12
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/text/clip_embedding.py +1 -1
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/text/e5_onnx_embedding.py +2 -2
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/text/onnx_embedding.py +14 -44
- fastembed_gpu-0.3.5/fastembed/text/pooled_embedding.py +87 -0
- fastembed_gpu-0.3.3/fastembed/text/jina_onnx_embedding.py → fastembed_gpu-0.3.5/fastembed/text/pooled_normalized_embedding.py +29 -19
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/text/text_embedding.py +4 -4
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/pyproject.toml +1 -1
- fastembed_gpu-0.3.3/fastembed/common/__init__.py +0 -3
- fastembed_gpu-0.3.3/fastembed/text/mini_lm_embedding.py +0 -58
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/LICENSE +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/__init__.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/common/onnx_model.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/common/utils.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/embedding.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/__init__.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/image_embedding_base.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/transform/functional.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/image/transform/operators.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/late_interaction/__init__.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/late_interaction/late_interaction_embedding_base.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/late_interaction/late_interaction_text_embedding.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/parallel_processor.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/__init__.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/sparse_embedding_base.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/sparse/utils/tokenizer.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/text/__init__.py +0 -0
- {fastembed_gpu-0.3.3 → fastembed_gpu-0.3.5}/fastembed/text/onnx_text_model.py +0 -0
- {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
|
+
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
|
|
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 [
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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 [
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
+
```
|
|
@@ -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(
|
|
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
|
-
|
|
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
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
69
|
-
"Please check the supported models using `
|
|
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": "
|
|
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": "
|
|
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
|
|
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[
|
|
57
|
+
def onnx_embed(self, images: List[ImageInput], **kwargs) -> OnnxOutputContext:
|
|
58
58
|
with contextlib.ExitStack():
|
|
59
|
-
image_files = [
|
|
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
|
|
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": ["
|
|
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(
|
|
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 / "
|
|
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
|
|
|
@@ -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": "
|
|
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
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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
|
-
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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
|
|
58
|
+
class PooledNormalizedEmbedding(PooledEmbedding):
|
|
39
59
|
@classmethod
|
|
40
60
|
def _get_worker_class(cls) -> Type[TextEmbeddingWorker]:
|
|
41
|
-
return
|
|
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
|
|
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
|
|
80
|
+
class PooledNormalizedEmbeddingWorker(OnnxTextEmbeddingWorker):
|
|
71
81
|
def init_embedding(
|
|
72
82
|
self, model_name: str, cache_dir: str, **kwargs
|
|
73
83
|
) -> OnnxTextEmbedding:
|
|
74
|
-
return
|
|
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.
|
|
9
|
-
from fastembed.text.
|
|
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
|
-
|
|
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
|
+
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,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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|