fastembed-gpu 0.6.1__tar.gz → 0.7.1__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.6.1 → fastembed_gpu-0.7.1}/PKG-INFO +1 -1
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/common/onnx_model.py +10 -1
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/common/preprocessor_utils.py +3 -3
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/common/types.py +1 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/image/image_embedding.py +34 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/image/image_embedding_base.py +11 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/image/onnx_embedding.py +7 -2
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/image/onnx_image_model.py +16 -3
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/image/transform/functional.py +10 -10
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/late_interaction/colbert.py +5 -2
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/late_interaction/late_interaction_embedding_base.py +11 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/late_interaction/late_interaction_text_embedding.py +34 -0
- fastembed_gpu-0.7.1/fastembed/late_interaction/token_embeddings.py +83 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/late_interaction_multimodal/colpali.py +7 -2
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/late_interaction_multimodal/late_interaction_multimodal_embedding.py +34 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/late_interaction_multimodal/late_interaction_multimodal_embedding_base.py +11 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/late_interaction_multimodal/onnx_multimodal_model.py +8 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/rerank/cross_encoder/onnx_text_cross_encoder.py +7 -2
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/rerank/cross_encoder/onnx_text_model.py +16 -1
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/sparse/bm25.py +10 -13
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/sparse/bm42.py +7 -2
- fastembed_gpu-0.7.1/fastembed/sparse/minicoil.py +356 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/sparse/sparse_text_embedding.py +3 -2
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/sparse/splade_pp.py +7 -2
- fastembed_gpu-0.7.1/fastembed/sparse/utils/minicoil_encoder.py +146 -0
- fastembed_gpu-0.7.1/fastembed/sparse/utils/sparse_vectors_converter.py +247 -0
- fastembed_gpu-0.7.1/fastembed/sparse/utils/vocab_resolver.py +202 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/text/clip_embedding.py +3 -1
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/text/custom_text_embedding.py +8 -1
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/text/onnx_embedding.py +7 -2
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/text/onnx_text_model.py +18 -3
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/text/pooled_embedding.py +3 -1
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/text/pooled_normalized_embedding.py +3 -1
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/text/text_embedding.py +41 -7
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/text/text_embedding_base.py +11 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/pyproject.toml +2 -2
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/LICENSE +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/NOTICE +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/README.md +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/__init__.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/common/__init__.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/common/model_description.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/common/model_management.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/common/utils.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/embedding.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/image/__init__.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/image/transform/operators.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/late_interaction/__init__.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/late_interaction/jina_colbert.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/late_interaction_multimodal/__init__.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/parallel_processor.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/py.typed +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/rerank/cross_encoder/__init__.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/rerank/cross_encoder/custom_text_cross_encoder.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/rerank/cross_encoder/text_cross_encoder.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/rerank/cross_encoder/text_cross_encoder_base.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/sparse/__init__.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/sparse/sparse_embedding_base.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/sparse/utils/tokenizer.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/text/__init__.py +0 -0
- {fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/text/multitask_embedding.py +0 -0
|
@@ -28,7 +28,16 @@ class OnnxModel(Generic[T]):
|
|
|
28
28
|
def _get_worker_class(cls) -> Type["EmbeddingWorker[T]"]:
|
|
29
29
|
raise NotImplementedError("Subclasses must implement this method")
|
|
30
30
|
|
|
31
|
-
def _post_process_onnx_output(self, output: OnnxOutputContext) -> Iterable[T]:
|
|
31
|
+
def _post_process_onnx_output(self, output: OnnxOutputContext, **kwargs: Any) -> Iterable[T]:
|
|
32
|
+
"""Post-process the ONNX model output to convert it into a usable format.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
output (OnnxOutputContext): The raw output from the ONNX model.
|
|
36
|
+
**kwargs: Additional keyword arguments that may be needed by specific implementations.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
Iterable[T]: Post-processed output as an iterable of type T.
|
|
40
|
+
"""
|
|
32
41
|
raise NotImplementedError("Subclasses must implement this method")
|
|
33
42
|
|
|
34
43
|
def __init__(self) -> None:
|
|
@@ -36,9 +36,9 @@ def load_tokenizer(model_dir: Path) -> tuple[Tokenizer, dict[str, int]]:
|
|
|
36
36
|
|
|
37
37
|
with open(str(tokenizer_config_path)) as tokenizer_config_file:
|
|
38
38
|
tokenizer_config = json.load(tokenizer_config_file)
|
|
39
|
-
assert (
|
|
40
|
-
"
|
|
41
|
-
)
|
|
39
|
+
assert "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
|
+
)
|
|
42
42
|
if "model_max_length" not in tokenizer_config:
|
|
43
43
|
max_context = tokenizer_config["max_length"]
|
|
44
44
|
elif "max_length" not in tokenizer_config:
|
|
@@ -77,6 +77,40 @@ class ImageEmbedding(ImageEmbeddingBase):
|
|
|
77
77
|
"Please check the supported models using `ImageEmbedding.list_supported_models()`"
|
|
78
78
|
)
|
|
79
79
|
|
|
80
|
+
@property
|
|
81
|
+
def embedding_size(self) -> int:
|
|
82
|
+
"""Get the embedding size of the current model"""
|
|
83
|
+
if self._embedding_size is None:
|
|
84
|
+
self._embedding_size = self.get_embedding_size(self.model_name)
|
|
85
|
+
return self._embedding_size
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def get_embedding_size(cls, model_name: str) -> int:
|
|
89
|
+
"""Get the embedding size of the passed model
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
model_name (str): The name of the model to get embedding size for.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
int: The size of the embedding.
|
|
96
|
+
|
|
97
|
+
Raises:
|
|
98
|
+
ValueError: If the model name is not found in the supported models.
|
|
99
|
+
"""
|
|
100
|
+
descriptions = cls._list_supported_models()
|
|
101
|
+
embedding_size: Optional[int] = None
|
|
102
|
+
for description in descriptions:
|
|
103
|
+
if description.model.lower() == model_name.lower():
|
|
104
|
+
embedding_size = description.dim
|
|
105
|
+
break
|
|
106
|
+
if embedding_size is None:
|
|
107
|
+
model_names = [description.model for description in descriptions]
|
|
108
|
+
raise ValueError(
|
|
109
|
+
f"Embedding size for model {model_name} was None. "
|
|
110
|
+
f"Available model names: {model_names}"
|
|
111
|
+
)
|
|
112
|
+
return embedding_size
|
|
113
|
+
|
|
80
114
|
def embed(
|
|
81
115
|
self,
|
|
82
116
|
images: Union[ImageInput, Iterable[ImageInput]],
|
|
@@ -18,6 +18,7 @@ class ImageEmbeddingBase(ModelManagement[DenseModelDescription]):
|
|
|
18
18
|
self.cache_dir = cache_dir
|
|
19
19
|
self.threads = threads
|
|
20
20
|
self._local_files_only = kwargs.pop("local_files_only", False)
|
|
21
|
+
self._embedding_size: Optional[int] = None
|
|
21
22
|
|
|
22
23
|
def embed(
|
|
23
24
|
self,
|
|
@@ -42,3 +43,13 @@ class ImageEmbeddingBase(ModelManagement[DenseModelDescription]):
|
|
|
42
43
|
Iterable[NdArray]: The embeddings.
|
|
43
44
|
"""
|
|
44
45
|
raise NotImplementedError()
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def get_embedding_size(cls, model_name: str) -> int:
|
|
49
|
+
"""Returns embedding size of the chosen model."""
|
|
50
|
+
raise NotImplementedError("Subclasses must implement this method")
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def embedding_size(self) -> int:
|
|
54
|
+
"""Returns embedding size for the current model"""
|
|
55
|
+
raise NotImplementedError("Subclasses must implement this method")
|
|
@@ -112,11 +112,12 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[NumpyArray]):
|
|
|
112
112
|
|
|
113
113
|
self.model_description = self._get_model_description(model_name)
|
|
114
114
|
self.cache_dir = str(define_cache_dir(cache_dir))
|
|
115
|
+
self._specific_model_path = specific_model_path
|
|
115
116
|
self._model_dir = self.download_model(
|
|
116
117
|
self.model_description,
|
|
117
118
|
self.cache_dir,
|
|
118
119
|
local_files_only=self._local_files_only,
|
|
119
|
-
specific_model_path=
|
|
120
|
+
specific_model_path=self._specific_model_path,
|
|
120
121
|
)
|
|
121
122
|
|
|
122
123
|
if not self.lazy_load:
|
|
@@ -177,6 +178,8 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[NumpyArray]):
|
|
|
177
178
|
providers=self.providers,
|
|
178
179
|
cuda=self.cuda,
|
|
179
180
|
device_ids=self.device_ids,
|
|
181
|
+
local_files_only=self._local_files_only,
|
|
182
|
+
specific_model_path=self._specific_model_path,
|
|
180
183
|
**kwargs,
|
|
181
184
|
)
|
|
182
185
|
|
|
@@ -193,7 +196,9 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[NumpyArray]):
|
|
|
193
196
|
|
|
194
197
|
return onnx_input
|
|
195
198
|
|
|
196
|
-
def _post_process_onnx_output(
|
|
199
|
+
def _post_process_onnx_output(
|
|
200
|
+
self, output: OnnxOutputContext, **kwargs: Any
|
|
201
|
+
) -> Iterable[NumpyArray]:
|
|
197
202
|
return normalize(output.model_output)
|
|
198
203
|
|
|
199
204
|
|
|
@@ -23,7 +23,16 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
23
23
|
def _get_worker_class(cls) -> Type["ImageEmbeddingWorker[T]"]:
|
|
24
24
|
raise NotImplementedError("Subclasses must implement this method")
|
|
25
25
|
|
|
26
|
-
def _post_process_onnx_output(self, output: OnnxOutputContext) -> Iterable[T]:
|
|
26
|
+
def _post_process_onnx_output(self, output: OnnxOutputContext, **kwargs: Any) -> Iterable[T]:
|
|
27
|
+
"""Post-process the ONNX model output to convert it into a usable format.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
output (OnnxOutputContext): The raw output from the ONNX model.
|
|
31
|
+
**kwargs: Additional keyword arguments that may be needed by specific implementations.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Iterable[T]: Post-processed output as an iterable of type T.
|
|
35
|
+
"""
|
|
27
36
|
raise NotImplementedError("Subclasses must implement this method")
|
|
28
37
|
|
|
29
38
|
def __init__(self) -> None:
|
|
@@ -88,6 +97,8 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
88
97
|
providers: Optional[Sequence[OnnxProvider]] = None,
|
|
89
98
|
cuda: bool = False,
|
|
90
99
|
device_ids: Optional[list[int]] = None,
|
|
100
|
+
local_files_only: bool = False,
|
|
101
|
+
specific_model_path: Optional[str] = None,
|
|
91
102
|
**kwargs: Any,
|
|
92
103
|
) -> Iterable[T]:
|
|
93
104
|
is_small = False
|
|
@@ -104,7 +115,7 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
104
115
|
self.load_onnx_model()
|
|
105
116
|
|
|
106
117
|
for batch in iter_batch(images, batch_size):
|
|
107
|
-
yield from self._post_process_onnx_output(self.onnx_embed(batch))
|
|
118
|
+
yield from self._post_process_onnx_output(self.onnx_embed(batch), **kwargs)
|
|
108
119
|
else:
|
|
109
120
|
if parallel == 0:
|
|
110
121
|
parallel = os.cpu_count()
|
|
@@ -114,6 +125,8 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
114
125
|
"model_name": model_name,
|
|
115
126
|
"cache_dir": cache_dir,
|
|
116
127
|
"providers": providers,
|
|
128
|
+
"local_files_only": local_files_only,
|
|
129
|
+
"specific_model_path": specific_model_path,
|
|
117
130
|
**kwargs,
|
|
118
131
|
}
|
|
119
132
|
|
|
@@ -125,7 +138,7 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
125
138
|
start_method=start_method,
|
|
126
139
|
)
|
|
127
140
|
for batch in pool.ordered_map(iter_batch(images, batch_size), **params):
|
|
128
|
-
yield from self._post_process_onnx_output(batch) # type: ignore
|
|
141
|
+
yield from self._post_process_onnx_output(batch, **kwargs) # type: ignore
|
|
129
142
|
|
|
130
143
|
|
|
131
144
|
class ImageEmbeddingWorker(EmbeddingWorker[T]):
|
|
@@ -72,26 +72,26 @@ def normalize(
|
|
|
72
72
|
if not np.issubdtype(image.dtype, np.floating):
|
|
73
73
|
image = image.astype(np.float32)
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
mean_list = mean if isinstance(mean, list) else [mean] * num_channels
|
|
76
76
|
|
|
77
|
-
if len(
|
|
77
|
+
if len(mean_list) != num_channels:
|
|
78
78
|
raise ValueError(
|
|
79
79
|
f"mean must have the same number of channels as the image, image has {num_channels} channels, got "
|
|
80
|
-
f"{len(
|
|
80
|
+
f"{len(mean_list)}"
|
|
81
81
|
)
|
|
82
82
|
|
|
83
|
-
mean_arr = np.array(
|
|
83
|
+
mean_arr = np.array(mean_list, dtype=np.float32)
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
if len(
|
|
85
|
+
std_list = std if isinstance(std, list) else [std] * num_channels
|
|
86
|
+
if len(std_list) != num_channels:
|
|
87
87
|
raise ValueError(
|
|
88
|
-
f"std must have the same number of channels as the image, image has {num_channels} channels, got {len(
|
|
88
|
+
f"std must have the same number of channels as the image, image has {num_channels} channels, got {len(std_list)}"
|
|
89
89
|
)
|
|
90
90
|
|
|
91
|
-
std_arr = np.array(
|
|
91
|
+
std_arr = np.array(std_list, dtype=np.float32)
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
return
|
|
93
|
+
image_upd = ((image.T - mean_arr) / std_arr).T
|
|
94
|
+
return image_upd
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
def resize(
|
|
@@ -43,7 +43,7 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[NumpyArray]):
|
|
|
43
43
|
MASK_TOKEN = "[MASK]"
|
|
44
44
|
|
|
45
45
|
def _post_process_onnx_output(
|
|
46
|
-
self, output: OnnxOutputContext, is_doc: bool = True
|
|
46
|
+
self, output: OnnxOutputContext, is_doc: bool = True, **kwargs: Any
|
|
47
47
|
) -> Iterable[NumpyArray]:
|
|
48
48
|
if not is_doc:
|
|
49
49
|
return output.model_output
|
|
@@ -169,11 +169,12 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[NumpyArray]):
|
|
|
169
169
|
self.model_description = self._get_model_description(model_name)
|
|
170
170
|
self.cache_dir = str(define_cache_dir(cache_dir))
|
|
171
171
|
|
|
172
|
+
self._specific_model_path = specific_model_path
|
|
172
173
|
self._model_dir = self.download_model(
|
|
173
174
|
self.model_description,
|
|
174
175
|
self.cache_dir,
|
|
175
176
|
local_files_only=self._local_files_only,
|
|
176
|
-
specific_model_path=
|
|
177
|
+
specific_model_path=self._specific_model_path,
|
|
177
178
|
)
|
|
178
179
|
self.mask_token_id: Optional[int] = None
|
|
179
180
|
self.pad_token_id: Optional[int] = None
|
|
@@ -233,6 +234,8 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[NumpyArray]):
|
|
|
233
234
|
providers=self.providers,
|
|
234
235
|
cuda=self.cuda,
|
|
235
236
|
device_ids=self.device_ids,
|
|
237
|
+
local_files_only=self._local_files_only,
|
|
238
|
+
specific_model_path=self._specific_model_path,
|
|
236
239
|
**kwargs,
|
|
237
240
|
)
|
|
238
241
|
|
|
@@ -17,6 +17,7 @@ class LateInteractionTextEmbeddingBase(ModelManagement[DenseModelDescription]):
|
|
|
17
17
|
self.cache_dir = cache_dir
|
|
18
18
|
self.threads = threads
|
|
19
19
|
self._local_files_only = kwargs.pop("local_files_only", False)
|
|
20
|
+
self._embedding_size: Optional[int] = None
|
|
20
21
|
|
|
21
22
|
def embed(
|
|
22
23
|
self,
|
|
@@ -58,3 +59,13 @@ class LateInteractionTextEmbeddingBase(ModelManagement[DenseModelDescription]):
|
|
|
58
59
|
yield from self.embed([query], **kwargs)
|
|
59
60
|
else:
|
|
60
61
|
yield from self.embed(query, **kwargs)
|
|
62
|
+
|
|
63
|
+
@classmethod
|
|
64
|
+
def get_embedding_size(cls, model_name: str) -> int:
|
|
65
|
+
"""Returns embedding size of the chosen model."""
|
|
66
|
+
raise NotImplementedError("Subclasses must implement this method")
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def embedding_size(self) -> int:
|
|
70
|
+
"""Returns embedding size for the current model"""
|
|
71
|
+
raise NotImplementedError("Subclasses must implement this method")
|
|
@@ -80,6 +80,40 @@ class LateInteractionTextEmbedding(LateInteractionTextEmbeddingBase):
|
|
|
80
80
|
"Please check the supported models using `LateInteractionTextEmbedding.list_supported_models()`"
|
|
81
81
|
)
|
|
82
82
|
|
|
83
|
+
@property
|
|
84
|
+
def embedding_size(self) -> int:
|
|
85
|
+
"""Get the embedding size of the current model"""
|
|
86
|
+
if self._embedding_size is None:
|
|
87
|
+
self._embedding_size = self.get_embedding_size(self.model_name)
|
|
88
|
+
return self._embedding_size
|
|
89
|
+
|
|
90
|
+
@classmethod
|
|
91
|
+
def get_embedding_size(cls, model_name: str) -> int:
|
|
92
|
+
"""Get the embedding size of the passed model
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
model_name (str): The name of the model to get embedding size for.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
int: The size of the embedding.
|
|
99
|
+
|
|
100
|
+
Raises:
|
|
101
|
+
ValueError: If the model name is not found in the supported models.
|
|
102
|
+
"""
|
|
103
|
+
descriptions = cls._list_supported_models()
|
|
104
|
+
embedding_size: Optional[int] = None
|
|
105
|
+
for description in descriptions:
|
|
106
|
+
if description.model.lower() == model_name.lower():
|
|
107
|
+
embedding_size = description.dim
|
|
108
|
+
break
|
|
109
|
+
if embedding_size is None:
|
|
110
|
+
model_names = [description.model for description in descriptions]
|
|
111
|
+
raise ValueError(
|
|
112
|
+
f"Embedding size for model {model_name} was None. "
|
|
113
|
+
f"Available model names: {model_names}"
|
|
114
|
+
)
|
|
115
|
+
return embedding_size
|
|
116
|
+
|
|
83
117
|
def embed(
|
|
84
118
|
self,
|
|
85
119
|
documents: Union[str, Iterable[str]],
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
from dataclasses import asdict
|
|
2
|
+
from typing import Union, Iterable, Optional, Any, Type
|
|
3
|
+
|
|
4
|
+
from fastembed.common.model_description import DenseModelDescription, ModelSource
|
|
5
|
+
from fastembed.common.onnx_model import OnnxOutputContext
|
|
6
|
+
from fastembed.common.types import NumpyArray
|
|
7
|
+
from fastembed.late_interaction.late_interaction_embedding_base import (
|
|
8
|
+
LateInteractionTextEmbeddingBase,
|
|
9
|
+
)
|
|
10
|
+
from fastembed.text.onnx_embedding import OnnxTextEmbedding
|
|
11
|
+
from fastembed.text.onnx_text_model import TextEmbeddingWorker
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
supported_token_embeddings_models = [
|
|
15
|
+
DenseModelDescription(
|
|
16
|
+
model="jinaai/jina-embeddings-v2-small-en-tokens",
|
|
17
|
+
dim=512,
|
|
18
|
+
description="Text embeddings, Unimodal (text), English, 8192 input tokens truncation,"
|
|
19
|
+
" Prefixes for queries/documents: not necessary, 2023 year.",
|
|
20
|
+
license="apache-2.0",
|
|
21
|
+
size_in_GB=0.12,
|
|
22
|
+
sources=ModelSource(hf="xenova/jina-embeddings-v2-small-en"),
|
|
23
|
+
model_file="onnx/model.onnx",
|
|
24
|
+
),
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class TokenEmbeddingsModel(OnnxTextEmbedding, LateInteractionTextEmbeddingBase):
|
|
29
|
+
@classmethod
|
|
30
|
+
def _list_supported_models(cls) -> list[DenseModelDescription]:
|
|
31
|
+
"""Lists the supported models.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
list[DenseModelDescription]: A list of DenseModelDescription objects containing the model information.
|
|
35
|
+
"""
|
|
36
|
+
return supported_token_embeddings_models
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def list_supported_models(cls) -> list[dict[str, Any]]:
|
|
40
|
+
"""Lists the supported models.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
list[dict[str, Any]]: A list of dictionaries containing the model information.
|
|
44
|
+
"""
|
|
45
|
+
return [asdict(model) for model in cls._list_supported_models()]
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def _get_worker_class(cls) -> Type[TextEmbeddingWorker[NumpyArray]]:
|
|
49
|
+
return TokensEmbeddingWorker
|
|
50
|
+
|
|
51
|
+
def _post_process_onnx_output(
|
|
52
|
+
self, output: OnnxOutputContext, **kwargs: Any
|
|
53
|
+
) -> Iterable[NumpyArray]:
|
|
54
|
+
# Size: (batch_size, sequence_length, hidden_size)
|
|
55
|
+
embeddings = output.model_output
|
|
56
|
+
# Size: (batch_size, sequence_length)
|
|
57
|
+
assert output.attention_mask is not None
|
|
58
|
+
masks = output.attention_mask
|
|
59
|
+
|
|
60
|
+
# For each document we only select those embeddings that are not masked out
|
|
61
|
+
for i in range(embeddings.shape[0]):
|
|
62
|
+
yield embeddings[i, masks[i] == 1]
|
|
63
|
+
|
|
64
|
+
def embed(
|
|
65
|
+
self,
|
|
66
|
+
documents: Union[str, Iterable[str]],
|
|
67
|
+
batch_size: int = 256,
|
|
68
|
+
parallel: Optional[int] = None,
|
|
69
|
+
**kwargs: Any,
|
|
70
|
+
) -> Iterable[NumpyArray]:
|
|
71
|
+
yield from super().embed(documents, batch_size=batch_size, parallel=parallel, **kwargs)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class TokensEmbeddingWorker(TextEmbeddingWorker[NumpyArray]):
|
|
75
|
+
def init_embedding(
|
|
76
|
+
self, model_name: str, cache_dir: str, **kwargs: Any
|
|
77
|
+
) -> TokenEmbeddingsModel:
|
|
78
|
+
return TokenEmbeddingsModel(
|
|
79
|
+
model_name=model_name,
|
|
80
|
+
cache_dir=cache_dir,
|
|
81
|
+
threads=1,
|
|
82
|
+
**kwargs,
|
|
83
|
+
)
|
{fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/late_interaction_multimodal/colpali.py
RENAMED
|
@@ -95,11 +95,12 @@ class ColPali(LateInteractionMultimodalEmbeddingBase, OnnxMultimodalModel[NumpyA
|
|
|
95
95
|
self.model_description = self._get_model_description(model_name)
|
|
96
96
|
self.cache_dir = str(define_cache_dir(cache_dir))
|
|
97
97
|
|
|
98
|
+
self._specific_model_path = specific_model_path
|
|
98
99
|
self._model_dir = self.download_model(
|
|
99
100
|
self.model_description,
|
|
100
101
|
self.cache_dir,
|
|
101
102
|
local_files_only=self._local_files_only,
|
|
102
|
-
specific_model_path=
|
|
103
|
+
specific_model_path=self._specific_model_path,
|
|
103
104
|
)
|
|
104
105
|
self.mask_token_id = None
|
|
105
106
|
self.pad_token_id = None
|
|
@@ -174,7 +175,7 @@ class ColPali(LateInteractionMultimodalEmbeddingBase, OnnxMultimodalModel[NumpyA
|
|
|
174
175
|
) -> dict[str, NumpyArray]:
|
|
175
176
|
onnx_input["input_ids"] = np.array(
|
|
176
177
|
[
|
|
177
|
-
self.QUERY_MARKER_TOKEN_ID + input_ids[2:].tolist()
|
|
178
|
+
self.QUERY_MARKER_TOKEN_ID + input_ids[2:].tolist() # type: ignore[index]
|
|
178
179
|
for input_ids in onnx_input["input_ids"]
|
|
179
180
|
]
|
|
180
181
|
)
|
|
@@ -235,6 +236,8 @@ class ColPali(LateInteractionMultimodalEmbeddingBase, OnnxMultimodalModel[NumpyA
|
|
|
235
236
|
providers=self.providers,
|
|
236
237
|
cuda=self.cuda,
|
|
237
238
|
device_ids=self.device_ids,
|
|
239
|
+
local_files_only=self._local_files_only,
|
|
240
|
+
specific_model_path=self._specific_model_path,
|
|
238
241
|
**kwargs,
|
|
239
242
|
)
|
|
240
243
|
|
|
@@ -268,6 +271,8 @@ class ColPali(LateInteractionMultimodalEmbeddingBase, OnnxMultimodalModel[NumpyA
|
|
|
268
271
|
providers=self.providers,
|
|
269
272
|
cuda=self.cuda,
|
|
270
273
|
device_ids=self.device_ids,
|
|
274
|
+
local_files_only=self._local_files_only,
|
|
275
|
+
specific_model_path=self._specific_model_path,
|
|
271
276
|
**kwargs,
|
|
272
277
|
)
|
|
273
278
|
|
|
@@ -83,6 +83,40 @@ class LateInteractionMultimodalEmbedding(LateInteractionMultimodalEmbeddingBase)
|
|
|
83
83
|
"Please check the supported models using `LateInteractionMultimodalEmbedding.list_supported_models()`"
|
|
84
84
|
)
|
|
85
85
|
|
|
86
|
+
@property
|
|
87
|
+
def embedding_size(self) -> int:
|
|
88
|
+
"""Get the embedding size of the current model"""
|
|
89
|
+
if self._embedding_size is None:
|
|
90
|
+
self._embedding_size = self.get_embedding_size(self.model_name)
|
|
91
|
+
return self._embedding_size
|
|
92
|
+
|
|
93
|
+
@classmethod
|
|
94
|
+
def get_embedding_size(cls, model_name: str) -> int:
|
|
95
|
+
"""Get the embedding size of the passed model
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
model_name (str): The name of the model to get embedding size for.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
int: The size of the embedding.
|
|
102
|
+
|
|
103
|
+
Raises:
|
|
104
|
+
ValueError: If the model name is not found in the supported models.
|
|
105
|
+
"""
|
|
106
|
+
descriptions = cls._list_supported_models()
|
|
107
|
+
embedding_size: Optional[int] = None
|
|
108
|
+
for description in descriptions:
|
|
109
|
+
if description.model.lower() == model_name.lower():
|
|
110
|
+
embedding_size = description.dim
|
|
111
|
+
break
|
|
112
|
+
if embedding_size is None:
|
|
113
|
+
model_names = [description.model for description in descriptions]
|
|
114
|
+
raise ValueError(
|
|
115
|
+
f"Embedding size for model {model_name} was None. "
|
|
116
|
+
f"Available model names: {model_names}"
|
|
117
|
+
)
|
|
118
|
+
return embedding_size
|
|
119
|
+
|
|
86
120
|
def embed_text(
|
|
87
121
|
self,
|
|
88
122
|
documents: Union[str, Iterable[str]],
|
|
@@ -19,6 +19,7 @@ class LateInteractionMultimodalEmbeddingBase(ModelManagement[DenseModelDescripti
|
|
|
19
19
|
self.cache_dir = cache_dir
|
|
20
20
|
self.threads = threads
|
|
21
21
|
self._local_files_only = kwargs.pop("local_files_only", False)
|
|
22
|
+
self._embedding_size: Optional[int] = None
|
|
22
23
|
|
|
23
24
|
def embed_text(
|
|
24
25
|
self,
|
|
@@ -65,3 +66,13 @@ class LateInteractionMultimodalEmbeddingBase(ModelManagement[DenseModelDescripti
|
|
|
65
66
|
List of embeddings, one per image
|
|
66
67
|
"""
|
|
67
68
|
raise NotImplementedError()
|
|
69
|
+
|
|
70
|
+
@classmethod
|
|
71
|
+
def get_embedding_size(cls, model_name: str) -> int:
|
|
72
|
+
"""Returns embedding size of the chosen model."""
|
|
73
|
+
raise NotImplementedError("Subclasses must implement this method")
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def embedding_size(self) -> int:
|
|
77
|
+
"""Returns embedding size for the current model"""
|
|
78
|
+
raise NotImplementedError("Subclasses must implement this method")
|
|
@@ -120,6 +120,8 @@ class OnnxMultimodalModel(OnnxModel[T]):
|
|
|
120
120
|
providers: Optional[Sequence[OnnxProvider]] = None,
|
|
121
121
|
cuda: bool = False,
|
|
122
122
|
device_ids: Optional[list[int]] = None,
|
|
123
|
+
local_files_only: bool = False,
|
|
124
|
+
specific_model_path: Optional[str] = None,
|
|
123
125
|
**kwargs: Any,
|
|
124
126
|
) -> Iterable[T]:
|
|
125
127
|
is_small = False
|
|
@@ -146,6 +148,8 @@ class OnnxMultimodalModel(OnnxModel[T]):
|
|
|
146
148
|
"model_name": model_name,
|
|
147
149
|
"cache_dir": cache_dir,
|
|
148
150
|
"providers": providers,
|
|
151
|
+
"local_files_only": local_files_only,
|
|
152
|
+
"specific_model_path": specific_model_path,
|
|
149
153
|
**kwargs,
|
|
150
154
|
}
|
|
151
155
|
|
|
@@ -183,6 +187,8 @@ class OnnxMultimodalModel(OnnxModel[T]):
|
|
|
183
187
|
providers: Optional[Sequence[OnnxProvider]] = None,
|
|
184
188
|
cuda: bool = False,
|
|
185
189
|
device_ids: Optional[list[int]] = None,
|
|
190
|
+
local_files_only: bool = False,
|
|
191
|
+
specific_model_path: Optional[str] = None,
|
|
186
192
|
**kwargs: Any,
|
|
187
193
|
) -> Iterable[T]:
|
|
188
194
|
is_small = False
|
|
@@ -209,6 +215,8 @@ class OnnxMultimodalModel(OnnxModel[T]):
|
|
|
209
215
|
"model_name": model_name,
|
|
210
216
|
"cache_dir": cache_dir,
|
|
211
217
|
"providers": providers,
|
|
218
|
+
"local_files_only": local_files_only,
|
|
219
|
+
"specific_model_path": specific_model_path,
|
|
212
220
|
**kwargs,
|
|
213
221
|
}
|
|
214
222
|
|
|
@@ -131,11 +131,12 @@ class OnnxTextCrossEncoder(TextCrossEncoderBase, OnnxCrossEncoderModel):
|
|
|
131
131
|
|
|
132
132
|
self.model_description = self._get_model_description(model_name)
|
|
133
133
|
self.cache_dir = str(define_cache_dir(cache_dir))
|
|
134
|
+
self._specific_model_path = specific_model_path
|
|
134
135
|
self._model_dir = self.download_model(
|
|
135
136
|
self.model_description,
|
|
136
137
|
self.cache_dir,
|
|
137
138
|
local_files_only=self._local_files_only,
|
|
138
|
-
specific_model_path=
|
|
139
|
+
specific_model_path=self._specific_model_path,
|
|
139
140
|
)
|
|
140
141
|
|
|
141
142
|
if not self.lazy_load:
|
|
@@ -189,6 +190,8 @@ class OnnxTextCrossEncoder(TextCrossEncoderBase, OnnxCrossEncoderModel):
|
|
|
189
190
|
providers=self.providers,
|
|
190
191
|
cuda=self.cuda,
|
|
191
192
|
device_ids=self.device_ids,
|
|
193
|
+
local_files_only=self._local_files_only,
|
|
194
|
+
specific_model_path=self._specific_model_path,
|
|
192
195
|
**kwargs,
|
|
193
196
|
)
|
|
194
197
|
|
|
@@ -196,7 +199,9 @@ class OnnxTextCrossEncoder(TextCrossEncoderBase, OnnxCrossEncoderModel):
|
|
|
196
199
|
def _get_worker_class(cls) -> Type[TextRerankerWorker]:
|
|
197
200
|
return TextCrossEncoderWorker
|
|
198
201
|
|
|
199
|
-
def _post_process_onnx_output(
|
|
202
|
+
def _post_process_onnx_output(
|
|
203
|
+
self, output: OnnxOutputContext, **kwargs: Any
|
|
204
|
+
) -> Iterable[float]:
|
|
200
205
|
return (float(elem) for elem in output.model_output)
|
|
201
206
|
|
|
202
207
|
|
{fastembed_gpu-0.6.1 → fastembed_gpu-0.7.1}/fastembed/rerank/cross_encoder/onnx_text_model.py
RENAMED
|
@@ -94,6 +94,8 @@ class OnnxCrossEncoderModel(OnnxModel[float]):
|
|
|
94
94
|
providers: Optional[Sequence[OnnxProvider]] = None,
|
|
95
95
|
cuda: bool = False,
|
|
96
96
|
device_ids: Optional[list[int]] = None,
|
|
97
|
+
local_files_only: bool = False,
|
|
98
|
+
specific_model_path: Optional[str] = None,
|
|
97
99
|
**kwargs: Any,
|
|
98
100
|
) -> Iterable[float]:
|
|
99
101
|
is_small = False
|
|
@@ -120,6 +122,8 @@ class OnnxCrossEncoderModel(OnnxModel[float]):
|
|
|
120
122
|
"model_name": model_name,
|
|
121
123
|
"cache_dir": cache_dir,
|
|
122
124
|
"providers": providers,
|
|
125
|
+
"local_files_only": local_files_only,
|
|
126
|
+
"specific_model_path": specific_model_path,
|
|
123
127
|
**kwargs,
|
|
124
128
|
}
|
|
125
129
|
|
|
@@ -133,7 +137,18 @@ class OnnxCrossEncoderModel(OnnxModel[float]):
|
|
|
133
137
|
for batch in pool.ordered_map(iter_batch(pairs, batch_size), **params):
|
|
134
138
|
yield from self._post_process_onnx_output(batch) # type: ignore
|
|
135
139
|
|
|
136
|
-
def _post_process_onnx_output(
|
|
140
|
+
def _post_process_onnx_output(
|
|
141
|
+
self, output: OnnxOutputContext, **kwargs: Any
|
|
142
|
+
) -> Iterable[float]:
|
|
143
|
+
"""Post-process the ONNX model output to convert it into a usable format.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
output (OnnxOutputContext): The raw output from the ONNX model.
|
|
147
|
+
**kwargs: Additional keyword arguments that may be needed by specific implementations.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Iterable[float]: Post-processed output as an iterable of float values.
|
|
151
|
+
"""
|
|
137
152
|
raise NotImplementedError("Subclasses must implement this method")
|
|
138
153
|
|
|
139
154
|
def _preprocess_onnx_input(
|