fastembed 0.3.2__tar.gz → 0.3.4__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-0.3.2 → fastembed-0.3.4}/PKG-INFO +3 -2
- {fastembed-0.3.2 → fastembed-0.3.4}/README.md +2 -2
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/common/model_management.py +40 -36
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/image/image_embedding.py +2 -2
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/image/onnx_embedding.py +29 -4
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/sparse/bm25.py +3 -2
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/sparse/bm42.py +1 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/text/onnx_embedding.py +6 -32
- fastembed-0.3.4/fastembed/text/pooled_embedding.py +87 -0
- fastembed-0.3.2/fastembed/text/jina_onnx_embedding.py → fastembed-0.3.4/fastembed/text/pooled_normalized_embedding.py +18 -16
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/text/text_embedding.py +4 -4
- {fastembed-0.3.2 → fastembed-0.3.4}/pyproject.toml +1 -1
- fastembed-0.3.2/fastembed/text/mini_lm_embedding.py +0 -58
- {fastembed-0.3.2 → fastembed-0.3.4}/LICENSE +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/__init__.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/common/__init__.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/common/onnx_model.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/common/preprocessor_utils.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/common/types.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/common/utils.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/embedding.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/image/__init__.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/image/image_embedding_base.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/image/onnx_image_model.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/image/transform/functional.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/image/transform/operators.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/late_interaction/__init__.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/late_interaction/colbert.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/late_interaction/late_interaction_embedding_base.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/late_interaction/late_interaction_text_embedding.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/parallel_processor.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/sparse/__init__.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/sparse/sparse_embedding_base.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/sparse/sparse_text_embedding.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/sparse/splade_pp.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/sparse/utils/tokenizer.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/text/__init__.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/text/clip_embedding.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/text/e5_onnx_embedding.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/text/onnx_text_model.py +0 -0
- {fastembed-0.3.2 → fastembed-0.3.4}/fastembed/text/text_embedding_base.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fastembed
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
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
|
|
@@ -43,7 +43,7 @@ The default text embedding (`TextEmbedding`) model is Flag Embedding, presented
|
|
|
43
43
|
|
|
44
44
|
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.
|
|
45
45
|
|
|
46
|
-
3. Accurate: FastEmbed is better than OpenAI Ada-002. We also [
|
|
46
|
+
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.
|
|
47
47
|
|
|
48
48
|
## 🚀 Installation
|
|
49
49
|
|
|
@@ -243,3 +243,4 @@ search_result = client.query(
|
|
|
243
243
|
)
|
|
244
244
|
print(search_result)
|
|
245
245
|
```
|
|
246
|
+
|
|
@@ -10,7 +10,7 @@ The default text embedding (`TextEmbedding`) model is Flag Embedding, presented
|
|
|
10
10
|
|
|
11
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
|
|
|
@@ -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
|
|
|
@@ -163,9 +160,7 @@ class ModelManagement:
|
|
|
163
160
|
return cache_dir
|
|
164
161
|
|
|
165
162
|
@classmethod
|
|
166
|
-
def retrieve_model_gcs(
|
|
167
|
-
cls, model_name: str, source_url: str, cache_dir: str
|
|
168
|
-
) -> Path:
|
|
163
|
+
def retrieve_model_gcs(cls, model_name: str, source_url: str, cache_dir: str) -> Path:
|
|
169
164
|
fast_model_name = f"fast-{model_name.split('/')[-1]}"
|
|
170
165
|
|
|
171
166
|
cache_tmp_dir = Path(cache_dir) / "tmp"
|
|
@@ -191,12 +186,8 @@ class ModelManagement:
|
|
|
191
186
|
output_path=str(model_tar_gz),
|
|
192
187
|
)
|
|
193
188
|
|
|
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}"
|
|
189
|
+
cls.decompress_to_cache(targz_path=str(model_tar_gz), cache_dir=str(cache_tmp_dir))
|
|
190
|
+
assert model_tmp_dir.exists(), f"Could not find {model_tmp_dir} in {cache_tmp_dir}"
|
|
200
191
|
|
|
201
192
|
model_tar_gz.unlink()
|
|
202
193
|
# Rename from tmp to final name is atomic
|
|
@@ -205,7 +196,7 @@ class ModelManagement:
|
|
|
205
196
|
return model_dir
|
|
206
197
|
|
|
207
198
|
@classmethod
|
|
208
|
-
def download_model(cls, model: Dict[str, Any], cache_dir: Path, **kwargs) -> Path:
|
|
199
|
+
def download_model(cls, model: Dict[str, Any], cache_dir: Path, retries=3, **kwargs) -> Path:
|
|
209
200
|
"""
|
|
210
201
|
Downloads a model from HuggingFace Hub or Google Cloud Storage.
|
|
211
202
|
|
|
@@ -225,6 +216,7 @@ class ModelManagement:
|
|
|
225
216
|
}
|
|
226
217
|
```
|
|
227
218
|
cache_dir (str): The path to the cache directory.
|
|
219
|
+
retries: (int): The number of times to retry (including the first attempt)
|
|
228
220
|
|
|
229
221
|
Returns:
|
|
230
222
|
Path: The path to the downloaded model directory.
|
|
@@ -233,26 +225,38 @@ class ModelManagement:
|
|
|
233
225
|
hf_source = model.get("sources", {}).get("hf")
|
|
234
226
|
url_source = model.get("sources", {}).get("url")
|
|
235
227
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
228
|
+
sleep = 3.0
|
|
229
|
+
while retries > 0:
|
|
230
|
+
retries -= 1
|
|
231
|
+
|
|
232
|
+
if hf_source:
|
|
233
|
+
extra_patterns = [model["model_file"]]
|
|
234
|
+
extra_patterns.extend(model.get("additional_files", []))
|
|
235
|
+
|
|
236
|
+
try:
|
|
237
|
+
return Path(
|
|
238
|
+
cls.download_files_from_huggingface(
|
|
239
|
+
hf_source,
|
|
240
|
+
cache_dir=str(cache_dir),
|
|
241
|
+
extra_patterns=extra_patterns,
|
|
242
|
+
local_files_only=kwargs.get("local_files_only", False),
|
|
243
|
+
)
|
|
247
244
|
)
|
|
248
|
-
)
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
245
|
+
except (EnvironmentError, RepositoryNotFoundError, ValueError) as e:
|
|
246
|
+
logger.error(
|
|
247
|
+
f"Could not download model from HuggingFace: {e} "
|
|
248
|
+
"Falling back to other sources."
|
|
249
|
+
)
|
|
250
|
+
if url_source:
|
|
251
|
+
try:
|
|
252
|
+
return cls.retrieve_model_gcs(model["model"], url_source, str(cache_dir))
|
|
253
|
+
except Exception:
|
|
254
|
+
logger.error(f"Could not download model from url: {url_source}")
|
|
255
|
+
|
|
256
|
+
logger.error(
|
|
257
|
+
f"Could not download model from either source, sleeping for {sleep} seconds, {retries} retries left."
|
|
258
|
+
)
|
|
259
|
+
time.sleep(sleep)
|
|
260
|
+
sleep *= 3
|
|
257
261
|
|
|
258
262
|
raise ValueError(f"Could not download model {model['model']} from any source.")
|
|
@@ -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(
|
|
@@ -29,9 +29,28 @@ supported_onnx_models = [
|
|
|
29
29
|
},
|
|
30
30
|
"model_file": "model.onnx",
|
|
31
31
|
},
|
|
32
|
+
{
|
|
33
|
+
"model": "Qdrant/Unicom-ViT-B-16",
|
|
34
|
+
"dim": 768,
|
|
35
|
+
"description": "Unicom Unicom-ViT-B-16 from open-metric-learning",
|
|
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": "Unicom Unicom-ViT-B-32 from open-metric-learning",
|
|
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
|
-
|
|
35
54
|
class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[np.ndarray]):
|
|
36
55
|
def __init__(
|
|
37
56
|
self,
|
|
@@ -122,10 +141,16 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[np.ndarray]):
|
|
|
122
141
|
|
|
123
142
|
return onnx_input
|
|
124
143
|
|
|
125
|
-
def _post_process_onnx_output(
|
|
144
|
+
def _post_process_onnx_output(
|
|
145
|
+
self, output: OnnxOutputContext
|
|
146
|
+
) -> Iterable[np.ndarray]:
|
|
126
147
|
return normalize(output.model_output).astype(np.float32)
|
|
127
148
|
|
|
128
149
|
|
|
129
150
|
class OnnxImageEmbeddingWorker(ImageEmbeddingWorker):
|
|
130
|
-
def init_embedding(
|
|
131
|
-
|
|
151
|
+
def init_embedding(
|
|
152
|
+
self, model_name: str, cache_dir: str, **kwargs
|
|
153
|
+
) -> OnnxImageEmbedding:
|
|
154
|
+
return OnnxImageEmbedding(
|
|
155
|
+
model_name=model_name, cache_dir=cache_dir, threads=1, **kwargs
|
|
156
|
+
)
|
|
@@ -27,6 +27,7 @@ supported_bm25_models = [
|
|
|
27
27
|
},
|
|
28
28
|
"model_file": "mock.file", # bm25 does not require a model, so we just use a mock
|
|
29
29
|
"additional_files": ["stopwords.txt"],
|
|
30
|
+
"requires_idf": True,
|
|
30
31
|
},
|
|
31
32
|
]
|
|
32
33
|
|
|
@@ -250,8 +251,8 @@ class Bm25(SparseTextEmbeddingBase):
|
|
|
250
251
|
tokens = self.tokenizer.tokenize(text)
|
|
251
252
|
stemmed_tokens = self._stem(tokens)
|
|
252
253
|
token_ids = np.array(
|
|
253
|
-
|
|
254
|
-
dtype=np.
|
|
254
|
+
list(set(self.compute_token_id(token) for token in stemmed_tokens)),
|
|
255
|
+
dtype=np.int32,
|
|
255
256
|
)
|
|
256
257
|
values = np.ones_like(token_ids)
|
|
257
258
|
yield SparseEmbedding(indices=token_ids, values=values)
|
|
@@ -80,36 +80,6 @@ supported_onnx_models = [
|
|
|
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,
|
|
@@ -274,7 +244,9 @@ class OnnxTextEmbedding(TextEmbeddingBase, OnnxTextModel[np.ndarray]):
|
|
|
274
244
|
"""
|
|
275
245
|
return onnx_input
|
|
276
246
|
|
|
277
|
-
def _post_process_onnx_output(
|
|
247
|
+
def _post_process_onnx_output(
|
|
248
|
+
self, output: OnnxOutputContext
|
|
249
|
+
) -> Iterable[np.ndarray]:
|
|
278
250
|
embeddings = output.model_output
|
|
279
251
|
return normalize(embeddings[:, 0]).astype(np.float32)
|
|
280
252
|
|
|
@@ -286,4 +258,6 @@ class OnnxTextEmbeddingWorker(TextEmbeddingWorker):
|
|
|
286
258
|
cache_dir: str,
|
|
287
259
|
**kwargs,
|
|
288
260
|
) -> OnnxTextEmbedding:
|
|
289
|
-
return OnnxTextEmbedding(
|
|
261
|
+
return OnnxTextEmbedding(
|
|
262
|
+
model_name=model_name, cache_dir=cache_dir, threads=1, **kwargs
|
|
263
|
+
)
|
|
@@ -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": "8192 context length english model",
|
|
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": "Quantized 8192 context length english model",
|
|
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": "8192 context length english model",
|
|
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,8 +6,20 @@ 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": "Sentence Transformer model, MiniLM-L6-v2",
|
|
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,
|
|
@@ -35,20 +47,10 @@ supported_jina_models = [
|
|
|
35
47
|
]
|
|
36
48
|
|
|
37
49
|
|
|
38
|
-
class
|
|
50
|
+
class PooledNormalizedEmbedding(PooledEmbedding):
|
|
39
51
|
@classmethod
|
|
40
52
|
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
|
|
53
|
+
return PooledNormalizedEmbeddingWorker
|
|
52
54
|
|
|
53
55
|
@classmethod
|
|
54
56
|
def list_supported_models(cls) -> List[Dict[str, Any]]:
|
|
@@ -57,7 +59,7 @@ class JinaOnnxEmbedding(OnnxTextEmbedding):
|
|
|
57
59
|
Returns:
|
|
58
60
|
List[Dict[str, Any]]: A list of dictionaries containing the model information.
|
|
59
61
|
"""
|
|
60
|
-
return
|
|
62
|
+
return supported_pooled_normalized_models
|
|
61
63
|
|
|
62
64
|
def _post_process_onnx_output(
|
|
63
65
|
self, output: OnnxOutputContext
|
|
@@ -67,10 +69,10 @@ class JinaOnnxEmbedding(OnnxTextEmbedding):
|
|
|
67
69
|
return normalize(self.mean_pooling(embeddings, attn_mask)).astype(np.float32)
|
|
68
70
|
|
|
69
71
|
|
|
70
|
-
class
|
|
72
|
+
class PooledNormalizedEmbeddingWorker(OnnxTextEmbeddingWorker):
|
|
71
73
|
def init_embedding(
|
|
72
74
|
self, model_name: str, cache_dir: str, **kwargs
|
|
73
75
|
) -> OnnxTextEmbedding:
|
|
74
|
-
return
|
|
76
|
+
return PooledNormalizedEmbedding(
|
|
75
77
|
model_name=model_name, cache_dir=cache_dir, threads=1, **kwargs
|
|
76
78
|
)
|
|
@@ -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"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.4"
|
|
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
|
{fastembed-0.3.2 → fastembed-0.3.4}/fastembed/late_interaction/late_interaction_embedding_base.py
RENAMED
|
File without changes
|
{fastembed-0.3.2 → fastembed-0.3.4}/fastembed/late_interaction/late_interaction_text_embedding.py
RENAMED
|
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
|