amazon-bedrock-haystack 6.2.1__tar.gz → 6.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/CHANGELOG.md +13 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/PKG-INFO +2 -2
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/pyproject.toml +1 -1
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/downloaders/s3/s3_downloader.py +6 -10
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/embedders/amazon_bedrock/document_embedder.py +6 -10
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/embedders/amazon_bedrock/document_image_embedder.py +6 -17
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/embedders/amazon_bedrock/text_embedder.py +6 -10
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/generators/amazon_bedrock/chat/chat_generator.py +24 -11
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/generators/amazon_bedrock/chat/utils.py +99 -30
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/generators/amazon_bedrock/generator.py +6 -10
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/rankers/amazon_bedrock/ranker.py +6 -10
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_chat_generator.py +55 -2
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_chat_generator_utils.py +224 -15
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/.gitignore +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/LICENSE.txt +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/README.md +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/examples/bedrock_ranker_example.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/examples/chatgenerator_example.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/examples/embedders_generator_with_rag_example.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/examples/s3_downloader_example.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/pydoc/config_docusaurus.yml +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/common/amazon_bedrock/__init__.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/common/amazon_bedrock/errors.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/common/amazon_bedrock/utils.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/common/py.typed +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/common/s3/__init__.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/common/s3/errors.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/common/s3/utils.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/downloaders/py.typed +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/downloaders/s3/__init__.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/embedders/amazon_bedrock/__init__.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/embedders/py.typed +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/generators/amazon_bedrock/__init__.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/generators/amazon_bedrock/adapters.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/generators/amazon_bedrock/chat/__init__.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/generators/py.typed +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/rankers/amazon_bedrock/__init__.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/src/haystack_integrations/components/rankers/py.typed +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/__init__.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/conftest.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_document_embedder.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_document_image_embedder.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_files/apple.jpg +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_files/haystack-logo.png +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_files/sample_pdf_1.pdf +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_generator.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_ranker.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_s3_downloader.py +0 -0
- {amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_text_embedder.py +0 -0
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [integrations/amazon_bedrock-v6.3.0] - 2026-01-28
|
|
4
|
+
|
|
5
|
+
### 🌀 Miscellaneous
|
|
6
|
+
|
|
7
|
+
- Feat: Bedrock - support images in tool results (#2783)
|
|
8
|
+
|
|
9
|
+
## [integrations/amazon_bedrock-v6.2.1] - 2026-01-15
|
|
10
|
+
|
|
11
|
+
### 🐛 Bug Fixes
|
|
12
|
+
|
|
13
|
+
- None value handling of flattened generation kwargs for AmazonBedrockChatGenerator (#2752)
|
|
14
|
+
|
|
15
|
+
|
|
3
16
|
## [integrations/amazon_bedrock-v6.2.0] - 2026-01-13
|
|
4
17
|
|
|
5
18
|
### 🚀 Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: amazon-bedrock-haystack
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.4.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
|
|
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
|
20
20
|
Requires-Python: >=3.10
|
|
21
21
|
Requires-Dist: aioboto3>=14.0.0
|
|
22
22
|
Requires-Dist: boto3>=1.28.57
|
|
23
|
-
Requires-Dist: haystack-ai>=2.
|
|
23
|
+
Requires-Dist: haystack-ai>=2.23.0
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
|
|
26
26
|
# amazon-bedrock-haystack
|
|
@@ -22,7 +22,7 @@ classifiers = [
|
|
|
22
22
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
23
23
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
24
24
|
]
|
|
25
|
-
dependencies = ["haystack-ai>=2.
|
|
25
|
+
dependencies = ["haystack-ai>=2.23.0", "boto3>=1.28.57", "aioboto3>=14.0.0"]
|
|
26
26
|
|
|
27
27
|
[project.urls]
|
|
28
28
|
Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/amazon_bedrock#readme"
|
|
@@ -11,7 +11,7 @@ from typing import Any
|
|
|
11
11
|
from botocore.config import Config
|
|
12
12
|
from haystack import component, default_from_dict, default_to_dict, logging
|
|
13
13
|
from haystack.dataclasses import Document
|
|
14
|
-
from haystack.utils.auth import Secret
|
|
14
|
+
from haystack.utils.auth import Secret
|
|
15
15
|
from haystack.utils.callable_serialization import deserialize_callable, serialize_callable
|
|
16
16
|
|
|
17
17
|
from haystack_integrations.common.amazon_bedrock.utils import get_aws_session
|
|
@@ -233,11 +233,11 @@ class S3Downloader:
|
|
|
233
233
|
|
|
234
234
|
return default_to_dict(
|
|
235
235
|
self,
|
|
236
|
-
aws_access_key_id=self.aws_access_key_id
|
|
237
|
-
aws_secret_access_key=self.aws_secret_access_key
|
|
238
|
-
aws_session_token=self.aws_session_token
|
|
239
|
-
aws_region_name=self.aws_region_name
|
|
240
|
-
aws_profile_name=self.aws_profile_name
|
|
236
|
+
aws_access_key_id=self.aws_access_key_id,
|
|
237
|
+
aws_secret_access_key=self.aws_secret_access_key,
|
|
238
|
+
aws_session_token=self.aws_session_token,
|
|
239
|
+
aws_region_name=self.aws_region_name,
|
|
240
|
+
aws_profile_name=self.aws_profile_name,
|
|
241
241
|
file_root_path=str(self.file_root_path),
|
|
242
242
|
max_workers=self.max_workers,
|
|
243
243
|
max_cache_size=self.max_cache_size,
|
|
@@ -260,8 +260,4 @@ class S3Downloader:
|
|
|
260
260
|
data["init_parameters"]["s3_key_generation_function"] = deserialize_callable(
|
|
261
261
|
s3_key_generation_function_name
|
|
262
262
|
)
|
|
263
|
-
deserialize_secrets_inplace(
|
|
264
|
-
data["init_parameters"],
|
|
265
|
-
["aws_access_key_id", "aws_secret_access_key", "aws_session_token", "aws_region_name", "aws_profile_name"],
|
|
266
|
-
)
|
|
267
263
|
return default_from_dict(cls, data)
|
|
@@ -6,7 +6,7 @@ from botocore.config import Config
|
|
|
6
6
|
from botocore.exceptions import ClientError
|
|
7
7
|
from haystack import component, default_from_dict, default_to_dict, logging
|
|
8
8
|
from haystack.dataclasses import Document
|
|
9
|
-
from haystack.utils.auth import Secret
|
|
9
|
+
from haystack.utils.auth import Secret
|
|
10
10
|
from tqdm import tqdm
|
|
11
11
|
|
|
12
12
|
from haystack_integrations.common.amazon_bedrock.errors import (
|
|
@@ -257,11 +257,11 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
257
257
|
"""
|
|
258
258
|
return default_to_dict(
|
|
259
259
|
self,
|
|
260
|
-
aws_access_key_id=self.aws_access_key_id
|
|
261
|
-
aws_secret_access_key=self.aws_secret_access_key
|
|
262
|
-
aws_session_token=self.aws_session_token
|
|
263
|
-
aws_region_name=self.aws_region_name
|
|
264
|
-
aws_profile_name=self.aws_profile_name
|
|
260
|
+
aws_access_key_id=self.aws_access_key_id,
|
|
261
|
+
aws_secret_access_key=self.aws_secret_access_key,
|
|
262
|
+
aws_session_token=self.aws_session_token,
|
|
263
|
+
aws_region_name=self.aws_region_name,
|
|
264
|
+
aws_profile_name=self.aws_profile_name,
|
|
265
265
|
model=self.model,
|
|
266
266
|
batch_size=self.batch_size,
|
|
267
267
|
progress_bar=self.progress_bar,
|
|
@@ -281,8 +281,4 @@ class AmazonBedrockDocumentEmbedder:
|
|
|
281
281
|
:returns:
|
|
282
282
|
Deserialized component.
|
|
283
283
|
"""
|
|
284
|
-
deserialize_secrets_inplace(
|
|
285
|
-
data["init_parameters"],
|
|
286
|
-
["aws_access_key_id", "aws_secret_access_key", "aws_session_token", "aws_region_name", "aws_profile_name"],
|
|
287
|
-
)
|
|
288
284
|
return default_from_dict(cls, data)
|
|
@@ -16,7 +16,7 @@ from haystack.components.converters.image.image_utils import (
|
|
|
16
16
|
_PDFPageInfo,
|
|
17
17
|
)
|
|
18
18
|
from haystack.dataclasses import ByteStream
|
|
19
|
-
from haystack.utils.auth import Secret
|
|
19
|
+
from haystack.utils.auth import Secret
|
|
20
20
|
from tqdm import tqdm
|
|
21
21
|
|
|
22
22
|
from haystack_integrations.common.amazon_bedrock.errors import (
|
|
@@ -178,11 +178,11 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
178
178
|
file_path_meta_field=self.file_path_meta_field,
|
|
179
179
|
root_path=self.root_path,
|
|
180
180
|
model=self.model,
|
|
181
|
-
aws_access_key_id=self.aws_access_key_id
|
|
182
|
-
aws_secret_access_key=self.aws_secret_access_key
|
|
183
|
-
aws_session_token=self.aws_session_token
|
|
184
|
-
aws_region_name=self.aws_region_name
|
|
185
|
-
aws_profile_name=self.aws_profile_name
|
|
181
|
+
aws_access_key_id=self.aws_access_key_id,
|
|
182
|
+
aws_secret_access_key=self.aws_secret_access_key,
|
|
183
|
+
aws_session_token=self.aws_session_token,
|
|
184
|
+
aws_region_name=self.aws_region_name,
|
|
185
|
+
aws_profile_name=self.aws_profile_name,
|
|
186
186
|
progress_bar=self.progress_bar,
|
|
187
187
|
boto3_config=self.boto3_config,
|
|
188
188
|
image_size=self.image_size,
|
|
@@ -200,17 +200,6 @@ class AmazonBedrockDocumentImageEmbedder:
|
|
|
200
200
|
:returns:
|
|
201
201
|
Deserialized component.
|
|
202
202
|
"""
|
|
203
|
-
init_params = data["init_parameters"]
|
|
204
|
-
deserialize_secrets_inplace(
|
|
205
|
-
init_params,
|
|
206
|
-
keys=[
|
|
207
|
-
"aws_access_key_id",
|
|
208
|
-
"aws_secret_access_key",
|
|
209
|
-
"aws_session_token",
|
|
210
|
-
"aws_region_name",
|
|
211
|
-
"aws_profile_name",
|
|
212
|
-
],
|
|
213
|
-
)
|
|
214
203
|
return default_from_dict(cls, data)
|
|
215
204
|
|
|
216
205
|
@component.output_types(documents=list[Document])
|
|
@@ -4,7 +4,7 @@ from typing import Any
|
|
|
4
4
|
from botocore.config import Config
|
|
5
5
|
from botocore.exceptions import ClientError
|
|
6
6
|
from haystack import component, default_from_dict, default_to_dict, logging
|
|
7
|
-
from haystack.utils.auth import Secret
|
|
7
|
+
from haystack.utils.auth import Secret
|
|
8
8
|
|
|
9
9
|
from haystack_integrations.common.amazon_bedrock.errors import (
|
|
10
10
|
AmazonBedrockConfigurationError,
|
|
@@ -180,11 +180,11 @@ class AmazonBedrockTextEmbedder:
|
|
|
180
180
|
"""
|
|
181
181
|
return default_to_dict(
|
|
182
182
|
self,
|
|
183
|
-
aws_access_key_id=self.aws_access_key_id
|
|
184
|
-
aws_secret_access_key=self.aws_secret_access_key
|
|
185
|
-
aws_session_token=self.aws_session_token
|
|
186
|
-
aws_region_name=self.aws_region_name
|
|
187
|
-
aws_profile_name=self.aws_profile_name
|
|
183
|
+
aws_access_key_id=self.aws_access_key_id,
|
|
184
|
+
aws_secret_access_key=self.aws_secret_access_key,
|
|
185
|
+
aws_session_token=self.aws_session_token,
|
|
186
|
+
aws_region_name=self.aws_region_name,
|
|
187
|
+
aws_profile_name=self.aws_profile_name,
|
|
188
188
|
model=self.model,
|
|
189
189
|
boto3_config=self.boto3_config,
|
|
190
190
|
**self.kwargs,
|
|
@@ -200,8 +200,4 @@ class AmazonBedrockTextEmbedder:
|
|
|
200
200
|
:returns:
|
|
201
201
|
Deserialized component.
|
|
202
202
|
"""
|
|
203
|
-
deserialize_secrets_inplace(
|
|
204
|
-
data["init_parameters"],
|
|
205
|
-
["aws_access_key_id", "aws_secret_access_key", "aws_session_token", "aws_region_name", "aws_profile_name"],
|
|
206
|
-
)
|
|
207
203
|
return default_from_dict(cls, data)
|
|
@@ -13,7 +13,7 @@ from haystack.tools import (
|
|
|
13
13
|
flatten_tools_or_toolsets,
|
|
14
14
|
serialize_tools_or_toolset,
|
|
15
15
|
)
|
|
16
|
-
from haystack.utils.auth import Secret
|
|
16
|
+
from haystack.utils.auth import Secret
|
|
17
17
|
from haystack.utils.callable_serialization import deserialize_callable, serialize_callable
|
|
18
18
|
|
|
19
19
|
from haystack_integrations.common.amazon_bedrock.errors import (
|
|
@@ -27,6 +27,7 @@ from haystack_integrations.components.generators.amazon_bedrock.chat.utils impor
|
|
|
27
27
|
_parse_completion_response,
|
|
28
28
|
_parse_streaming_response,
|
|
29
29
|
_parse_streaming_response_async,
|
|
30
|
+
_validate_and_format_cache_point,
|
|
30
31
|
_validate_guardrail_config,
|
|
31
32
|
)
|
|
32
33
|
|
|
@@ -142,6 +143,12 @@ class AmazonBedrockChatGenerator:
|
|
|
142
143
|
and `aws_region_name` as environment variables or pass them as
|
|
143
144
|
[Secret](https://docs.haystack.deepset.ai/docs/secret-management) arguments. Make sure the region you set
|
|
144
145
|
supports Amazon Bedrock.
|
|
146
|
+
|
|
147
|
+
This component supports prompt caching. You can use the `tools_cachepoint_config` parameter to configure the cache
|
|
148
|
+
point for tools.
|
|
149
|
+
To cache messages, you can use the `cachePoint` key in `ChatMessage.meta` attribute.
|
|
150
|
+
Example: `ChatMessage.from_user("Long message...", meta={"cachePoint": {"type": "default"}})`
|
|
151
|
+
For more information, see the [Amazon Bedrock documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html).
|
|
145
152
|
"""
|
|
146
153
|
|
|
147
154
|
def __init__(
|
|
@@ -160,6 +167,7 @@ class AmazonBedrockChatGenerator:
|
|
|
160
167
|
tools: ToolsType | None = None,
|
|
161
168
|
*,
|
|
162
169
|
guardrail_config: dict[str, str] | None = None,
|
|
170
|
+
tools_cachepoint_config: dict[str, str] | None = None,
|
|
163
171
|
) -> None:
|
|
164
172
|
"""
|
|
165
173
|
Initializes the `AmazonBedrockChatGenerator` with the provided parameters. The parameters are passed to the
|
|
@@ -201,6 +209,10 @@ class AmazonBedrockChatGenerator:
|
|
|
201
209
|
See the
|
|
202
210
|
[Guardrails Streaming documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-streaming.html)
|
|
203
211
|
for more information.
|
|
212
|
+
:param tools_cachepoint_config: Optional configuration to use prompt caching for tools.
|
|
213
|
+
The dictionary must match the
|
|
214
|
+
[CachePointBlock schema](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_CachePointBlock.html).
|
|
215
|
+
Example: `{"type": "default", "ttl": "5m"}`
|
|
204
216
|
|
|
205
217
|
|
|
206
218
|
:raises ValueError: If the model name is empty or None.
|
|
@@ -225,6 +237,10 @@ class AmazonBedrockChatGenerator:
|
|
|
225
237
|
_validate_guardrail_config(guardrail_config=guardrail_config, streaming=streaming_callback is not None)
|
|
226
238
|
self.guardrail_config = guardrail_config
|
|
227
239
|
|
|
240
|
+
self.tools_cachepoint_config = (
|
|
241
|
+
_validate_and_format_cache_point(tools_cachepoint_config) if tools_cachepoint_config else None
|
|
242
|
+
)
|
|
243
|
+
|
|
228
244
|
def resolve_secret(secret: Secret | None) -> str | None:
|
|
229
245
|
return secret.resolve_value() if secret else None
|
|
230
246
|
|
|
@@ -299,17 +315,18 @@ class AmazonBedrockChatGenerator:
|
|
|
299
315
|
callback_name = serialize_callable(self.streaming_callback) if self.streaming_callback else None
|
|
300
316
|
return default_to_dict(
|
|
301
317
|
self,
|
|
302
|
-
aws_access_key_id=self.aws_access_key_id
|
|
303
|
-
aws_secret_access_key=self.aws_secret_access_key
|
|
304
|
-
aws_session_token=self.aws_session_token
|
|
305
|
-
aws_region_name=self.aws_region_name
|
|
306
|
-
aws_profile_name=self.aws_profile_name
|
|
318
|
+
aws_access_key_id=self.aws_access_key_id,
|
|
319
|
+
aws_secret_access_key=self.aws_secret_access_key,
|
|
320
|
+
aws_session_token=self.aws_session_token,
|
|
321
|
+
aws_region_name=self.aws_region_name,
|
|
322
|
+
aws_profile_name=self.aws_profile_name,
|
|
307
323
|
model=self.model,
|
|
308
324
|
generation_kwargs=self.generation_kwargs,
|
|
309
325
|
streaming_callback=callback_name,
|
|
310
326
|
boto3_config=self.boto3_config,
|
|
311
327
|
tools=serialize_tools_or_toolset(self.tools),
|
|
312
328
|
guardrail_config=self.guardrail_config,
|
|
329
|
+
tools_cachepoint_config=self.tools_cachepoint_config,
|
|
313
330
|
)
|
|
314
331
|
|
|
315
332
|
@classmethod
|
|
@@ -331,10 +348,6 @@ class AmazonBedrockChatGenerator:
|
|
|
331
348
|
serialized_callback_handler = init_params.get("streaming_callback")
|
|
332
349
|
if serialized_callback_handler:
|
|
333
350
|
data["init_parameters"]["streaming_callback"] = deserialize_callable(serialized_callback_handler)
|
|
334
|
-
deserialize_secrets_inplace(
|
|
335
|
-
data["init_parameters"],
|
|
336
|
-
["aws_access_key_id", "aws_secret_access_key", "aws_session_token", "aws_region_name", "aws_profile_name"],
|
|
337
|
-
)
|
|
338
351
|
deserialize_tools_or_toolset_inplace(data["init_parameters"], key="tools")
|
|
339
352
|
return default_from_dict(cls, data)
|
|
340
353
|
|
|
@@ -389,7 +402,7 @@ class AmazonBedrockChatGenerator:
|
|
|
389
402
|
tool_config = merged_kwargs.pop("toolConfig", None)
|
|
390
403
|
if flattened_tools:
|
|
391
404
|
# Format Haystack tools to Bedrock format
|
|
392
|
-
tool_config = _format_tools(flattened_tools)
|
|
405
|
+
tool_config = _format_tools(flattened_tools, tools_cachepoint_config=self.tools_cachepoint_config)
|
|
393
406
|
|
|
394
407
|
# Any remaining kwargs go to additionalModelRequestFields
|
|
395
408
|
additional_fields = merged_kwargs if merged_kwargs else None
|
|
@@ -40,7 +40,9 @@ FINISH_REASON_MAPPING: dict[str, FinishReason] = {
|
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
# Haystack to Bedrock util methods
|
|
43
|
-
def _format_tools(
|
|
43
|
+
def _format_tools(
|
|
44
|
+
tools: list[Tool] | None = None, tools_cachepoint_config: dict[str, dict[str, str]] | None = None
|
|
45
|
+
) -> dict[str, Any] | None:
|
|
44
46
|
"""
|
|
45
47
|
Format Haystack Tool(s) to Amazon Bedrock toolConfig format.
|
|
46
48
|
|
|
@@ -51,13 +53,34 @@ def _format_tools(tools: list[Tool] | None = None) -> dict[str, Any] | None:
|
|
|
51
53
|
if not tools:
|
|
52
54
|
return None
|
|
53
55
|
|
|
54
|
-
tool_specs = []
|
|
56
|
+
tool_specs: list[dict[str, Any]] = []
|
|
55
57
|
for tool in tools:
|
|
56
58
|
tool_specs.append(
|
|
57
59
|
{"toolSpec": {"name": tool.name, "description": tool.description, "inputSchema": {"json": tool.parameters}}}
|
|
58
60
|
)
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
if tools_cachepoint_config:
|
|
63
|
+
tool_specs.append({"cachePoint": tools_cachepoint_config})
|
|
64
|
+
|
|
65
|
+
return {"tools": tool_specs}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _convert_image_content_to_bedrock_format(image_content: ImageContent) -> dict[str, Any]:
|
|
69
|
+
"""
|
|
70
|
+
Convert a Haystack ImageContent to Bedrock format.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
image_format = image_content.mime_type.split("/")[-1] if image_content.mime_type else None
|
|
74
|
+
if image_format not in IMAGE_SUPPORTED_FORMATS:
|
|
75
|
+
err_msg = (
|
|
76
|
+
f"Unsupported image format: {image_format}. "
|
|
77
|
+
f"Bedrock supports the following image formats: {IMAGE_SUPPORTED_FORMATS}"
|
|
78
|
+
)
|
|
79
|
+
raise ValueError(err_msg)
|
|
80
|
+
|
|
81
|
+
source = {"bytes": base64.b64decode(image_content.base64_image)}
|
|
82
|
+
|
|
83
|
+
return {"image": {"format": image_format, "source": source}}
|
|
61
84
|
|
|
62
85
|
|
|
63
86
|
def _format_tool_call_message(tool_call_message: ChatMessage) -> dict[str, Any]:
|
|
@@ -94,19 +117,30 @@ def _format_tool_result_message(tool_call_result_message: ChatMessage) -> dict[s
|
|
|
94
117
|
"""
|
|
95
118
|
# Assuming tool call result messages will only contain tool results
|
|
96
119
|
tool_results = []
|
|
97
|
-
for
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
120
|
+
for tool_call_result in tool_call_result_message.tool_call_results:
|
|
121
|
+
if isinstance(tool_call_result.result, str):
|
|
122
|
+
try:
|
|
123
|
+
json_result = json.loads(tool_call_result.result)
|
|
124
|
+
content = [{"json": json_result}]
|
|
125
|
+
except json.JSONDecodeError:
|
|
126
|
+
content = [{"text": tool_call_result.result}]
|
|
127
|
+
elif isinstance(tool_call_result.result, list):
|
|
128
|
+
content = []
|
|
129
|
+
for item in tool_call_result.result:
|
|
130
|
+
if isinstance(item, TextContent):
|
|
131
|
+
content.append({"text": item.text})
|
|
132
|
+
elif isinstance(item, ImageContent):
|
|
133
|
+
content.append(_convert_image_content_to_bedrock_format(item))
|
|
134
|
+
else:
|
|
135
|
+
err_msg = "Unsupported content type in tool call result"
|
|
136
|
+
raise ValueError(err_msg)
|
|
103
137
|
|
|
104
138
|
tool_results.append(
|
|
105
139
|
{
|
|
106
140
|
"toolResult": {
|
|
107
|
-
"toolUseId":
|
|
141
|
+
"toolUseId": tool_call_result.origin.id,
|
|
108
142
|
"content": content,
|
|
109
|
-
**({"status": "error"} if
|
|
143
|
+
**({"status": "error"} if tool_call_result.error else {}),
|
|
110
144
|
}
|
|
111
145
|
}
|
|
112
146
|
)
|
|
@@ -152,20 +186,23 @@ def _repair_tool_result_messages(bedrock_formatted_messages: list[dict[str, Any]
|
|
|
152
186
|
original_idx = None
|
|
153
187
|
for tool_call_id in tool_call_ids:
|
|
154
188
|
for idx, tool_result in tool_result_messages:
|
|
155
|
-
tool_result_contents = [c for c in tool_result["content"] if "toolResult" in c]
|
|
189
|
+
tool_result_contents = [c for c in tool_result["content"] if "toolResult" in c or "cachePoint" in c]
|
|
156
190
|
for content in tool_result_contents:
|
|
157
|
-
if content["toolResult"]["toolUseId"] == tool_call_id:
|
|
191
|
+
if "toolResult" in content and content["toolResult"]["toolUseId"] == tool_call_id:
|
|
158
192
|
regrouped_tool_result.append(content)
|
|
159
193
|
# Keep track of the original index of the last tool result message
|
|
160
194
|
original_idx = idx
|
|
195
|
+
elif "cachePoint" in content and content not in regrouped_tool_result:
|
|
196
|
+
regrouped_tool_result.append(content)
|
|
197
|
+
|
|
161
198
|
if regrouped_tool_result and original_idx is not None:
|
|
162
199
|
repaired_tool_result_prompts.append((original_idx, {"role": "user", "content": regrouped_tool_result}))
|
|
163
200
|
|
|
164
201
|
# Remove the tool result messages from bedrock_formatted_messages
|
|
165
202
|
bedrock_formatted_messages_minus_tool_results: list[tuple[int, Any]] = []
|
|
166
203
|
for idx, msg in enumerate(bedrock_formatted_messages):
|
|
167
|
-
#
|
|
168
|
-
if msg.get("content") and "toolResult"
|
|
204
|
+
# Filter out messages that contain toolResult (they are handled by repaired_tool_result_prompts)
|
|
205
|
+
if msg.get("content") and not any("toolResult" in c for c in msg["content"]):
|
|
169
206
|
bedrock_formatted_messages_minus_tool_results.append((idx, msg))
|
|
170
207
|
|
|
171
208
|
# Add the repaired tool result messages and sort to maintain the correct order
|
|
@@ -217,20 +254,37 @@ def _format_text_image_message(message: ChatMessage) -> dict[str, Any]:
|
|
|
217
254
|
if message.is_from(ChatRole.ASSISTANT):
|
|
218
255
|
err_msg = "Image content is not supported for assistant messages"
|
|
219
256
|
raise ValueError(err_msg)
|
|
220
|
-
|
|
221
|
-
image_format = part.mime_type.split("/")[-1] if part.mime_type else None
|
|
222
|
-
if image_format not in IMAGE_SUPPORTED_FORMATS:
|
|
223
|
-
err_msg = (
|
|
224
|
-
f"Unsupported image format: {image_format}. "
|
|
225
|
-
f"Bedrock supports the following image formats: {IMAGE_SUPPORTED_FORMATS}"
|
|
226
|
-
)
|
|
227
|
-
raise ValueError(err_msg)
|
|
228
|
-
source = {"bytes": base64.b64decode(part.base64_image)}
|
|
229
|
-
bedrock_content_blocks.append({"image": {"format": image_format, "source": source}})
|
|
257
|
+
bedrock_content_blocks.append(_convert_image_content_to_bedrock_format(part))
|
|
230
258
|
|
|
231
259
|
return {"role": message.role.value, "content": bedrock_content_blocks}
|
|
232
260
|
|
|
233
261
|
|
|
262
|
+
def _validate_and_format_cache_point(cache_point: dict[str, str] | None) -> dict[str, dict[str, str]] | None:
|
|
263
|
+
"""
|
|
264
|
+
Validate and format a cache point dictionary.
|
|
265
|
+
|
|
266
|
+
Schema available at https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_CachePointBlock.html
|
|
267
|
+
|
|
268
|
+
:param cache_point: Cache point dictionary to validate and format.
|
|
269
|
+
:returns: Dictionary in Bedrock cachePoint format or None if no cache point is provided.
|
|
270
|
+
:raises ValueError: If cache point is not valid.
|
|
271
|
+
"""
|
|
272
|
+
if not cache_point:
|
|
273
|
+
return None
|
|
274
|
+
|
|
275
|
+
if "type" not in cache_point or cache_point["type"] != "default":
|
|
276
|
+
err_msg = "Cache point must have a 'type' key with value 'default'."
|
|
277
|
+
raise ValueError(err_msg)
|
|
278
|
+
if not set(cache_point).issubset({"type", "ttl"}):
|
|
279
|
+
err_msg = "Cache point can only contain 'type' and 'ttl' keys."
|
|
280
|
+
raise ValueError(err_msg)
|
|
281
|
+
if "ttl" in cache_point and cache_point["ttl"] not in ("5m", "1h"):
|
|
282
|
+
err_msg = "Cache point 'ttl' must be one of '5m', '1h'."
|
|
283
|
+
raise ValueError(err_msg)
|
|
284
|
+
|
|
285
|
+
return {"cachePoint": cache_point}
|
|
286
|
+
|
|
287
|
+
|
|
234
288
|
def _format_messages(messages: list[ChatMessage]) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
|
|
235
289
|
"""
|
|
236
290
|
Format a list of Haystack ChatMessages to the format expected by Bedrock API.
|
|
@@ -244,21 +298,30 @@ def _format_messages(messages: list[ChatMessage]) -> tuple[list[dict[str, Any]],
|
|
|
244
298
|
non_system_messages is a list of properly formatted message dictionaries.
|
|
245
299
|
"""
|
|
246
300
|
# Separate system messages, tool calls, and tool results
|
|
247
|
-
system_prompts = []
|
|
301
|
+
system_prompts: list[dict[str, Any]] = []
|
|
248
302
|
bedrock_formatted_messages = []
|
|
249
303
|
for msg in messages:
|
|
304
|
+
cache_point = _validate_and_format_cache_point(msg.meta.get("cachePoint"))
|
|
250
305
|
if msg.is_from(ChatRole.SYSTEM):
|
|
251
306
|
# Assuming system messages can only contain text
|
|
252
307
|
# Don't need to track idx since system_messages are handled separately
|
|
253
308
|
system_prompts.append({"text": msg.text})
|
|
254
|
-
|
|
255
|
-
|
|
309
|
+
if cache_point:
|
|
310
|
+
system_prompts.append(cache_point)
|
|
311
|
+
continue
|
|
312
|
+
|
|
313
|
+
if msg.tool_calls:
|
|
314
|
+
formatted_msg = _format_tool_call_message(msg)
|
|
256
315
|
elif msg.tool_call_results:
|
|
257
|
-
|
|
316
|
+
formatted_msg = _format_tool_result_message(msg)
|
|
258
317
|
else:
|
|
259
|
-
|
|
318
|
+
formatted_msg = _format_text_image_message(msg)
|
|
319
|
+
if cache_point:
|
|
320
|
+
formatted_msg["content"].append(cache_point)
|
|
321
|
+
bedrock_formatted_messages.append(formatted_msg)
|
|
260
322
|
|
|
261
323
|
repaired_bedrock_formatted_messages = _repair_tool_result_messages(bedrock_formatted_messages)
|
|
324
|
+
|
|
262
325
|
return system_prompts, repaired_bedrock_formatted_messages
|
|
263
326
|
|
|
264
327
|
|
|
@@ -290,6 +353,9 @@ def _parse_completion_response(response_body: dict[str, Any], model: str) -> lis
|
|
|
290
353
|
"prompt_tokens": response_body.get("usage", {}).get("inputTokens", 0),
|
|
291
354
|
"completion_tokens": response_body.get("usage", {}).get("outputTokens", 0),
|
|
292
355
|
"total_tokens": response_body.get("usage", {}).get("totalTokens", 0),
|
|
356
|
+
"cache_read_input_tokens": response_body.get("usage", {}).get("cacheReadInputTokens", 0),
|
|
357
|
+
"cache_write_input_tokens": response_body.get("usage", {}).get("cacheWriteInputTokens", 0),
|
|
358
|
+
"cache_details": response_body.get("usage", {}).get("CacheDetails", {}),
|
|
293
359
|
},
|
|
294
360
|
}
|
|
295
361
|
# guardrail trace
|
|
@@ -441,6 +507,9 @@ def _convert_event_to_streaming_chunk(
|
|
|
441
507
|
"prompt_tokens": usage.get("inputTokens", 0),
|
|
442
508
|
"completion_tokens": usage.get("outputTokens", 0),
|
|
443
509
|
"total_tokens": usage.get("totalTokens", 0),
|
|
510
|
+
"cache_read_input_tokens": usage.get("cacheReadInputTokens", 0),
|
|
511
|
+
"cache_write_input_tokens": usage.get("cacheWriteInputTokens", 0),
|
|
512
|
+
"cache_details": usage.get("cacheDetails", {}),
|
|
444
513
|
}
|
|
445
514
|
if "trace" in event_meta:
|
|
446
515
|
chunk_meta["trace"] = event_meta["trace"]
|
|
@@ -8,7 +8,7 @@ from botocore.config import Config
|
|
|
8
8
|
from botocore.exceptions import ClientError
|
|
9
9
|
from haystack import component, default_from_dict, default_to_dict, logging
|
|
10
10
|
from haystack.dataclasses import StreamingChunk
|
|
11
|
-
from haystack.utils import Secret, deserialize_callable,
|
|
11
|
+
from haystack.utils import Secret, deserialize_callable, serialize_callable
|
|
12
12
|
|
|
13
13
|
from haystack_integrations.common.amazon_bedrock.errors import (
|
|
14
14
|
AmazonBedrockConfigurationError,
|
|
@@ -287,11 +287,11 @@ class AmazonBedrockGenerator:
|
|
|
287
287
|
callback_name = serialize_callable(self.streaming_callback) if self.streaming_callback else None
|
|
288
288
|
return default_to_dict(
|
|
289
289
|
self,
|
|
290
|
-
aws_access_key_id=self.aws_access_key_id
|
|
291
|
-
aws_secret_access_key=self.aws_secret_access_key
|
|
292
|
-
aws_session_token=self.aws_session_token
|
|
293
|
-
aws_region_name=self.aws_region_name
|
|
294
|
-
aws_profile_name=self.aws_profile_name
|
|
290
|
+
aws_access_key_id=self.aws_access_key_id,
|
|
291
|
+
aws_secret_access_key=self.aws_secret_access_key,
|
|
292
|
+
aws_session_token=self.aws_session_token,
|
|
293
|
+
aws_region_name=self.aws_region_name,
|
|
294
|
+
aws_profile_name=self.aws_profile_name,
|
|
295
295
|
model=self.model,
|
|
296
296
|
max_length=self.max_length,
|
|
297
297
|
streaming_callback=callback_name,
|
|
@@ -310,10 +310,6 @@ class AmazonBedrockGenerator:
|
|
|
310
310
|
:returns:
|
|
311
311
|
Deserialized component.
|
|
312
312
|
"""
|
|
313
|
-
deserialize_secrets_inplace(
|
|
314
|
-
data["init_parameters"],
|
|
315
|
-
["aws_access_key_id", "aws_secret_access_key", "aws_session_token", "aws_region_name", "aws_profile_name"],
|
|
316
|
-
)
|
|
317
313
|
init_params = data.get("init_parameters", {})
|
|
318
314
|
serialized_callback_handler = init_params.get("streaming_callback")
|
|
319
315
|
if serialized_callback_handler:
|
|
@@ -3,7 +3,7 @@ from typing import Any
|
|
|
3
3
|
|
|
4
4
|
from botocore.exceptions import ClientError
|
|
5
5
|
from haystack import Document, component, default_from_dict, default_to_dict, logging
|
|
6
|
-
from haystack.utils import Secret
|
|
6
|
+
from haystack.utils import Secret
|
|
7
7
|
|
|
8
8
|
from haystack_integrations.common.amazon_bedrock.errors import (
|
|
9
9
|
AmazonBedrockConfigurationError,
|
|
@@ -133,11 +133,11 @@ class AmazonBedrockRanker:
|
|
|
133
133
|
return default_to_dict(
|
|
134
134
|
self,
|
|
135
135
|
model=self.model_name,
|
|
136
|
-
aws_access_key_id=self.aws_access_key_id
|
|
137
|
-
aws_secret_access_key=self.aws_secret_access_key
|
|
138
|
-
aws_session_token=self.aws_session_token
|
|
139
|
-
aws_region_name=self.aws_region_name
|
|
140
|
-
aws_profile_name=self.aws_profile_name
|
|
136
|
+
aws_access_key_id=self.aws_access_key_id,
|
|
137
|
+
aws_secret_access_key=self.aws_secret_access_key,
|
|
138
|
+
aws_session_token=self.aws_session_token,
|
|
139
|
+
aws_region_name=self.aws_region_name,
|
|
140
|
+
aws_profile_name=self.aws_profile_name,
|
|
141
141
|
top_k=self.top_k,
|
|
142
142
|
max_chunks_per_doc=self.max_chunks_per_doc,
|
|
143
143
|
meta_fields_to_embed=self.meta_fields_to_embed,
|
|
@@ -154,10 +154,6 @@ class AmazonBedrockRanker:
|
|
|
154
154
|
:returns:
|
|
155
155
|
The deserialized component.
|
|
156
156
|
"""
|
|
157
|
-
deserialize_secrets_inplace(
|
|
158
|
-
data["init_parameters"],
|
|
159
|
-
["aws_access_key_id", "aws_secret_access_key", "aws_session_token", "aws_region_name", "aws_profile_name"],
|
|
160
|
-
)
|
|
161
157
|
return default_from_dict(cls, data)
|
|
162
158
|
|
|
163
159
|
def _prepare_bedrock_input_docs(self, documents: list[Document]) -> list[str]:
|
{amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_chat_generator.py
RENAMED
|
@@ -3,10 +3,11 @@ from typing import Any
|
|
|
3
3
|
|
|
4
4
|
import pytest
|
|
5
5
|
from haystack import Pipeline
|
|
6
|
+
from haystack.components.agents import Agent
|
|
6
7
|
from haystack.components.generators.utils import print_streaming_chunk
|
|
7
8
|
from haystack.components.tools import ToolInvoker
|
|
8
|
-
from haystack.dataclasses import ChatMessage, ChatRole, ImageContent, StreamingChunk, ToolCall
|
|
9
|
-
from haystack.tools import Tool, Toolset
|
|
9
|
+
from haystack.dataclasses import ChatMessage, ChatRole, ImageContent, StreamingChunk, TextContent, ToolCall
|
|
10
|
+
from haystack.tools import Tool, Toolset, create_tool_from_function
|
|
10
11
|
|
|
11
12
|
from haystack_integrations.components.generators.amazon_bedrock import AmazonBedrockChatGenerator
|
|
12
13
|
|
|
@@ -38,6 +39,10 @@ MODELS_TO_TEST_WITH_THINKING = [
|
|
|
38
39
|
"us.anthropic.claude-sonnet-4-20250514-v1:0",
|
|
39
40
|
]
|
|
40
41
|
|
|
42
|
+
MODELS_TO_TEST_WITH_PROMPT_CACHING = [
|
|
43
|
+
"amazon.nova-micro-v1:0" # cheap, fast model
|
|
44
|
+
]
|
|
45
|
+
|
|
41
46
|
|
|
42
47
|
def hello_world():
|
|
43
48
|
return "Hello, World!"
|
|
@@ -163,6 +168,7 @@ class TestAmazonBedrockChatGenerator:
|
|
|
163
168
|
"boto3_config": boto3_config,
|
|
164
169
|
"tools": None,
|
|
165
170
|
"guardrail_config": {"guardrailIdentifier": "test", "guardrailVersion": "test"},
|
|
171
|
+
"tools_cachepoint_config": None,
|
|
166
172
|
},
|
|
167
173
|
}
|
|
168
174
|
|
|
@@ -297,6 +303,7 @@ class TestAmazonBedrockChatGenerator:
|
|
|
297
303
|
}
|
|
298
304
|
],
|
|
299
305
|
"guardrail_config": None,
|
|
306
|
+
"tools_cachepoint_config": None,
|
|
300
307
|
},
|
|
301
308
|
}
|
|
302
309
|
},
|
|
@@ -514,6 +521,30 @@ class TestAmazonBedrockChatGeneratorInference:
|
|
|
514
521
|
assert first_reply.text
|
|
515
522
|
assert "apple" in first_reply.text.lower()
|
|
516
523
|
|
|
524
|
+
@pytest.mark.parametrize("model_name", MODELS_TO_TEST_WITH_IMAGE_INPUT)
|
|
525
|
+
def test_live_run_agent_with_images_in_tool_result(self, model_name, test_files_path):
|
|
526
|
+
def retrieve_image():
|
|
527
|
+
return [
|
|
528
|
+
TextContent("Here is the retrieved image."),
|
|
529
|
+
ImageContent.from_file_path(test_files_path / "apple.jpg", size=(100, 100)),
|
|
530
|
+
]
|
|
531
|
+
|
|
532
|
+
image_retriever_tool = create_tool_from_function(
|
|
533
|
+
name="retrieve_image", description="Tool to retrieve an image", function=retrieve_image
|
|
534
|
+
)
|
|
535
|
+
image_retriever_tool.outputs_to_string = {"raw_result": True}
|
|
536
|
+
|
|
537
|
+
agent = Agent(
|
|
538
|
+
chat_generator=AmazonBedrockChatGenerator(model=model_name),
|
|
539
|
+
system_prompt="You are an Agent that can retrieve images and describe them.",
|
|
540
|
+
tools=[image_retriever_tool],
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
user_message = ChatMessage.from_user("Retrieve the image and describe it in max 5 words.")
|
|
544
|
+
result = agent.run(messages=[user_message])
|
|
545
|
+
|
|
546
|
+
assert "apple" in result["last_message"].text.lower()
|
|
547
|
+
|
|
517
548
|
@pytest.mark.parametrize("model_name", MODELS_TO_TEST)
|
|
518
549
|
def test_default_inference_with_streaming(self, model_name, chat_messages):
|
|
519
550
|
streaming_callback_called = False
|
|
@@ -920,6 +951,28 @@ class TestAmazonBedrockChatGeneratorInference:
|
|
|
920
951
|
assert "trace" in results["replies"][0].meta
|
|
921
952
|
assert "guardrail" in results["replies"][0].meta["trace"]
|
|
922
953
|
|
|
954
|
+
@pytest.mark.parametrize("streaming_callback", [None, print_streaming_chunk])
|
|
955
|
+
@pytest.mark.parametrize("model_name", MODELS_TO_TEST_WITH_PROMPT_CACHING)
|
|
956
|
+
def test_prompt_caching_live_run_with_user_message(self, model_name, streaming_callback):
|
|
957
|
+
generator = AmazonBedrockChatGenerator(model=model_name, streaming_callback=streaming_callback)
|
|
958
|
+
|
|
959
|
+
system_message = ChatMessage.from_system("Always respond with: 'Life is beautiful' (and nothing else).")
|
|
960
|
+
|
|
961
|
+
user_message = ChatMessage.from_user(
|
|
962
|
+
"User message that should be long enough to cache. " * 100, meta={"cachePoint": {"type": "default"}}
|
|
963
|
+
)
|
|
964
|
+
messages = [system_message, user_message]
|
|
965
|
+
result = generator.run(messages=messages)
|
|
966
|
+
|
|
967
|
+
assert "replies" in result
|
|
968
|
+
assert len(result["replies"]) == 1
|
|
969
|
+
usage = result["replies"][0].meta["usage"]
|
|
970
|
+
|
|
971
|
+
# tests run in parallel based on the workflow matrix, so this request should either hit the cache (read tokens)
|
|
972
|
+
# or populate it (write tokens)
|
|
973
|
+
assert usage["cache_read_input_tokens"] > 1000 or usage["cache_write_input_tokens"] > 1000
|
|
974
|
+
assert "cache_details" in usage
|
|
975
|
+
|
|
923
976
|
@pytest.mark.parametrize("model_name", [MODELS_TO_TEST_WITH_TOOLS[0]]) # just one model is enough
|
|
924
977
|
def test_pipeline_with_amazon_bedrock_chat_generator(self, model_name, tools):
|
|
925
978
|
"""
|
{amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_chat_generator_utils.py
RENAMED
|
@@ -9,6 +9,7 @@ from haystack.dataclasses import (
|
|
|
9
9
|
ImageContent,
|
|
10
10
|
ReasoningContent,
|
|
11
11
|
StreamingChunk,
|
|
12
|
+
TextContent,
|
|
12
13
|
ToolCall,
|
|
13
14
|
ToolCallDelta,
|
|
14
15
|
)
|
|
@@ -21,6 +22,7 @@ from haystack_integrations.components.generators.amazon_bedrock.chat.utils impor
|
|
|
21
22
|
_format_tools,
|
|
22
23
|
_parse_completion_response,
|
|
23
24
|
_parse_streaming_response,
|
|
25
|
+
_validate_and_format_cache_point,
|
|
24
26
|
_validate_guardrail_config,
|
|
25
27
|
)
|
|
26
28
|
|
|
@@ -58,7 +60,7 @@ def tools():
|
|
|
58
60
|
|
|
59
61
|
class TestAmazonBedrockChatGeneratorUtils:
|
|
60
62
|
def test_format_tools(self, tools):
|
|
61
|
-
formatted_tool = _format_tools(tools)
|
|
63
|
+
formatted_tool = _format_tools(tools, tools_cachepoint_config={"type": "default"})
|
|
62
64
|
assert formatted_tool == {
|
|
63
65
|
"tools": [
|
|
64
66
|
{
|
|
@@ -83,7 +85,8 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
83
85
|
},
|
|
84
86
|
}
|
|
85
87
|
},
|
|
86
|
-
|
|
88
|
+
{"cachePoint": {"type": "default"}},
|
|
89
|
+
],
|
|
87
90
|
}
|
|
88
91
|
|
|
89
92
|
def test_format_messages(self):
|
|
@@ -120,6 +123,98 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
120
123
|
{"role": "assistant", "content": [{"text": "The weather in Paris is sunny and 25°C."}]},
|
|
121
124
|
]
|
|
122
125
|
|
|
126
|
+
def test_format_messages_with_cache_point(self):
|
|
127
|
+
meta = {"cachePoint": {"type": "default"}}
|
|
128
|
+
|
|
129
|
+
messages = [
|
|
130
|
+
ChatMessage.from_system("\\nYou are a helpful assistant, be super brief in your responses.", meta=meta),
|
|
131
|
+
ChatMessage.from_user("What is the weather in Paris?", meta=meta),
|
|
132
|
+
ChatMessage.from_assistant(
|
|
133
|
+
tool_calls=[ToolCall(id="123", tool_name="weather", arguments={"city": "Paris"})], meta=meta
|
|
134
|
+
),
|
|
135
|
+
ChatMessage.from_tool(
|
|
136
|
+
tool_result="Sunny and 25°C",
|
|
137
|
+
origin=ToolCall(id="123", tool_name="weather", arguments={"city": "Paris"}),
|
|
138
|
+
meta=meta,
|
|
139
|
+
),
|
|
140
|
+
ChatMessage.from_assistant("The weather in Paris is sunny and 25°C.", meta=meta),
|
|
141
|
+
]
|
|
142
|
+
formatted_system_prompts, formatted_messages = _format_messages(messages)
|
|
143
|
+
assert formatted_system_prompts == [
|
|
144
|
+
{"text": "\\nYou are a helpful assistant, be super brief in your responses."},
|
|
145
|
+
{"cachePoint": {"type": "default"}},
|
|
146
|
+
]
|
|
147
|
+
assert formatted_messages == [
|
|
148
|
+
{
|
|
149
|
+
"role": "user",
|
|
150
|
+
"content": [{"text": "What is the weather in Paris?"}, {"cachePoint": {"type": "default"}}],
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"role": "assistant",
|
|
154
|
+
"content": [
|
|
155
|
+
{"toolUse": {"toolUseId": "123", "name": "weather", "input": {"city": "Paris"}}},
|
|
156
|
+
{"cachePoint": {"type": "default"}},
|
|
157
|
+
],
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"role": "user",
|
|
161
|
+
"content": [
|
|
162
|
+
{"toolResult": {"toolUseId": "123", "content": [{"text": "Sunny and 25°C"}]}},
|
|
163
|
+
{"cachePoint": {"type": "default"}},
|
|
164
|
+
],
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"role": "assistant",
|
|
168
|
+
"content": [{"text": "The weather in Paris is sunny and 25°C."}, {"cachePoint": {"type": "default"}}],
|
|
169
|
+
},
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
def test_format_messages_tool_result_with_image(self):
|
|
173
|
+
base64_image = (
|
|
174
|
+
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg=="
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
messages = [
|
|
178
|
+
ChatMessage.from_user("Retrieve the image and describe it in max 5 words."),
|
|
179
|
+
ChatMessage.from_assistant(
|
|
180
|
+
tool_calls=[ToolCall(id="123", tool_name="image_retriever", arguments={"query": "random query"})]
|
|
181
|
+
),
|
|
182
|
+
ChatMessage.from_tool(
|
|
183
|
+
tool_result=[
|
|
184
|
+
TextContent("Here's the retrieved image"),
|
|
185
|
+
ImageContent(base64_image=base64_image, mime_type="image/png"),
|
|
186
|
+
],
|
|
187
|
+
origin=ToolCall(id="123", tool_name="image_retriever", arguments={"query": "random query"}),
|
|
188
|
+
),
|
|
189
|
+
ChatMessage.from_assistant("Beautiful landscape with mountains"),
|
|
190
|
+
]
|
|
191
|
+
formatted_system_prompts, formatted_messages = _format_messages(messages)
|
|
192
|
+
assert formatted_system_prompts == []
|
|
193
|
+
assert formatted_messages == [
|
|
194
|
+
{"role": "user", "content": [{"text": "Retrieve the image and describe it in max 5 words."}]},
|
|
195
|
+
{
|
|
196
|
+
"role": "assistant",
|
|
197
|
+
"content": [
|
|
198
|
+
{"toolUse": {"toolUseId": "123", "name": "image_retriever", "input": {"query": "random query"}}}
|
|
199
|
+
],
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"role": "user",
|
|
203
|
+
"content": [
|
|
204
|
+
{
|
|
205
|
+
"toolResult": {
|
|
206
|
+
"toolUseId": "123",
|
|
207
|
+
"content": [
|
|
208
|
+
{"text": "Here's the retrieved image"},
|
|
209
|
+
{"image": {"format": "png", "source": {"bytes": base64.b64decode(base64_image)}}},
|
|
210
|
+
],
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
],
|
|
214
|
+
},
|
|
215
|
+
{"role": "assistant", "content": [{"text": "Beautiful landscape with mountains"}]},
|
|
216
|
+
]
|
|
217
|
+
|
|
123
218
|
def test_format_message_thinking(self):
|
|
124
219
|
assistant_message = ChatMessage.from_assistant(
|
|
125
220
|
"This is a test message.",
|
|
@@ -373,7 +468,14 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
373
468
|
text_response = {
|
|
374
469
|
"output": {"message": {"role": "assistant", "content": [{"text": "This is a test response"}]}},
|
|
375
470
|
"stopReason": "end_turn",
|
|
376
|
-
"usage": {
|
|
471
|
+
"usage": {
|
|
472
|
+
"inputTokens": 10,
|
|
473
|
+
"outputTokens": 20,
|
|
474
|
+
"totalTokens": 30,
|
|
475
|
+
"cacheReadInputTokens": 1000,
|
|
476
|
+
"cacheWriteInputTokens": 0,
|
|
477
|
+
"cacheDetails": {},
|
|
478
|
+
},
|
|
377
479
|
}
|
|
378
480
|
|
|
379
481
|
replies = _parse_completion_response(text_response, model)
|
|
@@ -383,7 +485,14 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
383
485
|
assert replies[0].meta == {
|
|
384
486
|
"model": model,
|
|
385
487
|
"finish_reason": "stop",
|
|
386
|
-
"usage": {
|
|
488
|
+
"usage": {
|
|
489
|
+
"prompt_tokens": 10,
|
|
490
|
+
"completion_tokens": 20,
|
|
491
|
+
"total_tokens": 30,
|
|
492
|
+
"cache_read_input_tokens": 1000,
|
|
493
|
+
"cache_write_input_tokens": 0,
|
|
494
|
+
"cache_details": {},
|
|
495
|
+
},
|
|
387
496
|
"index": 0,
|
|
388
497
|
}
|
|
389
498
|
|
|
@@ -410,7 +519,14 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
410
519
|
assert replies[0].meta == {
|
|
411
520
|
"model": model,
|
|
412
521
|
"finish_reason": "tool_calls",
|
|
413
|
-
"usage": {
|
|
522
|
+
"usage": {
|
|
523
|
+
"prompt_tokens": 15,
|
|
524
|
+
"completion_tokens": 25,
|
|
525
|
+
"total_tokens": 40,
|
|
526
|
+
"cache_read_input_tokens": 0,
|
|
527
|
+
"cache_write_input_tokens": 0,
|
|
528
|
+
"cache_details": {},
|
|
529
|
+
},
|
|
414
530
|
"index": 0,
|
|
415
531
|
}
|
|
416
532
|
|
|
@@ -441,7 +557,14 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
441
557
|
assert replies[0].meta == {
|
|
442
558
|
"model": model,
|
|
443
559
|
"finish_reason": "stop",
|
|
444
|
-
"usage": {
|
|
560
|
+
"usage": {
|
|
561
|
+
"prompt_tokens": 25,
|
|
562
|
+
"completion_tokens": 35,
|
|
563
|
+
"total_tokens": 60,
|
|
564
|
+
"cache_read_input_tokens": 0,
|
|
565
|
+
"cache_write_input_tokens": 0,
|
|
566
|
+
"cache_details": {},
|
|
567
|
+
},
|
|
445
568
|
"index": 0,
|
|
446
569
|
}
|
|
447
570
|
|
|
@@ -509,7 +632,14 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
509
632
|
"model": "anthropic.claude-3-5-sonnet-20240620-v1:0",
|
|
510
633
|
"index": 0,
|
|
511
634
|
"finish_reason": "tool_calls",
|
|
512
|
-
"usage": {
|
|
635
|
+
"usage": {
|
|
636
|
+
"prompt_tokens": 366,
|
|
637
|
+
"completion_tokens": 134,
|
|
638
|
+
"total_tokens": 500,
|
|
639
|
+
"cache_read_input_tokens": 0,
|
|
640
|
+
"cache_write_input_tokens": 0,
|
|
641
|
+
"cache_details": {},
|
|
642
|
+
},
|
|
513
643
|
},
|
|
514
644
|
)
|
|
515
645
|
assert replies[0] == expected_message
|
|
@@ -563,6 +693,7 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
563
693
|
"totalTokens": 558,
|
|
564
694
|
"cacheReadInputTokens": 0,
|
|
565
695
|
"cacheWriteInputTokens": 0,
|
|
696
|
+
"cacheDetails": {},
|
|
566
697
|
},
|
|
567
698
|
"metrics": {"latencyMs": 4811},
|
|
568
699
|
}
|
|
@@ -599,7 +730,14 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
599
730
|
"model": "arn:aws:bedrock:us-east-1::inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0",
|
|
600
731
|
"index": 0,
|
|
601
732
|
"finish_reason": "tool_calls",
|
|
602
|
-
"usage": {
|
|
733
|
+
"usage": {
|
|
734
|
+
"prompt_tokens": 412,
|
|
735
|
+
"completion_tokens": 146,
|
|
736
|
+
"total_tokens": 558,
|
|
737
|
+
"cache_read_input_tokens": 0,
|
|
738
|
+
"cache_write_input_tokens": 0,
|
|
739
|
+
"cache_details": {},
|
|
740
|
+
},
|
|
603
741
|
},
|
|
604
742
|
)
|
|
605
743
|
assert replies[0] == expected_message
|
|
@@ -665,7 +803,14 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
665
803
|
"model": model,
|
|
666
804
|
"finish_reason": "content_filter",
|
|
667
805
|
"index": 0,
|
|
668
|
-
"usage": {
|
|
806
|
+
"usage": {
|
|
807
|
+
"prompt_tokens": 0,
|
|
808
|
+
"completion_tokens": 0,
|
|
809
|
+
"total_tokens": 0,
|
|
810
|
+
"cache_read_input_tokens": 0,
|
|
811
|
+
"cache_write_input_tokens": 0,
|
|
812
|
+
"cache_details": {},
|
|
813
|
+
},
|
|
669
814
|
"trace": trace,
|
|
670
815
|
}
|
|
671
816
|
|
|
@@ -737,7 +882,14 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
737
882
|
"model": model,
|
|
738
883
|
"index": 0,
|
|
739
884
|
"finish_reason": "tool_calls",
|
|
740
|
-
"usage": {
|
|
885
|
+
"usage": {
|
|
886
|
+
"prompt_tokens": 364,
|
|
887
|
+
"completion_tokens": 71,
|
|
888
|
+
"total_tokens": 435,
|
|
889
|
+
"cache_read_input_tokens": 0,
|
|
890
|
+
"cache_write_input_tokens": 0,
|
|
891
|
+
"cache_details": {},
|
|
892
|
+
},
|
|
741
893
|
},
|
|
742
894
|
)
|
|
743
895
|
]
|
|
@@ -805,7 +957,14 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
805
957
|
meta={
|
|
806
958
|
"model": model,
|
|
807
959
|
"received_at": ANY,
|
|
808
|
-
"usage": {
|
|
960
|
+
"usage": {
|
|
961
|
+
"prompt_tokens": 364,
|
|
962
|
+
"completion_tokens": 71,
|
|
963
|
+
"total_tokens": 435,
|
|
964
|
+
"cache_read_input_tokens": 0,
|
|
965
|
+
"cache_write_input_tokens": 0,
|
|
966
|
+
"cache_details": {},
|
|
967
|
+
},
|
|
809
968
|
},
|
|
810
969
|
component_info=c_info,
|
|
811
970
|
),
|
|
@@ -929,7 +1088,14 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
929
1088
|
"model": "arn:aws:bedrock:us-east-1::inference-profile/us.anthropic.claude-sonnet-4-20250514-v1:0",
|
|
930
1089
|
"index": 0,
|
|
931
1090
|
"finish_reason": "tool_calls",
|
|
932
|
-
"usage": {
|
|
1091
|
+
"usage": {
|
|
1092
|
+
"prompt_tokens": 412,
|
|
1093
|
+
"completion_tokens": 104,
|
|
1094
|
+
"total_tokens": 516,
|
|
1095
|
+
"cache_read_input_tokens": 0,
|
|
1096
|
+
"cache_write_input_tokens": 0,
|
|
1097
|
+
"cache_details": {},
|
|
1098
|
+
},
|
|
933
1099
|
"completion_start_time": ANY,
|
|
934
1100
|
},
|
|
935
1101
|
)
|
|
@@ -1015,7 +1181,14 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
1015
1181
|
"model": model,
|
|
1016
1182
|
"index": 0,
|
|
1017
1183
|
"finish_reason": "stop",
|
|
1018
|
-
"usage": {
|
|
1184
|
+
"usage": {
|
|
1185
|
+
"prompt_tokens": 461,
|
|
1186
|
+
"completion_tokens": 138,
|
|
1187
|
+
"total_tokens": 599,
|
|
1188
|
+
"cache_read_input_tokens": 0,
|
|
1189
|
+
"cache_write_input_tokens": 0,
|
|
1190
|
+
"cache_details": {},
|
|
1191
|
+
},
|
|
1019
1192
|
"completion_start_time": ANY,
|
|
1020
1193
|
},
|
|
1021
1194
|
)
|
|
@@ -1093,7 +1266,14 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
1093
1266
|
"model": "anthropic.claude-3-5-sonnet-20240620-v1:0",
|
|
1094
1267
|
"index": 0,
|
|
1095
1268
|
"finish_reason": "tool_calls",
|
|
1096
|
-
"usage": {
|
|
1269
|
+
"usage": {
|
|
1270
|
+
"prompt_tokens": 366,
|
|
1271
|
+
"completion_tokens": 83,
|
|
1272
|
+
"total_tokens": 449,
|
|
1273
|
+
"cache_read_input_tokens": 0,
|
|
1274
|
+
"cache_write_input_tokens": 0,
|
|
1275
|
+
"cache_details": {},
|
|
1276
|
+
},
|
|
1097
1277
|
"completion_start_time": ANY,
|
|
1098
1278
|
},
|
|
1099
1279
|
)
|
|
@@ -1169,7 +1349,14 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
1169
1349
|
"model": model,
|
|
1170
1350
|
"index": 0,
|
|
1171
1351
|
"finish_reason": "content_filter",
|
|
1172
|
-
"usage": {
|
|
1352
|
+
"usage": {
|
|
1353
|
+
"prompt_tokens": 0,
|
|
1354
|
+
"completion_tokens": 0,
|
|
1355
|
+
"total_tokens": 0,
|
|
1356
|
+
"cache_read_input_tokens": 0,
|
|
1357
|
+
"cache_write_input_tokens": 0,
|
|
1358
|
+
"cache_details": {},
|
|
1359
|
+
},
|
|
1173
1360
|
"trace": trace,
|
|
1174
1361
|
},
|
|
1175
1362
|
)
|
|
@@ -1403,3 +1590,25 @@ class TestAmazonBedrockChatGeneratorUtils:
|
|
|
1403
1590
|
},
|
|
1404
1591
|
streaming=False,
|
|
1405
1592
|
)
|
|
1593
|
+
|
|
1594
|
+
def test_validate_and_format_cache_point(self):
|
|
1595
|
+
cache_point = _validate_and_format_cache_point(None)
|
|
1596
|
+
assert cache_point is None
|
|
1597
|
+
|
|
1598
|
+
cache_point = _validate_and_format_cache_point({})
|
|
1599
|
+
assert cache_point is None
|
|
1600
|
+
|
|
1601
|
+
cache_point = _validate_and_format_cache_point({"type": "default"})
|
|
1602
|
+
assert cache_point == {"cachePoint": {"type": "default"}}
|
|
1603
|
+
|
|
1604
|
+
cache_point = _validate_and_format_cache_point({"type": "default", "ttl": "5m"})
|
|
1605
|
+
assert cache_point == {"cachePoint": {"type": "default", "ttl": "5m"}}
|
|
1606
|
+
|
|
1607
|
+
with pytest.raises(ValueError, match=r"Cache point must have a 'type' key with value 'default'."):
|
|
1608
|
+
_validate_and_format_cache_point({"invalid": "config"})
|
|
1609
|
+
|
|
1610
|
+
with pytest.raises(ValueError, match=r"Cache point must have a 'type' key with value 'default'."):
|
|
1611
|
+
_validate_and_format_cache_point({"type": "invalid"})
|
|
1612
|
+
|
|
1613
|
+
with pytest.raises(ValueError, match=r"Cache point can only contain 'type' and 'ttl' keys."):
|
|
1614
|
+
_validate_and_format_cache_point({"type": "default", "invalid": "config"})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/examples/bedrock_ranker_example.py
RENAMED
|
File without changes
|
{amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/examples/chatgenerator_example.py
RENAMED
|
File without changes
|
|
File without changes
|
{amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/examples/s3_downloader_example.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_document_embedder.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_files/haystack-logo.png
RENAMED
|
File without changes
|
{amazon_bedrock_haystack-6.2.1 → amazon_bedrock_haystack-6.4.0}/tests/test_files/sample_pdf_1.pdf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|