mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-10 12:22:16 +00:00
Translate advanced-tool-use to Bedrock-specific headers for Claude Opus 4.5
This commit is contained in:
+34
-4
@@ -162,6 +162,22 @@ class AmazonAnthropicClaudeMessagesConfig(
|
||||
|
||||
return any(pattern in model_lower for pattern in supported_patterns)
|
||||
|
||||
def _is_claude_opus_4_5(self, model: str) -> bool:
|
||||
"""
|
||||
Check if the model is Claude Opus 4.5.
|
||||
|
||||
Args:
|
||||
model: The model name
|
||||
|
||||
Returns:
|
||||
True if the model is Claude Opus 4.5
|
||||
"""
|
||||
model_lower = model.lower()
|
||||
opus_4_5_patterns = [
|
||||
"opus-4.5", "opus_4.5", "opus-4-5", "opus_4_5",
|
||||
]
|
||||
return any(pattern in model_lower for pattern in opus_4_5_patterns)
|
||||
|
||||
def _filter_unsupported_beta_headers_for_bedrock(
|
||||
self, model: str, beta_set: set
|
||||
) -> None:
|
||||
@@ -169,25 +185,32 @@ class AmazonAnthropicClaudeMessagesConfig(
|
||||
Remove beta headers that are not supported on Bedrock for the given model.
|
||||
|
||||
Extended thinking beta headers are only supported on specific Claude 4+ models.
|
||||
Advanced tool use headers are not supported on Bedrock Invoke API.
|
||||
Advanced tool use headers are not supported on Bedrock Invoke API, but need to be
|
||||
translated to Bedrock-specific headers for Claude Opus 4.5.
|
||||
This prevents 400 "invalid beta flag" errors on Bedrock.
|
||||
|
||||
Note: Bedrock Invoke API fails with a 400 error when unsupported beta headers
|
||||
are sent, returning: {"message":"invalid beta flag"}
|
||||
|
||||
Translation for Claude Opus 4.5:
|
||||
- advanced-tool-use-2025-11-20 -> tool-search-tool-2025-10-19 + tool-examples-2025-10-29
|
||||
|
||||
Args:
|
||||
model: The model name
|
||||
beta_set: The set of beta headers to filter in-place
|
||||
"""
|
||||
beta_headers_to_remove = set()
|
||||
has_advanced_tool_use = False
|
||||
|
||||
# 1. Filter out beta headers that are universally unsupported on Bedrock Invoke
|
||||
# 1. Filter out beta headers that are universally unsupported on Bedrock Invoke and track if advanced-tool-use header is present
|
||||
for beta in beta_set:
|
||||
for unsupported_pattern in self.UNSUPPORTED_BEDROCK_INVOKE_BETA_PATTERNS:
|
||||
if unsupported_pattern in beta.lower():
|
||||
beta_headers_to_remove.add(beta)
|
||||
has_advanced_tool_use = True
|
||||
break
|
||||
|
||||
|
||||
|
||||
# 2. Filter out extended thinking headers for models that don't support them
|
||||
extended_thinking_patterns = [
|
||||
"extended-thinking",
|
||||
@@ -203,6 +226,13 @@ class AmazonAnthropicClaudeMessagesConfig(
|
||||
# Remove all filtered headers
|
||||
for beta in beta_headers_to_remove:
|
||||
beta_set.discard(beta)
|
||||
|
||||
# 3. Translate advanced-tool-use to Bedrock-specific headers for Claude Opus 4.5
|
||||
# Ref: https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages-request-response.html
|
||||
if has_advanced_tool_use and self._is_claude_opus_4_5(model):
|
||||
beta_set.add("tool-search-tool-2025-10-19")
|
||||
beta_set.add("tool-examples-2025-10-29")
|
||||
|
||||
|
||||
def _get_tool_search_beta_header_for_bedrock(
|
||||
self,
|
||||
@@ -256,7 +286,7 @@ class AmazonAnthropicClaudeMessagesConfig(
|
||||
Ref: https://aws.amazon.com/blogs/machine-learning/structured-data-response-with-amazon-bedrock-prompt-engineering-and-tool-use/
|
||||
"""
|
||||
import json
|
||||
|
||||
|
||||
# Extract schema from output_format
|
||||
schema = output_format.get("schema")
|
||||
if not schema:
|
||||
|
||||
+185
@@ -279,3 +279,188 @@ def test_output_format_with_no_schema():
|
||||
# Content should remain as string (not converted to list)
|
||||
assert isinstance(last_user_message["content"], str)
|
||||
assert last_user_message["content"] == "Hello"
|
||||
|
||||
|
||||
def test_advanced_tool_use_header_translation_for_opus_4_5():
|
||||
"""
|
||||
Test that advanced-tool-use-2025-11-20 header is translated to Bedrock-specific headers
|
||||
for Claude Opus 4.5.
|
||||
|
||||
Regression test for: Claude Code sends advanced-tool-use header which needs to be
|
||||
translated to tool-search-tool-2025-10-19 and tool-examples-2025-10-29 for Bedrock
|
||||
Invoke API on Claude Opus 4.5.
|
||||
|
||||
Ref: https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages-request-response.html
|
||||
"""
|
||||
from litellm.llms.bedrock.messages.invoke_transformations.anthropic_claude3_transformation import (
|
||||
AmazonAnthropicClaudeMessagesConfig,
|
||||
)
|
||||
|
||||
config = AmazonAnthropicClaudeMessagesConfig()
|
||||
|
||||
messages = [
|
||||
{"role": "user", "content": "What's the weather like?"}
|
||||
]
|
||||
|
||||
anthropic_messages_optional_request_params = {
|
||||
"max_tokens": 100,
|
||||
}
|
||||
|
||||
# Simulate advanced-tool-use header from Claude Code
|
||||
headers = {
|
||||
"anthropic-beta": "advanced-tool-use-2025-11-20"
|
||||
}
|
||||
|
||||
# Test with Claude Opus 4.5
|
||||
result = config.transform_anthropic_messages_request(
|
||||
model="anthropic.claude-opus-4-5-20250514-v1:0",
|
||||
messages=messages,
|
||||
anthropic_messages_optional_request_params=anthropic_messages_optional_request_params,
|
||||
litellm_params={},
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
# Verify advanced-tool-use header was removed
|
||||
assert "anthropic_beta" in result
|
||||
beta_headers = result["anthropic_beta"]
|
||||
assert "advanced-tool-use-2025-11-20" not in beta_headers, \
|
||||
"advanced-tool-use header should be removed for Bedrock"
|
||||
|
||||
# Verify Bedrock-specific headers were added
|
||||
assert "tool-search-tool-2025-10-19" in beta_headers, \
|
||||
"tool-search-tool-2025-10-19 should be added for Opus 4.5"
|
||||
assert "tool-examples-2025-10-29" in beta_headers, \
|
||||
"tool-examples-2025-10-29 should be added for Opus 4.5"
|
||||
|
||||
|
||||
def test_advanced_tool_use_header_filtered_for_non_opus_4_5():
|
||||
"""
|
||||
Test that advanced-tool-use-2025-11-20 header is filtered out for non-Opus 4.5 models
|
||||
without adding Bedrock-specific headers.
|
||||
|
||||
The translation to tool-search-tool-2025-10-19 and tool-examples-2025-10-29 should
|
||||
only happen for Claude Opus 4.5.
|
||||
"""
|
||||
from litellm.llms.bedrock.messages.invoke_transformations.anthropic_claude3_transformation import (
|
||||
AmazonAnthropicClaudeMessagesConfig,
|
||||
)
|
||||
|
||||
config = AmazonAnthropicClaudeMessagesConfig()
|
||||
|
||||
messages = [
|
||||
{"role": "user", "content": "What's the weather like?"}
|
||||
]
|
||||
|
||||
anthropic_messages_optional_request_params = {
|
||||
"max_tokens": 100,
|
||||
}
|
||||
|
||||
# Simulate advanced-tool-use header from Claude Code
|
||||
headers = {
|
||||
"anthropic-beta": "advanced-tool-use-2025-11-20"
|
||||
}
|
||||
|
||||
# Test with Claude Sonnet 4.5 (not Opus 4.5)
|
||||
result = config.transform_anthropic_messages_request(
|
||||
model="anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
messages=messages,
|
||||
anthropic_messages_optional_request_params=anthropic_messages_optional_request_params,
|
||||
litellm_params={},
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
# Verify advanced-tool-use header was removed
|
||||
beta_headers = result.get("anthropic_beta", [])
|
||||
assert "advanced-tool-use-2025-11-20" not in beta_headers, \
|
||||
"advanced-tool-use header should be removed for Bedrock"
|
||||
|
||||
# Verify Bedrock-specific headers were NOT added (only for Opus 4.5)
|
||||
assert "tool-search-tool-2025-10-19" not in beta_headers, \
|
||||
"tool-search-tool should not be added for non-Opus 4.5 models"
|
||||
assert "tool-examples-2025-10-29" not in beta_headers, \
|
||||
"tool-examples should not be added for non-Opus 4.5 models"
|
||||
|
||||
|
||||
def test_advanced_tool_use_header_translation_with_multiple_beta_headers():
|
||||
"""
|
||||
Test that advanced-tool-use header translation works correctly when multiple
|
||||
beta headers are present.
|
||||
"""
|
||||
from litellm.llms.bedrock.messages.invoke_transformations.anthropic_claude3_transformation import (
|
||||
AmazonAnthropicClaudeMessagesConfig,
|
||||
)
|
||||
|
||||
config = AmazonAnthropicClaudeMessagesConfig()
|
||||
|
||||
messages = [
|
||||
{"role": "user", "content": "What's the weather like?"}
|
||||
]
|
||||
|
||||
anthropic_messages_optional_request_params = {
|
||||
"max_tokens": 100,
|
||||
}
|
||||
|
||||
# Multiple beta headers including advanced-tool-use
|
||||
headers = {
|
||||
"anthropic-beta": "claude-code-20250219,advanced-tool-use-2025-11-20,interleaved-thinking-2025-05-14"
|
||||
}
|
||||
|
||||
# Test with Claude Opus 4.5
|
||||
result = config.transform_anthropic_messages_request(
|
||||
model="anthropic.claude-opus-4-5-20250514-v1:0",
|
||||
messages=messages,
|
||||
anthropic_messages_optional_request_params=anthropic_messages_optional_request_params,
|
||||
litellm_params={},
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
beta_headers = result.get("anthropic_beta", [])
|
||||
|
||||
# Verify advanced-tool-use was removed
|
||||
assert "advanced-tool-use-2025-11-20" not in beta_headers
|
||||
|
||||
# Verify Bedrock-specific headers were added
|
||||
assert "tool-search-tool-2025-10-19" in beta_headers
|
||||
assert "tool-examples-2025-10-29" in beta_headers
|
||||
|
||||
# Verify other beta headers are preserved
|
||||
assert "claude-code-20250219" in beta_headers
|
||||
assert "interleaved-thinking-2025-05-14" in beta_headers
|
||||
|
||||
|
||||
def test_opus_4_5_model_detection():
|
||||
"""
|
||||
Test that the _is_claude_opus_4_5 method correctly identifies Opus 4.5 models
|
||||
with various naming conventions.
|
||||
"""
|
||||
from litellm.llms.bedrock.messages.invoke_transformations.anthropic_claude3_transformation import (
|
||||
AmazonAnthropicClaudeMessagesConfig,
|
||||
)
|
||||
|
||||
config = AmazonAnthropicClaudeMessagesConfig()
|
||||
|
||||
# Test various Opus 4.5 naming patterns
|
||||
opus_4_5_models = [
|
||||
"anthropic.claude-opus-4-5-20250514-v1:0",
|
||||
"anthropic.claude-opus-4.5-20250514-v1:0",
|
||||
"anthropic.claude-opus_4_5-20250514-v1:0",
|
||||
"anthropic.claude-opus_4.5-20250514-v1:0",
|
||||
"us.anthropic.claude-opus-4-5-20250514-v1:0",
|
||||
"ANTHROPIC.CLAUDE-OPUS-4-5-20250514-V1:0", # Case insensitive
|
||||
]
|
||||
|
||||
for model in opus_4_5_models:
|
||||
assert config._is_claude_opus_4_5(model), \
|
||||
f"Should detect {model} as Opus 4.5"
|
||||
|
||||
# Test non-Opus 4.5 models
|
||||
non_opus_4_5_models = [
|
||||
"anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
"anthropic.claude-opus-4-20250514-v1:0", # Opus 4, not 4.5
|
||||
"anthropic.claude-opus-4-1-20250514-v1:0", # Opus 4.1, not 4.5
|
||||
"anthropic.claude-haiku-4-5-20251001-v1:0",
|
||||
]
|
||||
|
||||
for model in non_opus_4_5_models:
|
||||
assert not config._is_claude_opus_4_5(model), \
|
||||
f"Should not detect {model} as Opus 4.5"
|
||||
|
||||
@@ -390,3 +390,66 @@ class TestAnthropicBetaHeaderSupport:
|
||||
"anthropic_beta SHOULD be added for Anthropic models with cross-region prefix."
|
||||
)
|
||||
assert "context-1m-2025-08-07" in additional_fields["anthropic_beta"]
|
||||
|
||||
def test_messages_advanced_tool_use_translation_opus_4_5(self):
|
||||
"""Test that advanced-tool-use header is translated to Bedrock-specific headers for Opus 4.5.
|
||||
|
||||
Regression test for: Claude Code sends advanced-tool-use-2025-11-20 header which needs
|
||||
to be translated to tool-search-tool-2025-10-19 and tool-examples-2025-10-29 for
|
||||
Bedrock Invoke API on Claude Opus 4.5.
|
||||
|
||||
Ref: https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages-request-response.html
|
||||
"""
|
||||
config = AmazonAnthropicClaudeMessagesConfig()
|
||||
headers = {"anthropic-beta": "advanced-tool-use-2025-11-20"}
|
||||
|
||||
result = config.transform_anthropic_messages_request(
|
||||
model="us.anthropic.claude-opus-4-5-20250514-v1:0",
|
||||
messages=[{"role": "user", "content": "Test"}],
|
||||
anthropic_messages_optional_request_params={"max_tokens": 100},
|
||||
litellm_params={},
|
||||
headers=headers
|
||||
)
|
||||
|
||||
assert "anthropic_beta" in result
|
||||
beta_headers = result["anthropic_beta"]
|
||||
|
||||
# advanced-tool-use should be removed
|
||||
assert "advanced-tool-use-2025-11-20" not in beta_headers, (
|
||||
"advanced-tool-use-2025-11-20 should be removed for Bedrock Invoke API"
|
||||
)
|
||||
|
||||
# Bedrock-specific headers should be added for Opus 4.5
|
||||
assert "tool-search-tool-2025-10-19" in beta_headers, (
|
||||
"tool-search-tool-2025-10-19 should be added for Opus 4.5"
|
||||
)
|
||||
assert "tool-examples-2025-10-29" in beta_headers, (
|
||||
"tool-examples-2025-10-29 should be added for Opus 4.5"
|
||||
)
|
||||
|
||||
def test_messages_advanced_tool_use_filtered_non_opus_4_5(self):
|
||||
"""Test that advanced-tool-use header is filtered out for non-Opus 4.5 models.
|
||||
|
||||
The translation to Bedrock-specific headers should only happen for Opus 4.5.
|
||||
For other models, the advanced-tool-use header should just be removed.
|
||||
"""
|
||||
config = AmazonAnthropicClaudeMessagesConfig()
|
||||
headers = {"anthropic-beta": "advanced-tool-use-2025-11-20"}
|
||||
|
||||
# Test with Sonnet 4.5 (not Opus 4.5)
|
||||
result = config.transform_anthropic_messages_request(
|
||||
model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
messages=[{"role": "user", "content": "Test"}],
|
||||
anthropic_messages_optional_request_params={"max_tokens": 100},
|
||||
litellm_params={},
|
||||
headers=headers
|
||||
)
|
||||
|
||||
beta_headers = result.get("anthropic_beta", [])
|
||||
|
||||
# advanced-tool-use should be removed
|
||||
assert "advanced-tool-use-2025-11-20" not in beta_headers
|
||||
|
||||
# Bedrock-specific headers should NOT be added for non-Opus 4.5
|
||||
assert "tool-search-tool-2025-10-19" not in beta_headers
|
||||
assert "tool-examples-2025-10-29" not in beta_headers
|
||||
|
||||
Reference in New Issue
Block a user