Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix image format to match OpenAI Responses API documentation
Co-authored-by: TomeHirata <[email protected]>
  • Loading branch information
Copilot and TomeHirata committed Oct 30, 2025
commit 6da81b36cca2b1c91c4452a9c0b71cf13b9e97cf
37 changes: 2 additions & 35 deletions dspy/clients/lm.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,48 +489,15 @@ def _convert_content_item_to_responses_format(item: dict[str, Any]) -> dict[str,
For images, converts from:
{"type": "image_url", "image_url": {"url": "..."}}
To:
{"type": "input_image", "source": {"type": "url", "url": "..."}}
or:
{"type": "input_image", "source": {"type": "base64", "media_type": "...", "data": "..."}}
{"type": "input_image", "image_url": "..."}

For text and other types, passes through as-is (already in correct format).
"""
if item.get("type") == "image_url":
image_url = item.get("image_url", {}).get("url", "")

# Check if it's a base64 data URI
if image_url.startswith("data:"):
# Extract media type and base64 data
# Format: data:image/png;base64,iVBORw0KG...
parts = image_url.split(",", 1)
if len(parts) == 2:
header, data = parts
# Extract media type from header (e.g., "data:image/png;base64" -> "image/png")
# Handle both "data:image/png;base64" and "data:image/png" formats
media_type_parts = header.split(";")[0].replace("data:", "")
if media_type_parts:
media_type = media_type_parts
else:
# Fallback to a default media type if extraction fails
media_type = "image/png"

return {
"type": "input_image",
"source": {
"type": "base64",
"media_type": media_type,
"data": data,
}
}
# If data URI is malformed (doesn't have comma separator), fall through to URL handling

# Otherwise treat as URL
return {
"type": "input_image",
"source": {
"type": "url",
"url": image_url,
}
"image_url": image_url,
}

# For non-image items, return as-is
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot I this we also need to convert text item from type: text to type: input_text. See https://platform.openai.com/docs/api-reference/responses

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Fixed in 0055def - now converting text items from type: "text" to type: "input_text" to match the OpenAI Responses API format.

Expand Down
10 changes: 3 additions & 7 deletions tests/clients/test_lm.py
Original file line number Diff line number Diff line change
Expand Up @@ -672,9 +672,7 @@ def test_responses_api_converts_images_correctly():

# Second item should be converted to input_image format
assert content[1]["type"] == "input_image"
assert content[1]["source"]["type"] == "base64"
assert content[1]["source"]["media_type"] == "image/png"
assert content[1]["source"]["data"] == "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
assert content[1]["image_url"] == "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="

# Test with URL image
request_with_url_image = {
Expand All @@ -699,8 +697,7 @@ def test_responses_api_converts_images_correctly():
content = result["input"][0]["content"]
assert len(content) == 1
assert content[0]["type"] == "input_image"
assert content[0]["source"]["type"] == "url"
assert content[0]["source"]["url"] == "https://example.com/image.jpg"
assert content[0]["image_url"] == "https://example.com/image.jpg"


def test_responses_api_with_image_input():
Expand Down Expand Up @@ -759,5 +756,4 @@ def test_responses_api_with_image_input():
# Check that image was converted to input_image format
image_content = [c for c in content if c.get("type") == "input_image"]
assert len(image_content) == 1
assert image_content[0]["source"]["type"] == "base64"
assert image_content[0]["source"]["media_type"] == "image/png"
assert image_content[0]["image_url"] == "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="