fastembed-gpu 0.3.0__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/PKG-INFO +97 -7
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/README.md +94 -4
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/__init__.py +2 -2
- fastembed_gpu-0.3.2/fastembed/common/__init__.py +3 -0
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/common/model_management.py +21 -8
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/common/onnx_model.py +19 -9
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/common/preprocessor_utils.py +4 -2
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/common/types.py +1 -1
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/common/utils.py +1 -1
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/image/__init__.py +0 -1
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/image/image_embedding.py +10 -3
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/image/image_embedding_base.py +5 -0
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/image/onnx_embedding.py +9 -12
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/image/onnx_image_model.py +15 -14
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/image/transform/functional.py +2 -3
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/image/transform/operators.py +70 -40
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/late_interaction/__init__.py +3 -2
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/late_interaction/colbert.py +9 -11
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/late_interaction/late_interaction_embedding_base.py +3 -1
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/late_interaction/late_interaction_text_embedding.py +9 -4
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/parallel_processor.py +6 -2
- fastembed_gpu-0.3.2/fastembed/sparse/bm25.py +284 -0
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/sparse/bm42.py +33 -22
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/sparse/sparse_embedding_base.py +18 -12
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/sparse/sparse_text_embedding.py +19 -9
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/sparse/splade_pp.py +10 -14
- fastembed_gpu-0.3.2/fastembed/sparse/utils/tokenizer.py +113 -0
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/text/clip_embedding.py +5 -5
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/text/e5_onnx_embedding.py +8 -6
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/text/jina_onnx_embedding.py +13 -5
- fastembed_gpu-0.3.2/fastembed/text/mini_lm_embedding.py +58 -0
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/text/onnx_embedding.py +8 -18
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/text/onnx_text_model.py +11 -8
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/text/text_embedding.py +12 -3
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/text/text_embedding_base.py +3 -1
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/pyproject.toml +3 -3
- fastembed_gpu-0.3.0/fastembed/common/__init__.py +0 -3
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/LICENSE +0 -0
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/embedding.py +0 -0
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/sparse/__init__.py +0 -0
- {fastembed_gpu-0.3.0 → fastembed_gpu-0.3.2}/fastembed/text/__init__.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.2
|
|
4
4
|
Summary: Fast, light, accurate library built for retrieval embedding generation
|
|
5
5
|
Home-page: https://github.com/qdrant/fastembed
|
|
6
6
|
License: Apache License
|
|
@@ -19,8 +19,8 @@ Requires-Dist: PyStemmer (>=2.2.0,<3.0.0)
|
|
|
19
19
|
Requires-Dist: huggingface-hub (>=0.20,<1.0)
|
|
20
20
|
Requires-Dist: loguru (>=0.7.2,<0.8.0)
|
|
21
21
|
Requires-Dist: mmh3 (>=4.0,<5.0)
|
|
22
|
-
Requires-Dist: numpy (>=1.21) ; python_version < "3.12"
|
|
23
|
-
Requires-Dist: numpy (>=1.26) ; python_version >= "3.12"
|
|
22
|
+
Requires-Dist: numpy (>=1.21,<2) ; python_version < "3.12"
|
|
23
|
+
Requires-Dist: numpy (>=1.26,<2) ; python_version >= "3.12"
|
|
24
24
|
Requires-Dist: onnxruntime-gpu (>=1.17.0,<2.0.0)
|
|
25
25
|
Requires-Dist: pillow (>=10.3.0,<11.0.0)
|
|
26
26
|
Requires-Dist: requests (>=2.31,<3.0)
|
|
@@ -50,11 +50,9 @@ To install the FastEmbed library, pip works best. You can install it with or wit
|
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
52
|
pip install fastembed
|
|
53
|
-
```
|
|
54
53
|
|
|
55
|
-
|
|
54
|
+
# or with GPU support
|
|
56
55
|
|
|
57
|
-
```bash
|
|
58
56
|
pip install fastembed-gpu
|
|
59
57
|
```
|
|
60
58
|
|
|
@@ -80,7 +78,99 @@ embeddings_list = list(embedding_model.embed(documents))
|
|
|
80
78
|
len(embeddings_list[0]) # Vector of 384 dimensions
|
|
81
79
|
```
|
|
82
80
|
|
|
83
|
-
|
|
81
|
+
Fastembed supports a variety of models for different tasks and modalities.
|
|
82
|
+
The list of all the available models can be found [here](https://qdrant.github.io/fastembed/examples/Supported_Models/)
|
|
83
|
+
### 🎒 Dense text embeddings
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from fastembed import TextEmbedding
|
|
87
|
+
|
|
88
|
+
model = TextEmbedding(model_name="BAAI/bge-small-en-v1.5")
|
|
89
|
+
embeddings = list(embedding_model.embed(documents))
|
|
90
|
+
|
|
91
|
+
# [
|
|
92
|
+
# array([-0.1115, 0.0097, 0.0052, 0.0195, ...], dtype=float32),
|
|
93
|
+
# array([-0.1019, 0.0635, -0.0332, 0.0522, ...], dtype=float32)
|
|
94
|
+
# ]
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
### 🔱 Sparse text embeddings
|
|
101
|
+
|
|
102
|
+
* SPLADE++
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from fastembed import SparseTextEmbedding
|
|
106
|
+
|
|
107
|
+
model = SparseTextEmbedding(model_name="prithivida/Splade_PP_en_v1")
|
|
108
|
+
embeddings = list(embedding_model.embed(documents))
|
|
109
|
+
|
|
110
|
+
# [
|
|
111
|
+
# SparseEmbedding(indices=[ 17, 123, 919, ... ], values=[0.71, 0.22, 0.39, ...]),
|
|
112
|
+
# SparseEmbedding(indices=[ 38, 12, 91, ... ], values=[0.11, 0.22, 0.39, ...])
|
|
113
|
+
# ]
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
<!--
|
|
117
|
+
* BM42 - ([link](ToDo))
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
from fastembed import SparseTextEmbedding
|
|
121
|
+
|
|
122
|
+
model = SparseTextEmbedding(model_name="Qdrant/bm42-all-minilm-l6-v2-attentions")
|
|
123
|
+
embeddings = list(embedding_model.embed(documents))
|
|
124
|
+
|
|
125
|
+
# [
|
|
126
|
+
# SparseEmbedding(indices=[ 17, 123, 919, ... ], values=[0.71, 0.22, 0.39, ...]),
|
|
127
|
+
# SparseEmbedding(indices=[ 38, 12, 91, ... ], values=[0.11, 0.22, 0.39, ...])
|
|
128
|
+
# ]
|
|
129
|
+
```
|
|
130
|
+
-->
|
|
131
|
+
|
|
132
|
+
### 🦥 Late interaction models (aka ColBERT)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from fastembed import LateInteractionTextEmbedding
|
|
137
|
+
|
|
138
|
+
model = LateInteractionTextEmbedding(model_name="colbert-ir/colbertv2.0")
|
|
139
|
+
embeddings = list(embedding_model.embed(documents))
|
|
140
|
+
|
|
141
|
+
# [
|
|
142
|
+
# array([
|
|
143
|
+
# [-0.1115, 0.0097, 0.0052, 0.0195, ...],
|
|
144
|
+
# [-0.1019, 0.0635, -0.0332, 0.0522, ...],
|
|
145
|
+
# ]),
|
|
146
|
+
# array([
|
|
147
|
+
# [-0.9019, 0.0335, -0.0032, 0.0991, ...],
|
|
148
|
+
# [-0.2115, 0.8097, 0.1052, 0.0195, ...],
|
|
149
|
+
# ]),
|
|
150
|
+
# ]
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 🖼️ Image embeddings
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
from fastembed import ImageEmbedding
|
|
157
|
+
|
|
158
|
+
images = [
|
|
159
|
+
"./path/to/image1.jpg",
|
|
160
|
+
"./path/to/image2.jpg",
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
model = ImageEmbedding(model_name="Qdrant/clip-ViT-B-32-vision")
|
|
164
|
+
embeddings = list(embedding_model.embed(images))
|
|
165
|
+
|
|
166
|
+
# [
|
|
167
|
+
# array([-0.1115, 0.0097, 0.0052, 0.0195, ...], dtype=float32),
|
|
168
|
+
# array([-0.1019, 0.0635, -0.0332, 0.0522, ...], dtype=float32)
|
|
169
|
+
# ]
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
## ⚡️ FastEmbed on a GPU
|
|
84
174
|
|
|
85
175
|
FastEmbed supports running on GPU devices.
|
|
86
176
|
It requires installation of the `fastembed-gpu` package.
|
|
@@ -18,11 +18,9 @@ To install the FastEmbed library, pip works best. You can install it with or wit
|
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
20
|
pip install fastembed
|
|
21
|
-
```
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
# or with GPU support
|
|
24
23
|
|
|
25
|
-
```bash
|
|
26
24
|
pip install fastembed-gpu
|
|
27
25
|
```
|
|
28
26
|
|
|
@@ -48,7 +46,99 @@ embeddings_list = list(embedding_model.embed(documents))
|
|
|
48
46
|
len(embeddings_list[0]) # Vector of 384 dimensions
|
|
49
47
|
```
|
|
50
48
|
|
|
51
|
-
|
|
49
|
+
Fastembed supports a variety of models for different tasks and modalities.
|
|
50
|
+
The list of all the available models can be found [here](https://qdrant.github.io/fastembed/examples/Supported_Models/)
|
|
51
|
+
### 🎒 Dense text embeddings
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from fastembed import TextEmbedding
|
|
55
|
+
|
|
56
|
+
model = TextEmbedding(model_name="BAAI/bge-small-en-v1.5")
|
|
57
|
+
embeddings = list(embedding_model.embed(documents))
|
|
58
|
+
|
|
59
|
+
# [
|
|
60
|
+
# array([-0.1115, 0.0097, 0.0052, 0.0195, ...], dtype=float32),
|
|
61
|
+
# array([-0.1019, 0.0635, -0.0332, 0.0522, ...], dtype=float32)
|
|
62
|
+
# ]
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
### 🔱 Sparse text embeddings
|
|
69
|
+
|
|
70
|
+
* SPLADE++
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from fastembed import SparseTextEmbedding
|
|
74
|
+
|
|
75
|
+
model = SparseTextEmbedding(model_name="prithivida/Splade_PP_en_v1")
|
|
76
|
+
embeddings = list(embedding_model.embed(documents))
|
|
77
|
+
|
|
78
|
+
# [
|
|
79
|
+
# SparseEmbedding(indices=[ 17, 123, 919, ... ], values=[0.71, 0.22, 0.39, ...]),
|
|
80
|
+
# SparseEmbedding(indices=[ 38, 12, 91, ... ], values=[0.11, 0.22, 0.39, ...])
|
|
81
|
+
# ]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
<!--
|
|
85
|
+
* BM42 - ([link](ToDo))
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
from fastembed import SparseTextEmbedding
|
|
89
|
+
|
|
90
|
+
model = SparseTextEmbedding(model_name="Qdrant/bm42-all-minilm-l6-v2-attentions")
|
|
91
|
+
embeddings = list(embedding_model.embed(documents))
|
|
92
|
+
|
|
93
|
+
# [
|
|
94
|
+
# SparseEmbedding(indices=[ 17, 123, 919, ... ], values=[0.71, 0.22, 0.39, ...]),
|
|
95
|
+
# SparseEmbedding(indices=[ 38, 12, 91, ... ], values=[0.11, 0.22, 0.39, ...])
|
|
96
|
+
# ]
|
|
97
|
+
```
|
|
98
|
+
-->
|
|
99
|
+
|
|
100
|
+
### 🦥 Late interaction models (aka ColBERT)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from fastembed import LateInteractionTextEmbedding
|
|
105
|
+
|
|
106
|
+
model = LateInteractionTextEmbedding(model_name="colbert-ir/colbertv2.0")
|
|
107
|
+
embeddings = list(embedding_model.embed(documents))
|
|
108
|
+
|
|
109
|
+
# [
|
|
110
|
+
# array([
|
|
111
|
+
# [-0.1115, 0.0097, 0.0052, 0.0195, ...],
|
|
112
|
+
# [-0.1019, 0.0635, -0.0332, 0.0522, ...],
|
|
113
|
+
# ]),
|
|
114
|
+
# array([
|
|
115
|
+
# [-0.9019, 0.0335, -0.0032, 0.0991, ...],
|
|
116
|
+
# [-0.2115, 0.8097, 0.1052, 0.0195, ...],
|
|
117
|
+
# ]),
|
|
118
|
+
# ]
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 🖼️ Image embeddings
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from fastembed import ImageEmbedding
|
|
125
|
+
|
|
126
|
+
images = [
|
|
127
|
+
"./path/to/image1.jpg",
|
|
128
|
+
"./path/to/image2.jpg",
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
model = ImageEmbedding(model_name="Qdrant/clip-ViT-B-32-vision")
|
|
132
|
+
embeddings = list(embedding_model.embed(images))
|
|
133
|
+
|
|
134
|
+
# [
|
|
135
|
+
# array([-0.1115, 0.0097, 0.0052, 0.0195, ...], dtype=float32),
|
|
136
|
+
# array([-0.1019, 0.0635, -0.0332, 0.0522, ...], dtype=float32)
|
|
137
|
+
# ]
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
## ⚡️ FastEmbed on a GPU
|
|
52
142
|
|
|
53
143
|
FastEmbed supports running on GPU devices.
|
|
54
144
|
It requires installation of the `fastembed-gpu` package.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import importlib.metadata
|
|
2
2
|
|
|
3
3
|
from fastembed.image import ImageEmbedding
|
|
4
|
-
from fastembed.text import TextEmbedding
|
|
5
|
-
from fastembed.sparse import SparseTextEmbedding, SparseEmbedding
|
|
6
4
|
from fastembed.late_interaction import LateInteractionTextEmbedding
|
|
5
|
+
from fastembed.sparse import SparseEmbedding, SparseTextEmbedding
|
|
6
|
+
from fastembed.text import TextEmbedding
|
|
7
7
|
|
|
8
8
|
try:
|
|
9
9
|
version = importlib.metadata.version("fastembed")
|
|
@@ -2,13 +2,13 @@ import os
|
|
|
2
2
|
import shutil
|
|
3
3
|
import tarfile
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Any, Dict, List, Optional
|
|
6
6
|
|
|
7
7
|
import requests
|
|
8
8
|
from huggingface_hub import snapshot_download
|
|
9
9
|
from huggingface_hub.utils import RepositoryNotFoundError
|
|
10
|
-
from tqdm import tqdm
|
|
11
10
|
from loguru import logger
|
|
11
|
+
from tqdm import tqdm
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class ModelManagement:
|
|
@@ -42,7 +42,9 @@ class ModelManagement:
|
|
|
42
42
|
raise ValueError(f"Model {model_name} is not supported in {cls.__name__}.")
|
|
43
43
|
|
|
44
44
|
@classmethod
|
|
45
|
-
def download_file_from_gcs(
|
|
45
|
+
def download_file_from_gcs(
|
|
46
|
+
cls, url: str, output_path: str, show_progress: bool = True
|
|
47
|
+
) -> str:
|
|
46
48
|
"""
|
|
47
49
|
Downloads a file from Google Cloud Storage.
|
|
48
50
|
|
|
@@ -71,12 +73,17 @@ class ModelManagement:
|
|
|
71
73
|
|
|
72
74
|
# Warn if the total size is zero
|
|
73
75
|
if total_size_in_bytes == 0:
|
|
74
|
-
print(
|
|
76
|
+
print(
|
|
77
|
+
f"Warning: Content-length header is missing or zero in the response from {url}."
|
|
78
|
+
)
|
|
75
79
|
|
|
76
80
|
show_progress = total_size_in_bytes and show_progress
|
|
77
81
|
|
|
78
82
|
with tqdm(
|
|
79
|
-
total=total_size_in_bytes,
|
|
83
|
+
total=total_size_in_bytes,
|
|
84
|
+
unit="iB",
|
|
85
|
+
unit_scale=True,
|
|
86
|
+
disable=not show_progress,
|
|
80
87
|
) as progress_bar:
|
|
81
88
|
with open(output_path, "wb") as file:
|
|
82
89
|
for chunk in response.iter_content(chunk_size=1024):
|
|
@@ -156,7 +163,9 @@ class ModelManagement:
|
|
|
156
163
|
return cache_dir
|
|
157
164
|
|
|
158
165
|
@classmethod
|
|
159
|
-
def retrieve_model_gcs(
|
|
166
|
+
def retrieve_model_gcs(
|
|
167
|
+
cls, model_name: str, source_url: str, cache_dir: str
|
|
168
|
+
) -> Path:
|
|
160
169
|
fast_model_name = f"fast-{model_name.split('/')[-1]}"
|
|
161
170
|
|
|
162
171
|
cache_tmp_dir = Path(cache_dir) / "tmp"
|
|
@@ -182,8 +191,12 @@ class ModelManagement:
|
|
|
182
191
|
output_path=str(model_tar_gz),
|
|
183
192
|
)
|
|
184
193
|
|
|
185
|
-
cls.decompress_to_cache(
|
|
186
|
-
|
|
194
|
+
cls.decompress_to_cache(
|
|
195
|
+
targz_path=str(model_tar_gz), cache_dir=str(cache_tmp_dir)
|
|
196
|
+
)
|
|
197
|
+
assert (
|
|
198
|
+
model_tmp_dir.exists()
|
|
199
|
+
), f"Could not find {model_tmp_dir} in {cache_tmp_dir}"
|
|
187
200
|
|
|
188
201
|
model_tar_gz.unlink()
|
|
189
202
|
# Rename from tmp to final name is atomic
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
import warnings
|
|
1
2
|
from dataclasses import dataclass
|
|
2
3
|
from pathlib import Path
|
|
3
|
-
from typing import
|
|
4
|
-
|
|
4
|
+
from typing import (
|
|
5
|
+
Any,
|
|
6
|
+
Dict,
|
|
7
|
+
Generic,
|
|
8
|
+
Iterable,
|
|
9
|
+
Optional,
|
|
10
|
+
Sequence,
|
|
11
|
+
Tuple,
|
|
12
|
+
Type,
|
|
13
|
+
TypeVar,
|
|
14
|
+
)
|
|
5
15
|
|
|
6
16
|
import numpy as np
|
|
7
17
|
import onnxruntime as ort
|
|
@@ -9,7 +19,6 @@ import onnxruntime as ort
|
|
|
9
19
|
from fastembed.common.types import OnnxProvider
|
|
10
20
|
from fastembed.parallel_processor import Worker
|
|
11
21
|
|
|
12
|
-
|
|
13
22
|
# Holds type of the embedding result
|
|
14
23
|
T = TypeVar("T")
|
|
15
24
|
|
|
@@ -51,7 +60,9 @@ class OnnxModel(Generic[T]):
|
|
|
51
60
|
model_path = model_dir / model_file
|
|
52
61
|
# List of Execution Providers: https://onnxruntime.ai/docs/execution-providers
|
|
53
62
|
|
|
54
|
-
onnx_providers =
|
|
63
|
+
onnx_providers = (
|
|
64
|
+
["CPUExecutionProvider"] if providers is None else list(providers)
|
|
65
|
+
)
|
|
55
66
|
available_providers = ort.get_available_providers()
|
|
56
67
|
requested_provider_names = []
|
|
57
68
|
for provider in onnx_providers:
|
|
@@ -92,6 +103,7 @@ class EmbeddingWorker(Worker):
|
|
|
92
103
|
self,
|
|
93
104
|
model_name: str,
|
|
94
105
|
cache_dir: str,
|
|
106
|
+
**kwargs,
|
|
95
107
|
) -> OnnxModel:
|
|
96
108
|
raise NotImplementedError()
|
|
97
109
|
|
|
@@ -99,15 +111,13 @@ class EmbeddingWorker(Worker):
|
|
|
99
111
|
self,
|
|
100
112
|
model_name: str,
|
|
101
113
|
cache_dir: str,
|
|
114
|
+
**kwargs,
|
|
102
115
|
):
|
|
103
|
-
self.model = self.init_embedding(model_name, cache_dir)
|
|
116
|
+
self.model = self.init_embedding(model_name, cache_dir, **kwargs)
|
|
104
117
|
|
|
105
118
|
@classmethod
|
|
106
119
|
def start(cls, model_name: str, cache_dir: str, **kwargs: Any) -> "EmbeddingWorker":
|
|
107
|
-
return cls(
|
|
108
|
-
model_name=model_name,
|
|
109
|
-
cache_dir=cache_dir,
|
|
110
|
-
)
|
|
120
|
+
return cls(model_name=model_name, cache_dir=cache_dir, **kwargs)
|
|
111
121
|
|
|
112
122
|
def process(self, items: Iterable[Tuple[int, Any]]) -> Iterable[Tuple[int, Any]]:
|
|
113
123
|
raise NotImplementedError("Subclasses must implement this method")
|
|
@@ -2,7 +2,7 @@ import json
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from typing import Tuple
|
|
4
4
|
|
|
5
|
-
from tokenizers import
|
|
5
|
+
from tokenizers import AddedToken, Tokenizer
|
|
6
6
|
|
|
7
7
|
from fastembed.image.transform.operators import Compose
|
|
8
8
|
|
|
@@ -40,7 +40,9 @@ def load_tokenizer(model_dir: Path, max_length: int = 512) -> Tuple[Tokenizer, d
|
|
|
40
40
|
tokens_map = load_special_tokens(model_dir)
|
|
41
41
|
|
|
42
42
|
tokenizer = Tokenizer.from_file(str(tokenizer_path))
|
|
43
|
-
tokenizer.enable_truncation(
|
|
43
|
+
tokenizer.enable_truncation(
|
|
44
|
+
max_length=min(tokenizer_config["model_max_length"], max_length)
|
|
45
|
+
)
|
|
44
46
|
tokenizer.enable_padding(
|
|
45
47
|
pad_id=config.get("pad_token_id", 0), pad_token=tokenizer_config["pad_token"]
|
|
46
48
|
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any, Dict, Iterable, List, Optional,
|
|
1
|
+
from typing import Any, Dict, Iterable, List, Optional, Sequence, Type
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
|
|
@@ -51,9 +51,16 @@ class ImageEmbedding(ImageEmbeddingBase):
|
|
|
51
51
|
|
|
52
52
|
for EMBEDDING_MODEL_TYPE in self.EMBEDDINGS_REGISTRY:
|
|
53
53
|
supported_models = EMBEDDING_MODEL_TYPE.list_supported_models()
|
|
54
|
-
if any(
|
|
54
|
+
if any(
|
|
55
|
+
model_name.lower() == model["model"].lower()
|
|
56
|
+
for model in supported_models
|
|
57
|
+
):
|
|
55
58
|
self.model = EMBEDDING_MODEL_TYPE(
|
|
56
|
-
model_name,
|
|
59
|
+
model_name,
|
|
60
|
+
cache_dir,
|
|
61
|
+
threads=threads,
|
|
62
|
+
providers=providers,
|
|
63
|
+
**kwargs,
|
|
57
64
|
)
|
|
58
65
|
return
|
|
59
66
|
|
|
@@ -31,6 +31,11 @@ class ImageEmbeddingBase(ModelManagement):
|
|
|
31
31
|
|
|
32
32
|
Args:
|
|
33
33
|
images - The list of image paths to preprocess and embed.
|
|
34
|
+
batch_size: Batch size for encoding
|
|
35
|
+
parallel:
|
|
36
|
+
If > 1, data-parallel encoding will be used, recommended for offline encoding of large datasets.
|
|
37
|
+
If 0, use all available cores.
|
|
38
|
+
If None, don't use data-parallel processing, use default onnxruntime threading instead.
|
|
34
39
|
**kwargs: Additional keyword argument to pass to the embed method.
|
|
35
40
|
|
|
36
41
|
Yields:
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Any, Dict, Iterable, List, Optional, Sequence, Type
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
|
|
5
|
-
from fastembed.common.onnx_model import OnnxOutputContext
|
|
6
|
-
from fastembed.common.utils import normalize, define_cache_dir
|
|
7
5
|
from fastembed.common import ImageInput, OnnxProvider
|
|
6
|
+
from fastembed.common.onnx_model import OnnxOutputContext
|
|
7
|
+
from fastembed.common.utils import define_cache_dir, normalize
|
|
8
8
|
from fastembed.image.image_embedding_base import ImageEmbeddingBase
|
|
9
|
-
from fastembed.image.onnx_image_model import
|
|
9
|
+
from fastembed.image.onnx_image_model import ImageEmbeddingWorker, OnnxImageModel
|
|
10
10
|
|
|
11
11
|
supported_onnx_models = [
|
|
12
12
|
{
|
|
@@ -56,9 +56,9 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[np.ndarray]):
|
|
|
56
56
|
super().__init__(model_name, cache_dir, threads, **kwargs)
|
|
57
57
|
|
|
58
58
|
model_description = self._get_model_description(model_name)
|
|
59
|
-
cache_dir = define_cache_dir(cache_dir)
|
|
59
|
+
self.cache_dir = define_cache_dir(cache_dir)
|
|
60
60
|
model_dir = self.download_model(
|
|
61
|
-
model_description, cache_dir, local_files_only=self._local_files_only
|
|
61
|
+
model_description, self.cache_dir, local_files_only=self._local_files_only
|
|
62
62
|
)
|
|
63
63
|
|
|
64
64
|
self.load_onnx_model(
|
|
@@ -106,6 +106,7 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[np.ndarray]):
|
|
|
106
106
|
images=images,
|
|
107
107
|
batch_size=batch_size,
|
|
108
108
|
parallel=parallel,
|
|
109
|
+
**kwargs,
|
|
109
110
|
)
|
|
110
111
|
|
|
111
112
|
@classmethod
|
|
@@ -126,9 +127,5 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[np.ndarray]):
|
|
|
126
127
|
|
|
127
128
|
|
|
128
129
|
class OnnxImageEmbeddingWorker(ImageEmbeddingWorker):
|
|
129
|
-
def init_embedding(
|
|
130
|
-
|
|
131
|
-
model_name: str,
|
|
132
|
-
cache_dir: str,
|
|
133
|
-
) -> OnnxImageEmbedding:
|
|
134
|
-
return OnnxImageEmbedding(model_name=model_name, cache_dir=cache_dir, threads=1)
|
|
130
|
+
def init_embedding(self, model_name: str, cache_dir: str, **kwargs) -> OnnxImageEmbedding:
|
|
131
|
+
return OnnxImageEmbedding(model_name=model_name, cache_dir=cache_dir, threads=1, **kwargs)
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import contextlib
|
|
2
|
+
import os
|
|
3
3
|
from multiprocessing import get_all_start_methods
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Any, Dict, Iterable, List, Optional, Tuple, Type
|
|
5
|
+
from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Type
|
|
6
6
|
|
|
7
|
-
from PIL import Image
|
|
8
7
|
import numpy as np
|
|
8
|
+
from PIL import Image
|
|
9
9
|
|
|
10
|
+
from fastembed.common import ImageInput, OnnxProvider, PathInput
|
|
11
|
+
from fastembed.common.onnx_model import EmbeddingWorker, OnnxModel, OnnxOutputContext, T
|
|
10
12
|
from fastembed.common.preprocessor_utils import load_preprocessor
|
|
11
|
-
from fastembed.common.onnx_model import OnnxModel, EmbeddingWorker, T, OnnxOutputContext
|
|
12
|
-
from fastembed.common import PathInput, ImageInput, OnnxProvider
|
|
13
13
|
from fastembed.common.utils import iter_batch
|
|
14
14
|
from fastembed.parallel_processor import ParallelWorkerPool
|
|
15
15
|
|
|
@@ -44,7 +44,10 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
44
44
|
providers: Optional[Sequence[OnnxProvider]] = None,
|
|
45
45
|
) -> None:
|
|
46
46
|
super().load_onnx_model(
|
|
47
|
-
model_dir=model_dir,
|
|
47
|
+
model_dir=model_dir,
|
|
48
|
+
model_file=model_file,
|
|
49
|
+
threads=threads,
|
|
50
|
+
providers=providers,
|
|
48
51
|
)
|
|
49
52
|
self.processor = load_preprocessor(model_dir=model_dir)
|
|
50
53
|
|
|
@@ -59,9 +62,7 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
59
62
|
onnx_input = self._preprocess_onnx_input(onnx_input)
|
|
60
63
|
model_output = self.model.run(None, onnx_input)
|
|
61
64
|
embeddings = model_output[0].reshape(len(images), -1)
|
|
62
|
-
return OnnxOutputContext(
|
|
63
|
-
model_output=embeddings
|
|
64
|
-
)
|
|
65
|
+
return OnnxOutputContext(model_output=embeddings)
|
|
65
66
|
|
|
66
67
|
def _embed_images(
|
|
67
68
|
self,
|
|
@@ -70,6 +71,7 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
70
71
|
images: ImageInput,
|
|
71
72
|
batch_size: int = 256,
|
|
72
73
|
parallel: Optional[int] = None,
|
|
74
|
+
**kwargs,
|
|
73
75
|
) -> Iterable[T]:
|
|
74
76
|
is_small = False
|
|
75
77
|
|
|
@@ -88,11 +90,10 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
88
90
|
for batch in iter_batch(images, batch_size):
|
|
89
91
|
yield from self._post_process_onnx_output(self.onnx_embed(batch))
|
|
90
92
|
else:
|
|
91
|
-
start_method =
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
93
|
+
start_method = (
|
|
94
|
+
"forkserver" if "forkserver" in get_all_start_methods() else "spawn"
|
|
95
|
+
)
|
|
96
|
+
params = {"model_name": model_name, "cache_dir": cache_dir, **kwargs}
|
|
96
97
|
pool = ParallelWorkerPool(
|
|
97
98
|
parallel, self._get_worker_class(), start_method=start_method
|
|
98
99
|
)
|