Skip to content

Commit 32caa89

Browse files
authored
feat: add "anthropic" cache strategy to bypass model ID check (#1808)
1 parent 31f1e64 commit 32caa89

3 files changed

Lines changed: 62 additions & 20 deletions

File tree

src/strands/models/bedrock.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,15 @@ def __init__(
178178
logger.debug("region=<%s> | bedrock client created", self.client.meta.region_name)
179179

180180
@property
181-
def _supports_caching(self) -> bool:
182-
"""Whether this model supports prompt caching.
181+
def _cache_strategy(self) -> str | None:
182+
"""The cache strategy for this model based on its model ID.
183183
184-
Returns True for Claude models on Bedrock.
184+
Returns the appropriate cache strategy name, or None if automatic caching is not supported for this model.
185185
"""
186186
model_id = self.config.get("model_id", "").lower()
187-
return "claude" in model_id or "anthropic" in model_id
187+
if "claude" in model_id or "anthropic" in model_id:
188+
return "anthropic"
189+
return None
188190

189191
@override
190192
def update_config(self, **model_config: Unpack[BedrockConfig]) -> None: # type: ignore
@@ -459,14 +461,17 @@ def _format_bedrock_messages(self, messages: Messages) -> list[dict[str, Any]]:
459461

460462
# Inject cache point into cleaned_messages (not original messages) if cache_config is set
461463
cache_config = self.config.get("cache_config")
462-
if cache_config and cache_config.strategy == "auto":
463-
if self._supports_caching:
464+
if cache_config:
465+
strategy: str | None = cache_config.strategy
466+
if strategy == "auto":
467+
strategy = self._cache_strategy
468+
if not strategy:
469+
logger.warning(
470+
"model_id=<%s> | cache_config is enabled but this model does not support automatic caching",
471+
self.config.get("model_id"),
472+
)
473+
if strategy == "anthropic":
464474
self._inject_cache_point(cleaned_messages)
465-
else:
466-
logger.warning(
467-
"model_id=<%s> | cache_config is enabled but this model does not support caching",
468-
self.config.get("model_id"),
469-
)
470475

471476
return cleaned_messages
472477

src/strands/models/model.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ class CacheConfig:
2323
2424
Attributes:
2525
strategy: Caching strategy to use.
26-
- "auto": Automatically inject cachePoint at optimal positions
26+
- "auto": Automatically detect model support and inject cachePoint to maximize cache coverage
27+
- "anthropic": Inject cachePoint in Anthropic-compatible format without model support check
2728
"""
2829

29-
strategy: Literal["auto"] = "auto"
30+
strategy: Literal["auto", "anthropic"] = "auto"
3031

3132

3233
class Model(abc.ABC):

tests/strands/models/test_bedrock.py

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2582,19 +2582,19 @@ async def test_format_request_with_guardrail_multiple_tool_results_same_message(
25822582
assert formatted_messages[0]["content"][0]["guardContent"]["text"]["text"] == "Question requiring multiple tools"
25832583

25842584

2585-
def test_supports_caching_true_for_claude(bedrock_client):
2586-
"""Test that supports_caching returns True for Claude models."""
2585+
def test_cache_strategy_anthropic_for_claude(bedrock_client):
2586+
"""Test that _cache_strategy returns 'anthropic' for Claude models."""
25872587
model = BedrockModel(model_id="us.anthropic.claude-sonnet-4-20250514-v1:0")
2588-
assert model._supports_caching is True
2588+
assert model._cache_strategy == "anthropic"
25892589

25902590
model2 = BedrockModel(model_id="anthropic.claude-3-haiku-20240307-v1:0")
2591-
assert model2._supports_caching is True
2591+
assert model2._cache_strategy == "anthropic"
25922592

25932593

2594-
def test_supports_caching_false_for_non_claude(bedrock_client):
2595-
"""Test that supports_caching returns False for non-Claude models."""
2594+
def test_cache_strategy_none_for_non_claude(bedrock_client):
2595+
"""Test that _cache_strategy returns None for unsupported models."""
25962596
model = BedrockModel(model_id="amazon.nova-pro-v1:0")
2597-
assert model._supports_caching is False
2597+
assert model._cache_strategy is None
25982598

25992599

26002600
def test_inject_cache_point_adds_to_last_assistant(bedrock_client):
@@ -2693,6 +2693,42 @@ def test_inject_cache_point_strips_existing_cache_points(bedrock_client):
26932693
assert "cachePoint" in cleaned_messages[3]["content"][-1]
26942694

26952695

2696+
def test_inject_cache_point_anthropic_strategy_skips_model_check(bedrock_client):
2697+
"""Test that anthropic strategy injects cache point without model support check."""
2698+
model = BedrockModel(
2699+
model_id="arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/a1b2c3d4e5f6",
2700+
cache_config=CacheConfig(strategy="anthropic"),
2701+
)
2702+
2703+
messages = [
2704+
{"role": "user", "content": [{"text": "Hello"}]},
2705+
{"role": "assistant", "content": [{"text": "Response"}]},
2706+
]
2707+
2708+
formatted = model._format_bedrock_messages(messages)
2709+
2710+
assert len(formatted[1]["content"]) == 2
2711+
assert "cachePoint" in formatted[1]["content"][-1]
2712+
assert formatted[1]["content"][-1]["cachePoint"]["type"] == "default"
2713+
2714+
2715+
def test_inject_cache_point_auto_strategy_resolves_to_anthropic_for_claude(bedrock_client):
2716+
"""Test that auto strategy resolves to anthropic strategy for Claude models."""
2717+
model = BedrockModel(
2718+
model_id="us.anthropic.claude-sonnet-4-20250514-v1:0", cache_config=CacheConfig(strategy="auto")
2719+
)
2720+
2721+
messages = [
2722+
{"role": "user", "content": [{"text": "Hello"}]},
2723+
{"role": "assistant", "content": [{"text": "Response"}]},
2724+
]
2725+
2726+
formatted = model._format_bedrock_messages(messages)
2727+
2728+
assert len(formatted[1]["content"]) == 2
2729+
assert "cachePoint" in formatted[1]["content"][-1]
2730+
2731+
26962732
def test_find_last_user_text_message_index_no_user_messages(bedrock_client):
26972733
"""Test _find_last_user_text_message_index returns None when no user text messages exist."""
26982734
model = BedrockModel(model_id="test-model")

0 commit comments

Comments
 (0)