amazon-bedrock-haystack 5.2.0__py3-none-any.whl → 5.3.1__py3-none-any.whl
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.
- {amazon_bedrock_haystack-5.2.0.dist-info → amazon_bedrock_haystack-5.3.1.dist-info}/METADATA +1 -1
- {amazon_bedrock_haystack-5.2.0.dist-info → amazon_bedrock_haystack-5.3.1.dist-info}/RECORD +13 -13
- {amazon_bedrock_haystack-5.2.0.dist-info → amazon_bedrock_haystack-5.3.1.dist-info}/WHEEL +1 -1
- haystack_integrations/components/downloaders/s3/s3_downloader.py +10 -10
- haystack_integrations/components/embedders/amazon_bedrock/document_embedder.py +27 -35
- haystack_integrations/components/embedders/amazon_bedrock/document_image_embedder.py +31 -30
- haystack_integrations/components/embedders/amazon_bedrock/text_embedder.py +23 -29
- haystack_integrations/components/generators/amazon_bedrock/adapters.py +33 -33
- haystack_integrations/components/generators/amazon_bedrock/chat/chat_generator.py +17 -17
- haystack_integrations/components/generators/amazon_bedrock/chat/utils.py +22 -22
- haystack_integrations/components/generators/amazon_bedrock/generator.py +10 -10
- haystack_integrations/components/rankers/amazon_bedrock/ranker.py +7 -7
- {amazon_bedrock_haystack-5.2.0.dist-info → amazon_bedrock_haystack-5.3.1.dist-info}/licenses/LICENSE.txt +0 -0
{amazon_bedrock_haystack-5.2.0.dist-info → amazon_bedrock_haystack-5.3.1.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: amazon-bedrock-haystack
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.3.1
|
|
4
4
|
Summary: An integration of AWS S3 and Bedrock as a Downloader and Generator components.
|
|
5
5
|
Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/amazon_bedrock#readme
|
|
6
6
|
Project-URL: Issues, https://github.com/deepset-ai/haystack-core-integrations/issues
|
|
@@ -7,23 +7,23 @@ haystack_integrations/common/s3/errors.py,sha256=BrTDLdhQvAuQutyg35cFyP5h8PNkDEi
|
|
|
7
7
|
haystack_integrations/common/s3/utils.py,sha256=OJupFj54aQmg6S8VuVq6Lc2qpFZyyJajRVIpwe3_6iA,4744
|
|
8
8
|
haystack_integrations/components/downloaders/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
haystack_integrations/components/downloaders/s3/__init__.py,sha256=2BOd3_N0kGqRJGH-ENrTJqOqzqHryRYaSuNqpLYKMFo,179
|
|
10
|
-
haystack_integrations/components/downloaders/s3/s3_downloader.py,sha256=
|
|
10
|
+
haystack_integrations/components/downloaders/s3/s3_downloader.py,sha256=jj9VMQ5QciTZvJ8Qki_zha0tcK0-APm2rMhMPObtr1M,12625
|
|
11
11
|
haystack_integrations/components/embedders/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
haystack_integrations/components/embedders/amazon_bedrock/__init__.py,sha256=7GlhHJ4jFHCxq5QN5losGuGtrGNjvEx2dSQvEYD2yG0,408
|
|
13
|
-
haystack_integrations/components/embedders/amazon_bedrock/document_embedder.py,sha256=
|
|
14
|
-
haystack_integrations/components/embedders/amazon_bedrock/document_image_embedder.py,sha256=
|
|
15
|
-
haystack_integrations/components/embedders/amazon_bedrock/text_embedder.py,sha256=
|
|
13
|
+
haystack_integrations/components/embedders/amazon_bedrock/document_embedder.py,sha256=EKLiKzN0al7OLvfIAnXXNgUTI4TbSc-qCkfjjDJeCd4,13216
|
|
14
|
+
haystack_integrations/components/embedders/amazon_bedrock/document_image_embedder.py,sha256=qKsWRGkubFMHDeqTbPgA5qvEag_CDNTnc5kEmDbc6IQ,16202
|
|
15
|
+
haystack_integrations/components/embedders/amazon_bedrock/text_embedder.py,sha256=rYmU39q_-9uKANBebcQsPtGE0EjrAkOQSFHL3e6WYag,9349
|
|
16
16
|
haystack_integrations/components/generators/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
haystack_integrations/components/generators/amazon_bedrock/__init__.py,sha256=lv4NouIVm78YavUssWQrHHP_81u-7j21qW8v1kZMJPQ,284
|
|
18
|
-
haystack_integrations/components/generators/amazon_bedrock/adapters.py,sha256=
|
|
19
|
-
haystack_integrations/components/generators/amazon_bedrock/generator.py,sha256=
|
|
18
|
+
haystack_integrations/components/generators/amazon_bedrock/adapters.py,sha256=SDCi_EA-1OUmTKrnbcql9oQQuLnoAGzF_XwrKnQ1_jk,19628
|
|
19
|
+
haystack_integrations/components/generators/amazon_bedrock/generator.py,sha256=1vuA0x6k8UOvPjeKjYvcYORpsTFXs1rKMUXlima51IY,14725
|
|
20
20
|
haystack_integrations/components/generators/amazon_bedrock/chat/__init__.py,sha256=6GZ8Y3Lw0rLOsOAqi6Tu5mZC977UzQvgDxKpOWr8IQw,110
|
|
21
|
-
haystack_integrations/components/generators/amazon_bedrock/chat/chat_generator.py,sha256=
|
|
22
|
-
haystack_integrations/components/generators/amazon_bedrock/chat/utils.py,sha256=
|
|
21
|
+
haystack_integrations/components/generators/amazon_bedrock/chat/chat_generator.py,sha256=batM98HDpUyZEwG-pGYhgTQ6Z9uoGE2TUb3EaZjmox4,26227
|
|
22
|
+
haystack_integrations/components/generators/amazon_bedrock/chat/utils.py,sha256=sWgh-58YeDIatDFNLX2YG1KPJghsyXK5p5uVM4pe8U4,27236
|
|
23
23
|
haystack_integrations/components/rankers/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
haystack_integrations/components/rankers/amazon_bedrock/__init__.py,sha256=mJQKShAP5AfZvfKQisSh7kfKu6RIXzsYdk4eqMtcaEk,75
|
|
25
|
-
haystack_integrations/components/rankers/amazon_bedrock/ranker.py,sha256=
|
|
26
|
-
amazon_bedrock_haystack-5.
|
|
27
|
-
amazon_bedrock_haystack-5.
|
|
28
|
-
amazon_bedrock_haystack-5.
|
|
29
|
-
amazon_bedrock_haystack-5.
|
|
25
|
+
haystack_integrations/components/rankers/amazon_bedrock/ranker.py,sha256=oFNTF2BnKNA1VERiF42ttTFDzxOiaBIA1H5ozLNFFFU,11800
|
|
26
|
+
amazon_bedrock_haystack-5.3.1.dist-info/METADATA,sha256=-icmdgZ9-poMEUHeBb470jU0VnpZwAzlHOcaUS57bLA,2228
|
|
27
|
+
amazon_bedrock_haystack-5.3.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
28
|
+
amazon_bedrock_haystack-5.3.1.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
|
|
29
|
+
amazon_bedrock_haystack-5.3.1.dist-info/RECORD,,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import os
|
|
6
6
|
from concurrent.futures import ThreadPoolExecutor
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Any, Callable,
|
|
8
|
+
from typing import Any, Callable, Optional
|
|
9
9
|
|
|
10
10
|
from botocore.config import Config
|
|
11
11
|
from haystack import component, default_from_dict, default_to_dict, logging
|
|
@@ -36,9 +36,9 @@ class S3Downloader:
|
|
|
36
36
|
aws_session_token: Optional[Secret] = Secret.from_env_var("AWS_SESSION_TOKEN", strict=False), # noqa: B008
|
|
37
37
|
aws_region_name: Optional[Secret] = Secret.from_env_var("AWS_DEFAULT_REGION", strict=False), # noqa: B008
|
|
38
38
|
aws_profile_name: Optional[Secret] = Secret.from_env_var("AWS_PROFILE", strict=False), # noqa: B008
|
|
39
|
-
boto3_config: Optional[
|
|
39
|
+
boto3_config: Optional[dict[str, Any]] = None,
|
|
40
40
|
file_root_path: Optional[str] = None,
|
|
41
|
-
file_extensions: Optional[
|
|
41
|
+
file_extensions: Optional[list[str]] = None,
|
|
42
42
|
file_name_meta_key: str = "file_name",
|
|
43
43
|
max_workers: int = 32,
|
|
44
44
|
max_cache_size: int = 100,
|
|
@@ -126,11 +126,11 @@ class S3Downloader:
|
|
|
126
126
|
self.file_root_path.mkdir(parents=True, exist_ok=True)
|
|
127
127
|
self._storage = S3Storage.from_env(session=self._session, config=self._config)
|
|
128
128
|
|
|
129
|
-
@component.output_types(documents=
|
|
129
|
+
@component.output_types(documents=list[Document])
|
|
130
130
|
def run(
|
|
131
131
|
self,
|
|
132
|
-
documents:
|
|
133
|
-
) ->
|
|
132
|
+
documents: list[Document],
|
|
133
|
+
) -> dict[str, list[Document]]:
|
|
134
134
|
"""Download files from AWS S3 Buckets to local filesystem.
|
|
135
135
|
|
|
136
136
|
Return enriched `Document`s with the path of the downloaded file.
|
|
@@ -160,7 +160,7 @@ class S3Downloader:
|
|
|
160
160
|
downloaded_documents = [d for d in iterable if d is not None]
|
|
161
161
|
return {"documents": downloaded_documents}
|
|
162
162
|
|
|
163
|
-
def _filter_documents_by_extensions(self, documents:
|
|
163
|
+
def _filter_documents_by_extensions(self, documents: list[Document]) -> list[Document]:
|
|
164
164
|
"""Filter documents by file extensions."""
|
|
165
165
|
if not self.file_extensions:
|
|
166
166
|
return documents
|
|
@@ -202,7 +202,7 @@ class S3Downloader:
|
|
|
202
202
|
document.meta["file_path"] = str(file_path)
|
|
203
203
|
return document
|
|
204
204
|
|
|
205
|
-
def _cleanup_cache(self, documents:
|
|
205
|
+
def _cleanup_cache(self, documents: list[Document]) -> None:
|
|
206
206
|
"""
|
|
207
207
|
Remove least-recently-accessed cache files when cache exceeds `max_cache_size`.
|
|
208
208
|
|
|
@@ -224,7 +224,7 @@ class S3Downloader:
|
|
|
224
224
|
except Exception as error:
|
|
225
225
|
logger.warning("Failed to remove cache file at {path} with error: {e}", path=p, e=error)
|
|
226
226
|
|
|
227
|
-
def to_dict(self) ->
|
|
227
|
+
def to_dict(self) -> dict[str, Any]:
|
|
228
228
|
"""Serialize the component to a dictionary."""
|
|
229
229
|
|
|
230
230
|
s3_key_generation_function_name = (
|
|
@@ -247,7 +247,7 @@ class S3Downloader:
|
|
|
247
247
|
)
|
|
248
248
|
|
|
249
249
|
@classmethod
|
|
250
|
-
def from_dict(cls, data:
|
|
250
|
+
def from_dict(cls, data: dict[str, Any]) -> "S3Downloader":
|
|
251
251
|
"""
|
|
252
252
|
Deserializes the component from a dictionary.
|
|
253
253
|
:param data:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from typing import Any,
|
|
2
|
+
from typing import Any, Optional
|
|
3
3
|
|
|
4
4
|
from botocore.config import Config
|
|
5
5
|
from botocore.exceptions import ClientError
|
|
@@ -16,14 +16,6 @@ from haystack_integrations.common.amazon_bedrock.utils import get_aws_session
|
|
|
16
16
|
|
|
17
17
|
logger = logging.getLogger(__name__)
|
|
18
18
|
|
|
19
|
-
SUPPORTED_EMBEDDING_MODELS = [
|
|
20
|
-
"amazon.titan-embed-text-v1",
|
|
21
|
-
"cohere.embed-english-v3",
|
|
22
|
-
"cohere.embed-multilingual-v3",
|
|
23
|
-
"amazon.titan-embed-text-v2:0",
|
|
24
|
-
"amazon.titan-embed-image-v1",
|
|
25
|
-
]
|
|
26
|
-
|
|
27
19
|
|
|
28
20
|
@component
|
|
29
21
|
class AmazonBedrockDocumentEmbedder:
|
|
@@ -57,13 +49,7 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
57
49
|
|
|
58
50
|
def __init__(
|
|
59
51
|
self,
|
|
60
|
-
model:
|
|
61
|
-
"amazon.titan-embed-text-v1",
|
|
62
|
-
"cohere.embed-english-v3",
|
|
63
|
-
"cohere.embed-multilingual-v3",
|
|
64
|
-
"amazon.titan-embed-text-v2:0",
|
|
65
|
-
"amazon.titan-embed-image-v1",
|
|
66
|
-
],
|
|
52
|
+
model: str,
|
|
67
53
|
aws_access_key_id: Optional[Secret] = Secret.from_env_var("AWS_ACCESS_KEY_ID", strict=False), # noqa: B008
|
|
68
54
|
aws_secret_access_key: Optional[Secret] = Secret.from_env_var( # noqa: B008
|
|
69
55
|
"AWS_SECRET_ACCESS_KEY", strict=False
|
|
@@ -73,9 +59,9 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
73
59
|
aws_profile_name: Optional[Secret] = Secret.from_env_var("AWS_PROFILE", strict=False), # noqa: B008
|
|
74
60
|
batch_size: int = 32,
|
|
75
61
|
progress_bar: bool = True,
|
|
76
|
-
meta_fields_to_embed: Optional[
|
|
62
|
+
meta_fields_to_embed: Optional[list[str]] = None,
|
|
77
63
|
embedding_separator: str = "\n",
|
|
78
|
-
boto3_config: Optional[
|
|
64
|
+
boto3_config: Optional[dict[str, Any]] = None,
|
|
79
65
|
**kwargs: Any,
|
|
80
66
|
) -> None:
|
|
81
67
|
"""
|
|
@@ -88,8 +74,13 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
88
74
|
constructor. Aside from model, three required parameters are `aws_access_key_id`, `aws_secret_access_key`,
|
|
89
75
|
and `aws_region_name`.
|
|
90
76
|
|
|
91
|
-
:param model: The embedding model to use.
|
|
92
|
-
|
|
77
|
+
:param model: The embedding model to use.
|
|
78
|
+
Amazon Titan and Cohere embedding models are supported, for example:
|
|
79
|
+
"amazon.titan-embed-text-v1", "amazon.titan-embed-text-v2:0", "amazon.titan-embed-image-v1",
|
|
80
|
+
"cohere.embed-english-v3", "cohere.embed-multilingual-v3", "cohere.embed-v4:0".
|
|
81
|
+
To find all supported models, refer to the Amazon Bedrock
|
|
82
|
+
[documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html) and
|
|
83
|
+
filter for "embedding", then select models from the Amazon Titan and Cohere series.
|
|
93
84
|
:param aws_access_key_id: AWS access key ID.
|
|
94
85
|
:param aws_secret_access_key: AWS secret access key.
|
|
95
86
|
:param aws_session_token: AWS session token.
|
|
@@ -107,11 +98,8 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
107
98
|
:raises ValueError: If the model is not supported.
|
|
108
99
|
:raises AmazonBedrockConfigurationError: If the AWS environment is not configured correctly.
|
|
109
100
|
"""
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
msg = "Please provide a valid model from the list of supported models: " + ", ".join(
|
|
113
|
-
SUPPORTED_EMBEDDING_MODELS
|
|
114
|
-
)
|
|
101
|
+
if "titan" not in model and "cohere" not in model:
|
|
102
|
+
msg = f"Model {model} is not supported. Only Amazon Titan and Cohere embedding models are supported."
|
|
115
103
|
raise ValueError(msg)
|
|
116
104
|
|
|
117
105
|
self.model = model
|
|
@@ -149,7 +137,7 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
149
137
|
)
|
|
150
138
|
raise AmazonBedrockConfigurationError(msg) from exception
|
|
151
139
|
|
|
152
|
-
def _prepare_texts_to_embed(self, documents:
|
|
140
|
+
def _prepare_texts_to_embed(self, documents: list[Document]) -> list[str]:
|
|
153
141
|
"""
|
|
154
142
|
Prepare the texts to embed by concatenating the Document text with the metadata fields to embed.
|
|
155
143
|
"""
|
|
@@ -162,7 +150,7 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
162
150
|
texts_to_embed.append(text_to_embed)
|
|
163
151
|
return texts_to_embed
|
|
164
152
|
|
|
165
|
-
def _embed_cohere(self, documents:
|
|
153
|
+
def _embed_cohere(self, documents: list[Document]) -> list[Document]:
|
|
166
154
|
"""
|
|
167
155
|
Internal method to embed Documents using Cohere models.
|
|
168
156
|
Batch inference is supported.
|
|
@@ -191,15 +179,19 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
191
179
|
msg = f"Could not perform inference for Amazon Bedrock model {self.model} due to:\n{exception}"
|
|
192
180
|
raise AmazonBedrockInferenceError(msg) from exception
|
|
193
181
|
|
|
194
|
-
|
|
195
|
-
|
|
182
|
+
cohere_embeddings = json.loads(response.get("body").read())["embeddings"]
|
|
183
|
+
# depending on the model, Cohere returns a dict with the embedding types as keys or a list of lists
|
|
184
|
+
embeddings_list = (
|
|
185
|
+
next(iter(cohere_embeddings.values())) if isinstance(cohere_embeddings, dict) else cohere_embeddings
|
|
186
|
+
)
|
|
187
|
+
all_embeddings.extend(embeddings_list)
|
|
196
188
|
|
|
197
189
|
for doc, emb in zip(documents, all_embeddings):
|
|
198
190
|
doc.embedding = emb
|
|
199
191
|
|
|
200
192
|
return documents
|
|
201
193
|
|
|
202
|
-
def _embed_titan(self, documents:
|
|
194
|
+
def _embed_titan(self, documents: list[Document]) -> list[Document]:
|
|
203
195
|
"""
|
|
204
196
|
Internal method to embed Documents using Amazon Titan models.
|
|
205
197
|
NOTE: Batch inference is not supported, so embeddings are created one by one.
|
|
@@ -227,8 +219,8 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
227
219
|
|
|
228
220
|
return documents
|
|
229
221
|
|
|
230
|
-
@component.output_types(documents=
|
|
231
|
-
def run(self, documents:
|
|
222
|
+
@component.output_types(documents=list[Document])
|
|
223
|
+
def run(self, documents: list[Document]) -> dict[str, list[Document]]:
|
|
232
224
|
"""Embed the provided `Document`s using the specified model.
|
|
233
225
|
|
|
234
226
|
:param documents: The `Document`s to embed.
|
|
@@ -248,12 +240,12 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
248
240
|
elif "titan" in self.model:
|
|
249
241
|
documents_with_embeddings = self._embed_titan(documents=documents)
|
|
250
242
|
else:
|
|
251
|
-
msg = f"Model {self.model} is not supported.
|
|
243
|
+
msg = f"Model {self.model} is not supported. Only Amazon Titan and Cohere embedding models are supported."
|
|
252
244
|
raise ValueError(msg)
|
|
253
245
|
|
|
254
246
|
return {"documents": documents_with_embeddings}
|
|
255
247
|
|
|
256
|
-
def to_dict(self) ->
|
|
248
|
+
def to_dict(self) -> dict[str, Any]:
|
|
257
249
|
"""
|
|
258
250
|
Serializes the component to a dictionary.
|
|
259
251
|
|
|
@@ -277,7 +269,7 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
277
269
|
)
|
|
278
270
|
|
|
279
271
|
@classmethod
|
|
280
|
-
def from_dict(cls, data:
|
|
272
|
+
def from_dict(cls, data: dict[str, Any]) -> "AmazonBedrockDocumentEmbedder":
|
|
281
273
|
"""
|
|
282
274
|
Deserializes the component from a dictionary.
|
|
283
275
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
from dataclasses import replace
|
|
7
|
-
from typing import Any,
|
|
7
|
+
from typing import Any, Optional
|
|
8
8
|
|
|
9
9
|
from botocore.config import Config
|
|
10
10
|
from botocore.exceptions import ClientError
|
|
@@ -27,8 +27,6 @@ from haystack_integrations.common.amazon_bedrock.utils import get_aws_session
|
|
|
27
27
|
|
|
28
28
|
logger = logging.getLogger(__name__)
|
|
29
29
|
|
|
30
|
-
SUPPORTED_EMBEDDING_MODELS = ["amazon.titan-embed-image-v1", "cohere.embed-english-v3", "cohere.embed-multilingual-v3"]
|
|
31
|
-
|
|
32
30
|
|
|
33
31
|
@component
|
|
34
32
|
class AmazonBedrockDocumentImageEmbedder:
|
|
@@ -69,7 +67,7 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
69
67
|
def __init__(
|
|
70
68
|
self,
|
|
71
69
|
*,
|
|
72
|
-
model:
|
|
70
|
+
model: str,
|
|
73
71
|
aws_access_key_id: Optional[Secret] = Secret.from_env_var("AWS_ACCESS_KEY_ID", strict=False), # noqa: B008
|
|
74
72
|
aws_secret_access_key: Optional[Secret] = Secret.from_env_var( # noqa: B008
|
|
75
73
|
"AWS_SECRET_ACCESS_KEY", strict=False
|
|
@@ -79,20 +77,21 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
79
77
|
aws_profile_name: Optional[Secret] = Secret.from_env_var("AWS_PROFILE", strict=False), # noqa: B008
|
|
80
78
|
file_path_meta_field: str = "file_path",
|
|
81
79
|
root_path: Optional[str] = None,
|
|
82
|
-
image_size: Optional[
|
|
80
|
+
image_size: Optional[tuple[int, int]] = None,
|
|
83
81
|
progress_bar: bool = True,
|
|
84
|
-
boto3_config: Optional[
|
|
82
|
+
boto3_config: Optional[dict[str, Any]] = None,
|
|
85
83
|
**kwargs: Any,
|
|
86
84
|
) -> None:
|
|
87
85
|
"""
|
|
88
86
|
Creates a AmazonBedrockDocumentImageEmbedder component.
|
|
89
87
|
|
|
90
|
-
:param model:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
-
|
|
88
|
+
:param model: The embedding model to use.
|
|
89
|
+
Amazon Titan and Cohere multimodal embedding models are supported, for example:
|
|
90
|
+
"amazon.titan-embed-image-v1", "cohere.embed-english-v3", "cohere.embed-multilingual-v3",
|
|
91
|
+
"cohere.embed-v4:0".
|
|
92
|
+
To find all supported models, refer to the Amazon Bedrock
|
|
93
|
+
[documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html) and
|
|
94
|
+
filter for "embedding", then select multimodal models from the Amazon Titan and Cohere series.
|
|
96
95
|
:param aws_access_key_id: AWS access key ID.
|
|
97
96
|
:param aws_secret_access_key: AWS secret access key.
|
|
98
97
|
:param aws_session_token: AWS session token.
|
|
@@ -114,9 +113,10 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
114
113
|
:raises ValueError: If the model is not supported.
|
|
115
114
|
:raises AmazonBedrockConfigurationError: If the AWS environment is not configured correctly.
|
|
116
115
|
"""
|
|
117
|
-
if not model
|
|
118
|
-
msg =
|
|
119
|
-
|
|
116
|
+
if "titan" not in model and "cohere" not in model:
|
|
117
|
+
msg = (
|
|
118
|
+
f"Model {model} is not supported. "
|
|
119
|
+
"Only Amazon Titan and Cohere multimodal embedding models are supported."
|
|
120
120
|
)
|
|
121
121
|
raise ValueError(msg)
|
|
122
122
|
|
|
@@ -135,14 +135,14 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
135
135
|
self.kwargs = kwargs
|
|
136
136
|
self.embedding_types = None
|
|
137
137
|
|
|
138
|
-
if
|
|
139
|
-
if len(
|
|
138
|
+
if embedding_types := self.kwargs.get("embedding_types"):
|
|
139
|
+
if len(embedding_types) > 1:
|
|
140
140
|
msg = (
|
|
141
141
|
"You have provided multiple embedding_types for Cohere model. "
|
|
142
142
|
"AmazonBedrockDocumentImageEmbedder only supports one embedding_type at a time."
|
|
143
143
|
)
|
|
144
144
|
raise ValueError(msg)
|
|
145
|
-
self.embedding_types =
|
|
145
|
+
self.embedding_types = embedding_types
|
|
146
146
|
|
|
147
147
|
def resolve_secret(secret: Optional[Secret]) -> Optional[str]:
|
|
148
148
|
return secret.resolve_value() if secret else None
|
|
@@ -280,7 +280,10 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
280
280
|
elif "titan" in self.model:
|
|
281
281
|
embeddings = self._embed_titan(images=images_to_embed)
|
|
282
282
|
else:
|
|
283
|
-
msg =
|
|
283
|
+
msg = (
|
|
284
|
+
f"Model {self.model} is not supported. "
|
|
285
|
+
"Only Amazon Titan and Cohere multimodal embedding models are supported."
|
|
286
|
+
)
|
|
284
287
|
raise ValueError(msg)
|
|
285
288
|
|
|
286
289
|
docs_with_embeddings = []
|
|
@@ -296,7 +299,7 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
296
299
|
|
|
297
300
|
return {"documents": docs_with_embeddings}
|
|
298
301
|
|
|
299
|
-
def _embed_titan(self, images:
|
|
302
|
+
def _embed_titan(self, images: list[str]) -> list[list[float]]:
|
|
300
303
|
"""
|
|
301
304
|
Internal method to embed base64 images using Amazon Titan models.
|
|
302
305
|
|
|
@@ -326,7 +329,7 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
326
329
|
|
|
327
330
|
return all_embeddings
|
|
328
331
|
|
|
329
|
-
def _embed_cohere(self, image_uris:
|
|
332
|
+
def _embed_cohere(self, image_uris: list[str]) -> list[list[float]]:
|
|
330
333
|
"""
|
|
331
334
|
Internal method to embed base64 images using Cohere models.
|
|
332
335
|
|
|
@@ -351,15 +354,13 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
351
354
|
raise AmazonBedrockInferenceError(msg) from exception
|
|
352
355
|
|
|
353
356
|
response_body = json.loads(response.get("body").read())
|
|
354
|
-
|
|
357
|
+
cohere_embeddings = response_body["embeddings"]
|
|
355
358
|
|
|
356
|
-
#
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
# a nested list of float embeddings
|
|
363
|
-
all_embeddings.append(embeddings[0])
|
|
359
|
+
# depending on the model and embedding_types, Cohere returns a dict with the embedding types as keys
|
|
360
|
+
# or a list of lists
|
|
361
|
+
embeddings_list = (
|
|
362
|
+
next(iter(cohere_embeddings.values())) if isinstance(cohere_embeddings, dict) else cohere_embeddings
|
|
363
|
+
)
|
|
364
|
+
all_embeddings.extend(embeddings_list)
|
|
364
365
|
|
|
365
366
|
return all_embeddings
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from typing import Any,
|
|
2
|
+
from typing import Any, Optional
|
|
3
3
|
|
|
4
4
|
from botocore.config import Config
|
|
5
5
|
from botocore.exceptions import ClientError
|
|
@@ -14,14 +14,6 @@ from haystack_integrations.common.amazon_bedrock.utils import get_aws_session
|
|
|
14
14
|
|
|
15
15
|
logger = logging.getLogger(__name__)
|
|
16
16
|
|
|
17
|
-
SUPPORTED_EMBEDDING_MODELS = [
|
|
18
|
-
"amazon.titan-embed-text-v1",
|
|
19
|
-
"cohere.embed-english-v3",
|
|
20
|
-
"cohere.embed-multilingual-v3",
|
|
21
|
-
"amazon.titan-embed-text-v2:0",
|
|
22
|
-
"amazon.titan-embed-image-v1",
|
|
23
|
-
]
|
|
24
|
-
|
|
25
17
|
|
|
26
18
|
@component
|
|
27
19
|
class AmazonBedrockTextEmbedder:
|
|
@@ -50,13 +42,7 @@ class AmazonBedrockTextEmbedder:
|
|
|
50
42
|
|
|
51
43
|
def __init__(
|
|
52
44
|
self,
|
|
53
|
-
model:
|
|
54
|
-
"amazon.titan-embed-text-v1",
|
|
55
|
-
"cohere.embed-english-v3",
|
|
56
|
-
"cohere.embed-multilingual-v3",
|
|
57
|
-
"amazon.titan-embed-text-v2:0",
|
|
58
|
-
"amazon.titan-embed-image-v1",
|
|
59
|
-
],
|
|
45
|
+
model: str,
|
|
60
46
|
aws_access_key_id: Optional[Secret] = Secret.from_env_var("AWS_ACCESS_KEY_ID", strict=False), # noqa: B008
|
|
61
47
|
aws_secret_access_key: Optional[Secret] = Secret.from_env_var( # noqa: B008
|
|
62
48
|
"AWS_SECRET_ACCESS_KEY", strict=False
|
|
@@ -64,7 +50,7 @@ class AmazonBedrockTextEmbedder:
|
|
|
64
50
|
aws_session_token: Optional[Secret] = Secret.from_env_var("AWS_SESSION_TOKEN", strict=False), # noqa: B008
|
|
65
51
|
aws_region_name: Optional[Secret] = Secret.from_env_var("AWS_DEFAULT_REGION", strict=False), # noqa: B008
|
|
66
52
|
aws_profile_name: Optional[Secret] = Secret.from_env_var("AWS_PROFILE", strict=False), # noqa: B008
|
|
67
|
-
boto3_config: Optional[
|
|
53
|
+
boto3_config: Optional[dict[str, Any]] = None,
|
|
68
54
|
**kwargs: Any,
|
|
69
55
|
) -> None:
|
|
70
56
|
"""
|
|
@@ -77,8 +63,13 @@ class AmazonBedrockTextEmbedder:
|
|
|
77
63
|
constructor. Aside from model, three required parameters are `aws_access_key_id`, `aws_secret_access_key`,
|
|
78
64
|
and `aws_region_name`.
|
|
79
65
|
|
|
80
|
-
:param model: The embedding model to use.
|
|
81
|
-
|
|
66
|
+
:param model: The embedding model to use.
|
|
67
|
+
Amazon Titan and Cohere embedding models are supported, for example:
|
|
68
|
+
"amazon.titan-embed-text-v1", "amazon.titan-embed-text-v2:0", "amazon.titan-embed-image-v1",
|
|
69
|
+
"cohere.embed-english-v3", "cohere.embed-multilingual-v3", "cohere.embed-v4:0".
|
|
70
|
+
To find all supported models, refer to the Amazon Bedrock
|
|
71
|
+
[documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html) and
|
|
72
|
+
filter for "embedding", then select models from the Amazon Titan and Cohere series.
|
|
82
73
|
:param aws_access_key_id: AWS access key ID.
|
|
83
74
|
:param aws_secret_access_key: AWS secret access key.
|
|
84
75
|
:param aws_session_token: AWS session token.
|
|
@@ -90,10 +81,8 @@ class AmazonBedrockTextEmbedder:
|
|
|
90
81
|
:raises ValueError: If the model is not supported.
|
|
91
82
|
:raises AmazonBedrockConfigurationError: If the AWS environment is not configured correctly.
|
|
92
83
|
"""
|
|
93
|
-
if not model
|
|
94
|
-
msg = "
|
|
95
|
-
SUPPORTED_EMBEDDING_MODELS
|
|
96
|
-
)
|
|
84
|
+
if "titan" not in model and "cohere" not in model:
|
|
85
|
+
msg = f"Model {model} is not supported. Only Amazon Titan and Cohere embedding models are supported."
|
|
97
86
|
raise ValueError(msg)
|
|
98
87
|
|
|
99
88
|
self.model = model
|
|
@@ -127,8 +116,8 @@ class AmazonBedrockTextEmbedder:
|
|
|
127
116
|
)
|
|
128
117
|
raise AmazonBedrockConfigurationError(msg) from exception
|
|
129
118
|
|
|
130
|
-
@component.output_types(embedding=
|
|
131
|
-
def run(self, text: str) ->
|
|
119
|
+
@component.output_types(embedding=list[float])
|
|
120
|
+
def run(self, text: str) -> dict[str, list[float]]:
|
|
132
121
|
"""Embeds the input text using the Amazon Bedrock model.
|
|
133
122
|
|
|
134
123
|
:param text: The input text to embed.
|
|
@@ -168,16 +157,21 @@ class AmazonBedrockTextEmbedder:
|
|
|
168
157
|
response_body = json.loads(response.get("body").read())
|
|
169
158
|
|
|
170
159
|
if "cohere" in self.model:
|
|
171
|
-
|
|
160
|
+
cohere_embeddings = response_body["embeddings"]
|
|
161
|
+
# depending on the model, Cohere returns a dict with the embedding types as keys or a list of lists
|
|
162
|
+
embeddings_list = (
|
|
163
|
+
next(iter(cohere_embeddings.values())) if isinstance(cohere_embeddings, dict) else cohere_embeddings
|
|
164
|
+
)
|
|
165
|
+
embedding = embeddings_list[0]
|
|
172
166
|
elif "titan" in self.model:
|
|
173
167
|
embedding = response_body["embedding"]
|
|
174
168
|
else:
|
|
175
|
-
msg = f"
|
|
169
|
+
msg = f"Model {self.model} is not supported. Only Amazon Titan and Cohere embedding models are supported."
|
|
176
170
|
raise ValueError(msg)
|
|
177
171
|
|
|
178
172
|
return {"embedding": embedding}
|
|
179
173
|
|
|
180
|
-
def to_dict(self) ->
|
|
174
|
+
def to_dict(self) -> dict[str, Any]:
|
|
181
175
|
"""
|
|
182
176
|
Serializes the component to a dictionary.
|
|
183
177
|
|
|
@@ -197,7 +191,7 @@ class AmazonBedrockTextEmbedder:
|
|
|
197
191
|
)
|
|
198
192
|
|
|
199
193
|
@classmethod
|
|
200
|
-
def from_dict(cls, data:
|
|
194
|
+
def from_dict(cls, data: dict[str, Any]) -> "AmazonBedrockTextEmbedder":
|
|
201
195
|
"""
|
|
202
196
|
Deserializes the component from a dictionary.
|
|
203
197
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from abc import ABC, abstractmethod
|
|
3
|
-
from typing import Any,
|
|
3
|
+
from typing import Any, Optional
|
|
4
4
|
|
|
5
5
|
from botocore.eventstream import EventStream
|
|
6
6
|
from haystack.dataclasses import StreamingChunk, SyncStreamingCallbackT
|
|
@@ -19,12 +19,12 @@ class BedrockModelAdapter(ABC):
|
|
|
19
19
|
It will be overridden by the corresponding parameter in the `model_kwargs` if it is present.
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
def __init__(self, model_kwargs:
|
|
22
|
+
def __init__(self, model_kwargs: dict[str, Any], max_length: Optional[int]) -> None:
|
|
23
23
|
self.model_kwargs = model_kwargs
|
|
24
24
|
self.max_length = max_length
|
|
25
25
|
|
|
26
26
|
@abstractmethod
|
|
27
|
-
def prepare_body(self, prompt: str, **inference_kwargs: Any) ->
|
|
27
|
+
def prepare_body(self, prompt: str, **inference_kwargs: Any) -> dict[str, Any]:
|
|
28
28
|
"""
|
|
29
29
|
Prepares the body for the Amazon Bedrock request.
|
|
30
30
|
Each subclass should implement this method to prepare the request body for the specific model.
|
|
@@ -34,7 +34,7 @@ class BedrockModelAdapter(ABC):
|
|
|
34
34
|
:returns: A dictionary containing the body for the request.
|
|
35
35
|
"""
|
|
36
36
|
|
|
37
|
-
def get_responses(self, response_body:
|
|
37
|
+
def get_responses(self, response_body: dict[str, Any]) -> list[str]:
|
|
38
38
|
"""
|
|
39
39
|
Extracts the responses from the Amazon Bedrock response.
|
|
40
40
|
|
|
@@ -45,7 +45,7 @@ class BedrockModelAdapter(ABC):
|
|
|
45
45
|
responses = [completion.lstrip() for completion in completions]
|
|
46
46
|
return responses
|
|
47
47
|
|
|
48
|
-
def get_stream_responses(self, stream: EventStream, streaming_callback: SyncStreamingCallbackT) ->
|
|
48
|
+
def get_stream_responses(self, stream: EventStream, streaming_callback: SyncStreamingCallbackT) -> list[str]:
|
|
49
49
|
"""
|
|
50
50
|
Extracts the responses from the Amazon Bedrock streaming response.
|
|
51
51
|
|
|
@@ -53,7 +53,7 @@ class BedrockModelAdapter(ABC):
|
|
|
53
53
|
:param streaming_callback: The handler for the streaming response.
|
|
54
54
|
:returns: A list of string responses.
|
|
55
55
|
"""
|
|
56
|
-
streaming_chunks:
|
|
56
|
+
streaming_chunks: list[StreamingChunk] = []
|
|
57
57
|
for event in stream:
|
|
58
58
|
chunk = event.get("chunk")
|
|
59
59
|
if chunk:
|
|
@@ -65,7 +65,7 @@ class BedrockModelAdapter(ABC):
|
|
|
65
65
|
responses = ["".join(streaming_chunk.content for streaming_chunk in streaming_chunks).lstrip()]
|
|
66
66
|
return responses
|
|
67
67
|
|
|
68
|
-
def _get_params(self, inference_kwargs:
|
|
68
|
+
def _get_params(self, inference_kwargs: dict[str, Any], default_params: dict[str, Any]) -> dict[str, Any]:
|
|
69
69
|
"""
|
|
70
70
|
Merges the default params with the inference kwargs and model kwargs.
|
|
71
71
|
|
|
@@ -83,7 +83,7 @@ class BedrockModelAdapter(ABC):
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
@abstractmethod
|
|
86
|
-
def _extract_completions_from_response(self, response_body:
|
|
86
|
+
def _extract_completions_from_response(self, response_body: dict[str, Any]) -> list[str]:
|
|
87
87
|
"""
|
|
88
88
|
Extracts the responses from the Amazon Bedrock response.
|
|
89
89
|
|
|
@@ -92,7 +92,7 @@ class BedrockModelAdapter(ABC):
|
|
|
92
92
|
"""
|
|
93
93
|
|
|
94
94
|
@abstractmethod
|
|
95
|
-
def _build_streaming_chunk(self, chunk:
|
|
95
|
+
def _build_streaming_chunk(self, chunk: dict[str, Any]) -> StreamingChunk:
|
|
96
96
|
"""
|
|
97
97
|
Extracts the content and meta from a streaming chunk.
|
|
98
98
|
|
|
@@ -115,7 +115,7 @@ class AnthropicClaudeAdapter(BedrockModelAdapter):
|
|
|
115
115
|
:param max_length: Maximum length of generated text
|
|
116
116
|
"""
|
|
117
117
|
|
|
118
|
-
def __init__(self, model_kwargs:
|
|
118
|
+
def __init__(self, model_kwargs: dict[str, Any], max_length: Optional[int]) -> None:
|
|
119
119
|
self.use_messages_api = model_kwargs.get("use_messages_api", True)
|
|
120
120
|
self.include_thinking = model_kwargs.get("include_thinking", True)
|
|
121
121
|
self.thinking_tag = model_kwargs.get("thinking_tag", "thinking")
|
|
@@ -123,7 +123,7 @@ class AnthropicClaudeAdapter(BedrockModelAdapter):
|
|
|
123
123
|
self.thinking_tag_end = f"</{self.thinking_tag}>\n\n" if self.thinking_tag else "\n\n"
|
|
124
124
|
super().__init__(model_kwargs, max_length)
|
|
125
125
|
|
|
126
|
-
def prepare_body(self, prompt: str, **inference_kwargs: Any) ->
|
|
126
|
+
def prepare_body(self, prompt: str, **inference_kwargs: Any) -> dict[str, Any]:
|
|
127
127
|
"""
|
|
128
128
|
Prepares the body for the Claude model
|
|
129
129
|
|
|
@@ -134,7 +134,7 @@ class AnthropicClaudeAdapter(BedrockModelAdapter):
|
|
|
134
134
|
- specified inference parameters.
|
|
135
135
|
"""
|
|
136
136
|
if self.use_messages_api:
|
|
137
|
-
default_params:
|
|
137
|
+
default_params: dict[str, Any] = {
|
|
138
138
|
"anthropic_version": "bedrock-2023-05-31",
|
|
139
139
|
"max_tokens": self.max_length,
|
|
140
140
|
"system": None,
|
|
@@ -160,7 +160,7 @@ class AnthropicClaudeAdapter(BedrockModelAdapter):
|
|
|
160
160
|
body = {"prompt": f"\n\nHuman: {prompt}\n\nAssistant:", **params}
|
|
161
161
|
return body
|
|
162
162
|
|
|
163
|
-
def _extract_completions_from_response(self, response_body:
|
|
163
|
+
def _extract_completions_from_response(self, response_body: dict[str, Any]) -> list[str]:
|
|
164
164
|
"""
|
|
165
165
|
Extracts the responses from the Amazon Bedrock response.
|
|
166
166
|
|
|
@@ -181,7 +181,7 @@ class AnthropicClaudeAdapter(BedrockModelAdapter):
|
|
|
181
181
|
|
|
182
182
|
return [response_body["completion"]]
|
|
183
183
|
|
|
184
|
-
def _build_streaming_chunk(self, chunk:
|
|
184
|
+
def _build_streaming_chunk(self, chunk: dict[str, Any]) -> StreamingChunk:
|
|
185
185
|
"""
|
|
186
186
|
Extracts the content and meta from a streaming chunk.
|
|
187
187
|
|
|
@@ -211,7 +211,7 @@ class MistralAdapter(BedrockModelAdapter):
|
|
|
211
211
|
Adapter for the Mistral models.
|
|
212
212
|
"""
|
|
213
213
|
|
|
214
|
-
def prepare_body(self, prompt: str, **inference_kwargs: Any) ->
|
|
214
|
+
def prepare_body(self, prompt: str, **inference_kwargs: Any) -> dict[str, Any]:
|
|
215
215
|
"""
|
|
216
216
|
Prepares the body for the Mistral model
|
|
217
217
|
|
|
@@ -221,7 +221,7 @@ class MistralAdapter(BedrockModelAdapter):
|
|
|
221
221
|
- `prompt`: The prompt to be sent to the model.
|
|
222
222
|
- specified inference parameters.
|
|
223
223
|
"""
|
|
224
|
-
default_params:
|
|
224
|
+
default_params: dict[str, Any] = {
|
|
225
225
|
"max_tokens": self.max_length,
|
|
226
226
|
"stop": [],
|
|
227
227
|
"temperature": None,
|
|
@@ -233,7 +233,7 @@ class MistralAdapter(BedrockModelAdapter):
|
|
|
233
233
|
formatted_prompt = f"<s>[INST] {prompt} [/INST]" if "INST" not in prompt else prompt
|
|
234
234
|
return {"prompt": formatted_prompt, **params}
|
|
235
235
|
|
|
236
|
-
def _extract_completions_from_response(self, response_body:
|
|
236
|
+
def _extract_completions_from_response(self, response_body: dict[str, Any]) -> list[str]:
|
|
237
237
|
"""
|
|
238
238
|
Extracts the responses from the Amazon Bedrock response.
|
|
239
239
|
|
|
@@ -242,7 +242,7 @@ class MistralAdapter(BedrockModelAdapter):
|
|
|
242
242
|
"""
|
|
243
243
|
return [output.get("text", "") for output in response_body.get("outputs", [])]
|
|
244
244
|
|
|
245
|
-
def _build_streaming_chunk(self, chunk:
|
|
245
|
+
def _build_streaming_chunk(self, chunk: dict[str, Any]) -> StreamingChunk:
|
|
246
246
|
"""
|
|
247
247
|
Extracts the content and meta from a streaming chunk.
|
|
248
248
|
|
|
@@ -261,7 +261,7 @@ class CohereCommandAdapter(BedrockModelAdapter):
|
|
|
261
261
|
Adapter for the Cohere Command model.
|
|
262
262
|
"""
|
|
263
263
|
|
|
264
|
-
def prepare_body(self, prompt: str, **inference_kwargs: Any) ->
|
|
264
|
+
def prepare_body(self, prompt: str, **inference_kwargs: Any) -> dict[str, Any]:
|
|
265
265
|
"""
|
|
266
266
|
Prepares the body for the Command model
|
|
267
267
|
|
|
@@ -288,7 +288,7 @@ class CohereCommandAdapter(BedrockModelAdapter):
|
|
|
288
288
|
body = {"prompt": prompt, **params}
|
|
289
289
|
return body
|
|
290
290
|
|
|
291
|
-
def _extract_completions_from_response(self, response_body:
|
|
291
|
+
def _extract_completions_from_response(self, response_body: dict[str, Any]) -> list[str]:
|
|
292
292
|
"""
|
|
293
293
|
Extracts the responses from the Cohere Command model response.
|
|
294
294
|
|
|
@@ -298,7 +298,7 @@ class CohereCommandAdapter(BedrockModelAdapter):
|
|
|
298
298
|
responses = [generation["text"] for generation in response_body["generations"]]
|
|
299
299
|
return responses
|
|
300
300
|
|
|
301
|
-
def _build_streaming_chunk(self, chunk:
|
|
301
|
+
def _build_streaming_chunk(self, chunk: dict[str, Any]) -> StreamingChunk:
|
|
302
302
|
"""
|
|
303
303
|
Extracts the content and meta from a streaming chunk.
|
|
304
304
|
|
|
@@ -313,7 +313,7 @@ class CohereCommandRAdapter(BedrockModelAdapter):
|
|
|
313
313
|
Adapter for the Cohere Command R models.
|
|
314
314
|
"""
|
|
315
315
|
|
|
316
|
-
def prepare_body(self, prompt: str, **inference_kwargs: Any) ->
|
|
316
|
+
def prepare_body(self, prompt: str, **inference_kwargs: Any) -> dict[str, Any]:
|
|
317
317
|
"""
|
|
318
318
|
Prepares the body for the Command model
|
|
319
319
|
|
|
@@ -347,7 +347,7 @@ class CohereCommandRAdapter(BedrockModelAdapter):
|
|
|
347
347
|
body = {"message": prompt, **params}
|
|
348
348
|
return body
|
|
349
349
|
|
|
350
|
-
def _extract_completions_from_response(self, response_body:
|
|
350
|
+
def _extract_completions_from_response(self, response_body: dict[str, Any]) -> list[str]:
|
|
351
351
|
"""
|
|
352
352
|
Extracts the responses from the Cohere Command model response.
|
|
353
353
|
|
|
@@ -357,7 +357,7 @@ class CohereCommandRAdapter(BedrockModelAdapter):
|
|
|
357
357
|
responses = [response_body["text"]]
|
|
358
358
|
return responses
|
|
359
359
|
|
|
360
|
-
def _build_streaming_chunk(self, chunk:
|
|
360
|
+
def _build_streaming_chunk(self, chunk: dict[str, Any]) -> StreamingChunk:
|
|
361
361
|
"""
|
|
362
362
|
Extracts the content and meta from a streaming chunk.
|
|
363
363
|
|
|
@@ -373,7 +373,7 @@ class AI21LabsJurassic2Adapter(BedrockModelAdapter):
|
|
|
373
373
|
Model adapter for AI21 Labs' Jurassic 2 models.
|
|
374
374
|
"""
|
|
375
375
|
|
|
376
|
-
def prepare_body(self, prompt: str, **inference_kwargs: Any) ->
|
|
376
|
+
def prepare_body(self, prompt: str, **inference_kwargs: Any) -> dict[str, Any]:
|
|
377
377
|
"""Prepares the body for the Jurassic 2 model.
|
|
378
378
|
|
|
379
379
|
:param prompt: The prompt to be sent to the model.
|
|
@@ -397,11 +397,11 @@ class AI21LabsJurassic2Adapter(BedrockModelAdapter):
|
|
|
397
397
|
body = {"prompt": prompt, **params}
|
|
398
398
|
return body
|
|
399
399
|
|
|
400
|
-
def _extract_completions_from_response(self, response_body:
|
|
400
|
+
def _extract_completions_from_response(self, response_body: dict[str, Any]) -> list[str]:
|
|
401
401
|
responses = [completion["data"]["text"] for completion in response_body["completions"]]
|
|
402
402
|
return responses
|
|
403
403
|
|
|
404
|
-
def _build_streaming_chunk(self, chunk:
|
|
404
|
+
def _build_streaming_chunk(self, chunk: dict[str, Any]) -> StreamingChunk:
|
|
405
405
|
msg = "Streaming is not supported for AI21 Jurassic 2 models."
|
|
406
406
|
raise NotImplementedError(msg)
|
|
407
407
|
|
|
@@ -411,7 +411,7 @@ class AmazonTitanAdapter(BedrockModelAdapter):
|
|
|
411
411
|
Adapter for Amazon's Titan models.
|
|
412
412
|
"""
|
|
413
413
|
|
|
414
|
-
def prepare_body(self, prompt: str, **inference_kwargs: Any) ->
|
|
414
|
+
def prepare_body(self, prompt: str, **inference_kwargs: Any) -> dict[str, Any]:
|
|
415
415
|
"""
|
|
416
416
|
Prepares the body for the Titan model
|
|
417
417
|
|
|
@@ -432,7 +432,7 @@ class AmazonTitanAdapter(BedrockModelAdapter):
|
|
|
432
432
|
body = {"inputText": prompt, "textGenerationConfig": params}
|
|
433
433
|
return body
|
|
434
434
|
|
|
435
|
-
def _extract_completions_from_response(self, response_body:
|
|
435
|
+
def _extract_completions_from_response(self, response_body: dict[str, Any]) -> list[str]:
|
|
436
436
|
"""
|
|
437
437
|
Extracts the responses from the Titan model response.
|
|
438
438
|
|
|
@@ -442,7 +442,7 @@ class AmazonTitanAdapter(BedrockModelAdapter):
|
|
|
442
442
|
responses = [result["outputText"] for result in response_body["results"]]
|
|
443
443
|
return responses
|
|
444
444
|
|
|
445
|
-
def _build_streaming_chunk(self, chunk:
|
|
445
|
+
def _build_streaming_chunk(self, chunk: dict[str, Any]) -> StreamingChunk:
|
|
446
446
|
"""
|
|
447
447
|
Extracts the content and meta from a streaming chunk.
|
|
448
448
|
|
|
@@ -457,7 +457,7 @@ class MetaLlamaAdapter(BedrockModelAdapter):
|
|
|
457
457
|
Adapter for Meta's Llama2 models.
|
|
458
458
|
"""
|
|
459
459
|
|
|
460
|
-
def prepare_body(self, prompt: str, **inference_kwargs: Any) ->
|
|
460
|
+
def prepare_body(self, prompt: str, **inference_kwargs: Any) -> dict[str, Any]:
|
|
461
461
|
"""
|
|
462
462
|
Prepares the body for the Llama2 model
|
|
463
463
|
|
|
@@ -477,7 +477,7 @@ class MetaLlamaAdapter(BedrockModelAdapter):
|
|
|
477
477
|
body = {"prompt": prompt, **params}
|
|
478
478
|
return body
|
|
479
479
|
|
|
480
|
-
def _extract_completions_from_response(self, response_body:
|
|
480
|
+
def _extract_completions_from_response(self, response_body: dict[str, Any]) -> list[str]:
|
|
481
481
|
"""
|
|
482
482
|
Extracts the responses from the Llama2 model response.
|
|
483
483
|
|
|
@@ -486,7 +486,7 @@ class MetaLlamaAdapter(BedrockModelAdapter):
|
|
|
486
486
|
"""
|
|
487
487
|
return [response_body["generation"]]
|
|
488
488
|
|
|
489
|
-
def _build_streaming_chunk(self, chunk:
|
|
489
|
+
def _build_streaming_chunk(self, chunk: dict[str, Any]) -> StreamingChunk:
|
|
490
490
|
"""
|
|
491
491
|
Extracts the content and meta from a streaming chunk.
|
|
492
492
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any,
|
|
1
|
+
from typing import Any, Optional
|
|
2
2
|
|
|
3
3
|
import aioboto3
|
|
4
4
|
from botocore.config import Config
|
|
@@ -154,12 +154,12 @@ class AmazonBedrockChatGenerator:
|
|
|
154
154
|
aws_session_token: Optional[Secret] = Secret.from_env_var(["AWS_SESSION_TOKEN"], strict=False), # noqa: B008
|
|
155
155
|
aws_region_name: Optional[Secret] = Secret.from_env_var(["AWS_DEFAULT_REGION"], strict=False), # noqa: B008
|
|
156
156
|
aws_profile_name: Optional[Secret] = Secret.from_env_var(["AWS_PROFILE"], strict=False), # noqa: B008
|
|
157
|
-
generation_kwargs: Optional[
|
|
157
|
+
generation_kwargs: Optional[dict[str, Any]] = None,
|
|
158
158
|
streaming_callback: Optional[StreamingCallbackT] = None,
|
|
159
|
-
boto3_config: Optional[
|
|
159
|
+
boto3_config: Optional[dict[str, Any]] = None,
|
|
160
160
|
tools: Optional[ToolsType] = None,
|
|
161
161
|
*,
|
|
162
|
-
guardrail_config: Optional[
|
|
162
|
+
guardrail_config: Optional[dict[str, str]] = None,
|
|
163
163
|
) -> None:
|
|
164
164
|
"""
|
|
165
165
|
Initializes the `AmazonBedrockChatGenerator` with the provided parameters. The parameters are passed to the
|
|
@@ -289,7 +289,7 @@ class AmazonBedrockChatGenerator:
|
|
|
289
289
|
)
|
|
290
290
|
raise AmazonBedrockConfigurationError(msg) from exception
|
|
291
291
|
|
|
292
|
-
def to_dict(self) ->
|
|
292
|
+
def to_dict(self) -> dict[str, Any]:
|
|
293
293
|
"""
|
|
294
294
|
Serializes the component to a dictionary.
|
|
295
295
|
|
|
@@ -313,7 +313,7 @@ class AmazonBedrockChatGenerator:
|
|
|
313
313
|
)
|
|
314
314
|
|
|
315
315
|
@classmethod
|
|
316
|
-
def from_dict(cls, data:
|
|
316
|
+
def from_dict(cls, data: dict[str, Any]) -> "AmazonBedrockChatGenerator":
|
|
317
317
|
"""
|
|
318
318
|
Deserializes the component from a dictionary.
|
|
319
319
|
|
|
@@ -340,12 +340,12 @@ class AmazonBedrockChatGenerator:
|
|
|
340
340
|
|
|
341
341
|
def _prepare_request_params(
|
|
342
342
|
self,
|
|
343
|
-
messages:
|
|
343
|
+
messages: list[ChatMessage],
|
|
344
344
|
streaming_callback: Optional[StreamingCallbackT] = None,
|
|
345
|
-
generation_kwargs: Optional[
|
|
345
|
+
generation_kwargs: Optional[dict[str, Any]] = None,
|
|
346
346
|
tools: Optional[ToolsType] = None,
|
|
347
347
|
requires_async: bool = False,
|
|
348
|
-
) ->
|
|
348
|
+
) -> tuple[dict[str, Any], Optional[StreamingCallbackT]]:
|
|
349
349
|
"""
|
|
350
350
|
Prepares and formats parameters required to call the Amazon Bedrock Converse API.
|
|
351
351
|
|
|
@@ -419,14 +419,14 @@ class AmazonBedrockChatGenerator:
|
|
|
419
419
|
|
|
420
420
|
return params, callback
|
|
421
421
|
|
|
422
|
-
@component.output_types(replies=
|
|
422
|
+
@component.output_types(replies=list[ChatMessage])
|
|
423
423
|
def run(
|
|
424
424
|
self,
|
|
425
|
-
messages:
|
|
425
|
+
messages: list[ChatMessage],
|
|
426
426
|
streaming_callback: Optional[StreamingCallbackT] = None,
|
|
427
|
-
generation_kwargs: Optional[
|
|
427
|
+
generation_kwargs: Optional[dict[str, Any]] = None,
|
|
428
428
|
tools: Optional[ToolsType] = None,
|
|
429
|
-
) ->
|
|
429
|
+
) -> dict[str, list[ChatMessage]]:
|
|
430
430
|
"""
|
|
431
431
|
Executes a synchronous inference call to the Amazon Bedrock model using the Converse API.
|
|
432
432
|
|
|
@@ -480,14 +480,14 @@ class AmazonBedrockChatGenerator:
|
|
|
480
480
|
|
|
481
481
|
return {"replies": replies}
|
|
482
482
|
|
|
483
|
-
@component.output_types(replies=
|
|
483
|
+
@component.output_types(replies=list[ChatMessage])
|
|
484
484
|
async def run_async(
|
|
485
485
|
self,
|
|
486
|
-
messages:
|
|
486
|
+
messages: list[ChatMessage],
|
|
487
487
|
streaming_callback: Optional[StreamingCallbackT] = None,
|
|
488
|
-
generation_kwargs: Optional[
|
|
488
|
+
generation_kwargs: Optional[dict[str, Any]] = None,
|
|
489
489
|
tools: Optional[ToolsType] = None,
|
|
490
|
-
) ->
|
|
490
|
+
) -> dict[str, list[ChatMessage]]:
|
|
491
491
|
"""
|
|
492
492
|
Executes an asynchronous inference call to the Amazon Bedrock model using the Converse API.
|
|
493
493
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import base64
|
|
2
2
|
import json
|
|
3
3
|
from datetime import datetime, timezone
|
|
4
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, Optional
|
|
5
5
|
|
|
6
6
|
from botocore.eventstream import EventStream
|
|
7
7
|
from haystack import logging
|
|
@@ -29,7 +29,7 @@ logger = logging.getLogger(__name__)
|
|
|
29
29
|
IMAGE_SUPPORTED_FORMATS = ["png", "jpeg", "gif", "webp"]
|
|
30
30
|
|
|
31
31
|
# see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_MessageStopEvent.html
|
|
32
|
-
FINISH_REASON_MAPPING:
|
|
32
|
+
FINISH_REASON_MAPPING: dict[str, FinishReason] = {
|
|
33
33
|
"end_turn": "stop",
|
|
34
34
|
"stop_sequence": "stop",
|
|
35
35
|
"max_tokens": "length",
|
|
@@ -40,7 +40,7 @@ FINISH_REASON_MAPPING: Dict[str, FinishReason] = {
|
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
# Haystack to Bedrock util methods
|
|
43
|
-
def _format_tools(tools: Optional[
|
|
43
|
+
def _format_tools(tools: Optional[list[Tool]] = None) -> Optional[dict[str, Any]]:
|
|
44
44
|
"""
|
|
45
45
|
Format Haystack Tool(s) to Amazon Bedrock toolConfig format.
|
|
46
46
|
|
|
@@ -60,7 +60,7 @@ def _format_tools(tools: Optional[List[Tool]] = None) -> Optional[Dict[str, Any]
|
|
|
60
60
|
return {"tools": tool_specs} if tool_specs else None
|
|
61
61
|
|
|
62
62
|
|
|
63
|
-
def _format_tool_call_message(tool_call_message: ChatMessage) ->
|
|
63
|
+
def _format_tool_call_message(tool_call_message: ChatMessage) -> dict[str, Any]:
|
|
64
64
|
"""
|
|
65
65
|
Format a Haystack ChatMessage containing tool calls into Bedrock format.
|
|
66
66
|
|
|
@@ -68,7 +68,7 @@ def _format_tool_call_message(tool_call_message: ChatMessage) -> Dict[str, Any]:
|
|
|
68
68
|
:returns:
|
|
69
69
|
Dictionary representing the tool call message in Bedrock's expected format
|
|
70
70
|
"""
|
|
71
|
-
content:
|
|
71
|
+
content: list[dict[str, Any]] = []
|
|
72
72
|
|
|
73
73
|
# tool call messages can contain reasoning content
|
|
74
74
|
if reasoning_content := tool_call_message.reasoning:
|
|
@@ -85,7 +85,7 @@ def _format_tool_call_message(tool_call_message: ChatMessage) -> Dict[str, Any]:
|
|
|
85
85
|
return {"role": tool_call_message.role.value, "content": content}
|
|
86
86
|
|
|
87
87
|
|
|
88
|
-
def _format_tool_result_message(tool_call_result_message: ChatMessage) ->
|
|
88
|
+
def _format_tool_result_message(tool_call_result_message: ChatMessage) -> dict[str, Any]:
|
|
89
89
|
"""
|
|
90
90
|
Format a Haystack ChatMessage containing tool call results into Bedrock format.
|
|
91
91
|
|
|
@@ -114,7 +114,7 @@ def _format_tool_result_message(tool_call_result_message: ChatMessage) -> Dict[s
|
|
|
114
114
|
return {"role": "user", "content": tool_results}
|
|
115
115
|
|
|
116
116
|
|
|
117
|
-
def _repair_tool_result_messages(bedrock_formatted_messages:
|
|
117
|
+
def _repair_tool_result_messages(bedrock_formatted_messages: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
118
118
|
"""
|
|
119
119
|
Repair and reorganize tool result messages to maintain proper ordering and grouping.
|
|
120
120
|
|
|
@@ -135,7 +135,7 @@ def _repair_tool_result_messages(bedrock_formatted_messages: List[Dict[str, Any]
|
|
|
135
135
|
tool_result_messages.append((idx, msg))
|
|
136
136
|
|
|
137
137
|
# Determine the tool call IDs for each tool call message
|
|
138
|
-
group_to_tool_call_ids:
|
|
138
|
+
group_to_tool_call_ids: dict[int, Any] = {idx: [] for idx, _ in tool_call_messages}
|
|
139
139
|
for idx, tool_call in tool_call_messages:
|
|
140
140
|
tool_use_contents = [c for c in tool_call["content"] if "toolUse" in c]
|
|
141
141
|
for content in tool_use_contents:
|
|
@@ -162,7 +162,7 @@ def _repair_tool_result_messages(bedrock_formatted_messages: List[Dict[str, Any]
|
|
|
162
162
|
repaired_tool_result_prompts.append((original_idx, {"role": "user", "content": regrouped_tool_result}))
|
|
163
163
|
|
|
164
164
|
# Remove the tool result messages from bedrock_formatted_messages
|
|
165
|
-
bedrock_formatted_messages_minus_tool_results:
|
|
165
|
+
bedrock_formatted_messages_minus_tool_results: list[tuple[int, Any]] = []
|
|
166
166
|
for idx, msg in enumerate(bedrock_formatted_messages):
|
|
167
167
|
# Assumes the content of tool result messages only contains 'toolResult': {...} objects (e.g. no 'text')
|
|
168
168
|
if msg.get("content") and "toolResult" not in msg["content"][0]:
|
|
@@ -176,7 +176,7 @@ def _repair_tool_result_messages(bedrock_formatted_messages: List[Dict[str, Any]
|
|
|
176
176
|
return [msg for _, msg in repaired_bedrock_formatted_messages]
|
|
177
177
|
|
|
178
178
|
|
|
179
|
-
def _format_reasoning_content(reasoning_content: ReasoningContent) ->
|
|
179
|
+
def _format_reasoning_content(reasoning_content: ReasoningContent) -> list[dict[str, Any]]:
|
|
180
180
|
"""
|
|
181
181
|
Format ReasoningContent to match Bedrock's expected structure.
|
|
182
182
|
|
|
@@ -194,7 +194,7 @@ def _format_reasoning_content(reasoning_content: ReasoningContent) -> List[Dict[
|
|
|
194
194
|
return formatted_contents
|
|
195
195
|
|
|
196
196
|
|
|
197
|
-
def _format_text_image_message(message: ChatMessage) ->
|
|
197
|
+
def _format_text_image_message(message: ChatMessage) -> dict[str, Any]:
|
|
198
198
|
"""
|
|
199
199
|
Format a Haystack ChatMessage containing text and optional image content into Bedrock format.
|
|
200
200
|
|
|
@@ -204,7 +204,7 @@ def _format_text_image_message(message: ChatMessage) -> Dict[str, Any]:
|
|
|
204
204
|
"""
|
|
205
205
|
content_parts = message._content
|
|
206
206
|
|
|
207
|
-
bedrock_content_blocks:
|
|
207
|
+
bedrock_content_blocks: list[dict[str, Any]] = []
|
|
208
208
|
# Add reasoning content if available as the first content block
|
|
209
209
|
if message.reasoning:
|
|
210
210
|
bedrock_content_blocks.extend(_format_reasoning_content(reasoning_content=message.reasoning))
|
|
@@ -231,7 +231,7 @@ def _format_text_image_message(message: ChatMessage) -> Dict[str, Any]:
|
|
|
231
231
|
return {"role": message.role.value, "content": bedrock_content_blocks}
|
|
232
232
|
|
|
233
233
|
|
|
234
|
-
def _format_messages(messages:
|
|
234
|
+
def _format_messages(messages: list[ChatMessage]) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
|
|
235
235
|
"""
|
|
236
236
|
Format a list of Haystack ChatMessages to the format expected by Bedrock API.
|
|
237
237
|
|
|
@@ -262,7 +262,7 @@ def _format_messages(messages: List[ChatMessage]) -> Tuple[List[Dict[str, Any]],
|
|
|
262
262
|
return system_prompts, repaired_bedrock_formatted_messages
|
|
263
263
|
|
|
264
264
|
|
|
265
|
-
def _parse_completion_response(response_body:
|
|
265
|
+
def _parse_completion_response(response_body: dict[str, Any], model: str) -> list[ChatMessage]:
|
|
266
266
|
"""
|
|
267
267
|
Parse a Bedrock API response into Haystack ChatMessage objects.
|
|
268
268
|
|
|
@@ -346,7 +346,7 @@ def _parse_completion_response(response_body: Dict[str, Any], model: str) -> Lis
|
|
|
346
346
|
|
|
347
347
|
|
|
348
348
|
def _convert_event_to_streaming_chunk(
|
|
349
|
-
event:
|
|
349
|
+
event: dict[str, Any], model: str, component_info: ComponentInfo
|
|
350
350
|
) -> StreamingChunk:
|
|
351
351
|
"""
|
|
352
352
|
Convert a Bedrock streaming event to a Haystack StreamingChunk.
|
|
@@ -433,7 +433,7 @@ def _convert_event_to_streaming_chunk(
|
|
|
433
433
|
|
|
434
434
|
elif "metadata" in event:
|
|
435
435
|
event_meta = event["metadata"]
|
|
436
|
-
chunk_meta:
|
|
436
|
+
chunk_meta: dict[str, Any] = {**base_meta}
|
|
437
437
|
|
|
438
438
|
if "usage" in event_meta:
|
|
439
439
|
usage = event_meta["usage"]
|
|
@@ -454,7 +454,7 @@ def _convert_event_to_streaming_chunk(
|
|
|
454
454
|
return streaming_chunk
|
|
455
455
|
|
|
456
456
|
|
|
457
|
-
def _process_reasoning_contents(chunks:
|
|
457
|
+
def _process_reasoning_contents(chunks: list[StreamingChunk]) -> Optional[ReasoningContent]:
|
|
458
458
|
"""
|
|
459
459
|
Process reasoning contents from a list of StreamingChunk objects into the Bedrock expected format.
|
|
460
460
|
|
|
@@ -536,7 +536,7 @@ def _parse_streaming_response(
|
|
|
536
536
|
streaming_callback: SyncStreamingCallbackT,
|
|
537
537
|
model: str,
|
|
538
538
|
component_info: ComponentInfo,
|
|
539
|
-
) ->
|
|
539
|
+
) -> list[ChatMessage]:
|
|
540
540
|
"""
|
|
541
541
|
Parse a streaming response from Bedrock.
|
|
542
542
|
|
|
@@ -547,7 +547,7 @@ def _parse_streaming_response(
|
|
|
547
547
|
:return: List of ChatMessage objects
|
|
548
548
|
"""
|
|
549
549
|
content_block_idxs = set()
|
|
550
|
-
chunks:
|
|
550
|
+
chunks: list[StreamingChunk] = []
|
|
551
551
|
for event in response_stream:
|
|
552
552
|
streaming_chunk = _convert_event_to_streaming_chunk(event=event, model=model, component_info=component_info)
|
|
553
553
|
content_block_idx = streaming_chunk.index
|
|
@@ -581,7 +581,7 @@ async def _parse_streaming_response_async(
|
|
|
581
581
|
streaming_callback: AsyncStreamingCallbackT,
|
|
582
582
|
model: str,
|
|
583
583
|
component_info: ComponentInfo,
|
|
584
|
-
) ->
|
|
584
|
+
) -> list[ChatMessage]:
|
|
585
585
|
"""
|
|
586
586
|
Parse a streaming response from Bedrock.
|
|
587
587
|
|
|
@@ -592,7 +592,7 @@ async def _parse_streaming_response_async(
|
|
|
592
592
|
:return: List of ChatMessage objects
|
|
593
593
|
"""
|
|
594
594
|
content_block_idxs = set()
|
|
595
|
-
chunks:
|
|
595
|
+
chunks: list[StreamingChunk] = []
|
|
596
596
|
async for event in response_stream:
|
|
597
597
|
streaming_chunk = _convert_event_to_streaming_chunk(event=event, model=model, component_info=component_info)
|
|
598
598
|
content_block_idx = streaming_chunk.index
|
|
@@ -613,7 +613,7 @@ async def _parse_streaming_response_async(
|
|
|
613
613
|
return [reply]
|
|
614
614
|
|
|
615
615
|
|
|
616
|
-
def _validate_guardrail_config(guardrail_config: Optional[
|
|
616
|
+
def _validate_guardrail_config(guardrail_config: Optional[dict[str, str]] = None, streaming: bool = False) -> None:
|
|
617
617
|
"""
|
|
618
618
|
Validate the guardrail configuration.
|
|
619
619
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import re
|
|
3
3
|
import warnings
|
|
4
|
-
from typing import Any, Callable, ClassVar,
|
|
4
|
+
from typing import Any, Callable, ClassVar, Literal, Optional, Union, get_args
|
|
5
5
|
|
|
6
6
|
from botocore.config import Config
|
|
7
7
|
from botocore.exceptions import ClientError
|
|
@@ -62,7 +62,7 @@ class AmazonBedrockGenerator:
|
|
|
62
62
|
supports Amazon Bedrock.
|
|
63
63
|
"""
|
|
64
64
|
|
|
65
|
-
SUPPORTED_MODEL_PATTERNS: ClassVar[
|
|
65
|
+
SUPPORTED_MODEL_PATTERNS: ClassVar[dict[str, type[BedrockModelAdapter]]] = {
|
|
66
66
|
r"([a-z]{2}\.)?amazon.titan-text.*": AmazonTitanAdapter,
|
|
67
67
|
r"([a-z]{2}\.)?ai21.j2.*": AI21LabsJurassic2Adapter,
|
|
68
68
|
r"([a-z]{2}\.)?cohere.command-[^r].*": CohereCommandAdapter,
|
|
@@ -72,7 +72,7 @@ class AmazonBedrockGenerator:
|
|
|
72
72
|
r"([a-z]{2}\.)?mistral.*": MistralAdapter,
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
SUPPORTED_MODEL_FAMILIES: ClassVar[
|
|
75
|
+
SUPPORTED_MODEL_FAMILIES: ClassVar[dict[str, type[BedrockModelAdapter]]] = {
|
|
76
76
|
"amazon.titan-text": AmazonTitanAdapter,
|
|
77
77
|
"ai21.j2": AI21LabsJurassic2Adapter,
|
|
78
78
|
"cohere.command": CohereCommandAdapter,
|
|
@@ -105,7 +105,7 @@ class AmazonBedrockGenerator:
|
|
|
105
105
|
max_length: Optional[int] = None,
|
|
106
106
|
truncate: Optional[bool] = None,
|
|
107
107
|
streaming_callback: Optional[Callable[[StreamingChunk], None]] = None,
|
|
108
|
-
boto3_config: Optional[
|
|
108
|
+
boto3_config: Optional[dict[str, Any]] = None,
|
|
109
109
|
model_family: Optional[MODEL_FAMILIES] = None,
|
|
110
110
|
**kwargs: Any,
|
|
111
111
|
) -> None:
|
|
@@ -183,13 +183,13 @@ class AmazonBedrockGenerator:
|
|
|
183
183
|
model_adapter_cls = self.get_model_adapter(model=model, model_family=model_family)
|
|
184
184
|
self.model_adapter = model_adapter_cls(model_kwargs=model_input_kwargs, max_length=self.max_length)
|
|
185
185
|
|
|
186
|
-
@component.output_types(replies=
|
|
186
|
+
@component.output_types(replies=list[str], meta=dict[str, Any])
|
|
187
187
|
def run(
|
|
188
188
|
self,
|
|
189
189
|
prompt: str,
|
|
190
190
|
streaming_callback: Optional[Callable[[StreamingChunk], None]] = None,
|
|
191
|
-
generation_kwargs: Optional[
|
|
192
|
-
) ->
|
|
191
|
+
generation_kwargs: Optional[dict[str, Any]] = None,
|
|
192
|
+
) -> dict[str, Union[list[str], dict[str, Any]]]:
|
|
193
193
|
"""
|
|
194
194
|
Generates a list of string response to the given prompt.
|
|
195
195
|
|
|
@@ -240,7 +240,7 @@ class AmazonBedrockGenerator:
|
|
|
240
240
|
return {"replies": replies, "meta": metadata}
|
|
241
241
|
|
|
242
242
|
@classmethod
|
|
243
|
-
def get_model_adapter(cls, model: str, model_family: Optional[str] = None) ->
|
|
243
|
+
def get_model_adapter(cls, model: str, model_family: Optional[str] = None) -> type[BedrockModelAdapter]:
|
|
244
244
|
"""
|
|
245
245
|
Gets the model adapter for the given model.
|
|
246
246
|
|
|
@@ -273,7 +273,7 @@ class AmazonBedrockGenerator:
|
|
|
273
273
|
)
|
|
274
274
|
raise AmazonBedrockConfigurationError(msg)
|
|
275
275
|
|
|
276
|
-
def to_dict(self) ->
|
|
276
|
+
def to_dict(self) -> dict[str, Any]:
|
|
277
277
|
"""
|
|
278
278
|
Serializes the component to a dictionary.
|
|
279
279
|
|
|
@@ -297,7 +297,7 @@ class AmazonBedrockGenerator:
|
|
|
297
297
|
)
|
|
298
298
|
|
|
299
299
|
@classmethod
|
|
300
|
-
def from_dict(cls, data:
|
|
300
|
+
def from_dict(cls, data: dict[str, Any]) -> "AmazonBedrockGenerator":
|
|
301
301
|
"""
|
|
302
302
|
Deserializes the component from a dictionary.
|
|
303
303
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any,
|
|
1
|
+
from typing import Any, Optional
|
|
2
2
|
|
|
3
3
|
from botocore.exceptions import ClientError
|
|
4
4
|
from haystack import Document, component, default_from_dict, default_to_dict, logging
|
|
@@ -68,7 +68,7 @@ class AmazonBedrockRanker:
|
|
|
68
68
|
aws_region_name: Optional[Secret] = Secret.from_env_var(["AWS_DEFAULT_REGION"], strict=False), # noqa: B008
|
|
69
69
|
aws_profile_name: Optional[Secret] = Secret.from_env_var(["AWS_PROFILE"], strict=False), # noqa: B008
|
|
70
70
|
max_chunks_per_doc: Optional[int] = None,
|
|
71
|
-
meta_fields_to_embed: Optional[
|
|
71
|
+
meta_fields_to_embed: Optional[list[str]] = None,
|
|
72
72
|
meta_data_separator: str = "\n",
|
|
73
73
|
) -> None:
|
|
74
74
|
if not model:
|
|
@@ -122,7 +122,7 @@ class AmazonBedrockRanker:
|
|
|
122
122
|
)
|
|
123
123
|
raise AmazonBedrockConfigurationError(msg) from exception
|
|
124
124
|
|
|
125
|
-
def to_dict(self) ->
|
|
125
|
+
def to_dict(self) -> dict[str, Any]:
|
|
126
126
|
"""
|
|
127
127
|
Serializes the component to a dictionary.
|
|
128
128
|
|
|
@@ -144,7 +144,7 @@ class AmazonBedrockRanker:
|
|
|
144
144
|
)
|
|
145
145
|
|
|
146
146
|
@classmethod
|
|
147
|
-
def from_dict(cls, data:
|
|
147
|
+
def from_dict(cls, data: dict[str, Any]) -> "AmazonBedrockRanker":
|
|
148
148
|
"""
|
|
149
149
|
Deserializes the component from a dictionary.
|
|
150
150
|
|
|
@@ -159,7 +159,7 @@ class AmazonBedrockRanker:
|
|
|
159
159
|
)
|
|
160
160
|
return default_from_dict(cls, data)
|
|
161
161
|
|
|
162
|
-
def _prepare_bedrock_input_docs(self, documents:
|
|
162
|
+
def _prepare_bedrock_input_docs(self, documents: list[Document]) -> list[str]:
|
|
163
163
|
"""
|
|
164
164
|
Prepare the input by concatenating the document text with the metadata fields specified.
|
|
165
165
|
:param documents: The list of Document objects.
|
|
@@ -176,8 +176,8 @@ class AmazonBedrockRanker:
|
|
|
176
176
|
|
|
177
177
|
return concatenated_input_list
|
|
178
178
|
|
|
179
|
-
@component.output_types(documents=
|
|
180
|
-
def run(self, query: str, documents:
|
|
179
|
+
@component.output_types(documents=list[Document])
|
|
180
|
+
def run(self, query: str, documents: list[Document], top_k: Optional[int] = None) -> dict[str, list[Document]]:
|
|
181
181
|
"""
|
|
182
182
|
Use the Amazon Bedrock Reranker to re-rank the list of documents based on the query.
|
|
183
183
|
|
|
File without changes
|