mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-25 05:54:53 +00:00
Merge 68f1ba1e5a into c80f1c2ec8
This commit is contained in:
commit
2d1563a1ed
2 changed files with 92 additions and 1 deletions
|
|
@ -520,8 +520,25 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
self._add_prompt_cache_breakpoint_if_present(content, image_obj)
|
||||
)
|
||||
elif content.get("type") == "document":
|
||||
# Convert Anthropic document format (PDF, etc.) to OpenAI format
|
||||
# Convert Anthropic document format to OpenAI format.
|
||||
# Only image/* media types can be forwarded as image_url;
|
||||
# non-image documents (e.g. application/pdf) are not
|
||||
# accepted by image-only backends and must be rejected
|
||||
# with a clear error rather than silently producing a
|
||||
# malformed request.
|
||||
source = content.get("source", {})
|
||||
media_type = source.get("media_type", "") if isinstance(source, dict) else ""
|
||||
if media_type and not str(media_type).startswith("image/"):
|
||||
raise litellm.BadRequestError(
|
||||
message=(
|
||||
f"Document content block with media_type='{media_type}' cannot be "
|
||||
"forwarded to this model as an image_url. Only image/* documents "
|
||||
"are supported. For PDF documents, convert the pages to images "
|
||||
"before sending."
|
||||
),
|
||||
model=model,
|
||||
llm_provider="anthropic",
|
||||
)
|
||||
openai_image_url = self._translate_anthropic_image_to_openai(cast(dict, source))
|
||||
|
||||
if openai_image_url:
|
||||
|
|
|
|||
|
|
@ -5235,3 +5235,77 @@ def test_eager_input_streaming_tool_reaches_bedrock_converse_as_beta():
|
|||
|
||||
assert data["additionalModelRequestFields"]["anthropic_beta"] == ["fine-grained-tool-streaming-2025-05-14"]
|
||||
assert data["toolConfig"]["tools"][0]["toolSpec"]["inputSchema"]["json"] == EAGER_INPUT_SCHEMA
|
||||
|
||||
|
||||
def test_document_pdf_raises_bad_request_error() -> None:
|
||||
"""
|
||||
Regression test for https://github.com/BerriAI/litellm/issues/46117
|
||||
|
||||
An Anthropic document block with media_type='application/pdf' must raise
|
||||
BadRequestError when translated to OpenAI format, not silently produce a
|
||||
malformed image_url with a PDF MIME type that the downstream backend rejects.
|
||||
"""
|
||||
adapter = LiteLLMAnthropicMessagesAdapter()
|
||||
|
||||
messages = [
|
||||
AnthropicMessagesUserMessageParam(
|
||||
role="user",
|
||||
content=[
|
||||
{
|
||||
"type": "document",
|
||||
"source": {
|
||||
"type": "base64",
|
||||
"media_type": "application/pdf",
|
||||
"data": "JVBERi0xLjQK", # minimal synthetic PDF header
|
||||
},
|
||||
},
|
||||
{"type": "text", "text": "Summarize this document."},
|
||||
],
|
||||
)
|
||||
]
|
||||
|
||||
with pytest.raises(litellm.BadRequestError) as exc_info:
|
||||
adapter.translate_anthropic_messages_to_openai(
|
||||
messages=messages,
|
||||
model="chatgpt/gpt-6.1-sol",
|
||||
)
|
||||
|
||||
assert "application/pdf" in str(exc_info.value)
|
||||
|
||||
|
||||
def test_document_image_jpeg_passes_through() -> None:
|
||||
"""
|
||||
An Anthropic document block with media_type='image/jpeg' must still be
|
||||
translated to image_url without raising an error.
|
||||
"""
|
||||
adapter = LiteLLMAnthropicMessagesAdapter()
|
||||
|
||||
messages = [
|
||||
AnthropicMessagesUserMessageParam(
|
||||
role="user",
|
||||
content=[
|
||||
{
|
||||
"type": "document",
|
||||
"source": {
|
||||
"type": "base64",
|
||||
"media_type": "image/jpeg",
|
||||
"data": "/9j/4AAQSkZJRgAB", # minimal JPEG header
|
||||
},
|
||||
},
|
||||
{"type": "text", "text": "Describe this image."},
|
||||
],
|
||||
)
|
||||
]
|
||||
|
||||
# Should not raise
|
||||
result = adapter.translate_anthropic_messages_to_openai(
|
||||
messages=messages,
|
||||
model="chatgpt/gpt-6.1-sol",
|
||||
)
|
||||
# The image document should be translated to an image_url content block
|
||||
user_msg = next(m for m in result if m.get("role") == "user")
|
||||
content = user_msg.get("content", [])
|
||||
image_blocks = [c for c in content if isinstance(c, dict) and c.get("type") == "image_url"]
|
||||
assert len(image_blocks) == 1
|
||||
url = image_blocks[0]["image_url"]["url"]
|
||||
assert url.startswith("data:image/jpeg;base64,")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue