PR #22867 added _remove_scope_from_cache_control for Bedrock and Azur… (#23183)

* PR #22867 added _remove_scope_from_cache_control for Bedrock and Azure AI but omitted Vertex AI. This applies the same pattern to VertexAIPartnerModelsAnthropicMessagesConfig."

* PR #22867 added _remove_scope_from_cache_control for Bedrock and Azure AI but omitted Vertex AI. This applies the same pattern to VertexAIPartnerModelsAnthropicMessagesConfig."

* PR #22867 added _remove_scope_from_cache_control to AzureAnthropicMessagesConfig
 but missed VertexAIPartnerModelsAnthropicMessagesConfi Rather than duplicating the method again, moved it up to the base AnthropicMessagesConfig so all providers
  inherit it, and removed the now-redundant copy from the Azure AI subclass.

* PR #22867 added _remove_scope_from_cache_control to AzureAnthropicMessagesConfig
 but missed VertexAIPartnerModelsAnthropicMessagesConfi Rather than duplicating the method again, moved it up to the base AnthropicMessagesConfig so all providers
  inherit it, and removed the now-redundant copy from the Azure AI subclass.

---------

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
This commit is contained in:
Awais Qureshi 2026-03-14 10:41:25 +05:00 committed by GitHub
parent 7bb2d78394
commit c7ba7948bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 79 additions and 0 deletions

View file

@ -50,6 +50,38 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig):
# "metadata",
]
def _remove_scope_from_cache_control(
self, anthropic_messages_request: Dict
) -> None:
"""
Remove `scope` field from cache_control blocks.
Some providers (Vertex AI, Azure AI Foundry) do not support the `scope`
field in cache_control (e.g. "global" for cross-request caching).
Processes both `system` and `messages` content blocks.
"""
def _sanitize(cache_control: Any) -> None:
if isinstance(cache_control, dict):
cache_control.pop("scope", None)
def _process_content_list(content: list) -> None:
for item in content:
if isinstance(item, dict) and "cache_control" in item:
_sanitize(item["cache_control"])
if "system" in anthropic_messages_request:
system = anthropic_messages_request["system"]
if isinstance(system, list):
_process_content_list(system)
if "messages" in anthropic_messages_request:
for message in anthropic_messages_request["messages"]:
if isinstance(message, dict) and "content" in message:
content = message["content"]
if isinstance(content, list):
_process_content_list(content)
@staticmethod
def _filter_billing_headers_from_system(system_param):
"""

View file

@ -150,6 +150,8 @@ class VertexAIPartnerModelsAnthropicMessagesConfig(AnthropicMessagesConfig, Vert
headers=headers,
)
self._remove_scope_from_cache_control(anthropic_messages_request)
anthropic_messages_request["anthropic_version"] = "vertex-2023-10-16"
anthropic_messages_request.pop(

View file

@ -5,6 +5,7 @@ import pytest
from litellm.llms.vertex_ai.vertex_ai_partner_models.anthropic.experimental_pass_through.transformation import (
VertexAIPartnerModelsAnthropicMessagesConfig,
)
from litellm.types.router import GenericLiteLLMParams
def test_validate_environment_uses_vertex_ai_location():
@ -248,3 +249,47 @@ def test_validate_environment_with_authorization_header_calculates_api_base():
# Verify Authorization header is still present
assert "Authorization" in updated_headers, \
"Authorization header should be preserved"
def test_transform_anthropic_messages_request_removes_scope_from_cache_control():
"""Ensure scope field is removed from cache_control for Vertex AI (not supported)."""
config = VertexAIPartnerModelsAnthropicMessagesConfig()
messages = [
{
"role": "user",
"content": [
{
"type": "text",
"text": "Hello",
"cache_control": {"type": "ephemeral", "scope": "global"},
}
],
}
]
anthropic_messages_optional_request_params = {
"max_tokens": 1024,
"system": [
{
"type": "text",
"text": "You are an AI assistant.",
"cache_control": {"type": "ephemeral", "scope": "global"},
}
],
}
result = config.transform_anthropic_messages_request(
model="claude-sonnet-4-6",
messages=messages,
anthropic_messages_optional_request_params=anthropic_messages_optional_request_params,
litellm_params=GenericLiteLLMParams(),
headers={},
)
# scope removed from system
assert "scope" not in result["system"][0]["cache_control"]
assert result["system"][0]["cache_control"]["type"] == "ephemeral"
# scope removed from message content
assert "scope" not in result["messages"][0]["content"][0]["cache_control"]
assert result["messages"][0]["content"][0]["cache_control"]["type"] == "ephemeral"