Skip to content

Commit f8e434a

Browse files
author
Bob Strahan
committed
2 parents 49b9254 + dd2b7b4 commit f8e434a

File tree

3 files changed

+72
-24
lines changed

3 files changed

+72
-24
lines changed

lib/idp_common_pkg/idp_common/extraction/agentic_idp.py

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,33 @@
4747
view_todo_list,
4848
)
4949

50+
# Supported image formats for Bedrock API
51+
SUPPORTED_IMAGE_FORMATS = {"jpeg", "png", "gif", "webp"}
52+
53+
54+
def detect_image_format(image_bytes: bytes) -> str:
55+
"""
56+
Detect the image format from raw bytes.
57+
58+
Args:
59+
image_bytes: Raw image bytes
60+
61+
Returns:
62+
Image format string suitable for Bedrock API ('jpeg', 'png', 'gif', 'webp')
63+
64+
Raises:
65+
ValueError: If the image format is unsupported or cannot be detected
66+
"""
67+
img = Image.open(io.BytesIO(image_bytes))
68+
69+
if not img.format or img.format.lower() not in SUPPORTED_IMAGE_FORMATS:
70+
raise ValueError(
71+
f"Unsupported image format: {img.format}. "
72+
f"Supported formats: {', '.join(SUPPORTED_IMAGE_FORMATS)}"
73+
)
74+
return img.format.lower()
75+
76+
5077
# Use AWS Lambda Powertools Logger for structured logging
5178
# Automatically logs as JSON with Lambda context, request_id, timestamp, etc.
5279
# In Lambda: Full JSON structured logs
@@ -207,11 +234,15 @@ def view_image(image_index: int, agent: Agent) -> dict:
207234
# Get the base image (already has grid overlay)
208235
img_bytes = page_images[image_index]
209236

237+
# Detect actual image format from bytes
238+
img_format = detect_image_format(img_bytes)
239+
210240
logger.info(
211241
"Returning image to agent",
212242
extra={
213243
"image_index": image_index,
214244
"image_size_bytes": len(img_bytes),
245+
"image_format": img_format,
215246
},
216247
)
217248

@@ -220,7 +251,7 @@ def view_image(image_index: int, agent: Agent) -> dict:
220251
"content": [
221252
{
222253
"image": {
223-
"format": "png",
254+
"format": img_format,
224255
"source": {
225256
"bytes": img_bytes,
226257
},
@@ -775,12 +806,17 @@ def _prepare_prompt_content(
775806
extra={"image_count": len(page_images)},
776807
)
777808

778-
prompt_content += [
779-
ContentBlock(
780-
image=ImageContent(format="png", source=ImageSource(bytes=img_bytes))
809+
for img_bytes in page_images:
810+
# Detect actual image format from bytes
811+
img_format = detect_image_format(img_bytes)
812+
prompt_content.append(
813+
ContentBlock(
814+
image=ImageContent(
815+
format=img_format, # pyright: ignore[reportArgumentType]
816+
source=ImageSource(bytes=img_bytes),
817+
)
818+
)
781819
)
782-
for img_bytes in page_images
783-
]
784820

785821
# Add existing data context if provided
786822
if existing_data:

lib/idp_common_pkg/tests/unit/test_delete_tests.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,19 @@
1414
sys.modules["idp_common_pkg"] = Mock()
1515
sys.modules["idp_common_pkg.logger"] = Mock()
1616

17-
# Add the lambda directory to the path for importing
18-
lambda_path = os.path.join(
19-
os.path.dirname(__file__), "../../../../src/lambda/delete_tests"
20-
)
21-
sys.path.insert(0, lambda_path)
17+
# Mock boto3 before importing the Lambda module to prevent NoRegionError
18+
# The Lambda creates boto3 clients at module level which requires AWS region
19+
with patch("boto3.resource") as mock_resource, patch("boto3.client") as mock_client:
20+
mock_resource.return_value = Mock()
21+
mock_client.return_value = Mock()
22+
23+
# Add the lambda directory to the path for importing
24+
lambda_path = os.path.join(
25+
os.path.dirname(__file__), "../../../../src/lambda/delete_tests"
26+
)
27+
sys.path.insert(0, lambda_path)
2228

23-
import index # type: ignore[import-untyped] # noqa: E402
29+
import index # type: ignore[import-untyped] # noqa: E402
2430

2531

2632
@pytest.mark.unit

lib/idp_common_pkg/tests/unit/test_results_resolver.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,24 @@
88

99
import pytest
1010

11-
# Import the specific lambda module using importlib to avoid conflicts
12-
spec = importlib.util.spec_from_file_location(
13-
"results_index",
14-
os.path.join(
15-
os.path.dirname(__file__),
16-
"../../../../src/lambda/test_results_resolver/index.py",
17-
),
18-
)
19-
if spec is None or spec.loader is None:
20-
raise ImportError("Could not load test_results_resolver module")
21-
index = importlib.util.module_from_spec(spec)
22-
spec.loader.exec_module(index)
11+
# Mock boto3 before importing the Lambda module to prevent NoRegionError
12+
# The Lambda creates boto3 clients at module level which requires AWS region
13+
with patch("boto3.resource") as mock_resource, patch("boto3.client") as mock_client:
14+
mock_resource.return_value = Mock()
15+
mock_client.return_value = Mock()
16+
17+
# Import the specific lambda module using importlib to avoid conflicts
18+
spec = importlib.util.spec_from_file_location(
19+
"results_index",
20+
os.path.join(
21+
os.path.dirname(__file__),
22+
"../../../../src/lambda/test_results_resolver/index.py",
23+
),
24+
)
25+
if spec is None or spec.loader is None:
26+
raise ImportError("Could not load test_results_resolver module")
27+
index = importlib.util.module_from_spec(spec)
28+
spec.loader.exec_module(index)
2329

2430

2531
@pytest.mark.unit

0 commit comments

Comments
 (0)