amazon-bedrock-haystack 5.1.0__py3-none-any.whl → 5.3.0__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.1.0.dist-info → amazon_bedrock_haystack-5.3.0.dist-info}/METADATA +2 -2
- {amazon_bedrock_haystack-5.1.0.dist-info → amazon_bedrock_haystack-5.3.0.dist-info}/RECORD +13 -13
- {amazon_bedrock_haystack-5.1.0.dist-info → amazon_bedrock_haystack-5.3.0.dist-info}/WHEEL +1 -1
- haystack_integrations/components/downloaders/s3/s3_downloader.py +10 -10
- haystack_integrations/components/embedders/amazon_bedrock/document_embedder.py +22 -16
- haystack_integrations/components/embedders/amazon_bedrock/document_image_embedder.py +28 -19
- haystack_integrations/components/embedders/amazon_bedrock/text_embedder.py +18 -11
- haystack_integrations/components/generators/amazon_bedrock/adapters.py +33 -33
- haystack_integrations/components/generators/amazon_bedrock/chat/chat_generator.py +36 -34
- 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.1.0.dist-info → amazon_bedrock_haystack-5.3.0.dist-info}/licenses/LICENSE.txt +0 -0
{amazon_bedrock_haystack-5.1.0.dist-info → amazon_bedrock_haystack-5.3.0.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.0
|
|
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
|
|
@@ -21,7 +21,7 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
|
21
21
|
Requires-Python: >=3.9
|
|
22
22
|
Requires-Dist: aioboto3>=14.0.0
|
|
23
23
|
Requires-Dist: boto3>=1.28.57
|
|
24
|
-
Requires-Dist: haystack-ai>=2.
|
|
24
|
+
Requires-Dist: haystack-ai>=2.19.0
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
26
26
|
|
|
27
27
|
# amazon-bedrock-haystack
|
|
@@ -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=vRBdqqIv09dbL9qWWy3BlrwK2P036q2d30zsIzWs-A0,13387
|
|
14
|
+
haystack_integrations/components/embedders/amazon_bedrock/document_image_embedder.py,sha256=qpvsJsrJ7wi9mV_euQ4pX3wqcqJjJUPW6dfoYRvi0eM,16212
|
|
15
|
+
haystack_integrations/components/embedders/amazon_bedrock/text_embedder.py,sha256=o7ERGCH0F6h3QzULy3yXxGxFxZdeyW8wAz4fPL3pvzQ,9513
|
|
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.0.dist-info/METADATA,sha256=2z-MOhgu2Qp1Jnc56fs6ANIcmZo7ocLfwgtek22dvJY,2228
|
|
27
|
+
amazon_bedrock_haystack-5.3.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
28
|
+
amazon_bedrock_haystack-5.3.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
|
|
29
|
+
amazon_bedrock_haystack-5.3.0.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, Literal, Optional
|
|
3
3
|
|
|
4
4
|
from botocore.config import Config
|
|
5
5
|
from botocore.exceptions import ClientError
|
|
@@ -18,10 +18,11 @@ logger = logging.getLogger(__name__)
|
|
|
18
18
|
|
|
19
19
|
SUPPORTED_EMBEDDING_MODELS = [
|
|
20
20
|
"amazon.titan-embed-text-v1",
|
|
21
|
-
"cohere.embed-english-v3",
|
|
22
|
-
"cohere.embed-multilingual-v3",
|
|
23
21
|
"amazon.titan-embed-text-v2:0",
|
|
24
22
|
"amazon.titan-embed-image-v1",
|
|
23
|
+
"cohere.embed-english-v3",
|
|
24
|
+
"cohere.embed-multilingual-v3",
|
|
25
|
+
"cohere.embed-v4:0",
|
|
25
26
|
]
|
|
26
27
|
|
|
27
28
|
|
|
@@ -59,10 +60,11 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
59
60
|
self,
|
|
60
61
|
model: Literal[
|
|
61
62
|
"amazon.titan-embed-text-v1",
|
|
62
|
-
"cohere.embed-english-v3",
|
|
63
|
-
"cohere.embed-multilingual-v3",
|
|
64
63
|
"amazon.titan-embed-text-v2:0",
|
|
65
64
|
"amazon.titan-embed-image-v1",
|
|
65
|
+
"cohere.embed-english-v3",
|
|
66
|
+
"cohere.embed-multilingual-v3",
|
|
67
|
+
"cohere.embed-v4:0",
|
|
66
68
|
],
|
|
67
69
|
aws_access_key_id: Optional[Secret] = Secret.from_env_var("AWS_ACCESS_KEY_ID", strict=False), # noqa: B008
|
|
68
70
|
aws_secret_access_key: Optional[Secret] = Secret.from_env_var( # noqa: B008
|
|
@@ -73,9 +75,9 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
73
75
|
aws_profile_name: Optional[Secret] = Secret.from_env_var("AWS_PROFILE", strict=False), # noqa: B008
|
|
74
76
|
batch_size: int = 32,
|
|
75
77
|
progress_bar: bool = True,
|
|
76
|
-
meta_fields_to_embed: Optional[
|
|
78
|
+
meta_fields_to_embed: Optional[list[str]] = None,
|
|
77
79
|
embedding_separator: str = "\n",
|
|
78
|
-
boto3_config: Optional[
|
|
80
|
+
boto3_config: Optional[dict[str, Any]] = None,
|
|
79
81
|
**kwargs: Any,
|
|
80
82
|
) -> None:
|
|
81
83
|
"""
|
|
@@ -149,7 +151,7 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
149
151
|
)
|
|
150
152
|
raise AmazonBedrockConfigurationError(msg) from exception
|
|
151
153
|
|
|
152
|
-
def _prepare_texts_to_embed(self, documents:
|
|
154
|
+
def _prepare_texts_to_embed(self, documents: list[Document]) -> list[str]:
|
|
153
155
|
"""
|
|
154
156
|
Prepare the texts to embed by concatenating the Document text with the metadata fields to embed.
|
|
155
157
|
"""
|
|
@@ -162,7 +164,7 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
162
164
|
texts_to_embed.append(text_to_embed)
|
|
163
165
|
return texts_to_embed
|
|
164
166
|
|
|
165
|
-
def _embed_cohere(self, documents:
|
|
167
|
+
def _embed_cohere(self, documents: list[Document]) -> list[Document]:
|
|
166
168
|
"""
|
|
167
169
|
Internal method to embed Documents using Cohere models.
|
|
168
170
|
Batch inference is supported.
|
|
@@ -191,15 +193,19 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
191
193
|
msg = f"Could not perform inference for Amazon Bedrock model {self.model} due to:\n{exception}"
|
|
192
194
|
raise AmazonBedrockInferenceError(msg) from exception
|
|
193
195
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
+
cohere_embeddings = json.loads(response.get("body").read())["embeddings"]
|
|
197
|
+
# depending on the model, Cohere returns a dict with the embedding types as keys or a list of lists
|
|
198
|
+
embeddings_list = (
|
|
199
|
+
next(iter(cohere_embeddings.values())) if isinstance(cohere_embeddings, dict) else cohere_embeddings
|
|
200
|
+
)
|
|
201
|
+
all_embeddings.extend(embeddings_list)
|
|
196
202
|
|
|
197
203
|
for doc, emb in zip(documents, all_embeddings):
|
|
198
204
|
doc.embedding = emb
|
|
199
205
|
|
|
200
206
|
return documents
|
|
201
207
|
|
|
202
|
-
def _embed_titan(self, documents:
|
|
208
|
+
def _embed_titan(self, documents: list[Document]) -> list[Document]:
|
|
203
209
|
"""
|
|
204
210
|
Internal method to embed Documents using Amazon Titan models.
|
|
205
211
|
NOTE: Batch inference is not supported, so embeddings are created one by one.
|
|
@@ -227,8 +233,8 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
227
233
|
|
|
228
234
|
return documents
|
|
229
235
|
|
|
230
|
-
@component.output_types(documents=
|
|
231
|
-
def run(self, documents:
|
|
236
|
+
@component.output_types(documents=list[Document])
|
|
237
|
+
def run(self, documents: list[Document]) -> dict[str, list[Document]]:
|
|
232
238
|
"""Embed the provided `Document`s using the specified model.
|
|
233
239
|
|
|
234
240
|
:param documents: The `Document`s to embed.
|
|
@@ -253,7 +259,7 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
253
259
|
|
|
254
260
|
return {"documents": documents_with_embeddings}
|
|
255
261
|
|
|
256
|
-
def to_dict(self) ->
|
|
262
|
+
def to_dict(self) -> dict[str, Any]:
|
|
257
263
|
"""
|
|
258
264
|
Serializes the component to a dictionary.
|
|
259
265
|
|
|
@@ -277,7 +283,7 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
277
283
|
)
|
|
278
284
|
|
|
279
285
|
@classmethod
|
|
280
|
-
def from_dict(cls, data:
|
|
286
|
+
def from_dict(cls, data: dict[str, Any]) -> "AmazonBedrockDocumentEmbedder":
|
|
281
287
|
"""
|
|
282
288
|
Deserializes the component from a dictionary.
|
|
283
289
|
|
|
@@ -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, Literal, Optional
|
|
8
8
|
|
|
9
9
|
from botocore.config import Config
|
|
10
10
|
from botocore.exceptions import ClientError
|
|
@@ -27,7 +27,12 @@ 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 = [
|
|
30
|
+
SUPPORTED_EMBEDDING_MODELS = [
|
|
31
|
+
"amazon.titan-embed-image-v1",
|
|
32
|
+
"cohere.embed-english-v3",
|
|
33
|
+
"cohere.embed-multilingual-v3",
|
|
34
|
+
"cohere.embed-v4:0",
|
|
35
|
+
]
|
|
31
36
|
|
|
32
37
|
|
|
33
38
|
@component
|
|
@@ -69,7 +74,12 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
69
74
|
def __init__(
|
|
70
75
|
self,
|
|
71
76
|
*,
|
|
72
|
-
model: Literal[
|
|
77
|
+
model: Literal[
|
|
78
|
+
"amazon.titan-embed-image-v1",
|
|
79
|
+
"cohere.embed-english-v3",
|
|
80
|
+
"cohere.embed-multilingual-v3",
|
|
81
|
+
"cohere.embed-v4:0",
|
|
82
|
+
],
|
|
73
83
|
aws_access_key_id: Optional[Secret] = Secret.from_env_var("AWS_ACCESS_KEY_ID", strict=False), # noqa: B008
|
|
74
84
|
aws_secret_access_key: Optional[Secret] = Secret.from_env_var( # noqa: B008
|
|
75
85
|
"AWS_SECRET_ACCESS_KEY", strict=False
|
|
@@ -79,9 +89,9 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
79
89
|
aws_profile_name: Optional[Secret] = Secret.from_env_var("AWS_PROFILE", strict=False), # noqa: B008
|
|
80
90
|
file_path_meta_field: str = "file_path",
|
|
81
91
|
root_path: Optional[str] = None,
|
|
82
|
-
image_size: Optional[
|
|
92
|
+
image_size: Optional[tuple[int, int]] = None,
|
|
83
93
|
progress_bar: bool = True,
|
|
84
|
-
boto3_config: Optional[
|
|
94
|
+
boto3_config: Optional[dict[str, Any]] = None,
|
|
85
95
|
**kwargs: Any,
|
|
86
96
|
) -> None:
|
|
87
97
|
"""
|
|
@@ -93,6 +103,7 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
93
103
|
- "amazon.titan-embed-image-v1"
|
|
94
104
|
- "cohere.embed-english-v3"
|
|
95
105
|
- "cohere.embed-multilingual-v3"
|
|
106
|
+
- "cohere.embed-v4:0"
|
|
96
107
|
:param aws_access_key_id: AWS access key ID.
|
|
97
108
|
:param aws_secret_access_key: AWS secret access key.
|
|
98
109
|
:param aws_session_token: AWS session token.
|
|
@@ -135,14 +146,14 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
135
146
|
self.kwargs = kwargs
|
|
136
147
|
self.embedding_types = None
|
|
137
148
|
|
|
138
|
-
if
|
|
139
|
-
if len(
|
|
149
|
+
if embedding_types := self.kwargs.get("embedding_types"):
|
|
150
|
+
if len(embedding_types) > 1:
|
|
140
151
|
msg = (
|
|
141
152
|
"You have provided multiple embedding_types for Cohere model. "
|
|
142
153
|
"AmazonBedrockDocumentImageEmbedder only supports one embedding_type at a time."
|
|
143
154
|
)
|
|
144
155
|
raise ValueError(msg)
|
|
145
|
-
self.embedding_types =
|
|
156
|
+
self.embedding_types = embedding_types
|
|
146
157
|
|
|
147
158
|
def resolve_secret(secret: Optional[Secret]) -> Optional[str]:
|
|
148
159
|
return secret.resolve_value() if secret else None
|
|
@@ -296,7 +307,7 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
296
307
|
|
|
297
308
|
return {"documents": docs_with_embeddings}
|
|
298
309
|
|
|
299
|
-
def _embed_titan(self, images:
|
|
310
|
+
def _embed_titan(self, images: list[str]) -> list[list[float]]:
|
|
300
311
|
"""
|
|
301
312
|
Internal method to embed base64 images using Amazon Titan models.
|
|
302
313
|
|
|
@@ -326,7 +337,7 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
326
337
|
|
|
327
338
|
return all_embeddings
|
|
328
339
|
|
|
329
|
-
def _embed_cohere(self, image_uris:
|
|
340
|
+
def _embed_cohere(self, image_uris: list[str]) -> list[list[float]]:
|
|
330
341
|
"""
|
|
331
342
|
Internal method to embed base64 images using Cohere models.
|
|
332
343
|
|
|
@@ -351,15 +362,13 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
351
362
|
raise AmazonBedrockInferenceError(msg) from exception
|
|
352
363
|
|
|
353
364
|
response_body = json.loads(response.get("body").read())
|
|
354
|
-
|
|
365
|
+
cohere_embeddings = response_body["embeddings"]
|
|
355
366
|
|
|
356
|
-
#
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
# a nested list of float embeddings
|
|
363
|
-
all_embeddings.append(embeddings[0])
|
|
367
|
+
# depending on the model and embedding_types, Cohere returns a dict with the embedding types as keys
|
|
368
|
+
# or a list of lists
|
|
369
|
+
embeddings_list = (
|
|
370
|
+
next(iter(cohere_embeddings.values())) if isinstance(cohere_embeddings, dict) else cohere_embeddings
|
|
371
|
+
)
|
|
372
|
+
all_embeddings.extend(embeddings_list)
|
|
364
373
|
|
|
365
374
|
return all_embeddings
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from typing import Any,
|
|
2
|
+
from typing import Any, Literal, Optional
|
|
3
3
|
|
|
4
4
|
from botocore.config import Config
|
|
5
5
|
from botocore.exceptions import ClientError
|
|
@@ -16,10 +16,11 @@ logger = logging.getLogger(__name__)
|
|
|
16
16
|
|
|
17
17
|
SUPPORTED_EMBEDDING_MODELS = [
|
|
18
18
|
"amazon.titan-embed-text-v1",
|
|
19
|
-
"cohere.embed-english-v3",
|
|
20
|
-
"cohere.embed-multilingual-v3",
|
|
21
19
|
"amazon.titan-embed-text-v2:0",
|
|
22
20
|
"amazon.titan-embed-image-v1",
|
|
21
|
+
"cohere.embed-english-v3",
|
|
22
|
+
"cohere.embed-multilingual-v3",
|
|
23
|
+
"cohere.embed-v4:0",
|
|
23
24
|
]
|
|
24
25
|
|
|
25
26
|
|
|
@@ -52,10 +53,11 @@ class AmazonBedrockTextEmbedder:
|
|
|
52
53
|
self,
|
|
53
54
|
model: Literal[
|
|
54
55
|
"amazon.titan-embed-text-v1",
|
|
55
|
-
"cohere.embed-english-v3",
|
|
56
|
-
"cohere.embed-multilingual-v3",
|
|
57
56
|
"amazon.titan-embed-text-v2:0",
|
|
58
57
|
"amazon.titan-embed-image-v1",
|
|
58
|
+
"cohere.embed-english-v3",
|
|
59
|
+
"cohere.embed-multilingual-v3",
|
|
60
|
+
"cohere.embed-v4:0",
|
|
59
61
|
],
|
|
60
62
|
aws_access_key_id: Optional[Secret] = Secret.from_env_var("AWS_ACCESS_KEY_ID", strict=False), # noqa: B008
|
|
61
63
|
aws_secret_access_key: Optional[Secret] = Secret.from_env_var( # noqa: B008
|
|
@@ -64,7 +66,7 @@ class AmazonBedrockTextEmbedder:
|
|
|
64
66
|
aws_session_token: Optional[Secret] = Secret.from_env_var("AWS_SESSION_TOKEN", strict=False), # noqa: B008
|
|
65
67
|
aws_region_name: Optional[Secret] = Secret.from_env_var("AWS_DEFAULT_REGION", strict=False), # noqa: B008
|
|
66
68
|
aws_profile_name: Optional[Secret] = Secret.from_env_var("AWS_PROFILE", strict=False), # noqa: B008
|
|
67
|
-
boto3_config: Optional[
|
|
69
|
+
boto3_config: Optional[dict[str, Any]] = None,
|
|
68
70
|
**kwargs: Any,
|
|
69
71
|
) -> None:
|
|
70
72
|
"""
|
|
@@ -127,8 +129,8 @@ class AmazonBedrockTextEmbedder:
|
|
|
127
129
|
)
|
|
128
130
|
raise AmazonBedrockConfigurationError(msg) from exception
|
|
129
131
|
|
|
130
|
-
@component.output_types(embedding=
|
|
131
|
-
def run(self, text: str) ->
|
|
132
|
+
@component.output_types(embedding=list[float])
|
|
133
|
+
def run(self, text: str) -> dict[str, list[float]]:
|
|
132
134
|
"""Embeds the input text using the Amazon Bedrock model.
|
|
133
135
|
|
|
134
136
|
:param text: The input text to embed.
|
|
@@ -168,7 +170,12 @@ class AmazonBedrockTextEmbedder:
|
|
|
168
170
|
response_body = json.loads(response.get("body").read())
|
|
169
171
|
|
|
170
172
|
if "cohere" in self.model:
|
|
171
|
-
|
|
173
|
+
cohere_embeddings = response_body["embeddings"]
|
|
174
|
+
# depending on the model, Cohere returns a dict with the embedding types as keys or a list of lists
|
|
175
|
+
embeddings_list = (
|
|
176
|
+
next(iter(cohere_embeddings.values())) if isinstance(cohere_embeddings, dict) else cohere_embeddings
|
|
177
|
+
)
|
|
178
|
+
embedding = embeddings_list[0]
|
|
172
179
|
elif "titan" in self.model:
|
|
173
180
|
embedding = response_body["embedding"]
|
|
174
181
|
else:
|
|
@@ -177,7 +184,7 @@ class AmazonBedrockTextEmbedder:
|
|
|
177
184
|
|
|
178
185
|
return {"embedding": embedding}
|
|
179
186
|
|
|
180
|
-
def to_dict(self) ->
|
|
187
|
+
def to_dict(self) -> dict[str, Any]:
|
|
181
188
|
"""
|
|
182
189
|
Serializes the component to a dictionary.
|
|
183
190
|
|
|
@@ -197,7 +204,7 @@ class AmazonBedrockTextEmbedder:
|
|
|
197
204
|
)
|
|
198
205
|
|
|
199
206
|
@classmethod
|
|
200
|
-
def from_dict(cls, data:
|
|
207
|
+
def from_dict(cls, data: dict[str, Any]) -> "AmazonBedrockTextEmbedder":
|
|
201
208
|
"""
|
|
202
209
|
Deserializes the component from a dictionary.
|
|
203
210
|
|
|
@@ -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
|
|
@@ -7,10 +7,10 @@ from botocore.exceptions import ClientError
|
|
|
7
7
|
from haystack import component, default_from_dict, default_to_dict, logging
|
|
8
8
|
from haystack.dataclasses import ChatMessage, ComponentInfo, StreamingCallbackT, select_streaming_callback
|
|
9
9
|
from haystack.tools import (
|
|
10
|
-
|
|
11
|
-
Toolset,
|
|
10
|
+
ToolsType,
|
|
12
11
|
_check_duplicate_tool_names,
|
|
13
12
|
deserialize_tools_or_toolset_inplace,
|
|
13
|
+
flatten_tools_or_toolsets,
|
|
14
14
|
serialize_tools_or_toolset,
|
|
15
15
|
)
|
|
16
16
|
from haystack.utils.auth import Secret, deserialize_secrets_inplace
|
|
@@ -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[
|
|
160
|
-
tools: Optional[
|
|
159
|
+
boto3_config: Optional[dict[str, Any]] = None,
|
|
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
|
|
@@ -187,7 +187,8 @@ class AmazonBedrockChatGenerator:
|
|
|
187
187
|
[StreamingChunk](https://docs.haystack.deepset.ai/docs/data-classes#streamingchunk) object and switches
|
|
188
188
|
the streaming mode on.
|
|
189
189
|
:param boto3_config: The configuration for the boto3 client.
|
|
190
|
-
:param tools: A list of Tool objects or a Toolset
|
|
190
|
+
:param tools: A list of Tool and/or Toolset objects, or a single Toolset for which the model can prepare calls.
|
|
191
|
+
Each tool should have a unique name.
|
|
191
192
|
:param guardrail_config: Optional configuration for a guardrail that has been created in Amazon Bedrock.
|
|
192
193
|
This must be provided as a dictionary matching either
|
|
193
194
|
[GuardrailConfiguration](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_GuardrailConfiguration.html).
|
|
@@ -218,7 +219,7 @@ class AmazonBedrockChatGenerator:
|
|
|
218
219
|
self.streaming_callback = streaming_callback
|
|
219
220
|
self.boto3_config = boto3_config
|
|
220
221
|
|
|
221
|
-
_check_duplicate_tool_names(
|
|
222
|
+
_check_duplicate_tool_names(flatten_tools_or_toolsets(tools))
|
|
222
223
|
self.tools = tools
|
|
223
224
|
|
|
224
225
|
_validate_guardrail_config(guardrail_config=guardrail_config, streaming=streaming_callback is not None)
|
|
@@ -288,7 +289,7 @@ class AmazonBedrockChatGenerator:
|
|
|
288
289
|
)
|
|
289
290
|
raise AmazonBedrockConfigurationError(msg) from exception
|
|
290
291
|
|
|
291
|
-
def to_dict(self) ->
|
|
292
|
+
def to_dict(self) -> dict[str, Any]:
|
|
292
293
|
"""
|
|
293
294
|
Serializes the component to a dictionary.
|
|
294
295
|
|
|
@@ -312,7 +313,7 @@ class AmazonBedrockChatGenerator:
|
|
|
312
313
|
)
|
|
313
314
|
|
|
314
315
|
@classmethod
|
|
315
|
-
def from_dict(cls, data:
|
|
316
|
+
def from_dict(cls, data: dict[str, Any]) -> "AmazonBedrockChatGenerator":
|
|
316
317
|
"""
|
|
317
318
|
Deserializes the component from a dictionary.
|
|
318
319
|
|
|
@@ -339,12 +340,12 @@ class AmazonBedrockChatGenerator:
|
|
|
339
340
|
|
|
340
341
|
def _prepare_request_params(
|
|
341
342
|
self,
|
|
342
|
-
messages:
|
|
343
|
+
messages: list[ChatMessage],
|
|
343
344
|
streaming_callback: Optional[StreamingCallbackT] = None,
|
|
344
|
-
generation_kwargs: Optional[
|
|
345
|
-
tools: Optional[
|
|
345
|
+
generation_kwargs: Optional[dict[str, Any]] = None,
|
|
346
|
+
tools: Optional[ToolsType] = None,
|
|
346
347
|
requires_async: bool = False,
|
|
347
|
-
) ->
|
|
348
|
+
) -> tuple[dict[str, Any], Optional[StreamingCallbackT]]:
|
|
348
349
|
"""
|
|
349
350
|
Prepares and formats parameters required to call the Amazon Bedrock Converse API.
|
|
350
351
|
|
|
@@ -358,7 +359,8 @@ class AmazonBedrockChatGenerator:
|
|
|
358
359
|
- `stopSequences`: List of stop sequences to stop generation.
|
|
359
360
|
- `temperature`: Sampling temperature.
|
|
360
361
|
- `topP`: Nucleus sampling parameter.
|
|
361
|
-
:param tools:
|
|
362
|
+
:param tools: A list of Tool and/or Toolset objects, or a single Toolset for which the model can prepare calls.
|
|
363
|
+
Each tool should have a unique name.
|
|
362
364
|
:param requires_async: Boolean flag to indicate if an async-compatible streaming callback function is needed.
|
|
363
365
|
|
|
364
366
|
:returns:
|
|
@@ -380,14 +382,12 @@ class AmazonBedrockChatGenerator:
|
|
|
380
382
|
|
|
381
383
|
# Handle tools - either toolConfig or Haystack Tool objects but not both
|
|
382
384
|
tools = tools or self.tools
|
|
383
|
-
|
|
385
|
+
flattened_tools = flatten_tools_or_toolsets(tools)
|
|
386
|
+
_check_duplicate_tool_names(flattened_tools)
|
|
384
387
|
tool_config = merged_kwargs.pop("toolConfig", None)
|
|
385
|
-
if
|
|
386
|
-
# Convert Toolset to list if needed
|
|
387
|
-
if isinstance(tools, Toolset):
|
|
388
|
-
tools = list(tools)
|
|
388
|
+
if flattened_tools:
|
|
389
389
|
# Format Haystack tools to Bedrock format
|
|
390
|
-
tool_config = _format_tools(
|
|
390
|
+
tool_config = _format_tools(flattened_tools)
|
|
391
391
|
|
|
392
392
|
# Any remaining kwargs go to additionalModelRequestFields
|
|
393
393
|
additional_fields = merged_kwargs if merged_kwargs else None
|
|
@@ -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[
|
|
428
|
-
tools: Optional[
|
|
429
|
-
) ->
|
|
427
|
+
generation_kwargs: Optional[dict[str, Any]] = None,
|
|
428
|
+
tools: Optional[ToolsType] = None,
|
|
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
|
|
|
@@ -439,7 +439,8 @@ class AmazonBedrockChatGenerator:
|
|
|
439
439
|
- `stopSequences`: List of stop sequences to stop generation.
|
|
440
440
|
- `temperature`: Sampling temperature.
|
|
441
441
|
- `topP`: Nucleus sampling parameter.
|
|
442
|
-
:param tools:
|
|
442
|
+
:param tools: A list of Tool and/or Toolset objects, or a single Toolset for which the model can prepare calls.
|
|
443
|
+
Each tool should have a unique name.
|
|
443
444
|
|
|
444
445
|
:returns:
|
|
445
446
|
A dictionary containing the model-generated replies under the `"replies"` key.
|
|
@@ -479,14 +480,14 @@ class AmazonBedrockChatGenerator:
|
|
|
479
480
|
|
|
480
481
|
return {"replies": replies}
|
|
481
482
|
|
|
482
|
-
@component.output_types(replies=
|
|
483
|
+
@component.output_types(replies=list[ChatMessage])
|
|
483
484
|
async def run_async(
|
|
484
485
|
self,
|
|
485
|
-
messages:
|
|
486
|
+
messages: list[ChatMessage],
|
|
486
487
|
streaming_callback: Optional[StreamingCallbackT] = None,
|
|
487
|
-
generation_kwargs: Optional[
|
|
488
|
-
tools: Optional[
|
|
489
|
-
) ->
|
|
488
|
+
generation_kwargs: Optional[dict[str, Any]] = None,
|
|
489
|
+
tools: Optional[ToolsType] = None,
|
|
490
|
+
) -> dict[str, list[ChatMessage]]:
|
|
490
491
|
"""
|
|
491
492
|
Executes an asynchronous inference call to the Amazon Bedrock model using the Converse API.
|
|
492
493
|
|
|
@@ -499,7 +500,8 @@ class AmazonBedrockChatGenerator:
|
|
|
499
500
|
- `stopSequences`: List of stop sequences to stop generation.
|
|
500
501
|
- `temperature`: Sampling temperature.
|
|
501
502
|
- `topP`: Nucleus sampling parameter.
|
|
502
|
-
:param tools:
|
|
503
|
+
:param tools: A list of Tool and/or Toolset objects, or a single Toolset for which the model can prepare calls.
|
|
504
|
+
Each tool should have a unique name.
|
|
503
505
|
|
|
504
506
|
:returns:
|
|
505
507
|
A dictionary containing the model-generated replies under the `"replies"` key.
|
|
@@ -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
|