fastembed-gpu 0.4.2__tar.gz → 0.5.0__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.4.2 → fastembed_gpu-0.5.0}/PKG-INFO +14 -11
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/README.md +3 -4
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/common/model_management.py +23 -11
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/common/onnx_model.py +11 -4
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/common/preprocessor_utils.py +2 -2
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/common/types.py +2 -2
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/common/utils.py +6 -6
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/image/image_embedding.py +5 -5
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/image/onnx_embedding.py +18 -7
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/image/onnx_image_model.py +7 -7
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/image/transform/functional.py +34 -8
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/image/transform/operators.py +99 -29
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/late_interaction/colbert.py +13 -10
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/late_interaction/jina_colbert.py +5 -5
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/late_interaction/late_interaction_text_embedding.py +5 -5
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/parallel_processor.py +8 -7
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/rerank/cross_encoder/onnx_text_cross_encoder.py +57 -10
- fastembed_gpu-0.5.0/fastembed/rerank/cross_encoder/onnx_text_model.py +150 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/rerank/cross_encoder/text_cross_encoder.py +42 -9
- fastembed_gpu-0.5.0/fastembed/rerank/cross_encoder/text_cross_encoder_base.py +58 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/sparse/bm25.py +29 -15
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/sparse/bm42.py +14 -14
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/sparse/sparse_embedding_base.py +6 -10
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/sparse/sparse_text_embedding.py +5 -5
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/sparse/splade_pp.py +5 -5
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/sparse/utils/tokenizer.py +2 -3
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/text/clip_embedding.py +3 -3
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/text/e5_onnx_embedding.py +5 -5
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/text/onnx_embedding.py +28 -8
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/text/onnx_text_model.py +8 -9
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/text/pooled_embedding.py +3 -3
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/text/pooled_normalized_embedding.py +30 -3
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/text/text_embedding.py +6 -6
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/pyproject.toml +15 -9
- fastembed_gpu-0.4.2/fastembed/rerank/cross_encoder/onnx_text_model.py +0 -70
- fastembed_gpu-0.4.2/fastembed/rerank/cross_encoder/text_cross_encoder_base.py +0 -37
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/LICENSE +0 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/NOTICE +0 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/__init__.py +0 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/common/__init__.py +0 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/embedding.py +0 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/image/__init__.py +0 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/image/image_embedding_base.py +0 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/late_interaction/__init__.py +0 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/late_interaction/late_interaction_embedding_base.py +0 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/rerank/cross_encoder/__init__.py +0 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/sparse/__init__.py +0 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/text/__init__.py +0 -0
- {fastembed_gpu-0.4.2 → fastembed_gpu-0.5.0}/fastembed/text/text_embedding_base.py +0 -0
|
@@ -1,27 +1,31 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fastembed-gpu
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
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
|
|
7
7
|
Keywords: vector,embedding,neural,search,qdrant,sentence-transformers
|
|
8
8
|
Author: Qdrant Team
|
|
9
9
|
Author-email: info@qdrant.tech
|
|
10
|
-
Requires-Python: >=3.
|
|
10
|
+
Requires-Python: >=3.9.0
|
|
11
11
|
Classifier: License :: Other/Proprietary License
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.9
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
18
|
Requires-Dist: huggingface-hub (>=0.20,<1.0)
|
|
19
19
|
Requires-Dist: loguru (>=0.7.2,<0.8.0)
|
|
20
20
|
Requires-Dist: mmh3 (>=4.1.0,<5.0.0)
|
|
21
|
-
Requires-Dist: numpy (>=1.21) ; python_version < "3.12"
|
|
22
|
-
Requires-Dist: numpy (>=1.
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist:
|
|
21
|
+
Requires-Dist: numpy (>=1.21) ; python_version >= "3.10" and python_version < "3.12"
|
|
22
|
+
Requires-Dist: numpy (>=1.21,<2.1.0) ; python_version < "3.10"
|
|
23
|
+
Requires-Dist: numpy (>=1.26) ; python_version >= "3.12" and python_version < "3.13"
|
|
24
|
+
Requires-Dist: numpy (>=2.1.0) ; python_version >= "3.13"
|
|
25
|
+
Requires-Dist: onnx (>=1.15.0)
|
|
26
|
+
Requires-Dist: onnxruntime-gpu (>1.20.0) ; python_version >= "3.13"
|
|
27
|
+
Requires-Dist: onnxruntime-gpu (>=1.17.0,!=1.20.0) ; python_version >= "3.10" and python_version < "3.13"
|
|
28
|
+
Requires-Dist: onnxruntime-gpu (>=1.17.0,<1.20.0) ; python_version < "3.10"
|
|
25
29
|
Requires-Dist: pillow (>=10.3.0,<11.0.0)
|
|
26
30
|
Requires-Dist: py-rust-stemmers (>=0.1.0,<0.2.0)
|
|
27
31
|
Requires-Dist: requests (>=2.31,<3.0)
|
|
@@ -60,10 +64,10 @@ pip install fastembed-gpu
|
|
|
60
64
|
|
|
61
65
|
```python
|
|
62
66
|
from fastembed import TextEmbedding
|
|
63
|
-
|
|
67
|
+
|
|
64
68
|
|
|
65
69
|
# Example list of documents
|
|
66
|
-
documents:
|
|
70
|
+
documents: list[str] = [
|
|
67
71
|
"This is built to be faster and lighter than other embedding libraries e.g. Transformers, Sentence-Transformers, etc.",
|
|
68
72
|
"fastembed is supported by and maintained by Qdrant.",
|
|
69
73
|
]
|
|
@@ -171,11 +175,10 @@ embeddings = list(model.embed(images))
|
|
|
171
175
|
|
|
172
176
|
### 🔄 Rerankers
|
|
173
177
|
```python
|
|
174
|
-
from typing import List
|
|
175
178
|
from fastembed.rerank.cross_encoder import TextCrossEncoder
|
|
176
179
|
|
|
177
180
|
query = "Who is maintaining Qdrant?"
|
|
178
|
-
documents:
|
|
181
|
+
documents: list[str] = [
|
|
179
182
|
"This is built to be faster and lighter than other embedding libraries e.g. Transformers, Sentence-Transformers, etc.",
|
|
180
183
|
"fastembed is supported by and maintained by Qdrant.",
|
|
181
184
|
]
|
|
@@ -28,10 +28,10 @@ pip install fastembed-gpu
|
|
|
28
28
|
|
|
29
29
|
```python
|
|
30
30
|
from fastembed import TextEmbedding
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
|
|
33
33
|
# Example list of documents
|
|
34
|
-
documents:
|
|
34
|
+
documents: list[str] = [
|
|
35
35
|
"This is built to be faster and lighter than other embedding libraries e.g. Transformers, Sentence-Transformers, etc.",
|
|
36
36
|
"fastembed is supported by and maintained by Qdrant.",
|
|
37
37
|
]
|
|
@@ -139,11 +139,10 @@ embeddings = list(model.embed(images))
|
|
|
139
139
|
|
|
140
140
|
### 🔄 Rerankers
|
|
141
141
|
```python
|
|
142
|
-
from typing import List
|
|
143
142
|
from fastembed.rerank.cross_encoder import TextCrossEncoder
|
|
144
143
|
|
|
145
144
|
query = "Who is maintaining Qdrant?"
|
|
146
|
-
documents:
|
|
145
|
+
documents: list[str] = [
|
|
147
146
|
"This is built to be faster and lighter than other embedding libraries e.g. Transformers, Sentence-Transformers, etc.",
|
|
148
147
|
"fastembed is supported by and maintained by Qdrant.",
|
|
149
148
|
]
|
|
@@ -3,27 +3,31 @@ import time
|
|
|
3
3
|
import shutil
|
|
4
4
|
import tarfile
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import Any,
|
|
6
|
+
from typing import Any, Optional
|
|
7
7
|
|
|
8
8
|
import requests
|
|
9
9
|
from huggingface_hub import snapshot_download
|
|
10
|
-
from huggingface_hub.utils import
|
|
10
|
+
from huggingface_hub.utils import (
|
|
11
|
+
RepositoryNotFoundError,
|
|
12
|
+
disable_progress_bars,
|
|
13
|
+
enable_progress_bars,
|
|
14
|
+
)
|
|
11
15
|
from loguru import logger
|
|
12
16
|
from tqdm import tqdm
|
|
13
17
|
|
|
14
18
|
|
|
15
19
|
class ModelManagement:
|
|
16
20
|
@classmethod
|
|
17
|
-
def list_supported_models(cls) ->
|
|
21
|
+
def list_supported_models(cls) -> list[dict[str, Any]]:
|
|
18
22
|
"""Lists the supported models.
|
|
19
23
|
|
|
20
24
|
Returns:
|
|
21
|
-
|
|
25
|
+
list[dict[str, Any]]: A list of dictionaries containing the model information.
|
|
22
26
|
"""
|
|
23
27
|
raise NotImplementedError()
|
|
24
28
|
|
|
25
29
|
@classmethod
|
|
26
|
-
def _get_model_description(cls, model_name: str) ->
|
|
30
|
+
def _get_model_description(cls, model_name: str) -> dict[str, Any]:
|
|
27
31
|
"""
|
|
28
32
|
Gets the model description from the model_name.
|
|
29
33
|
|
|
@@ -34,7 +38,7 @@ class ModelManagement:
|
|
|
34
38
|
ValueError: If the model_name is not supported.
|
|
35
39
|
|
|
36
40
|
Returns:
|
|
37
|
-
|
|
41
|
+
dict[str, Any]: The model description.
|
|
38
42
|
"""
|
|
39
43
|
for model in cls.list_supported_models():
|
|
40
44
|
if model_name.lower() == model["model"].lower():
|
|
@@ -93,8 +97,8 @@ class ModelManagement:
|
|
|
93
97
|
def download_files_from_huggingface(
|
|
94
98
|
cls,
|
|
95
99
|
hf_source_repo: str,
|
|
96
|
-
cache_dir:
|
|
97
|
-
extra_patterns: Optional[
|
|
100
|
+
cache_dir: str,
|
|
101
|
+
extra_patterns: Optional[list[str]] = None,
|
|
98
102
|
local_files_only: bool = False,
|
|
99
103
|
**kwargs,
|
|
100
104
|
) -> str:
|
|
@@ -103,7 +107,7 @@ class ModelManagement:
|
|
|
103
107
|
Args:
|
|
104
108
|
hf_source_repo (str): Name of the model on HuggingFace Hub, e.g. "qdrant/all-MiniLM-L6-v2-onnx".
|
|
105
109
|
cache_dir (Optional[str]): The path to the cache directory.
|
|
106
|
-
extra_patterns (Optional[
|
|
110
|
+
extra_patterns (Optional[list[str]]): extra patterns to allow in the snapshot download, typically
|
|
107
111
|
includes the required model files.
|
|
108
112
|
local_files_only (bool, optional): Whether to only use local files. Defaults to False.
|
|
109
113
|
Returns:
|
|
@@ -119,6 +123,12 @@ class ModelManagement:
|
|
|
119
123
|
if extra_patterns is not None:
|
|
120
124
|
allow_patterns.extend(extra_patterns)
|
|
121
125
|
|
|
126
|
+
snapshot_dir = Path(cache_dir) / f"models--{hf_source_repo.replace('/', '--')}"
|
|
127
|
+
is_cached = snapshot_dir.exists()
|
|
128
|
+
|
|
129
|
+
if is_cached:
|
|
130
|
+
disable_progress_bars()
|
|
131
|
+
|
|
122
132
|
return snapshot_download(
|
|
123
133
|
repo_id=hf_source_repo,
|
|
124
134
|
allow_patterns=allow_patterns,
|
|
@@ -211,13 +221,13 @@ class ModelManagement:
|
|
|
211
221
|
|
|
212
222
|
@classmethod
|
|
213
223
|
def download_model(
|
|
214
|
-
cls, model:
|
|
224
|
+
cls, model: dict[str, Any], cache_dir: Path, retries: int = 3, **kwargs
|
|
215
225
|
) -> Path:
|
|
216
226
|
"""
|
|
217
227
|
Downloads a model from HuggingFace Hub or Google Cloud Storage.
|
|
218
228
|
|
|
219
229
|
Args:
|
|
220
|
-
model (
|
|
230
|
+
model (dict[str, Any]): The model description.
|
|
221
231
|
Example:
|
|
222
232
|
```
|
|
223
233
|
{
|
|
@@ -265,6 +275,8 @@ class ModelManagement:
|
|
|
265
275
|
f"Could not download model from HuggingFace: {e} "
|
|
266
276
|
"Falling back to other sources."
|
|
267
277
|
)
|
|
278
|
+
finally:
|
|
279
|
+
enable_progress_bars()
|
|
268
280
|
if url_source or local_files_only:
|
|
269
281
|
try:
|
|
270
282
|
return cls.retrieve_model_gcs(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import warnings
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, Generic, Iterable, Optional, Sequence, Type, TypeVar
|
|
5
5
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
import onnxruntime as ort
|
|
@@ -33,8 +33,8 @@ class OnnxModel(Generic[T]):
|
|
|
33
33
|
self.tokenizer = None
|
|
34
34
|
|
|
35
35
|
def _preprocess_onnx_input(
|
|
36
|
-
self, onnx_input:
|
|
37
|
-
) ->
|
|
36
|
+
self, onnx_input: dict[str, np.ndarray], **kwargs
|
|
37
|
+
) -> dict[str, np.ndarray]:
|
|
38
38
|
"""
|
|
39
39
|
Preprocess the onnx input.
|
|
40
40
|
"""
|
|
@@ -52,6 +52,13 @@ class OnnxModel(Generic[T]):
|
|
|
52
52
|
model_path = model_dir / model_file
|
|
53
53
|
# List of Execution Providers: https://onnxruntime.ai/docs/execution-providers
|
|
54
54
|
|
|
55
|
+
if cuda and providers is not None:
|
|
56
|
+
warnings.warn(
|
|
57
|
+
f"`cuda` and `providers` are mutually exclusive parameters, cuda: {cuda}, providers: {providers}",
|
|
58
|
+
category=UserWarning,
|
|
59
|
+
stacklevel=6,
|
|
60
|
+
)
|
|
61
|
+
|
|
55
62
|
if providers is not None:
|
|
56
63
|
onnx_providers = list(providers)
|
|
57
64
|
elif cuda:
|
|
@@ -121,5 +128,5 @@ class EmbeddingWorker(Worker):
|
|
|
121
128
|
def start(cls, model_name: str, cache_dir: str, **kwargs: Any) -> "EmbeddingWorker":
|
|
122
129
|
return cls(model_name=model_name, cache_dir=cache_dir, **kwargs)
|
|
123
130
|
|
|
124
|
-
def process(self, items: Iterable[
|
|
131
|
+
def process(self, items: Iterable[tuple[int, Any]]) -> Iterable[tuple[int, Any]]:
|
|
125
132
|
raise NotImplementedError("Subclasses must implement this method")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
from tokenizers import AddedToken, Tokenizer
|
|
5
5
|
|
|
6
6
|
from fastembed.image.transform.operators import Compose
|
|
@@ -17,7 +17,7 @@ def load_special_tokens(model_dir: Path) -> dict:
|
|
|
17
17
|
return tokens_map
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def load_tokenizer(model_dir: Path) ->
|
|
20
|
+
def load_tokenizer(model_dir: Path) -> tuple[Tokenizer, dict]:
|
|
21
21
|
config_path = model_dir / "config.json"
|
|
22
22
|
if not config_path.exists():
|
|
23
23
|
raise ValueError(f"Could not find config.json in {model_dir}")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
3
|
from PIL import Image
|
|
4
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, Iterable, Union
|
|
5
5
|
|
|
6
6
|
if sys.version_info >= (3, 10):
|
|
7
7
|
from typing import TypeAlias
|
|
@@ -13,4 +13,4 @@ PathInput: TypeAlias = Union[str, os.PathLike]
|
|
|
13
13
|
PilInput: TypeAlias = Union[Image.Image, Iterable[Image.Image]]
|
|
14
14
|
ImageInput: TypeAlias = Union[PathInput, Iterable[PathInput], PilInput]
|
|
15
15
|
|
|
16
|
-
OnnxProvider: TypeAlias = Union[str,
|
|
16
|
+
OnnxProvider: TypeAlias = Union[str, tuple[str, dict[Any, Any]]]
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import sys
|
|
3
|
+
import re
|
|
2
4
|
import tempfile
|
|
3
|
-
|
|
5
|
+
import unicodedata
|
|
4
6
|
from pathlib import Path
|
|
7
|
+
from itertools import islice
|
|
5
8
|
from typing import Generator, Iterable, Optional, Union
|
|
6
|
-
|
|
7
|
-
import sys
|
|
9
|
+
|
|
8
10
|
import numpy as np
|
|
9
|
-
import re
|
|
10
|
-
from typing import Set
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def normalize(input_array, p=2, dim=1, eps=1e-12) -> np.ndarray:
|
|
@@ -45,7 +45,7 @@ def define_cache_dir(cache_dir: Optional[str] = None) -> Path:
|
|
|
45
45
|
return cache_path
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
def get_all_punctuation() ->
|
|
48
|
+
def get_all_punctuation() -> set[str]:
|
|
49
49
|
return set(
|
|
50
50
|
chr(i) for i in range(sys.maxunicode) if unicodedata.category(chr(i)).startswith("P")
|
|
51
51
|
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any,
|
|
1
|
+
from typing import Any, Iterable, Optional, Sequence, Type
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
|
|
@@ -8,15 +8,15 @@ from fastembed.image.onnx_embedding import OnnxImageEmbedding
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class ImageEmbedding(ImageEmbeddingBase):
|
|
11
|
-
EMBEDDINGS_REGISTRY:
|
|
11
|
+
EMBEDDINGS_REGISTRY: list[Type[ImageEmbeddingBase]] = [OnnxImageEmbedding]
|
|
12
12
|
|
|
13
13
|
@classmethod
|
|
14
|
-
def list_supported_models(cls) ->
|
|
14
|
+
def list_supported_models(cls) -> list[dict[str, Any]]:
|
|
15
15
|
"""
|
|
16
16
|
Lists the supported models.
|
|
17
17
|
|
|
18
18
|
Returns:
|
|
19
|
-
|
|
19
|
+
list[dict[str, Any]]: A list of dictionaries containing the model information.
|
|
20
20
|
|
|
21
21
|
Example:
|
|
22
22
|
```
|
|
@@ -47,7 +47,7 @@ class ImageEmbedding(ImageEmbeddingBase):
|
|
|
47
47
|
threads: Optional[int] = None,
|
|
48
48
|
providers: Optional[Sequence[OnnxProvider]] = None,
|
|
49
49
|
cuda: bool = False,
|
|
50
|
-
device_ids: Optional[
|
|
50
|
+
device_ids: Optional[list[int]] = None,
|
|
51
51
|
lazy_load: bool = False,
|
|
52
52
|
**kwargs,
|
|
53
53
|
):
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any,
|
|
1
|
+
from typing import Any, Iterable, Optional, Sequence, Type
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
|
|
@@ -53,6 +53,17 @@ supported_onnx_models = [
|
|
|
53
53
|
},
|
|
54
54
|
"model_file": "model.onnx",
|
|
55
55
|
},
|
|
56
|
+
{
|
|
57
|
+
"model": "jinaai/jina-clip-v1",
|
|
58
|
+
"dim": 768,
|
|
59
|
+
"description": "Image embeddings, Multimodal (text&image), 2024 year",
|
|
60
|
+
"license": "apache-2.0",
|
|
61
|
+
"size_in_GB": 0.34,
|
|
62
|
+
"sources": {
|
|
63
|
+
"hf": "jinaai/jina-clip-v1",
|
|
64
|
+
},
|
|
65
|
+
"model_file": "onnx/vision_model.onnx",
|
|
66
|
+
},
|
|
56
67
|
]
|
|
57
68
|
|
|
58
69
|
|
|
@@ -64,7 +75,7 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[np.ndarray]):
|
|
|
64
75
|
threads: Optional[int] = None,
|
|
65
76
|
providers: Optional[Sequence[OnnxProvider]] = None,
|
|
66
77
|
cuda: bool = False,
|
|
67
|
-
device_ids: Optional[
|
|
78
|
+
device_ids: Optional[list[int]] = None,
|
|
68
79
|
lazy_load: bool = False,
|
|
69
80
|
device_id: Optional[int] = None,
|
|
70
81
|
**kwargs,
|
|
@@ -80,7 +91,7 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[np.ndarray]):
|
|
|
80
91
|
Mutually exclusive with the `cuda` and `device_ids` arguments. Defaults to None.
|
|
81
92
|
cuda (bool, optional): Whether to use cuda for inference. Mutually exclusive with `providers`
|
|
82
93
|
Defaults to False.
|
|
83
|
-
device_ids (Optional[
|
|
94
|
+
device_ids (Optional[list[int]], optional): The list of device ids to use for data parallel processing in
|
|
84
95
|
workers. Should be used with `cuda=True`, mutually exclusive with `providers`. Defaults to None.
|
|
85
96
|
lazy_load (bool, optional): Whether to load the model during class initialization or on demand.
|
|
86
97
|
Should be set to True when using multiple-gpu and parallel encoding. Defaults to False.
|
|
@@ -129,12 +140,12 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[np.ndarray]):
|
|
|
129
140
|
)
|
|
130
141
|
|
|
131
142
|
@classmethod
|
|
132
|
-
def list_supported_models(cls) ->
|
|
143
|
+
def list_supported_models(cls) -> list[dict[str, Any]]:
|
|
133
144
|
"""
|
|
134
145
|
Lists the supported models.
|
|
135
146
|
|
|
136
147
|
Returns:
|
|
137
|
-
|
|
148
|
+
list[Dict[str, Any]]: A list of dictionaries containing the model information.
|
|
138
149
|
"""
|
|
139
150
|
return supported_onnx_models
|
|
140
151
|
|
|
@@ -178,8 +189,8 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[np.ndarray]):
|
|
|
178
189
|
return OnnxImageEmbeddingWorker
|
|
179
190
|
|
|
180
191
|
def _preprocess_onnx_input(
|
|
181
|
-
self, onnx_input:
|
|
182
|
-
) ->
|
|
192
|
+
self, onnx_input: dict[str, np.ndarray], **kwargs
|
|
193
|
+
) -> dict[str, np.ndarray]:
|
|
183
194
|
"""
|
|
184
195
|
Preprocess the onnx input.
|
|
185
196
|
"""
|
|
@@ -2,7 +2,7 @@ import contextlib
|
|
|
2
2
|
import os
|
|
3
3
|
from multiprocessing import get_all_start_methods
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Any,
|
|
5
|
+
from typing import Any, Iterable, Optional, Sequence, Type
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
from PIL import Image
|
|
@@ -29,8 +29,8 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
29
29
|
self.processor = None
|
|
30
30
|
|
|
31
31
|
def _preprocess_onnx_input(
|
|
32
|
-
self, onnx_input:
|
|
33
|
-
) ->
|
|
32
|
+
self, onnx_input: dict[str, np.ndarray], **kwargs
|
|
33
|
+
) -> dict[str, np.ndarray]:
|
|
34
34
|
"""
|
|
35
35
|
Preprocess the onnx input.
|
|
36
36
|
"""
|
|
@@ -58,10 +58,10 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
58
58
|
def load_onnx_model(self) -> None:
|
|
59
59
|
raise NotImplementedError("Subclasses must implement this method")
|
|
60
60
|
|
|
61
|
-
def _build_onnx_input(self, encoded: np.ndarray) ->
|
|
61
|
+
def _build_onnx_input(self, encoded: np.ndarray) -> dict[str, np.ndarray]:
|
|
62
62
|
return {node.name: encoded for node in self.model.get_inputs()}
|
|
63
63
|
|
|
64
|
-
def onnx_embed(self, images:
|
|
64
|
+
def onnx_embed(self, images: list[ImageInput], **kwargs) -> OnnxOutputContext:
|
|
65
65
|
with contextlib.ExitStack():
|
|
66
66
|
image_files = [
|
|
67
67
|
Image.open(image) if not isinstance(image, Image.Image) else image
|
|
@@ -83,7 +83,7 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
83
83
|
parallel: Optional[int] = None,
|
|
84
84
|
providers: Optional[Sequence[OnnxProvider]] = None,
|
|
85
85
|
cuda: bool = False,
|
|
86
|
-
device_ids: Optional[
|
|
86
|
+
device_ids: Optional[list[int]] = None,
|
|
87
87
|
**kwargs,
|
|
88
88
|
) -> Iterable[T]:
|
|
89
89
|
is_small = False
|
|
@@ -125,7 +125,7 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
125
125
|
|
|
126
126
|
|
|
127
127
|
class ImageEmbeddingWorker(EmbeddingWorker):
|
|
128
|
-
def process(self, items: Iterable[
|
|
128
|
+
def process(self, items: Iterable[tuple[int, Any]]) -> Iterable[tuple[int, Any]]:
|
|
129
129
|
for idx, batch in items:
|
|
130
130
|
embeddings = self.model.onnx_embed(batch)
|
|
131
131
|
yield idx, embeddings
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Sized,
|
|
1
|
+
from typing import Sized, Union
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
from PIL import Image
|
|
@@ -14,7 +14,7 @@ def convert_to_rgb(image: Image.Image) -> Image.Image:
|
|
|
14
14
|
|
|
15
15
|
def center_crop(
|
|
16
16
|
image: Union[Image.Image, np.ndarray],
|
|
17
|
-
size:
|
|
17
|
+
size: tuple[int, int],
|
|
18
18
|
) -> np.ndarray:
|
|
19
19
|
if isinstance(image, np.ndarray):
|
|
20
20
|
_, orig_height, orig_width = image.shape
|
|
@@ -62,8 +62,8 @@ def center_crop(
|
|
|
62
62
|
|
|
63
63
|
def normalize(
|
|
64
64
|
image: np.ndarray,
|
|
65
|
-
mean
|
|
66
|
-
std
|
|
65
|
+
mean: Union[float, np.ndarray],
|
|
66
|
+
std: Union[float, np.ndarray],
|
|
67
67
|
) -> np.ndarray:
|
|
68
68
|
if not isinstance(image, np.ndarray):
|
|
69
69
|
raise ValueError("image must be a numpy array")
|
|
@@ -96,10 +96,10 @@ def normalize(
|
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
def resize(
|
|
99
|
-
image: Image,
|
|
100
|
-
size: Union[int,
|
|
101
|
-
resample: Image.Resampling = Image.Resampling.BILINEAR,
|
|
102
|
-
) -> Image:
|
|
99
|
+
image: Image.Image,
|
|
100
|
+
size: Union[int, tuple[int, int]],
|
|
101
|
+
resample: Union[int, Image.Resampling] = Image.Resampling.BILINEAR,
|
|
102
|
+
) -> Image.Image:
|
|
103
103
|
if isinstance(size, tuple):
|
|
104
104
|
return image.resize(size, resample)
|
|
105
105
|
|
|
@@ -122,3 +122,29 @@ def pil2ndarray(image: Union[Image.Image, np.ndarray]):
|
|
|
122
122
|
if isinstance(image, Image.Image):
|
|
123
123
|
return np.asarray(image).transpose((2, 0, 1))
|
|
124
124
|
return image
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def pad2square(
|
|
128
|
+
image: Image.Image,
|
|
129
|
+
size: int,
|
|
130
|
+
fill_color: Union[str, int, tuple[int, ...]] = 0,
|
|
131
|
+
) -> Image.Image:
|
|
132
|
+
height, width = image.height, image.width
|
|
133
|
+
|
|
134
|
+
left, right = 0, width
|
|
135
|
+
top, bottom = 0, height
|
|
136
|
+
|
|
137
|
+
crop_required = False
|
|
138
|
+
if width > size:
|
|
139
|
+
left = (width - size) // 2
|
|
140
|
+
right = left + size
|
|
141
|
+
crop_required = True
|
|
142
|
+
|
|
143
|
+
if height > size:
|
|
144
|
+
top = (height - size) // 2
|
|
145
|
+
bottom = top + size
|
|
146
|
+
crop_required = True
|
|
147
|
+
|
|
148
|
+
new_image = Image.new(mode="RGB", size=(size, size), color=fill_color)
|
|
149
|
+
new_image.paste(image.crop((left, top, right, bottom)) if crop_required else image)
|
|
150
|
+
return new_image
|