fix: cache_control directive dropped anthropic document/file blocks#23911
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…file-message-blocks
Greptile SummaryThis PR fixes a silent data-loss bug where Key changes:
Minor note: The Confidence Score: 4/5
|
| Filename | Overview |
|---|---|
| litellm/litellm_core_utils/prompt_templates/factory.py | Bug fix: cache_control is now correctly propagated for document and file content blocks via add_cache_control_to_content. The file handling has a minor type annotation inaccuracy where the result is always cast to AnthropicMessagesDocumentParam even though the conversion function can return image or container-upload blocks. |
| tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py | Two new unit tests cover the regression (file block with and without cache_control). Tests are mock-only and follow existing patterns in the file, satisfying the no-real-network-calls rule. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["anthropic_messages_pt() iterates content blocks"] --> B{block type?}
B -->|"image_url"| C["_anthropic_content_element_factory()"]
C --> D["add_cache_control_to_content() ✅ existing"]
D --> E["user_content.append()"]
B -->|"text"| F["AnthropicMessagesTextParam()"]
F --> G["add_cache_control_to_content() ✅ existing"]
G --> E
B -->|"document"| H["cast(AnthropicMessagesDocumentParam, m)"]
H --> I["add_cache_control_to_content() ✅ NEW fix"]
I --> E
B -->|"file"| J["anthropic_process_openai_file_message()"]
J --> K{file subtype}
K -->|"PDF / text"| L["AnthropicMessagesDocumentParam"]
K -->|"image/*"| M["AnthropicMessagesImageParam"]
K -->|"container"| N["AnthropicMessagesContainerUploadParam"]
L & M & N --> O["add_cache_control_to_content() ✅ NEW fix\n(cast to DocumentParam — minor type issue)"]
O --> E
Last reviewed commit: "Merge branch 'main' ..."
| _file_content_element = add_cache_control_to_content( | ||
| anthropic_content_element=cast(AnthropicMessagesDocumentParam, _file_content_element), | ||
| original_content_element=dict(m), | ||
| ) | ||
| user_content.append(cast(AnthropicMessagesDocumentParam,_file_content_element)) |
There was a problem hiding this comment.
Inaccurate cast for non-document file types
anthropic_process_openai_file_message can return AnthropicMessagesImageParam (for image MIME types like image/jpeg, image/png) or AnthropicMessagesContainerUploadParam (for container uploads) in addition to AnthropicMessagesDocumentParam. Casting to AnthropicMessagesDocumentParam in both the add_cache_control_to_content call and the user_content.append call is incorrect for those cases.
Since cast() is a no-op at runtime and add_cache_control_to_content already accepts dict in its union type, this will not cause a runtime error today, but it misleads static type checkers and would hide any future type-level validation. Consider using a union cast that matches the actual return type:
elif m.get("type", "") == "file":
_file_content_element = anthropic_process_openai_file_message(
cast(ChatCompletionFileObject, m)
)
_file_content_element = add_cache_control_to_content(
anthropic_content_element=_file_content_element,
original_content_element=dict(m),
)
user_content.append(_file_content_element)This is safe because add_cache_control_to_content accepts dict (which all TypedDicts satisfy at runtime), and user_content already accepts a union of multiple content param types.
Relevant issues
Fixes #23873: cache_control being silently dropped from
filecontent blocks during Anthropic message conversion, preventing prompt caching from working for PDF/document inputs.Pre-Submission checklist
tests/test_litellm/directory, Adding at least 1 test is a hard requirement - see detailsmake test-unit@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewDelays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
CI (LiteLLM team)
Branch creation CI run
Link:
CI run for the last commit
Link:
Merge / cherry-pick CI run
Links:
Type
🐛 Bug Fix
Changes
Problem
When sending messages with
fileordocumentcontent blocks that includecache_control: {"type": "ephemeral"}, thecache_controlmetadata is silently dropped during the OpenAI → Anthropic message format conversion. This prevents Anthropic prompt caching from working for PDF and document inputs.Root Cause
In
anthropic_messages_pt()(litellm/litellm_core_utils/prompt_templates/factory.py),textandimage_urlcontent blocks correctly preservecache_controlviaadd_cache_control_to_content(). However:fileblocks are converted byanthropic_process_openai_file_message(), which creates a newAnthropicMessagesDocumentParamwithout copyingcache_controlfrom the original block.documentblocks are appended directly viacast()without callingadd_cache_control_to_content(), socache_controlis also not preserved.Fix
Call
add_cache_control_to_content()on the converted result for bothfileanddocumentblocks, matching the existing pattern used fortextandimage_urlblocks.Before
After