amazon-bedrock-haystack 3.7.0__py3-none-any.whl → 3.9.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-3.7.0.dist-info → amazon_bedrock_haystack-3.9.0.dist-info}/METADATA +2 -2
- {amazon_bedrock_haystack-3.7.0.dist-info → amazon_bedrock_haystack-3.9.0.dist-info}/RECORD +6 -6
- haystack_integrations/components/generators/amazon_bedrock/chat/chat_generator.py +36 -4
- haystack_integrations/components/generators/amazon_bedrock/chat/utils.py +54 -5
- {amazon_bedrock_haystack-3.7.0.dist-info → amazon_bedrock_haystack-3.9.0.dist-info}/WHEEL +0 -0
- {amazon_bedrock_haystack-3.7.0.dist-info → amazon_bedrock_haystack-3.9.0.dist-info}/licenses/LICENSE.txt +0 -0
{amazon_bedrock_haystack-3.7.0.dist-info → amazon_bedrock_haystack-3.9.0.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: amazon-bedrock-haystack
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.9.0
|
|
4
4
|
Summary: An integration of Amazon Bedrock as an AmazonBedrockGenerator component.
|
|
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.16.0
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
26
26
|
|
|
27
27
|
# amazon-bedrock-haystack
|
|
@@ -11,12 +11,12 @@ haystack_integrations/components/generators/amazon_bedrock/__init__.py,sha256=lv
|
|
|
11
11
|
haystack_integrations/components/generators/amazon_bedrock/adapters.py,sha256=yBC-3YwV6qAwSXMtdZiLSYh2lUpPQIDy7Efl7w-Cu-k,19640
|
|
12
12
|
haystack_integrations/components/generators/amazon_bedrock/generator.py,sha256=c_saV5zxFYQVJT0Hzo80lKty46itL0Dp31VuDueYa3M,14716
|
|
13
13
|
haystack_integrations/components/generators/amazon_bedrock/chat/__init__.py,sha256=6GZ8Y3Lw0rLOsOAqi6Tu5mZC977UzQvgDxKpOWr8IQw,110
|
|
14
|
-
haystack_integrations/components/generators/amazon_bedrock/chat/chat_generator.py,sha256=
|
|
15
|
-
haystack_integrations/components/generators/amazon_bedrock/chat/utils.py,sha256=
|
|
14
|
+
haystack_integrations/components/generators/amazon_bedrock/chat/chat_generator.py,sha256=iIaMsOOX9eYvR1GNgpxNKxaOli91ShrCv3MuBBK1NSs,24743
|
|
15
|
+
haystack_integrations/components/generators/amazon_bedrock/chat/utils.py,sha256=GLGbUSpnmGLUQyBNrlHMR_GaS_zpSQbVIzXVTL8F3IU,23188
|
|
16
16
|
haystack_integrations/components/rankers/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
haystack_integrations/components/rankers/amazon_bedrock/__init__.py,sha256=Zrc3BSVkEaXYpliEi6hKG9bqW4J7DNk93p50SuoyT1Q,107
|
|
18
18
|
haystack_integrations/components/rankers/amazon_bedrock/ranker.py,sha256=enAjf2QyDwfpidKkFCdLz954cx-Tjh9emrOS3vINJDg,12344
|
|
19
|
-
amazon_bedrock_haystack-3.
|
|
20
|
-
amazon_bedrock_haystack-3.
|
|
21
|
-
amazon_bedrock_haystack-3.
|
|
22
|
-
amazon_bedrock_haystack-3.
|
|
19
|
+
amazon_bedrock_haystack-3.9.0.dist-info/METADATA,sha256=GgpwClHZ8LJLpikG4KNZDUdSjsaWzpamMRe3zfWf-aw,2287
|
|
20
|
+
amazon_bedrock_haystack-3.9.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
21
|
+
amazon_bedrock_haystack-3.9.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
|
|
22
|
+
amazon_bedrock_haystack-3.9.0.dist-info/RECORD,,
|
|
@@ -5,7 +5,7 @@ from botocore.config import Config
|
|
|
5
5
|
from botocore.eventstream import EventStream
|
|
6
6
|
from botocore.exceptions import ClientError
|
|
7
7
|
from haystack import component, default_from_dict, default_to_dict, logging
|
|
8
|
-
from haystack.dataclasses import ChatMessage, StreamingCallbackT, select_streaming_callback
|
|
8
|
+
from haystack.dataclasses import ChatMessage, ComponentInfo, StreamingCallbackT, select_streaming_callback
|
|
9
9
|
from haystack.tools import (
|
|
10
10
|
Tool,
|
|
11
11
|
Toolset,
|
|
@@ -56,6 +56,22 @@ class AmazonBedrockChatGenerator:
|
|
|
56
56
|
client.run(messages, generation_kwargs={"max_tokens": 512})
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
### Multimodal example
|
|
60
|
+
```python
|
|
61
|
+
from haystack.dataclasses import ChatMessage, ImageContent
|
|
62
|
+
from haystack_integrations.components.generators.amazon_bedrock import AmazonBedrockChatGenerator
|
|
63
|
+
|
|
64
|
+
generator = AmazonBedrockChatGenerator(model="anthropic.claude-3-5-sonnet-20240620-v1:0")
|
|
65
|
+
|
|
66
|
+
image_content = ImageContent.from_file_path(file_path="apple.jpg")
|
|
67
|
+
|
|
68
|
+
message = ChatMessage.from_user(content_parts=["Describe the image using 10 words at most.", image_content])
|
|
69
|
+
|
|
70
|
+
response = generator.run(messages=[message])["replies"][0].text
|
|
71
|
+
|
|
72
|
+
print(response)
|
|
73
|
+
> The image shows a red apple.
|
|
74
|
+
|
|
59
75
|
### Tool usage example
|
|
60
76
|
# AmazonBedrockChatGenerator supports Haystack's unified tool architecture, allowing tools to be used
|
|
61
77
|
# across different chat generators. The same tool definitions and usage patterns work consistently
|
|
@@ -371,7 +387,9 @@ class AmazonBedrockChatGenerator:
|
|
|
371
387
|
if additional_fields:
|
|
372
388
|
params["additionalModelRequestFields"] = additional_fields
|
|
373
389
|
|
|
374
|
-
|
|
390
|
+
# overloads that exhaust finite Literals(bool) not treated as exhaustive
|
|
391
|
+
# see https://github.com/python/mypy/issues/14764
|
|
392
|
+
callback = select_streaming_callback( # type: ignore[call-overload]
|
|
375
393
|
init_callback=self.streaming_callback,
|
|
376
394
|
runtime_callback=streaming_callback,
|
|
377
395
|
requires_async=requires_async,
|
|
@@ -406,6 +424,8 @@ class AmazonBedrockChatGenerator:
|
|
|
406
424
|
:raises AmazonBedrockInferenceError:
|
|
407
425
|
If the Bedrock inference API call fails.
|
|
408
426
|
"""
|
|
427
|
+
component_info = ComponentInfo.from_component(self)
|
|
428
|
+
|
|
409
429
|
params, callback = self._prepare_request_params(
|
|
410
430
|
messages=messages,
|
|
411
431
|
streaming_callback=streaming_callback,
|
|
@@ -422,7 +442,12 @@ class AmazonBedrockChatGenerator:
|
|
|
422
442
|
msg = "No stream found in the response."
|
|
423
443
|
raise AmazonBedrockInferenceError(msg)
|
|
424
444
|
# the type of streaming callback is checked in _prepare_request_params, but mypy doesn't know
|
|
425
|
-
replies = _parse_streaming_response(
|
|
445
|
+
replies = _parse_streaming_response(
|
|
446
|
+
response_stream=response_stream,
|
|
447
|
+
streaming_callback=callback, # type: ignore[arg-type]
|
|
448
|
+
model=self.model,
|
|
449
|
+
component_info=component_info,
|
|
450
|
+
)
|
|
426
451
|
else:
|
|
427
452
|
response = self.client.converse(**params)
|
|
428
453
|
replies = _parse_completion_response(response, self.model)
|
|
@@ -459,6 +484,8 @@ class AmazonBedrockChatGenerator:
|
|
|
459
484
|
:raises AmazonBedrockInferenceError:
|
|
460
485
|
If the Bedrock inference API call fails.
|
|
461
486
|
"""
|
|
487
|
+
component_info = ComponentInfo.from_component(self)
|
|
488
|
+
|
|
462
489
|
params, callback = self._prepare_request_params(
|
|
463
490
|
messages=messages,
|
|
464
491
|
streaming_callback=streaming_callback,
|
|
@@ -479,7 +506,12 @@ class AmazonBedrockChatGenerator:
|
|
|
479
506
|
msg = "No stream found in the response."
|
|
480
507
|
raise AmazonBedrockInferenceError(msg)
|
|
481
508
|
# the type of streaming callback is checked in _prepare_request_params, but mypy doesn't know
|
|
482
|
-
replies = await _parse_streaming_response_async(
|
|
509
|
+
replies = await _parse_streaming_response_async(
|
|
510
|
+
response_stream=response_stream,
|
|
511
|
+
streaming_callback=callback, # type: ignore[arg-type]
|
|
512
|
+
model=self.model,
|
|
513
|
+
component_info=component_info,
|
|
514
|
+
)
|
|
483
515
|
else:
|
|
484
516
|
response = await async_client.converse(**params)
|
|
485
517
|
replies = _parse_completion_response(response, self.model)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import base64
|
|
1
2
|
import json
|
|
2
3
|
from datetime import datetime, timezone
|
|
3
4
|
from typing import Any, Dict, List, Optional, Tuple
|
|
@@ -8,8 +9,11 @@ from haystack.dataclasses import (
|
|
|
8
9
|
AsyncStreamingCallbackT,
|
|
9
10
|
ChatMessage,
|
|
10
11
|
ChatRole,
|
|
12
|
+
ComponentInfo,
|
|
13
|
+
ImageContent,
|
|
11
14
|
StreamingChunk,
|
|
12
15
|
SyncStreamingCallbackT,
|
|
16
|
+
TextContent,
|
|
13
17
|
ToolCall,
|
|
14
18
|
)
|
|
15
19
|
from haystack.tools import Tool
|
|
@@ -17,6 +21,10 @@ from haystack.tools import Tool
|
|
|
17
21
|
logger = logging.getLogger(__name__)
|
|
18
22
|
|
|
19
23
|
|
|
24
|
+
# see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ImageBlock.html for supported formats
|
|
25
|
+
IMAGE_SUPPORTED_FORMATS = ["png", "jpeg", "gif", "webp"]
|
|
26
|
+
|
|
27
|
+
|
|
20
28
|
# Haystack to Bedrock util methods
|
|
21
29
|
def _format_tools(tools: Optional[List[Tool]] = None) -> Optional[Dict[str, Any]]:
|
|
22
30
|
"""
|
|
@@ -149,6 +157,39 @@ def _repair_tool_result_messages(bedrock_formatted_messages: List[Dict[str, Any]
|
|
|
149
157
|
return [msg for _, msg in repaired_bedrock_formatted_messages]
|
|
150
158
|
|
|
151
159
|
|
|
160
|
+
def _format_text_image_message(message: ChatMessage) -> Dict[str, Any]:
|
|
161
|
+
"""
|
|
162
|
+
Format a Haystack ChatMessage containing text and optional image content into Bedrock format.
|
|
163
|
+
|
|
164
|
+
:param message: Haystack ChatMessage.
|
|
165
|
+
:returns: Dictionary representing the message in Bedrock's expected format.
|
|
166
|
+
:raises ValueError: If image content is found in an assistant message or an unsupported image format is used.
|
|
167
|
+
"""
|
|
168
|
+
content_parts = message._content
|
|
169
|
+
|
|
170
|
+
bedrock_content_blocks: List[Dict[str, Any]] = []
|
|
171
|
+
for part in content_parts:
|
|
172
|
+
if isinstance(part, TextContent):
|
|
173
|
+
bedrock_content_blocks.append({"text": part.text})
|
|
174
|
+
|
|
175
|
+
elif isinstance(part, ImageContent):
|
|
176
|
+
if message.is_from(ChatRole.ASSISTANT):
|
|
177
|
+
err_msg = "Image content is not supported for assistant messages"
|
|
178
|
+
raise ValueError(err_msg)
|
|
179
|
+
|
|
180
|
+
image_format = part.mime_type.split("/")[-1] if part.mime_type else None
|
|
181
|
+
if image_format not in IMAGE_SUPPORTED_FORMATS:
|
|
182
|
+
err_msg = (
|
|
183
|
+
f"Unsupported image format: {image_format}. "
|
|
184
|
+
f"Bedrock supports the following image formats: {IMAGE_SUPPORTED_FORMATS}"
|
|
185
|
+
)
|
|
186
|
+
raise ValueError(err_msg)
|
|
187
|
+
source = {"bytes": base64.b64decode(part.base64_image)}
|
|
188
|
+
bedrock_content_blocks.append({"image": {"format": image_format, "source": source}})
|
|
189
|
+
|
|
190
|
+
return {"role": message.role.value, "content": bedrock_content_blocks}
|
|
191
|
+
|
|
192
|
+
|
|
152
193
|
def _format_messages(messages: List[ChatMessage]) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]:
|
|
153
194
|
"""
|
|
154
195
|
Format a list of Haystack ChatMessages to the format expected by Bedrock API.
|
|
@@ -174,8 +215,7 @@ def _format_messages(messages: List[ChatMessage]) -> Tuple[List[Dict[str, Any]],
|
|
|
174
215
|
elif msg.tool_call_results:
|
|
175
216
|
bedrock_formatted_messages.append(_format_tool_result_message(msg))
|
|
176
217
|
else:
|
|
177
|
-
|
|
178
|
-
bedrock_formatted_messages.append({"role": msg.role.value, "content": [{"text": msg.text}]})
|
|
218
|
+
bedrock_formatted_messages.append(_format_text_image_message(msg))
|
|
179
219
|
|
|
180
220
|
repaired_bedrock_formatted_messages = _repair_tool_result_messages(bedrock_formatted_messages)
|
|
181
221
|
return system_prompts, repaired_bedrock_formatted_messages
|
|
@@ -235,7 +275,9 @@ def _parse_completion_response(response_body: Dict[str, Any], model: str) -> Lis
|
|
|
235
275
|
|
|
236
276
|
|
|
237
277
|
# Bedrock streaming to Haystack util methods
|
|
238
|
-
def _convert_event_to_streaming_chunk(
|
|
278
|
+
def _convert_event_to_streaming_chunk(
|
|
279
|
+
event: Dict[str, Any], model: str, component_info: ComponentInfo
|
|
280
|
+
) -> StreamingChunk:
|
|
239
281
|
"""
|
|
240
282
|
Convert a Bedrock streaming event to a Haystack StreamingChunk.
|
|
241
283
|
|
|
@@ -244,6 +286,7 @@ def _convert_event_to_streaming_chunk(event: Dict[str, Any], model: str) -> Stre
|
|
|
244
286
|
|
|
245
287
|
:param event: Dictionary containing a Bedrock streaming event.
|
|
246
288
|
:param model: The model ID used for generation, included in chunk metadata.
|
|
289
|
+
:param component_info: ComponentInfo object
|
|
247
290
|
:returns: StreamingChunk object containing the content and metadata extracted from the event.
|
|
248
291
|
"""
|
|
249
292
|
# Initialize an empty StreamingChunk to return if no relevant event is found
|
|
@@ -358,6 +401,8 @@ def _convert_event_to_streaming_chunk(event: Dict[str, Any], model: str) -> Stre
|
|
|
358
401
|
},
|
|
359
402
|
)
|
|
360
403
|
|
|
404
|
+
streaming_chunk.component_info = component_info
|
|
405
|
+
|
|
361
406
|
return streaming_chunk
|
|
362
407
|
|
|
363
408
|
|
|
@@ -438,6 +483,7 @@ def _parse_streaming_response(
|
|
|
438
483
|
response_stream: EventStream,
|
|
439
484
|
streaming_callback: SyncStreamingCallbackT,
|
|
440
485
|
model: str,
|
|
486
|
+
component_info: ComponentInfo,
|
|
441
487
|
) -> List[ChatMessage]:
|
|
442
488
|
"""
|
|
443
489
|
Parse a streaming response from Bedrock.
|
|
@@ -445,11 +491,12 @@ def _parse_streaming_response(
|
|
|
445
491
|
:param response_stream: EventStream from Bedrock API
|
|
446
492
|
:param streaming_callback: Callback for streaming chunks
|
|
447
493
|
:param model: The model ID used for generation
|
|
494
|
+
:param component_info: ComponentInfo object
|
|
448
495
|
:return: List of ChatMessage objects
|
|
449
496
|
"""
|
|
450
497
|
chunks: List[StreamingChunk] = []
|
|
451
498
|
for event in response_stream:
|
|
452
|
-
streaming_chunk = _convert_event_to_streaming_chunk(event=event, model=model)
|
|
499
|
+
streaming_chunk = _convert_event_to_streaming_chunk(event=event, model=model, component_info=component_info)
|
|
453
500
|
streaming_callback(streaming_chunk)
|
|
454
501
|
chunks.append(streaming_chunk)
|
|
455
502
|
replies = [_convert_streaming_chunks_to_chat_message(chunks=chunks)]
|
|
@@ -460,6 +507,7 @@ async def _parse_streaming_response_async(
|
|
|
460
507
|
response_stream: EventStream,
|
|
461
508
|
streaming_callback: AsyncStreamingCallbackT,
|
|
462
509
|
model: str,
|
|
510
|
+
component_info: ComponentInfo,
|
|
463
511
|
) -> List[ChatMessage]:
|
|
464
512
|
"""
|
|
465
513
|
Parse a streaming response from Bedrock.
|
|
@@ -467,11 +515,12 @@ async def _parse_streaming_response_async(
|
|
|
467
515
|
:param response_stream: EventStream from Bedrock API
|
|
468
516
|
:param streaming_callback: Callback for streaming chunks
|
|
469
517
|
:param model: The model ID used for generation
|
|
518
|
+
:param component_info: ComponentInfo object
|
|
470
519
|
:return: List of ChatMessage objects
|
|
471
520
|
"""
|
|
472
521
|
chunks: List[StreamingChunk] = []
|
|
473
522
|
async for event in response_stream:
|
|
474
|
-
streaming_chunk = _convert_event_to_streaming_chunk(event=event, model=model)
|
|
523
|
+
streaming_chunk = _convert_event_to_streaming_chunk(event=event, model=model, component_info=component_info)
|
|
475
524
|
await streaming_callback(streaming_chunk)
|
|
476
525
|
chunks.append(streaming_chunk)
|
|
477
526
|
replies = [_convert_streaming_chunks_to_chat_message(chunks=chunks)]
|
|
File without changes
|
|
File without changes
|