fix(aws): preserve image format for Bedrock images#6328
Open
VectorPeak wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes AWS Bedrock chat-context formatting for non-JPEG
ImageContentinputs by deriving the Bedrock image block format from the serialized image MIME type instead of always declaringjpeg.What Problem This Solves
AWS Bedrock image blocks require the declared
formatto match the image bytes being sent.LiveKit already preserves that information when it serializes an
ImageContentdata URL. For example, a PNG data URL is decoded into raw PNG bytes withmime_type="image/png":The bug is in the AWS formatter. It receives the serialized image, but always declares the Bedrock image format as
jpeg:{ "image": { "format": "jpeg", "source": {"bytes": img.data_bytes}, } }That is correct only when the serialized image is actually JPEG. For PNG, GIF, or WebP data URLs, the formatter keeps the original non-JPEG bytes but labels them as JPEG in the Bedrock request.
So the problem is not that LiveKit loses or rewrites the image bytes. The problem is that the AWS request metadata no longer matches those bytes.
AWS Bedrock supports
png,jpeg,gif, andwebpasImageBlock.formatvalues, so the formatter should use the serialized MIME type to choose the matching Bedrock format.Change
Map
SerializedImage.mime_typeto the corresponding Bedrock image format:This keeps the existing JPEG behavior for
VideoFrameinputs, becauseserialize_image()currently encodes frames as JPEG.This also keeps the current Bedrock behavior for external image URLs unchanged: external URLs are still rejected because this formatter path only builds inline Bedrock image blocks.
Evidence
A PNG
ImageContentcan currently be serialized with the correct MIME type but formatted for AWS with the wrong Bedrock format:Before this fix, the generated Bedrock message declares the image as JPEG:
{ "image": { "format": "jpeg", "source": {"bytes": b"<original png bytes>"}, } }After this fix, the declared format matches the serialized image bytes:
{ "image": { "format": "png", "source": {"bytes": b"<original png bytes>"}, } }The same mapping applies to JPEG, GIF, and WebP inputs.
AWS documents
ImageBlock.formatvalid values aspng | jpeg | gif | webp: https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ImageBlock.htmlPossible call chain / impact
The affected path is only AWS Bedrock chat-context conversion for inline image inputs.
This PR does not change:
VideoFrameencoding behaviorSibling provider surfaces already preserve image MIME type differently: OpenAI and Mistral include the MIME type in data URLs, Anthropic passes
media_type, and Google passesmime_typein image parts. AWS was the outlier because it dropped the MIME type and hardcoded the Bedrock format.Validation
uv run --no-sync pytest tests/test_chat_ctx.py -q- passed, 27 passed / 1 skippeduv run --no-sync pytest tests/test_chat_ctx.py -q -k aws_image_content- passed, 5 passeduv run --no-sync ruff check livekit-agents/livekit/agents/llm/_provider_format/aws.py tests/test_chat_ctx.py- passeduv run --no-sync ruff format --check livekit-agents/livekit/agents/llm/_provider_format/aws.py tests/test_chat_ctx.py- passedgit diff --check- passed