fastembed-gpu 0.7.2__tar.gz → 0.7.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_gpu-0.7.2 → fastembed_gpu-0.7.4}/PKG-INFO +13 -6
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/common/model_management.py +26 -11
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/common/onnx_model.py +38 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/image/onnx_embedding.py +3 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/image/onnx_image_model.py +6 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/late_interaction/colbert.py +65 -34
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/late_interaction/late_interaction_embedding_base.py +9 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/late_interaction/late_interaction_text_embedding.py +27 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/late_interaction_multimodal/colpali.py +22 -1
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/late_interaction_multimodal/late_interaction_multimodal_embedding.py +21 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/late_interaction_multimodal/late_interaction_multimodal_embedding_base.py +8 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/late_interaction_multimodal/onnx_multimodal_model.py +10 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/rerank/cross_encoder/onnx_text_cross_encoder.py +17 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/rerank/cross_encoder/onnx_text_model.py +20 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/rerank/cross_encoder/text_cross_encoder.py +14 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/rerank/cross_encoder/text_cross_encoder_base.py +4 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/sparse/bm25.py +9 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/sparse/bm42.py +20 -2
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/sparse/minicoil.py +18 -2
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/sparse/sparse_embedding_base.py +4 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/sparse/sparse_text_embedding.py +14 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/sparse/splade_pp.py +8 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/text/onnx_embedding.py +8 -1
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/text/onnx_text_model.py +21 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/text/text_embedding.py +14 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/text/text_embedding_base.py +4 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/pyproject.toml +17 -8
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/LICENSE +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/NOTICE +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/README.md +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/__init__.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/common/__init__.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/common/model_description.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/common/preprocessor_utils.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/common/types.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/common/utils.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/embedding.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/image/__init__.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/image/image_embedding.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/image/image_embedding_base.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/image/transform/functional.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/image/transform/operators.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/late_interaction/__init__.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/late_interaction/jina_colbert.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/late_interaction/token_embeddings.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/late_interaction_multimodal/__init__.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/parallel_processor.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/postprocess/__init__.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/postprocess/muvera.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/py.typed +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/rerank/cross_encoder/__init__.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/rerank/cross_encoder/custom_text_cross_encoder.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/sparse/__init__.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/sparse/utils/minicoil_encoder.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/sparse/utils/sparse_vectors_converter.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/sparse/utils/tokenizer.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/sparse/utils/vocab_resolver.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/text/__init__.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/text/clip_embedding.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/text/custom_text_embedding.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/text/multitask_embedding.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/text/pooled_embedding.py +0 -0
- {fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/text/pooled_normalized_embedding.py +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: fastembed-gpu
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: Fast, light, accurate library built for retrieval embedding generation
|
|
5
5
|
License: Apache License
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
License-File: NOTICE
|
|
6
8
|
Keywords: vector,embedding,neural,search,qdrant,sentence-transformers
|
|
7
9
|
Author: Qdrant Team
|
|
8
10
|
Author-email: info@qdrant.tech
|
|
@@ -14,17 +16,22 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
14
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
-
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Requires-Dist: huggingface-hub (>=0.20,<2.0)
|
|
18
21
|
Requires-Dist: loguru (>=0.7.2,<0.8.0)
|
|
19
22
|
Requires-Dist: mmh3 (>=4.1.0,<6.0.0)
|
|
20
|
-
Requires-Dist: numpy (>=1.21) ; python_version
|
|
23
|
+
Requires-Dist: numpy (>=1.21) ; python_version == "3.11"
|
|
21
24
|
Requires-Dist: numpy (>=1.21,<2.1.0) ; python_version < "3.10"
|
|
25
|
+
Requires-Dist: numpy (>=1.21,<2.3.0) ; python_version == "3.10"
|
|
22
26
|
Requires-Dist: numpy (>=1.26) ; python_version == "3.12"
|
|
23
|
-
Requires-Dist: numpy (>=2.1.0) ; python_version
|
|
27
|
+
Requires-Dist: numpy (>=2.1.0) ; python_version == "3.13"
|
|
28
|
+
Requires-Dist: numpy (>=2.3.0) ; python_version >= "3.14"
|
|
24
29
|
Requires-Dist: onnxruntime-gpu (>1.20.0) ; python_version >= "3.13"
|
|
25
30
|
Requires-Dist: onnxruntime-gpu (>=1.17.0,!=1.20.0) ; python_version >= "3.10" and python_version < "3.13"
|
|
26
31
|
Requires-Dist: onnxruntime-gpu (>=1.17.0,<1.20.0) ; python_version < "3.10"
|
|
27
|
-
Requires-Dist: pillow (>=10.3.0,<
|
|
32
|
+
Requires-Dist: pillow (>=10.3.0,<11.0) ; python_version < "3.10"
|
|
33
|
+
Requires-Dist: pillow (>=10.3.0,<12.0) ; python_version >= "3.10" and python_version < "3.13"
|
|
34
|
+
Requires-Dist: pillow (>=11.0.0,<12.0) ; python_version >= "3.13"
|
|
28
35
|
Requires-Dist: py-rust-stemmers (>=0.1.0,<0.2.0)
|
|
29
36
|
Requires-Dist: requests (>=2.31,<3.0)
|
|
30
37
|
Requires-Dist: tokenizers (>=0.15,<1.0)
|
|
@@ -3,6 +3,7 @@ import time
|
|
|
3
3
|
import json
|
|
4
4
|
import shutil
|
|
5
5
|
import tarfile
|
|
6
|
+
from copy import deepcopy
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
from typing import Any, Optional, Union, TypeVar, Generic
|
|
8
9
|
|
|
@@ -224,11 +225,6 @@ class ModelManagement(Generic[T]):
|
|
|
224
225
|
logger.warning(
|
|
225
226
|
"Local file sizes do not match the metadata."
|
|
226
227
|
) # do not raise, still make an attempt to load the model
|
|
227
|
-
else:
|
|
228
|
-
logger.warning(
|
|
229
|
-
"Metadata file not found. Proceeding without checking local files."
|
|
230
|
-
) # if users have downloaded models from hf manually, or they're updating from previous versions of
|
|
231
|
-
# fastembed
|
|
232
228
|
result = snapshot_download(
|
|
233
229
|
repo_id=hf_source_repo,
|
|
234
230
|
allow_patterns=allow_patterns,
|
|
@@ -408,14 +404,32 @@ class ModelManagement(Generic[T]):
|
|
|
408
404
|
hf_source = model.sources.hf
|
|
409
405
|
url_source = model.sources.url
|
|
410
406
|
|
|
407
|
+
extra_patterns = [model.model_file]
|
|
408
|
+
extra_patterns.extend(model.additional_files)
|
|
409
|
+
|
|
410
|
+
if hf_source:
|
|
411
|
+
try:
|
|
412
|
+
cache_kwargs = deepcopy(kwargs)
|
|
413
|
+
cache_kwargs["local_files_only"] = True
|
|
414
|
+
return Path(
|
|
415
|
+
cls.download_files_from_huggingface(
|
|
416
|
+
hf_source,
|
|
417
|
+
cache_dir=cache_dir,
|
|
418
|
+
extra_patterns=extra_patterns,
|
|
419
|
+
**cache_kwargs,
|
|
420
|
+
)
|
|
421
|
+
)
|
|
422
|
+
except Exception:
|
|
423
|
+
pass
|
|
424
|
+
finally:
|
|
425
|
+
enable_progress_bars()
|
|
426
|
+
|
|
411
427
|
sleep = 3.0
|
|
412
428
|
while retries > 0:
|
|
413
429
|
retries -= 1
|
|
414
430
|
|
|
415
|
-
if hf_source:
|
|
416
|
-
|
|
417
|
-
extra_patterns.extend(model.additional_files)
|
|
418
|
-
|
|
431
|
+
if hf_source and not local_files_only:
|
|
432
|
+
# we have already tried loading with `local_files_only=True` via hf and we failed
|
|
419
433
|
try:
|
|
420
434
|
return Path(
|
|
421
435
|
cls.download_files_from_huggingface(
|
|
@@ -448,11 +462,12 @@ class ModelManagement(Generic[T]):
|
|
|
448
462
|
|
|
449
463
|
if local_files_only:
|
|
450
464
|
logger.error("Could not find model in cache_dir")
|
|
465
|
+
break
|
|
451
466
|
else:
|
|
452
467
|
logger.error(
|
|
453
468
|
f"Could not download model from either source, sleeping for {sleep} seconds, {retries} retries left."
|
|
454
469
|
)
|
|
455
|
-
|
|
456
|
-
|
|
470
|
+
time.sleep(sleep)
|
|
471
|
+
sleep *= 3
|
|
457
472
|
|
|
458
473
|
raise ValueError(f"Could not load model {model.model} from any source.")
|
|
@@ -24,6 +24,8 @@ class OnnxOutputContext:
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class OnnxModel(Generic[T]):
|
|
27
|
+
EXPOSED_SESSION_OPTIONS = ("enable_cpu_mem_arena",)
|
|
28
|
+
|
|
27
29
|
@classmethod
|
|
28
30
|
def _get_worker_class(cls) -> Type["EmbeddingWorker[T]"]:
|
|
29
31
|
raise NotImplementedError("Subclasses must implement this method")
|
|
@@ -60,6 +62,7 @@ class OnnxModel(Generic[T]):
|
|
|
60
62
|
providers: Optional[Sequence[OnnxProvider]] = None,
|
|
61
63
|
cuda: bool = False,
|
|
62
64
|
device_id: Optional[int] = None,
|
|
65
|
+
extra_session_options: Optional[dict[str, Any]] = None,
|
|
63
66
|
) -> None:
|
|
64
67
|
model_path = model_dir / model_file
|
|
65
68
|
# List of Execution Providers: https://onnxruntime.ai/docs/execution-providers
|
|
@@ -99,6 +102,9 @@ class OnnxModel(Generic[T]):
|
|
|
99
102
|
so.intra_op_num_threads = threads
|
|
100
103
|
so.inter_op_num_threads = threads
|
|
101
104
|
|
|
105
|
+
if extra_session_options is not None:
|
|
106
|
+
self.add_extra_session_options(so, extra_session_options)
|
|
107
|
+
|
|
102
108
|
self.model = ort.InferenceSession(
|
|
103
109
|
str(model_path), providers=onnx_providers, sess_options=so
|
|
104
110
|
)
|
|
@@ -113,6 +119,38 @@ class OnnxModel(Generic[T]):
|
|
|
113
119
|
RuntimeWarning,
|
|
114
120
|
)
|
|
115
121
|
|
|
122
|
+
@classmethod
|
|
123
|
+
def _select_exposed_session_options(cls, model_kwargs: dict[str, Any]) -> dict[str, Any]:
|
|
124
|
+
"""A convenience method to select the exposed session options in models
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
model_kwargs (dict[str, Any]): The model kwargs.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
dict[str, Any]: a dict with filtered exposed session options.
|
|
131
|
+
"""
|
|
132
|
+
return {k: v for k, v in model_kwargs.items() if k in cls.EXPOSED_SESSION_OPTIONS}
|
|
133
|
+
|
|
134
|
+
@classmethod
|
|
135
|
+
def add_extra_session_options(
|
|
136
|
+
cls, session_options: ort.SessionOptions, extra_options: dict[str, Any]
|
|
137
|
+
) -> None:
|
|
138
|
+
"""Add extra session options to the existing options object in-place
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
session_options (ort.SessionOptions): The existing session options object.
|
|
142
|
+
extra_options (dict[str, Any]): The extra session options available in cls.EXPOSED_SESSION_OPTIONS.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
None
|
|
146
|
+
"""
|
|
147
|
+
for option in extra_options:
|
|
148
|
+
assert (
|
|
149
|
+
option in cls.EXPOSED_SESSION_OPTIONS
|
|
150
|
+
), f"{option} is unknown or not exposed (exposed options: {cls.EXPOSED_SESSION_OPTIONS})"
|
|
151
|
+
if "enable_cpu_mem_arena" in extra_options:
|
|
152
|
+
session_options.enable_cpu_mem_arena = extra_options["enable_cpu_mem_arena"]
|
|
153
|
+
|
|
116
154
|
def load_onnx_model(self) -> None:
|
|
117
155
|
raise NotImplementedError("Subclasses must implement this method")
|
|
118
156
|
|
|
@@ -98,6 +98,7 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[NumpyArray]):
|
|
|
98
98
|
super().__init__(model_name, cache_dir, threads, **kwargs)
|
|
99
99
|
self.providers = providers
|
|
100
100
|
self.lazy_load = lazy_load
|
|
101
|
+
self._extra_session_options = self._select_exposed_session_options(kwargs)
|
|
101
102
|
|
|
102
103
|
# List of device ids, that can be used for data parallel processing in workers
|
|
103
104
|
self.device_ids = device_ids
|
|
@@ -134,6 +135,7 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[NumpyArray]):
|
|
|
134
135
|
providers=self.providers,
|
|
135
136
|
cuda=self.cuda,
|
|
136
137
|
device_id=self.device_id,
|
|
138
|
+
extra_session_options=self._extra_session_options,
|
|
137
139
|
)
|
|
138
140
|
|
|
139
141
|
@classmethod
|
|
@@ -180,6 +182,7 @@ class OnnxImageEmbedding(ImageEmbeddingBase, OnnxImageModel[NumpyArray]):
|
|
|
180
182
|
device_ids=self.device_ids,
|
|
181
183
|
local_files_only=self._local_files_only,
|
|
182
184
|
specific_model_path=self._specific_model_path,
|
|
185
|
+
extra_session_options=self._extra_session_options,
|
|
183
186
|
**kwargs,
|
|
184
187
|
)
|
|
185
188
|
|
|
@@ -55,6 +55,7 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
55
55
|
providers: Optional[Sequence[OnnxProvider]] = None,
|
|
56
56
|
cuda: bool = False,
|
|
57
57
|
device_id: Optional[int] = None,
|
|
58
|
+
extra_session_options: Optional[dict[str, Any]] = None,
|
|
58
59
|
) -> None:
|
|
59
60
|
super()._load_onnx_model(
|
|
60
61
|
model_dir=model_dir,
|
|
@@ -63,6 +64,7 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
63
64
|
providers=providers,
|
|
64
65
|
cuda=cuda,
|
|
65
66
|
device_id=device_id,
|
|
67
|
+
extra_session_options=extra_session_options,
|
|
66
68
|
)
|
|
67
69
|
self.processor = load_preprocessor(model_dir=model_dir)
|
|
68
70
|
|
|
@@ -99,6 +101,7 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
99
101
|
device_ids: Optional[list[int]] = None,
|
|
100
102
|
local_files_only: bool = False,
|
|
101
103
|
specific_model_path: Optional[str] = None,
|
|
104
|
+
extra_session_options: Optional[dict[str, Any]] = None,
|
|
102
105
|
**kwargs: Any,
|
|
103
106
|
) -> Iterable[T]:
|
|
104
107
|
is_small = False
|
|
@@ -130,6 +133,9 @@ class OnnxImageModel(OnnxModel[T]):
|
|
|
130
133
|
**kwargs,
|
|
131
134
|
}
|
|
132
135
|
|
|
136
|
+
if extra_session_options is not None:
|
|
137
|
+
params.update(extra_session_options)
|
|
138
|
+
|
|
133
139
|
pool = ParallelWorkerPool(
|
|
134
140
|
num_workers=parallel or 1,
|
|
135
141
|
worker=self._get_worker_class(),
|
|
@@ -2,12 +2,13 @@ import string
|
|
|
2
2
|
from typing import Any, Iterable, Optional, Sequence, Type, Union
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
|
-
from tokenizers import Encoding
|
|
5
|
+
from tokenizers import Encoding, Tokenizer
|
|
6
6
|
|
|
7
|
+
from fastembed.common.preprocessor_utils import load_tokenizer
|
|
7
8
|
from fastembed.common.types import NumpyArray
|
|
8
9
|
from fastembed.common import OnnxProvider
|
|
9
10
|
from fastembed.common.onnx_model import OnnxOutputContext
|
|
10
|
-
from fastembed.common.utils import define_cache_dir
|
|
11
|
+
from fastembed.common.utils import define_cache_dir, iter_batch
|
|
11
12
|
from fastembed.late_interaction.late_interaction_embedding_base import (
|
|
12
13
|
LateInteractionTextEmbeddingBase,
|
|
13
14
|
)
|
|
@@ -48,24 +49,24 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[NumpyArray]):
|
|
|
48
49
|
if not is_doc:
|
|
49
50
|
for embedding in output.model_output:
|
|
50
51
|
yield embedding
|
|
52
|
+
else:
|
|
53
|
+
if output.input_ids is None or output.attention_mask is None:
|
|
54
|
+
raise ValueError(
|
|
55
|
+
"input_ids and attention_mask must be provided for document post-processing"
|
|
56
|
+
)
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
for i, token_sequence in enumerate(output.input_ids):
|
|
58
|
-
for j, token_id in enumerate(token_sequence): # type: ignore
|
|
59
|
-
if token_id in self.skip_list or token_id == self.pad_token_id:
|
|
60
|
-
output.attention_mask[i, j] = 0
|
|
58
|
+
for i, token_sequence in enumerate(output.input_ids):
|
|
59
|
+
for j, token_id in enumerate(token_sequence): # type: ignore
|
|
60
|
+
if token_id in self.skip_list or token_id == self.pad_token_id:
|
|
61
|
+
output.attention_mask[i, j] = 0
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
output.model_output *= np.expand_dims(output.attention_mask, 2)
|
|
64
|
+
norm = np.linalg.norm(output.model_output, ord=2, axis=2, keepdims=True)
|
|
65
|
+
norm_clamped = np.maximum(norm, 1e-12)
|
|
66
|
+
output.model_output /= norm_clamped
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
for embedding, attention_mask in zip(output.model_output, output.attention_mask):
|
|
69
|
+
yield embedding[attention_mask == 1]
|
|
69
70
|
|
|
70
71
|
def _preprocess_onnx_input(
|
|
71
72
|
self, onnx_input: dict[str, NumpyArray], is_doc: bool = True, **kwargs: Any
|
|
@@ -87,29 +88,46 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[NumpyArray]):
|
|
|
87
88
|
)
|
|
88
89
|
|
|
89
90
|
def _tokenize_query(self, query: str) -> list[Encoding]:
|
|
90
|
-
assert self.
|
|
91
|
-
encoded = self.
|
|
92
|
-
# colbert authors recommend to pad queries with [MASK] tokens for query augmentation to improve performance
|
|
93
|
-
if len(encoded[0].ids) < self.MIN_QUERY_LENGTH:
|
|
94
|
-
prev_padding = None
|
|
95
|
-
if self.tokenizer.padding:
|
|
96
|
-
prev_padding = self.tokenizer.padding
|
|
97
|
-
self.tokenizer.enable_padding(
|
|
98
|
-
pad_token=self.MASK_TOKEN,
|
|
99
|
-
pad_id=self.mask_token_id,
|
|
100
|
-
length=self.MIN_QUERY_LENGTH,
|
|
101
|
-
)
|
|
102
|
-
encoded = self.tokenizer.encode_batch([query])
|
|
103
|
-
if prev_padding is None:
|
|
104
|
-
self.tokenizer.no_padding()
|
|
105
|
-
else:
|
|
106
|
-
self.tokenizer.enable_padding(**prev_padding)
|
|
91
|
+
assert self.query_tokenizer is not None
|
|
92
|
+
encoded = self.query_tokenizer.encode_batch([query])
|
|
107
93
|
return encoded
|
|
108
94
|
|
|
109
95
|
def _tokenize_documents(self, documents: list[str]) -> list[Encoding]:
|
|
110
96
|
encoded = self.tokenizer.encode_batch(documents) # type: ignore[union-attr]
|
|
111
97
|
return encoded
|
|
112
98
|
|
|
99
|
+
def token_count(
|
|
100
|
+
self,
|
|
101
|
+
texts: Union[str, Iterable[str]],
|
|
102
|
+
batch_size: int = 1024,
|
|
103
|
+
is_doc: bool = True,
|
|
104
|
+
include_extension: bool = False,
|
|
105
|
+
**kwargs: Any,
|
|
106
|
+
) -> int:
|
|
107
|
+
if not hasattr(self, "model") or self.model is None:
|
|
108
|
+
self.load_onnx_model() # loads the tokenizer as well
|
|
109
|
+
token_num = 0
|
|
110
|
+
texts = [texts] if isinstance(texts, str) else texts
|
|
111
|
+
tokenizer = self.tokenizer if is_doc else self.query_tokenizer
|
|
112
|
+
assert tokenizer is not None
|
|
113
|
+
for batch in iter_batch(texts, batch_size):
|
|
114
|
+
for tokens in tokenizer.encode_batch(batch):
|
|
115
|
+
if is_doc:
|
|
116
|
+
token_num += sum(tokens.attention_mask)
|
|
117
|
+
else:
|
|
118
|
+
attend_count = sum(tokens.attention_mask)
|
|
119
|
+
if include_extension:
|
|
120
|
+
token_num += max(attend_count, self.MIN_QUERY_LENGTH)
|
|
121
|
+
|
|
122
|
+
else:
|
|
123
|
+
token_num += attend_count
|
|
124
|
+
if include_extension:
|
|
125
|
+
token_num += len(
|
|
126
|
+
batch
|
|
127
|
+
) # add 1 for each cls.DOC_MARKER_TOKEN_ID or cls.QUERY_MARKER_TOKEN_ID
|
|
128
|
+
|
|
129
|
+
return token_num
|
|
130
|
+
|
|
113
131
|
@classmethod
|
|
114
132
|
def _list_supported_models(cls) -> list[DenseModelDescription]:
|
|
115
133
|
"""Lists the supported models.
|
|
@@ -157,6 +175,7 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[NumpyArray]):
|
|
|
157
175
|
super().__init__(model_name, cache_dir, threads, **kwargs)
|
|
158
176
|
self.providers = providers
|
|
159
177
|
self.lazy_load = lazy_load
|
|
178
|
+
self._extra_session_options = self._select_exposed_session_options(kwargs)
|
|
160
179
|
|
|
161
180
|
# List of device ids, that can be used for data parallel processing in workers
|
|
162
181
|
self.device_ids = device_ids
|
|
@@ -183,6 +202,8 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[NumpyArray]):
|
|
|
183
202
|
self.pad_token_id: Optional[int] = None
|
|
184
203
|
self.skip_list: set[int] = set()
|
|
185
204
|
|
|
205
|
+
self.query_tokenizer: Optional[Tokenizer] = None
|
|
206
|
+
|
|
186
207
|
if not self.lazy_load:
|
|
187
208
|
self.load_onnx_model()
|
|
188
209
|
|
|
@@ -194,7 +215,10 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[NumpyArray]):
|
|
|
194
215
|
providers=self.providers,
|
|
195
216
|
cuda=self.cuda,
|
|
196
217
|
device_id=self.device_id,
|
|
218
|
+
extra_session_options=self._extra_session_options,
|
|
197
219
|
)
|
|
220
|
+
self.query_tokenizer, _ = load_tokenizer(model_dir=self._model_dir)
|
|
221
|
+
|
|
198
222
|
assert self.tokenizer is not None
|
|
199
223
|
self.mask_token_id = self.special_token_to_id[self.MASK_TOKEN]
|
|
200
224
|
self.pad_token_id = self.tokenizer.padding["pad_id"]
|
|
@@ -205,6 +229,12 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[NumpyArray]):
|
|
|
205
229
|
current_max_length = self.tokenizer.truncation["max_length"]
|
|
206
230
|
# ensure not to overflow after adding document-marker
|
|
207
231
|
self.tokenizer.enable_truncation(max_length=current_max_length - 1)
|
|
232
|
+
self.query_tokenizer.enable_truncation(max_length=current_max_length - 1)
|
|
233
|
+
self.query_tokenizer.enable_padding(
|
|
234
|
+
pad_token=self.MASK_TOKEN,
|
|
235
|
+
pad_id=self.mask_token_id,
|
|
236
|
+
length=self.MIN_QUERY_LENGTH,
|
|
237
|
+
)
|
|
208
238
|
|
|
209
239
|
def embed(
|
|
210
240
|
self,
|
|
@@ -239,6 +269,7 @@ class Colbert(LateInteractionTextEmbeddingBase, OnnxTextModel[NumpyArray]):
|
|
|
239
269
|
device_ids=self.device_ids,
|
|
240
270
|
local_files_only=self._local_files_only,
|
|
241
271
|
specific_model_path=self._specific_model_path,
|
|
272
|
+
extra_session_options=self._extra_session_options,
|
|
242
273
|
**kwargs,
|
|
243
274
|
)
|
|
244
275
|
|
|
@@ -69,3 +69,12 @@ class LateInteractionTextEmbeddingBase(ModelManagement[DenseModelDescription]):
|
|
|
69
69
|
def embedding_size(self) -> int:
|
|
70
70
|
"""Returns embedding size for the current model"""
|
|
71
71
|
raise NotImplementedError("Subclasses must implement this method")
|
|
72
|
+
|
|
73
|
+
def token_count(
|
|
74
|
+
self,
|
|
75
|
+
texts: Union[str, Iterable[str]],
|
|
76
|
+
batch_size: int = 1024,
|
|
77
|
+
**kwargs: Any,
|
|
78
|
+
) -> int:
|
|
79
|
+
"""Returns the number of tokens in the texts."""
|
|
80
|
+
raise NotImplementedError("Subclasses must implement this method")
|
|
@@ -151,3 +151,30 @@ class LateInteractionTextEmbedding(LateInteractionTextEmbeddingBase):
|
|
|
151
151
|
|
|
152
152
|
# This is model-specific, so that different models can have specialized implementations
|
|
153
153
|
yield from self.model.query_embed(query, **kwargs)
|
|
154
|
+
|
|
155
|
+
def token_count(
|
|
156
|
+
self,
|
|
157
|
+
texts: Union[str, Iterable[str]],
|
|
158
|
+
batch_size: int = 1024,
|
|
159
|
+
is_doc: bool = True,
|
|
160
|
+
include_extension: bool = False,
|
|
161
|
+
**kwargs: Any,
|
|
162
|
+
) -> int:
|
|
163
|
+
"""Returns the number of tokens in the texts.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
texts (str | Iterable[str]): The list of texts to embed.
|
|
167
|
+
batch_size (int): Batch size for encoding
|
|
168
|
+
is_doc (bool): Whether the texts are documents (disable embedding a query with include_mask=True).
|
|
169
|
+
include_extension (bool): Turn on to count DOC / QUERY marker tokens, and [MASK] token in query mode.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
int: Sum of number of tokens in the texts.
|
|
173
|
+
"""
|
|
174
|
+
return self.model.token_count(
|
|
175
|
+
texts,
|
|
176
|
+
batch_size=batch_size,
|
|
177
|
+
is_doc=is_doc,
|
|
178
|
+
include_extension=include_extension,
|
|
179
|
+
**kwargs,
|
|
180
|
+
)
|
{fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/late_interaction_multimodal/colpali.py
RENAMED
|
@@ -6,7 +6,7 @@ from tokenizers import Encoding
|
|
|
6
6
|
from fastembed.common import OnnxProvider, ImageInput
|
|
7
7
|
from fastembed.common.onnx_model import OnnxOutputContext
|
|
8
8
|
from fastembed.common.types import NumpyArray
|
|
9
|
-
from fastembed.common.utils import define_cache_dir
|
|
9
|
+
from fastembed.common.utils import define_cache_dir, iter_batch
|
|
10
10
|
from fastembed.late_interaction_multimodal.late_interaction_multimodal_embedding_base import (
|
|
11
11
|
LateInteractionMultimodalEmbeddingBase,
|
|
12
12
|
)
|
|
@@ -80,6 +80,7 @@ class ColPali(LateInteractionMultimodalEmbeddingBase, OnnxMultimodalModel[NumpyA
|
|
|
80
80
|
super().__init__(model_name, cache_dir, threads, **kwargs)
|
|
81
81
|
self.providers = providers
|
|
82
82
|
self.lazy_load = lazy_load
|
|
83
|
+
self._extra_session_options = self._select_exposed_session_options(kwargs)
|
|
83
84
|
|
|
84
85
|
# List of device ids, that can be used for data parallel processing in workers
|
|
85
86
|
self.device_ids = device_ids
|
|
@@ -125,6 +126,7 @@ class ColPali(LateInteractionMultimodalEmbeddingBase, OnnxMultimodalModel[NumpyA
|
|
|
125
126
|
providers=self.providers,
|
|
126
127
|
cuda=self.cuda,
|
|
127
128
|
device_id=self.device_id,
|
|
129
|
+
extra_session_options=self._extra_session_options,
|
|
128
130
|
)
|
|
129
131
|
|
|
130
132
|
def _post_process_onnx_image_output(
|
|
@@ -170,6 +172,23 @@ class ColPali(LateInteractionMultimodalEmbeddingBase, OnnxMultimodalModel[NumpyA
|
|
|
170
172
|
encoded = self.tokenizer.encode_batch(texts_query) # type: ignore[union-attr]
|
|
171
173
|
return encoded
|
|
172
174
|
|
|
175
|
+
def token_count(
|
|
176
|
+
self,
|
|
177
|
+
texts: Union[str, Iterable[str]],
|
|
178
|
+
batch_size: int = 1024,
|
|
179
|
+
include_extension: bool = False,
|
|
180
|
+
**kwargs: Any,
|
|
181
|
+
) -> int:
|
|
182
|
+
if not hasattr(self, "model") or self.model is None:
|
|
183
|
+
self.load_onnx_model() # loads the tokenizer as well
|
|
184
|
+
token_num = 0
|
|
185
|
+
texts = [texts] if isinstance(texts, str) else texts
|
|
186
|
+
assert self.tokenizer is not None
|
|
187
|
+
tokenize_func = self.tokenize if include_extension else self.tokenizer.encode_batch
|
|
188
|
+
for batch in iter_batch(texts, batch_size):
|
|
189
|
+
token_num += sum([sum(encoding.attention_mask) for encoding in tokenize_func(batch)])
|
|
190
|
+
return token_num
|
|
191
|
+
|
|
173
192
|
def _preprocess_onnx_text_input(
|
|
174
193
|
self, onnx_input: dict[str, NumpyArray], **kwargs: Any
|
|
175
194
|
) -> dict[str, NumpyArray]:
|
|
@@ -238,6 +257,7 @@ class ColPali(LateInteractionMultimodalEmbeddingBase, OnnxMultimodalModel[NumpyA
|
|
|
238
257
|
device_ids=self.device_ids,
|
|
239
258
|
local_files_only=self._local_files_only,
|
|
240
259
|
specific_model_path=self._specific_model_path,
|
|
260
|
+
extra_session_options=self._extra_session_options,
|
|
241
261
|
**kwargs,
|
|
242
262
|
)
|
|
243
263
|
|
|
@@ -273,6 +293,7 @@ class ColPali(LateInteractionMultimodalEmbeddingBase, OnnxMultimodalModel[NumpyA
|
|
|
273
293
|
device_ids=self.device_ids,
|
|
274
294
|
local_files_only=self._local_files_only,
|
|
275
295
|
specific_model_path=self._specific_model_path,
|
|
296
|
+
extra_session_options=self._extra_session_options,
|
|
276
297
|
**kwargs,
|
|
277
298
|
)
|
|
278
299
|
|
|
@@ -162,3 +162,24 @@ class LateInteractionMultimodalEmbedding(LateInteractionMultimodalEmbeddingBase)
|
|
|
162
162
|
List of embeddings, one per image
|
|
163
163
|
"""
|
|
164
164
|
yield from self.model.embed_image(images, batch_size, parallel, **kwargs)
|
|
165
|
+
|
|
166
|
+
def token_count(
|
|
167
|
+
self,
|
|
168
|
+
texts: Union[str, Iterable[str]],
|
|
169
|
+
batch_size: int = 1024,
|
|
170
|
+
include_extension: bool = False,
|
|
171
|
+
**kwargs: Any,
|
|
172
|
+
) -> int:
|
|
173
|
+
"""Returns the number of tokens in the texts.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
texts (str | Iterable[str]): The list of texts to embed.
|
|
177
|
+
batch_size (int): Batch size for encoding
|
|
178
|
+
include_extension (bool): Whether to include tokens added by preprocessing
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
int: Sum of number of tokens in the texts.
|
|
182
|
+
"""
|
|
183
|
+
return self.model.token_count(
|
|
184
|
+
texts, batch_size=batch_size, include_extension=include_extension, **kwargs
|
|
185
|
+
)
|
|
@@ -76,3 +76,11 @@ class LateInteractionMultimodalEmbeddingBase(ModelManagement[DenseModelDescripti
|
|
|
76
76
|
def embedding_size(self) -> int:
|
|
77
77
|
"""Returns embedding size for the current model"""
|
|
78
78
|
raise NotImplementedError("Subclasses must implement this method")
|
|
79
|
+
|
|
80
|
+
def token_count(
|
|
81
|
+
self,
|
|
82
|
+
texts: Union[str, Iterable[str]],
|
|
83
|
+
**kwargs: Any,
|
|
84
|
+
) -> int:
|
|
85
|
+
"""Returns the number of tokens in the texts."""
|
|
86
|
+
raise NotImplementedError("Subclasses must implement this method")
|
|
@@ -64,6 +64,7 @@ class OnnxMultimodalModel(OnnxModel[T]):
|
|
|
64
64
|
providers: Optional[Sequence[OnnxProvider]] = None,
|
|
65
65
|
cuda: bool = False,
|
|
66
66
|
device_id: Optional[int] = None,
|
|
67
|
+
extra_session_options: Optional[dict[str, Any]] = None,
|
|
67
68
|
) -> None:
|
|
68
69
|
super()._load_onnx_model(
|
|
69
70
|
model_dir=model_dir,
|
|
@@ -72,6 +73,7 @@ class OnnxMultimodalModel(OnnxModel[T]):
|
|
|
72
73
|
providers=providers,
|
|
73
74
|
cuda=cuda,
|
|
74
75
|
device_id=device_id,
|
|
76
|
+
extra_session_options=extra_session_options,
|
|
75
77
|
)
|
|
76
78
|
self.tokenizer, self.special_token_to_id = load_tokenizer(model_dir=model_dir)
|
|
77
79
|
assert self.tokenizer is not None
|
|
@@ -122,6 +124,7 @@ class OnnxMultimodalModel(OnnxModel[T]):
|
|
|
122
124
|
device_ids: Optional[list[int]] = None,
|
|
123
125
|
local_files_only: bool = False,
|
|
124
126
|
specific_model_path: Optional[str] = None,
|
|
127
|
+
extra_session_options: Optional[dict[str, Any]] = None,
|
|
125
128
|
**kwargs: Any,
|
|
126
129
|
) -> Iterable[T]:
|
|
127
130
|
is_small = False
|
|
@@ -153,6 +156,9 @@ class OnnxMultimodalModel(OnnxModel[T]):
|
|
|
153
156
|
**kwargs,
|
|
154
157
|
}
|
|
155
158
|
|
|
159
|
+
if extra_session_options is not None:
|
|
160
|
+
params.update(extra_session_options)
|
|
161
|
+
|
|
156
162
|
pool = ParallelWorkerPool(
|
|
157
163
|
num_workers=parallel or 1,
|
|
158
164
|
worker=self._get_text_worker_class(),
|
|
@@ -189,6 +195,7 @@ class OnnxMultimodalModel(OnnxModel[T]):
|
|
|
189
195
|
device_ids: Optional[list[int]] = None,
|
|
190
196
|
local_files_only: bool = False,
|
|
191
197
|
specific_model_path: Optional[str] = None,
|
|
198
|
+
extra_session_options: Optional[dict[str, Any]] = None,
|
|
192
199
|
**kwargs: Any,
|
|
193
200
|
) -> Iterable[T]:
|
|
194
201
|
is_small = False
|
|
@@ -220,6 +227,9 @@ class OnnxMultimodalModel(OnnxModel[T]):
|
|
|
220
227
|
**kwargs,
|
|
221
228
|
}
|
|
222
229
|
|
|
230
|
+
if extra_session_options is not None:
|
|
231
|
+
params.update(extra_session_options)
|
|
232
|
+
|
|
223
233
|
pool = ParallelWorkerPool(
|
|
224
234
|
num_workers=parallel or 1,
|
|
225
235
|
worker=self._get_image_worker_class(),
|
|
@@ -111,6 +111,7 @@ class OnnxTextCrossEncoder(TextCrossEncoderBase, OnnxCrossEncoderModel):
|
|
|
111
111
|
super().__init__(model_name, cache_dir, threads, **kwargs)
|
|
112
112
|
self.providers = providers
|
|
113
113
|
self.lazy_load = lazy_load
|
|
114
|
+
self._extra_session_options = self._select_exposed_session_options(kwargs)
|
|
114
115
|
|
|
115
116
|
# List of device ids, that can be used for data parallel processing in workers
|
|
116
117
|
self.device_ids = device_ids
|
|
@@ -150,6 +151,7 @@ class OnnxTextCrossEncoder(TextCrossEncoderBase, OnnxCrossEncoderModel):
|
|
|
150
151
|
providers=self.providers,
|
|
151
152
|
cuda=self.cuda,
|
|
152
153
|
device_id=self.device_id,
|
|
154
|
+
extra_session_options=self._extra_session_options,
|
|
153
155
|
)
|
|
154
156
|
|
|
155
157
|
def rerank(
|
|
@@ -192,6 +194,7 @@ class OnnxTextCrossEncoder(TextCrossEncoderBase, OnnxCrossEncoderModel):
|
|
|
192
194
|
device_ids=self.device_ids,
|
|
193
195
|
local_files_only=self._local_files_only,
|
|
194
196
|
specific_model_path=self._specific_model_path,
|
|
197
|
+
extra_session_options=self._extra_session_options,
|
|
195
198
|
**kwargs,
|
|
196
199
|
)
|
|
197
200
|
|
|
@@ -204,6 +207,20 @@ class OnnxTextCrossEncoder(TextCrossEncoderBase, OnnxCrossEncoderModel):
|
|
|
204
207
|
) -> Iterable[float]:
|
|
205
208
|
return (float(elem) for elem in output.model_output)
|
|
206
209
|
|
|
210
|
+
def token_count(
|
|
211
|
+
self, pairs: Iterable[tuple[str, str]], batch_size: int = 1024, **kwargs: Any
|
|
212
|
+
) -> int:
|
|
213
|
+
"""Returns the number of tokens in the pairs.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
pairs: Iterable of tuples, where each tuple contains a query and a document to be tokenized
|
|
217
|
+
batch_size: Batch size for tokenizing
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
token count: overall number of tokens in the pairs
|
|
221
|
+
"""
|
|
222
|
+
return self._token_count(pairs, batch_size=batch_size, **kwargs)
|
|
223
|
+
|
|
207
224
|
|
|
208
225
|
class TextCrossEncoderWorker(TextRerankerWorker):
|
|
209
226
|
def init_embedding(
|
{fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/rerank/cross_encoder/onnx_text_model.py
RENAMED
|
@@ -33,6 +33,7 @@ class OnnxCrossEncoderModel(OnnxModel[float]):
|
|
|
33
33
|
providers: Optional[Sequence[OnnxProvider]] = None,
|
|
34
34
|
cuda: bool = False,
|
|
35
35
|
device_id: Optional[int] = None,
|
|
36
|
+
extra_session_options: Optional[dict[str, Any]] = None,
|
|
36
37
|
) -> None:
|
|
37
38
|
super()._load_onnx_model(
|
|
38
39
|
model_dir=model_dir,
|
|
@@ -41,6 +42,7 @@ class OnnxCrossEncoderModel(OnnxModel[float]):
|
|
|
41
42
|
providers=providers,
|
|
42
43
|
cuda=cuda,
|
|
43
44
|
device_id=device_id,
|
|
45
|
+
extra_session_options=extra_session_options,
|
|
44
46
|
)
|
|
45
47
|
self.tokenizer, _ = load_tokenizer(model_dir=model_dir)
|
|
46
48
|
assert self.tokenizer is not None
|
|
@@ -96,6 +98,7 @@ class OnnxCrossEncoderModel(OnnxModel[float]):
|
|
|
96
98
|
device_ids: Optional[list[int]] = None,
|
|
97
99
|
local_files_only: bool = False,
|
|
98
100
|
specific_model_path: Optional[str] = None,
|
|
101
|
+
extra_session_options: Optional[dict[str, Any]] = None,
|
|
99
102
|
**kwargs: Any,
|
|
100
103
|
) -> Iterable[float]:
|
|
101
104
|
is_small = False
|
|
@@ -127,6 +130,9 @@ class OnnxCrossEncoderModel(OnnxModel[float]):
|
|
|
127
130
|
**kwargs,
|
|
128
131
|
}
|
|
129
132
|
|
|
133
|
+
if extra_session_options is not None:
|
|
134
|
+
params.update(extra_session_options)
|
|
135
|
+
|
|
130
136
|
pool = ParallelWorkerPool(
|
|
131
137
|
num_workers=parallel or 1,
|
|
132
138
|
worker=self._get_worker_class(),
|
|
@@ -159,6 +165,20 @@ class OnnxCrossEncoderModel(OnnxModel[float]):
|
|
|
159
165
|
"""
|
|
160
166
|
return onnx_input
|
|
161
167
|
|
|
168
|
+
def _token_count(
|
|
169
|
+
self, pairs: Iterable[tuple[str, str]], batch_size: int = 1024, **_: Any
|
|
170
|
+
) -> int:
|
|
171
|
+
if not hasattr(self, "model") or self.model is None:
|
|
172
|
+
self.load_onnx_model() # loads the tokenizer as well
|
|
173
|
+
|
|
174
|
+
token_num = 0
|
|
175
|
+
assert self.tokenizer is not None
|
|
176
|
+
for batch in iter_batch(pairs, batch_size):
|
|
177
|
+
for tokens in self.tokenizer.encode_batch(batch):
|
|
178
|
+
token_num += sum(tokens.attention_mask)
|
|
179
|
+
|
|
180
|
+
return token_num
|
|
181
|
+
|
|
162
182
|
|
|
163
183
|
class TextRerankerWorker(EmbeddingWorker[float]):
|
|
164
184
|
def __init__(
|
{fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/rerank/cross_encoder/text_cross_encoder.py
RENAMED
|
@@ -161,3 +161,17 @@ class TextCrossEncoder(TextCrossEncoderBase):
|
|
|
161
161
|
additional_files=additional_files or [],
|
|
162
162
|
)
|
|
163
163
|
)
|
|
164
|
+
|
|
165
|
+
def token_count(
|
|
166
|
+
self, pairs: Iterable[tuple[str, str]], batch_size: int = 1024, **kwargs: Any
|
|
167
|
+
) -> int:
|
|
168
|
+
"""Returns the number of tokens in the pairs.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
pairs: Iterable of tuples, where each tuple contains a query and a document to be tokenized
|
|
172
|
+
batch_size: Batch size for tokenizing
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
token count: overall number of tokens in the pairs
|
|
176
|
+
"""
|
|
177
|
+
return self.model.token_count(pairs, batch_size=batch_size, **kwargs)
|
|
@@ -57,3 +57,7 @@ class TextCrossEncoderBase(ModelManagement[BaseModelDescription]):
|
|
|
57
57
|
Iterable[float]: Scores for each individual pair
|
|
58
58
|
"""
|
|
59
59
|
raise NotImplementedError("This method should be overridden by subclasses")
|
|
60
|
+
|
|
61
|
+
def token_count(self, pairs: Iterable[tuple[str, str]], **kwargs: Any) -> int:
|
|
62
|
+
"""Returns the number of tokens in the pairs."""
|
|
63
|
+
raise NotImplementedError("This method should be overridden by subclasses")
|
|
@@ -268,6 +268,15 @@ class Bm25(SparseTextEmbeddingBase):
|
|
|
268
268
|
embeddings.append(SparseEmbedding.from_dict(token_id2value))
|
|
269
269
|
return embeddings
|
|
270
270
|
|
|
271
|
+
def token_count(self, texts: Union[str, Iterable[str]], **kwargs: Any) -> int:
|
|
272
|
+
token_num = 0
|
|
273
|
+
texts = [texts] if isinstance(texts, str) else texts
|
|
274
|
+
for text in texts:
|
|
275
|
+
document = remove_non_alphanumeric(text)
|
|
276
|
+
tokens = self.tokenizer.tokenize(document)
|
|
277
|
+
token_num += len(tokens)
|
|
278
|
+
return token_num
|
|
279
|
+
|
|
271
280
|
def _term_frequency(self, tokens: list[str]) -> dict[int, float]:
|
|
272
281
|
"""Calculate the term frequency part of the BM25 formula.
|
|
273
282
|
|
|
@@ -31,9 +31,17 @@ supported_bm42_models: list[SparseModelDescription] = [
|
|
|
31
31
|
),
|
|
32
32
|
]
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
|
|
35
|
+
_MODEL_TO_LANGUAGE = {
|
|
35
36
|
"Qdrant/bm42-all-minilm-l6-v2-attentions": "english",
|
|
36
37
|
}
|
|
38
|
+
MODEL_TO_LANGUAGE = {
|
|
39
|
+
model_name.lower(): language for model_name, language in _MODEL_TO_LANGUAGE.items()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_language_by_model_name(model_name: str) -> str:
|
|
44
|
+
return MODEL_TO_LANGUAGE[model_name.lower()]
|
|
37
45
|
|
|
38
46
|
|
|
39
47
|
class Bm42(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
@@ -95,6 +103,7 @@ class Bm42(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
95
103
|
super().__init__(model_name, cache_dir, threads, **kwargs)
|
|
96
104
|
self.providers = providers
|
|
97
105
|
self.lazy_load = lazy_load
|
|
106
|
+
self._extra_session_options = self._select_exposed_session_options(kwargs)
|
|
98
107
|
|
|
99
108
|
# List of device ids, that can be used for data parallel processing in workers
|
|
100
109
|
self.device_ids = device_ids
|
|
@@ -124,7 +133,7 @@ class Bm42(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
124
133
|
self.special_tokens_ids: set[int] = set()
|
|
125
134
|
self.punctuation = set(string.punctuation)
|
|
126
135
|
self.stopwords = set(self._load_stopwords(self._model_dir))
|
|
127
|
-
self.stemmer = SnowballStemmer(
|
|
136
|
+
self.stemmer = SnowballStemmer(get_language_by_model_name(self.model_name))
|
|
128
137
|
self.alpha = alpha
|
|
129
138
|
|
|
130
139
|
if not self.lazy_load:
|
|
@@ -138,6 +147,7 @@ class Bm42(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
138
147
|
providers=self.providers,
|
|
139
148
|
cuda=self.cuda,
|
|
140
149
|
device_id=self.device_id,
|
|
150
|
+
extra_session_options=self._extra_session_options,
|
|
141
151
|
)
|
|
142
152
|
|
|
143
153
|
for token, idx in self.tokenizer.get_vocab().items(): # type: ignore[union-attr]
|
|
@@ -304,6 +314,7 @@ class Bm42(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
304
314
|
alpha=self.alpha,
|
|
305
315
|
local_files_only=self._local_files_only,
|
|
306
316
|
specific_model_path=self._specific_model_path,
|
|
317
|
+
extra_session_options=self._extra_session_options,
|
|
307
318
|
)
|
|
308
319
|
|
|
309
320
|
@classmethod
|
|
@@ -341,6 +352,13 @@ class Bm42(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
341
352
|
def _get_worker_class(cls) -> Type[TextEmbeddingWorker[SparseEmbedding]]:
|
|
342
353
|
return Bm42TextEmbeddingWorker
|
|
343
354
|
|
|
355
|
+
def token_count(
|
|
356
|
+
self, texts: Union[str, Iterable[str]], batch_size: int = 1024, **kwargs: Any
|
|
357
|
+
) -> int:
|
|
358
|
+
if not hasattr(self, "model") or self.model is None:
|
|
359
|
+
self.load_onnx_model() # loads the tokenizer as well
|
|
360
|
+
return self._token_count(texts, batch_size=batch_size, **kwargs)
|
|
361
|
+
|
|
344
362
|
|
|
345
363
|
class Bm42TextEmbeddingWorker(TextEmbeddingWorker[SparseEmbedding]):
|
|
346
364
|
def init_embedding(self, model_name: str, cache_dir: str, **kwargs: Any) -> Bm42:
|
|
@@ -46,9 +46,16 @@ supported_minicoil_models: list[SparseModelDescription] = [
|
|
|
46
46
|
),
|
|
47
47
|
]
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
_MODEL_TO_LANGUAGE = {
|
|
50
50
|
"Qdrant/minicoil-v1": "english",
|
|
51
51
|
}
|
|
52
|
+
MODEL_TO_LANGUAGE = {
|
|
53
|
+
model_name.lower(): language for model_name, language in _MODEL_TO_LANGUAGE.items()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_language_by_model_name(model_name: str) -> str:
|
|
58
|
+
return MODEL_TO_LANGUAGE[model_name.lower()]
|
|
52
59
|
|
|
53
60
|
|
|
54
61
|
class MiniCOIL(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
@@ -110,6 +117,8 @@ class MiniCOIL(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
110
117
|
self.device_ids = device_ids
|
|
111
118
|
self.cuda = cuda
|
|
112
119
|
self.device_id = device_id
|
|
120
|
+
self._extra_session_options = self._select_exposed_session_options(kwargs)
|
|
121
|
+
|
|
113
122
|
self.k = k
|
|
114
123
|
self.b = b
|
|
115
124
|
self.avg_len = avg_len
|
|
@@ -146,6 +155,7 @@ class MiniCOIL(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
146
155
|
providers=self.providers,
|
|
147
156
|
cuda=self.cuda,
|
|
148
157
|
device_id=self.device_id,
|
|
158
|
+
extra_session_options=self._extra_session_options,
|
|
149
159
|
)
|
|
150
160
|
|
|
151
161
|
assert self.tokenizer is not None
|
|
@@ -156,7 +166,7 @@ class MiniCOIL(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
156
166
|
self.special_tokens_ids = set(self.special_token_to_id.values())
|
|
157
167
|
self.stopwords = set(self._load_stopwords(self._model_dir))
|
|
158
168
|
|
|
159
|
-
stemmer = SnowballStemmer(
|
|
169
|
+
stemmer = SnowballStemmer(get_language_by_model_name(self.model_name))
|
|
160
170
|
|
|
161
171
|
self.vocab_resolver = VocabResolver(
|
|
162
172
|
tokenizer=VocabTokenizer(self.tokenizer),
|
|
@@ -177,6 +187,11 @@ class MiniCOIL(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
177
187
|
avg_len=self.avg_len,
|
|
178
188
|
)
|
|
179
189
|
|
|
190
|
+
def token_count(
|
|
191
|
+
self, texts: Union[str, Iterable[str]], batch_size: int = 1024, **kwargs: Any
|
|
192
|
+
) -> int:
|
|
193
|
+
return self._token_count(texts, batch_size=batch_size, **kwargs)
|
|
194
|
+
|
|
180
195
|
def embed(
|
|
181
196
|
self,
|
|
182
197
|
documents: Union[str, Iterable[str]],
|
|
@@ -214,6 +229,7 @@ class MiniCOIL(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
214
229
|
is_query=False,
|
|
215
230
|
local_files_only=self._local_files_only,
|
|
216
231
|
specific_model_path=self._specific_model_path,
|
|
232
|
+
extra_session_options=self._extra_session_options,
|
|
217
233
|
**kwargs,
|
|
218
234
|
)
|
|
219
235
|
|
|
@@ -86,3 +86,7 @@ class SparseTextEmbeddingBase(ModelManagement[SparseModelDescription]):
|
|
|
86
86
|
yield from self.embed([query], **kwargs)
|
|
87
87
|
else:
|
|
88
88
|
yield from self.embed(query, **kwargs)
|
|
89
|
+
|
|
90
|
+
def token_count(self, texts: Union[str, Iterable[str]], **kwargs: Any) -> int:
|
|
91
|
+
"""Returns the number of tokens in the texts."""
|
|
92
|
+
raise NotImplementedError("Subclasses must implement this method")
|
|
@@ -128,3 +128,17 @@ class SparseTextEmbedding(SparseTextEmbeddingBase):
|
|
|
128
128
|
Iterable[SparseEmbedding]: The sparse embeddings.
|
|
129
129
|
"""
|
|
130
130
|
yield from self.model.query_embed(query, **kwargs)
|
|
131
|
+
|
|
132
|
+
def token_count(
|
|
133
|
+
self, texts: Union[str, Iterable[str]], batch_size: int = 1024, **kwargs: Any
|
|
134
|
+
) -> int:
|
|
135
|
+
"""Returns the number of tokens in the texts.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
texts (str | Iterable[str]): The list of texts to embed.
|
|
139
|
+
batch_size (int): Batch size for encoding
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
int: Sum of number of tokens in the texts.
|
|
143
|
+
"""
|
|
144
|
+
return self.model.token_count(texts, batch_size=batch_size, **kwargs)
|
|
@@ -53,6 +53,11 @@ class SpladePP(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
53
53
|
scores = row_scores[indices]
|
|
54
54
|
yield SparseEmbedding(values=scores, indices=indices)
|
|
55
55
|
|
|
56
|
+
def token_count(
|
|
57
|
+
self, texts: Union[str, Iterable[str]], batch_size: int = 1024, **kwargs: Any
|
|
58
|
+
) -> int:
|
|
59
|
+
return self._token_count(texts, batch_size=batch_size, **kwargs)
|
|
60
|
+
|
|
56
61
|
@classmethod
|
|
57
62
|
def _list_supported_models(cls) -> list[SparseModelDescription]:
|
|
58
63
|
"""Lists the supported models.
|
|
@@ -99,6 +104,7 @@ class SpladePP(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
99
104
|
super().__init__(model_name, cache_dir, threads, **kwargs)
|
|
100
105
|
self.providers = providers
|
|
101
106
|
self.lazy_load = lazy_load
|
|
107
|
+
self._extra_session_options = self._select_exposed_session_options(kwargs)
|
|
102
108
|
|
|
103
109
|
# List of device ids, that can be used for data parallel processing in workers
|
|
104
110
|
self.device_ids = device_ids
|
|
@@ -133,6 +139,7 @@ class SpladePP(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
133
139
|
providers=self.providers,
|
|
134
140
|
cuda=self.cuda,
|
|
135
141
|
device_id=self.device_id,
|
|
142
|
+
extra_session_options=self._extra_session_options,
|
|
136
143
|
)
|
|
137
144
|
|
|
138
145
|
def embed(
|
|
@@ -168,6 +175,7 @@ class SpladePP(SparseTextEmbeddingBase, OnnxTextModel[SparseEmbedding]):
|
|
|
168
175
|
device_ids=self.device_ids,
|
|
169
176
|
local_files_only=self._local_files_only,
|
|
170
177
|
specific_model_path=self._specific_model_path,
|
|
178
|
+
extra_session_options=self._extra_session_options,
|
|
171
179
|
**kwargs,
|
|
172
180
|
)
|
|
173
181
|
|
|
@@ -233,7 +233,7 @@ class OnnxTextEmbedding(TextEmbeddingBase, OnnxTextModel[NumpyArray]):
|
|
|
233
233
|
super().__init__(model_name, cache_dir, threads, **kwargs)
|
|
234
234
|
self.providers = providers
|
|
235
235
|
self.lazy_load = lazy_load
|
|
236
|
-
|
|
236
|
+
self._extra_session_options = self._select_exposed_session_options(kwargs)
|
|
237
237
|
# List of device ids, that can be used for data parallel processing in workers
|
|
238
238
|
self.device_ids = device_ids
|
|
239
239
|
self.cuda = cuda
|
|
@@ -291,6 +291,7 @@ class OnnxTextEmbedding(TextEmbeddingBase, OnnxTextModel[NumpyArray]):
|
|
|
291
291
|
device_ids=self.device_ids,
|
|
292
292
|
local_files_only=self._local_files_only,
|
|
293
293
|
specific_model_path=self._specific_model_path,
|
|
294
|
+
extra_session_options=self._extra_session_options,
|
|
294
295
|
**kwargs,
|
|
295
296
|
)
|
|
296
297
|
|
|
@@ -327,8 +328,14 @@ class OnnxTextEmbedding(TextEmbeddingBase, OnnxTextModel[NumpyArray]):
|
|
|
327
328
|
providers=self.providers,
|
|
328
329
|
cuda=self.cuda,
|
|
329
330
|
device_id=self.device_id,
|
|
331
|
+
extra_session_options=self._extra_session_options,
|
|
330
332
|
)
|
|
331
333
|
|
|
334
|
+
def token_count(
|
|
335
|
+
self, texts: Union[str, Iterable[str]], batch_size: int = 1024, **kwargs: Any
|
|
336
|
+
) -> int:
|
|
337
|
+
return self._token_count(texts, batch_size=batch_size, **kwargs)
|
|
338
|
+
|
|
332
339
|
|
|
333
340
|
class OnnxTextEmbeddingWorker(TextEmbeddingWorker[NumpyArray]):
|
|
334
341
|
def init_embedding(
|
|
@@ -54,6 +54,7 @@ class OnnxTextModel(OnnxModel[T]):
|
|
|
54
54
|
providers: Optional[Sequence[OnnxProvider]] = None,
|
|
55
55
|
cuda: bool = False,
|
|
56
56
|
device_id: Optional[int] = None,
|
|
57
|
+
extra_session_options: Optional[dict[str, Any]] = None,
|
|
57
58
|
) -> None:
|
|
58
59
|
super()._load_onnx_model(
|
|
59
60
|
model_dir=model_dir,
|
|
@@ -62,6 +63,7 @@ class OnnxTextModel(OnnxModel[T]):
|
|
|
62
63
|
providers=providers,
|
|
63
64
|
cuda=cuda,
|
|
64
65
|
device_id=device_id,
|
|
66
|
+
extra_session_options=extra_session_options,
|
|
65
67
|
)
|
|
66
68
|
self.tokenizer, self.special_token_to_id = load_tokenizer(model_dir=model_dir)
|
|
67
69
|
|
|
@@ -110,6 +112,7 @@ class OnnxTextModel(OnnxModel[T]):
|
|
|
110
112
|
device_ids: Optional[list[int]] = None,
|
|
111
113
|
local_files_only: bool = False,
|
|
112
114
|
specific_model_path: Optional[str] = None,
|
|
115
|
+
extra_session_options: Optional[dict[str, Any]] = None,
|
|
113
116
|
**kwargs: Any,
|
|
114
117
|
) -> Iterable[T]:
|
|
115
118
|
is_small = False
|
|
@@ -143,6 +146,9 @@ class OnnxTextModel(OnnxModel[T]):
|
|
|
143
146
|
**kwargs,
|
|
144
147
|
}
|
|
145
148
|
|
|
149
|
+
if extra_session_options is not None:
|
|
150
|
+
params.update(extra_session_options)
|
|
151
|
+
|
|
146
152
|
pool = ParallelWorkerPool(
|
|
147
153
|
num_workers=parallel or 1,
|
|
148
154
|
worker=self._get_worker_class(),
|
|
@@ -153,6 +159,21 @@ class OnnxTextModel(OnnxModel[T]):
|
|
|
153
159
|
for batch in pool.ordered_map(iter_batch(documents, batch_size), **params):
|
|
154
160
|
yield from self._post_process_onnx_output(batch, **kwargs) # type: ignore
|
|
155
161
|
|
|
162
|
+
def _token_count(
|
|
163
|
+
self, texts: Union[str, Iterable[str]], batch_size: int = 1024, **_: Any
|
|
164
|
+
) -> int:
|
|
165
|
+
if not hasattr(self, "model") or self.model is None:
|
|
166
|
+
self.load_onnx_model() # loads the tokenizer as well
|
|
167
|
+
|
|
168
|
+
token_num = 0
|
|
169
|
+
assert self.tokenizer is not None
|
|
170
|
+
texts = [texts] if isinstance(texts, str) else texts
|
|
171
|
+
for batch in iter_batch(texts, batch_size):
|
|
172
|
+
for tokens in self.tokenizer.encode_batch(batch):
|
|
173
|
+
token_num += sum(tokens.attention_mask)
|
|
174
|
+
|
|
175
|
+
return token_num
|
|
176
|
+
|
|
156
177
|
|
|
157
178
|
class TextEmbeddingWorker(EmbeddingWorker[T]):
|
|
158
179
|
def process(self, items: Iterable[tuple[int, Any]]) -> Iterable[tuple[int, OnnxOutputContext]]:
|
|
@@ -212,3 +212,17 @@ class TextEmbedding(TextEmbeddingBase):
|
|
|
212
212
|
"""
|
|
213
213
|
# This is model-specific, so that different models can have specialized implementations
|
|
214
214
|
yield from self.model.passage_embed(texts, **kwargs)
|
|
215
|
+
|
|
216
|
+
def token_count(
|
|
217
|
+
self, texts: Union[str, Iterable[str]], batch_size: int = 1024, **kwargs: Any
|
|
218
|
+
) -> int:
|
|
219
|
+
"""Returns the number of tokens in the texts.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
texts (str | Iterable[str]): The list of texts to embed.
|
|
223
|
+
batch_size (int): Batch size for encoding
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
int: Sum of number of tokens in the texts.
|
|
227
|
+
"""
|
|
228
|
+
return self.model.token_count(texts, batch_size=batch_size, **kwargs)
|
|
@@ -69,3 +69,7 @@ class TextEmbeddingBase(ModelManagement[DenseModelDescription]):
|
|
|
69
69
|
def embedding_size(self) -> int:
|
|
70
70
|
"""Returns embedding size for the current model"""
|
|
71
71
|
raise NotImplementedError("Subclasses must implement this method")
|
|
72
|
+
|
|
73
|
+
def token_count(self, texts: Union[str, Iterable[str]], **kwargs: Any) -> int:
|
|
74
|
+
"""Returns the number of tokens in the texts."""
|
|
75
|
+
raise NotImplementedError("Subclasses must implement this method")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "fastembed-gpu"
|
|
3
|
-
version = "0.7.
|
|
3
|
+
version = "0.7.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"
|
|
@@ -13,10 +13,12 @@ keywords = ["vector", "embedding", "neural", "search", "qdrant", "sentence-trans
|
|
|
13
13
|
[tool.poetry.dependencies]
|
|
14
14
|
python = ">=3.9.0"
|
|
15
15
|
numpy = [
|
|
16
|
-
{ version = ">=1.21", python = ">=3.10,<3.12" },
|
|
17
|
-
{ version = ">=1.26", python = ">=3.12,<3.13" },
|
|
18
|
-
{ version = ">=2.1.0", python = ">=3.13" },
|
|
19
16
|
{ version = ">=1.21,<2.1.0", python = "<3.10" },
|
|
17
|
+
{ version = ">=1.21,<2.3.0", python = ">=3.10,<3.11" },
|
|
18
|
+
{ version = ">=1.21", python = ">=3.11,<3.12" },
|
|
19
|
+
{ version = ">=1.26", python = ">=3.12,<3.13" },
|
|
20
|
+
{ version = ">=2.1.0", python = ">=3.13,<3.14" },
|
|
21
|
+
{ version = ">=2.3.0", python = ">=3.14" },
|
|
20
22
|
]
|
|
21
23
|
onnxruntime-gpu = [
|
|
22
24
|
{ version = ">=1.17.0,<1.20.0", python = "<3.10" },
|
|
@@ -26,9 +28,13 @@ onnxruntime-gpu = [
|
|
|
26
28
|
tqdm = "^4.66"
|
|
27
29
|
requests = "^2.31"
|
|
28
30
|
tokenizers = ">=0.15,<1.0"
|
|
29
|
-
huggingface-hub = ">=0.20,<
|
|
31
|
+
huggingface-hub = ">=0.20,<2.0"
|
|
30
32
|
loguru = "^0.7.2"
|
|
31
|
-
pillow =
|
|
33
|
+
pillow = [
|
|
34
|
+
{ version = ">=10.3.0,<11.0", python = "<3.10" },
|
|
35
|
+
{ version = ">=10.3.0,<12.0", python = ">=3.10,<3.13" },
|
|
36
|
+
{ version = ">=11.0.0,<12.0", python = ">=3.13" },
|
|
37
|
+
]
|
|
32
38
|
mmh3 = ">=4.1.0,<6.0.0"
|
|
33
39
|
py-rust-stemmers = "^0.1.0"
|
|
34
40
|
|
|
@@ -39,12 +45,15 @@ ruff = ">=0.3.1,<1.0"
|
|
|
39
45
|
[tool.poetry.group.dev.dependencies]
|
|
40
46
|
notebook = ">=7.0.2"
|
|
41
47
|
pre-commit = "^3.6.2"
|
|
42
|
-
onnx =
|
|
48
|
+
onnx = [
|
|
49
|
+
{ version = ">=1.15.0", python = "<3.13" },
|
|
50
|
+
{ version = ">=1.18.0", python = ">=3.13" },
|
|
51
|
+
]
|
|
43
52
|
|
|
44
53
|
[tool.poetry.group.docs.dependencies]
|
|
45
54
|
mkdocs-material = "^9.5.10"
|
|
46
55
|
mkdocstrings = "^0.24.0"
|
|
47
|
-
pillow = ">=10.3.0,<
|
|
56
|
+
pillow = ">=10.3.0,<13.0.0"
|
|
48
57
|
cairosvg = "^2.7.1"
|
|
49
58
|
mknotebooks = "^0.8.0"
|
|
50
59
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/late_interaction_multimodal/__init__.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
|
{fastembed_gpu-0.7.2 → fastembed_gpu-0.7.4}/fastembed/sparse/utils/sparse_vectors_converter.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
|