refactor(bedrock): rename is_claude_4_5_on_bedrock to supports_bedrock_prompt_cache_ttl (#46058)

Co-authored-by: kerry <kerry@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
devin-ai-integration[bot] 2026-10-12 18:34:33 +00:00 • committed by GitHub
parent a4382657fd
commit 249add6f0d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 50 additions and 34 deletions

View file

@ -5093,7 +5093,7 @@ def make_valid_bedrock_tool_name(input_tool_name: str) -> str:
def add_cache_point_tool_block(tool: dict, model: str | None = None) -> BedrockToolBlock | None:
from litellm.llms.bedrock.common_utils import (
bedrock_model_accepts_cache_points,
is_claude_4_5_on_bedrock,
supports_bedrock_prompt_cache_ttl,
)
cache_control: Final = tool.get("cache_control", None)
@ -5103,7 +5103,7 @@ def add_cache_point_tool_block(tool: dict, model: str | None = None) -> BedrockT
cache_point_block: Final[CachePointBlock] = {"type": "default"}
if isinstance(cache_control, dict) and "ttl" in cache_control:
ttl: Final = cache_control["ttl"]
if ttl in ["5m", "1h"] and model is not None and is_claude_4_5_on_bedrock(model):
if ttl in ["5m", "1h"] and model is not None and supports_bedrock_prompt_cache_ttl(model):
cache_point_block["ttl"] = ttl
return {"cachePoint": cache_point_block}
return None

View file

@ -110,8 +110,8 @@ from ..common_utils import (
get_anthropic_beta_from_headers,
get_bedrock_tool_name,
is_bedrock_application_inference_profile_arn,
is_claude_4_5_on_bedrock,
normalize_bedrock_opus_output_config_effort,
supports_bedrock_prompt_cache_ttl,
)
if TYPE_CHECKING:
@ -1385,7 +1385,7 @@ class AmazonConverseConfig(BaseConfig):
cache_point: Final = CachePointBlock(type="default")
if isinstance(control, dict) and "ttl" in control:
ttl: Final = control["ttl"]
if ttl in ["5m", "1h"] and model is not None and is_claude_4_5_on_bedrock(model):
if ttl in ["5m", "1h"] and model is not None and supports_bedrock_prompt_cache_ttl(model):
cache_point["ttl"] = ttl
return cache_point

View file

@ -9,6 +9,7 @@ import functools
import json
import os
import re
import warnings
from collections.abc import Iterator, Mapping, Sequence
from types import MappingProxyType
from typing import TYPE_CHECKING, Any, Final, Literal, TypeAlias
@ -1230,15 +1231,11 @@ def bedrock_supports_tool_search(model: str) -> bool:
return AnthropicModelInfo.supports_model_capability(model, "supports_tool_search", "bedrock")
def is_claude_4_5_on_bedrock(model: str) -> bool:
def supports_bedrock_prompt_cache_ttl(model: str) -> bool:
"""
Check if the model supports Bedrock prompt caching with an extended '1h' TTL
(in addition to the default 5m TTL).
Backed by the ``cache_creation_input_token_cost_above_1hr`` field in
``model_prices_and_context_window.json`` instead of a hardcoded list of
model-name patterns, so newly released models pick up support as soon as
their pricing entry ships, with no code change required here.
Whether Bedrock accepts a ``ttl`` ("5m"/"1h") on prompt ``cache_control``
for this model, decided by ``cache_creation_input_token_cost_above_1hr`` on
the model's or its base model's cost-map entry.
"""
return any(
(litellm.model_cost.get(candidate) or {}).get("cache_creation_input_token_cost_above_1hr") is not None
@ -1246,6 +1243,15 @@ def is_claude_4_5_on_bedrock(model: str) -> bool:
)
def is_claude_4_5_on_bedrock(model: str) -> bool:
warnings.warn(
"is_claude_4_5_on_bedrock is deprecated, use supports_bedrock_prompt_cache_ttl",
UserWarning,
stacklevel=2,
)
return supports_bedrock_prompt_cache_ttl(model)
_BEDROCK_MODEL_VERSION_SUFFIX_RE: Final = re.compile(r"-v\d+(?::\d+)?$")
_DEPLOYMENT_MODEL_INFO: Final = TypeAdapter(dict[str, object])

View file

@ -34,11 +34,11 @@ from litellm.llms.bedrock.common_utils import (
bedrock_supports_tool_search,
ensure_bedrock_anthropic_messages_tool_names,
get_anthropic_beta_from_headers,
is_claude_4_5_on_bedrock,
normalize_bedrock_opus_output_config_effort,
normalize_custom_field_on_tools,
normalize_tool_input_schema_types_for_bedrock_invoke,
strip_unsupported_bedrock_invoke_output_config_keys,
supports_bedrock_prompt_cache_ttl,
tools_without_eager_input_streaming,
)
from litellm.llms.bedrock.request_metadata import (
@ -169,9 +169,9 @@ class AmazonAnthropicClaudeMessagesConfig(
anthropic_messages_request: The request dictionary to modify in-place
model: The model name to check if it supports ttl
"""
is_claude_4_5 = False
supports_ttl = False
if model:
is_claude_4_5 = self._is_claude_4_5_on_bedrock(model)
supports_ttl = self._supports_prompt_cache_ttl(model)
def _sanitize_cache_control(cache_control: dict) -> None:
if not isinstance(cache_control, dict):
@ -181,7 +181,7 @@ class AmazonAnthropicClaudeMessagesConfig(
# Remove ttl for models that don't support it
if "ttl" in cache_control:
ttl: Final = cache_control["ttl"]
if is_claude_4_5 and ttl in ["5m", "1h"]:
if supports_ttl and ttl in ["5m", "1h"]:
return
cache_control.pop("ttl", None)
@ -386,19 +386,9 @@ class AmazonAnthropicClaudeMessagesConfig(
]
return any(pattern in model_lower for pattern in opus_4_5_patterns)
def _is_claude_4_5_on_bedrock(self, model: str) -> bool:
"""
Check if the model is Claude 4.5 on Bedrock.
Claude Sonnet 4.5, Haiku 4.5, and Opus 4.5 support 1-hour prompt caching.
Args:
model: The model name
Returns:
True if the model is Claude 4.5
"""
return is_claude_4_5_on_bedrock(model)
def _supports_prompt_cache_ttl(self, model: str) -> bool:
"""Whether Bedrock accepts a ``ttl`` on prompt ``cache_control`` for ``model``."""
return supports_bedrock_prompt_cache_ttl(model)
def _supports_tool_search_on_bedrock(self, model: str) -> bool:
"""

View file

@ -5347,12 +5347,12 @@ def test_parallel_tool_calls_flag_decoupled_from_ttl_pricing(monkeypatch):
The disable_parallel_tool_use gate must read supports_parallel_tool_use_config,
not the 1h-TTL pricing field: a model carrying only the former still gets the flag.
"""
from litellm.llms.bedrock.common_utils import is_claude_4_5_on_bedrock
from litellm.llms.bedrock.common_utils import supports_bedrock_prompt_cache_ttl
config = AmazonConverseConfig()
model = "anthropic.claude-parallel-tool-use-only"
monkeypatch.setitem(litellm.model_cost, model, {"supports_parallel_tool_use_config": True})
assert is_claude_4_5_on_bedrock(model) is False
assert supports_bedrock_prompt_cache_ttl(model) is False
messages = [{"role": "user", "content": "What's the weather in SF and NYC?"}]
optional_params = config.map_openai_params(
@ -5924,7 +5924,7 @@ def test_cache_control_injection_tool_config_honors_ttl_for_supported_model(monk
cache_control behavior, instead of always emitting a bare
{"type": "default"} cachePoint with no ttl.
Forces the bundled local cost map so `is_claude_4_5_on_bedrock` (which
Forces the bundled local cost map so `supports_bedrock_prompt_cache_ttl` (which
reads `cache_creation_input_token_cost_above_1hr` from litellm.model_cost)
sees this branch's pricing data rather than the network-fetched `main`
copy, which lacks it until merge.

View file

@ -473,7 +473,7 @@ def test_capability_lookups_fall_back_to_base_model_when_regional_entry_lacks_fi
import litellm
from litellm.llms.bedrock.common_utils import (
bedrock_converse_supports_parallel_tool_use_config,
is_claude_4_5_on_bedrock,
supports_bedrock_prompt_cache_ttl,
)
base = "anthropic.claude-fallback-test"
@ -488,10 +488,30 @@ def test_capability_lookups_fall_back_to_base_model_when_regional_entry_lacks_fi
},
)
assert is_claude_4_5_on_bedrock(regional) is True
assert supports_bedrock_prompt_cache_ttl(regional) is True
assert bedrock_converse_supports_parallel_tool_use_config(regional) is True
def test_deprecated_is_claude_4_5_on_bedrock_warns_and_matches_new_name(monkeypatch):
import litellm
from litellm.llms.bedrock.common_utils import (
is_claude_4_5_on_bedrock,
supports_bedrock_prompt_cache_ttl,
)
with_ttl = "anthropic.claude-ttl-supported"
without_ttl = "anthropic.claude-ttl-unsupported"
monkeypatch.setitem(litellm.model_cost, with_ttl, {"cache_creation_input_token_cost_above_1hr": 1e-05})
monkeypatch.setitem(litellm.model_cost, without_ttl, {"input_cost_per_token": 1e-06})
with pytest.warns(UserWarning, match="supports_bedrock_prompt_cache_ttl"):
assert is_claude_4_5_on_bedrock(with_ttl) is True
with pytest.warns(UserWarning, match="supports_bedrock_prompt_cache_ttl"):
assert is_claude_4_5_on_bedrock(without_ttl) is False
assert supports_bedrock_prompt_cache_ttl(with_ttl) is True
assert supports_bedrock_prompt_cache_ttl(without_ttl) is False
@pytest.mark.parametrize(
("entry", "expected"),
[