mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-06 02:48:13 +00:00
Merge pull request #41702 from BerriAI/litellm_bedrock_invoke_tool_search_opus48_gen5
fix(bedrock): gate Invoke tool search on the model map for Opus 4.8 and gen 5 Claude
This commit is contained in:
commit
2fb502a556
9 changed files with 248 additions and 67 deletions
|
|
@ -18,6 +18,7 @@ from litellm.llms.bedrock.chat.invoke_transformations.base_invoke_transformation
|
|||
)
|
||||
from litellm.llms.bedrock.common_utils import (
|
||||
apply_bedrock_invoke_structured_output,
|
||||
bedrock_supports_tool_search,
|
||||
get_anthropic_beta_from_headers,
|
||||
normalize_bedrock_opus_output_config_effort,
|
||||
normalize_custom_field_on_tools,
|
||||
|
|
@ -265,7 +266,7 @@ class AmazonAnthropicClaudeConfig(AmazonInvokeConfig, AnthropicConfig):
|
|||
|
||||
if tool_search_used and not (programmatic_tool_calling_used or input_examples_used):
|
||||
beta_set.discard(ANTHROPIC_TOOL_SEARCH_BETA_HEADER)
|
||||
if "opus-4" in model.lower() or "opus_4" in model.lower():
|
||||
if bedrock_supports_tool_search(model):
|
||||
beta_set.add("tool-search-tool-2025-10-19")
|
||||
|
||||
auto_beta_list: Final = filter_and_transform_beta_headers(
|
||||
|
|
|
|||
|
|
@ -902,6 +902,20 @@ def bedrock_model_accepts_cache_points(model: str | None) -> bool:
|
|||
return any(entry.get("supports_prompt_caching") is True for entry in entries)
|
||||
|
||||
|
||||
def bedrock_supports_tool_search(model: str) -> bool:
|
||||
"""
|
||||
Whether Bedrock InvokeModel admits the ``tool_search_tool_*`` tool types on ``model``.
|
||||
|
||||
Backed by the ``supports_tool_search`` flag in ``model_prices_and_context_window.json``,
|
||||
an exact entry or the ``claude-tool-search`` fallback rule for Claude 4.5 and newer, so a
|
||||
newly released Claude carries the flag with no code change. An explicit ``false`` on the
|
||||
resolved entry wins over the rule.
|
||||
"""
|
||||
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
|
||||
|
||||
return AnthropicModelInfo._supports_model_capability(model, "supports_tool_search", "bedrock")
|
||||
|
||||
|
||||
def is_claude_4_5_on_bedrock(model: str) -> bool:
|
||||
"""
|
||||
Check if the model supports Bedrock prompt caching with an extended '1h' TTL
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ from litellm.llms.bedrock.chat.invoke_transformations.base_invoke_transformation
|
|||
from litellm.llms.bedrock.common_utils import (
|
||||
BedrockError,
|
||||
apply_bedrock_invoke_structured_output,
|
||||
bedrock_supports_tool_search,
|
||||
ensure_bedrock_anthropic_messages_tool_names,
|
||||
get_anthropic_beta_from_headers,
|
||||
is_claude_4_5_on_bedrock,
|
||||
|
|
@ -386,9 +387,10 @@ class AmazonAnthropicClaudeMessagesConfig(
|
|||
"""
|
||||
Check if the model supports tool search on Bedrock.
|
||||
|
||||
The model map's ``supports_tool_search`` flag is authoritative when
|
||||
``model`` resolves to an entry that sets it; the name patterns below
|
||||
cover ids the map cannot resolve (ARNs, unlisted regional variants).
|
||||
The model map's ``supports_tool_search`` flag is authoritative: an exact
|
||||
entry, or the ``claude-tool-search`` fallback rule (Claude 4.5 and newer)
|
||||
for ids the map cannot resolve (ARNs, unlisted regional variants) and for
|
||||
mapped entries that carry no opinion.
|
||||
|
||||
Ref: https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool
|
||||
|
||||
|
|
@ -398,46 +400,7 @@ class AmazonAnthropicClaudeMessagesConfig(
|
|||
Returns:
|
||||
True if the model supports tool search on Bedrock
|
||||
"""
|
||||
catalog: Final = AnthropicModelInfo._get_provider_resolved_capability(model, "supports_tool_search", "bedrock")
|
||||
if catalog is not None:
|
||||
return catalog
|
||||
|
||||
model_lower: Final = model.lower()
|
||||
|
||||
supported_patterns: Final = [
|
||||
# Opus 4.5
|
||||
"opus-4.5",
|
||||
"opus_4.5",
|
||||
"opus-4-5",
|
||||
"opus_4_5",
|
||||
# Sonnet 4.5
|
||||
"sonnet-4.5",
|
||||
"sonnet_4.5",
|
||||
"sonnet-4-5",
|
||||
"sonnet_4_5",
|
||||
# Opus 4.6
|
||||
"opus-4.6",
|
||||
"opus_4.6",
|
||||
"opus-4-6",
|
||||
"opus_4_6",
|
||||
# sonnet 4.6
|
||||
"sonnet-4.6",
|
||||
"sonnet_4.6",
|
||||
"sonnet-4-6",
|
||||
"sonnet_4_6",
|
||||
# Opus 4.7
|
||||
"opus-4.7",
|
||||
"opus_4.7",
|
||||
"opus-4-7",
|
||||
"opus_4_7",
|
||||
# Haiku 4.5
|
||||
"haiku-4.5",
|
||||
"haiku_4.5",
|
||||
"haiku-4-5",
|
||||
"haiku_4_5",
|
||||
]
|
||||
|
||||
return any(pattern in model_lower for pattern in supported_patterns)
|
||||
return bedrock_supports_tool_search(model)
|
||||
|
||||
def _get_tool_search_beta_header_for_bedrock(
|
||||
self,
|
||||
|
|
@ -453,7 +416,8 @@ class AmazonAnthropicClaudeMessagesConfig(
|
|||
Bedrock requires a different beta header for tool search than the
|
||||
Anthropic API when tool search is used without programmatic tool
|
||||
calling or input examples: `tool-search-tool-2025-10-19`, and only on
|
||||
the models listed in `_supports_tool_search_on_bedrock`.
|
||||
the models the model map flags as `supports_tool_search`
|
||||
(`_supports_tool_search_on_bedrock`).
|
||||
|
||||
Ref: https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool
|
||||
|
||||
|
|
|
|||
|
|
@ -1810,6 +1810,7 @@
|
|||
"cache_read_input_token_cost": 5e-07,
|
||||
"input_cost_per_token": 5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -1847,6 +1848,7 @@
|
|||
"cache_read_input_token_cost": 5e-07,
|
||||
"input_cost_per_token": 5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -1884,6 +1886,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -1921,6 +1924,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -1957,6 +1961,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -1993,6 +1998,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2029,6 +2035,7 @@
|
|||
"cache_read_input_token_cost": 5e-07,
|
||||
"input_cost_per_token": 5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2067,6 +2074,7 @@
|
|||
"cache_read_input_token_cost": 5e-07,
|
||||
"input_cost_per_token": 5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2105,6 +2113,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2143,6 +2152,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2180,6 +2190,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2217,6 +2228,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2287,6 +2299,7 @@
|
|||
"cache_read_input_token_cost": 2e-07,
|
||||
"input_cost_per_token": 2e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2325,6 +2338,7 @@
|
|||
"cache_read_input_token_cost": 2e-07,
|
||||
"input_cost_per_token": 2e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2363,6 +2377,7 @@
|
|||
"cache_read_input_token_cost": 2.2e-07,
|
||||
"input_cost_per_token": 2.2e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2401,6 +2416,7 @@
|
|||
"cache_read_input_token_cost": 2.2e-07,
|
||||
"input_cost_per_token": 2.2e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2438,6 +2454,7 @@
|
|||
"cache_read_input_token_cost": 2.2e-07,
|
||||
"input_cost_per_token": 2.2e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2475,6 +2492,7 @@
|
|||
"cache_read_input_token_cost": 2.2e-07,
|
||||
"input_cost_per_token": 2.2e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -46130,6 +46148,7 @@
|
|||
"cache_read_input_token_cost": 2.4e-07,
|
||||
"input_cost_per_token": 2.4e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -46163,6 +46182,7 @@
|
|||
"cache_read_input_token_cost": 6e-07,
|
||||
"input_cost_per_token": 6e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -46195,6 +46215,7 @@
|
|||
"cache_read_input_token_cost": 6e-07,
|
||||
"input_cost_per_token": 6e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -59505,6 +59526,15 @@
|
|||
"supports_mid_conversation_system": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "claude-tool-search",
|
||||
"pattern": "claude-[a-z]+-(?:4[-._](?:[5-9]|[1-9]\\d)(?!\\d)|[5-9](?!\\d)(?:[-._]\\d{1,2}(?!\\d))?)",
|
||||
"fill_missing_for_providers": ["anthropic", "bedrock", "bedrock_converse", "vertex_ai-anthropic_models"],
|
||||
"description": "Claude at version 4.5 or higher, in any id shape that contains claude-<family>-: minors 4.5 through 4.99, any later major-minor, and bare 5+ majors so a new family like claude-fable-5 matches. Two-digit majors are deliberately not matched so ids like claude-opus-41 (4.1) are not read as major 41. Anthropic's tool search docs list every Claude 4.5 and newer model as supported and Opus 4.1 and earlier as unsupported, so the flag follows the version instead of a per-model list. azure_ai is left out on purpose: Anthropic documents tool search as unavailable on Azure-hosted Foundry deployments, and the azure_ai/ key cannot tell those from Anthropic-hosted ones.",
|
||||
"model_info": {
|
||||
"supports_tool_search": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wandb-reasoning-baseline",
|
||||
"pattern": "^wandb/",
|
||||
|
|
@ -63253,6 +63283,7 @@
|
|||
"cache_read_input_token_cost": 2.4e-07,
|
||||
"input_cost_per_token": 2.4e-06,
|
||||
"litellm_provider": "bedrock",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -63285,6 +63316,7 @@
|
|||
"cache_read_input_token_cost": 6e-07,
|
||||
"input_cost_per_token": 6e-06,
|
||||
"litellm_provider": "bedrock",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -63316,6 +63348,7 @@
|
|||
"cache_read_input_token_cost": 6e-07,
|
||||
"input_cost_per_token": 6e-06,
|
||||
"litellm_provider": "bedrock",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -63456,6 +63489,7 @@
|
|||
"cache_read_input_token_cost": 2.4e-07,
|
||||
"input_cost_per_token": 2.4e-06,
|
||||
"litellm_provider": "bedrock",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -63488,6 +63522,7 @@
|
|||
"cache_read_input_token_cost": 6e-07,
|
||||
"input_cost_per_token": 6e-06,
|
||||
"litellm_provider": "bedrock",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -63519,6 +63554,7 @@
|
|||
"cache_read_input_token_cost": 6e-07,
|
||||
"input_cost_per_token": 6e-06,
|
||||
"litellm_provider": "bedrock",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
|
|||
|
|
@ -1810,6 +1810,7 @@
|
|||
"cache_read_input_token_cost": 5e-07,
|
||||
"input_cost_per_token": 5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -1847,6 +1848,7 @@
|
|||
"cache_read_input_token_cost": 5e-07,
|
||||
"input_cost_per_token": 5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -1884,6 +1886,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -1921,6 +1924,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -1957,6 +1961,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -1993,6 +1998,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2029,6 +2035,7 @@
|
|||
"cache_read_input_token_cost": 5e-07,
|
||||
"input_cost_per_token": 5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2067,6 +2074,7 @@
|
|||
"cache_read_input_token_cost": 5e-07,
|
||||
"input_cost_per_token": 5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2105,6 +2113,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2143,6 +2152,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2180,6 +2190,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2217,6 +2228,7 @@
|
|||
"cache_read_input_token_cost": 5.5e-07,
|
||||
"input_cost_per_token": 5.5e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2287,6 +2299,7 @@
|
|||
"cache_read_input_token_cost": 2e-07,
|
||||
"input_cost_per_token": 2e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2325,6 +2338,7 @@
|
|||
"cache_read_input_token_cost": 2e-07,
|
||||
"input_cost_per_token": 2e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2363,6 +2377,7 @@
|
|||
"cache_read_input_token_cost": 2.2e-07,
|
||||
"input_cost_per_token": 2.2e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2401,6 +2416,7 @@
|
|||
"cache_read_input_token_cost": 2.2e-07,
|
||||
"input_cost_per_token": 2.2e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2438,6 +2454,7 @@
|
|||
"cache_read_input_token_cost": 2.2e-07,
|
||||
"input_cost_per_token": 2.2e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -2475,6 +2492,7 @@
|
|||
"cache_read_input_token_cost": 2.2e-07,
|
||||
"input_cost_per_token": 2.2e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -46130,6 +46148,7 @@
|
|||
"cache_read_input_token_cost": 2.4e-07,
|
||||
"input_cost_per_token": 2.4e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -46163,6 +46182,7 @@
|
|||
"cache_read_input_token_cost": 6e-07,
|
||||
"input_cost_per_token": 6e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -46195,6 +46215,7 @@
|
|||
"cache_read_input_token_cost": 6e-07,
|
||||
"input_cost_per_token": 6e-06,
|
||||
"litellm_provider": "bedrock_converse",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -59505,6 +59526,15 @@
|
|||
"supports_mid_conversation_system": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "claude-tool-search",
|
||||
"pattern": "claude-[a-z]+-(?:4[-._](?:[5-9]|[1-9]\\d)(?!\\d)|[5-9](?!\\d)(?:[-._]\\d{1,2}(?!\\d))?)",
|
||||
"fill_missing_for_providers": ["anthropic", "bedrock", "bedrock_converse", "vertex_ai-anthropic_models"],
|
||||
"description": "Claude at version 4.5 or higher, in any id shape that contains claude-<family>-: minors 4.5 through 4.99, any later major-minor, and bare 5+ majors so a new family like claude-fable-5 matches. Two-digit majors are deliberately not matched so ids like claude-opus-41 (4.1) are not read as major 41. Anthropic's tool search docs list every Claude 4.5 and newer model as supported and Opus 4.1 and earlier as unsupported, so the flag follows the version instead of a per-model list. azure_ai is left out on purpose: Anthropic documents tool search as unavailable on Azure-hosted Foundry deployments, and the azure_ai/ key cannot tell those from Anthropic-hosted ones.",
|
||||
"model_info": {
|
||||
"supports_tool_search": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wandb-reasoning-baseline",
|
||||
"pattern": "^wandb/",
|
||||
|
|
@ -63253,6 +63283,7 @@
|
|||
"cache_read_input_token_cost": 2.4e-07,
|
||||
"input_cost_per_token": 2.4e-06,
|
||||
"litellm_provider": "bedrock",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -63285,6 +63316,7 @@
|
|||
"cache_read_input_token_cost": 6e-07,
|
||||
"input_cost_per_token": 6e-06,
|
||||
"litellm_provider": "bedrock",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -63316,6 +63348,7 @@
|
|||
"cache_read_input_token_cost": 6e-07,
|
||||
"input_cost_per_token": 6e-06,
|
||||
"litellm_provider": "bedrock",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -63456,6 +63489,7 @@
|
|||
"cache_read_input_token_cost": 2.4e-07,
|
||||
"input_cost_per_token": 2.4e-06,
|
||||
"litellm_provider": "bedrock",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -63488,6 +63522,7 @@
|
|||
"cache_read_input_token_cost": 6e-07,
|
||||
"input_cost_per_token": 6e-06,
|
||||
"litellm_provider": "bedrock",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
@ -63519,6 +63554,7 @@
|
|||
"cache_read_input_token_cost": 6e-07,
|
||||
"input_cost_per_token": 6e-06,
|
||||
"litellm_provider": "bedrock",
|
||||
"supports_tool_search": true,
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
|
|
|
|||
|
|
@ -206,6 +206,21 @@ def local_model_cost_map(monkeypatch):
|
|||
litellm.get_model_info.cache_clear()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def local_beta_headers_config(monkeypatch):
|
||||
"""Pin the bundled ``anthropic_beta_headers_config.json`` so beta header assertions
|
||||
do not depend on the network-fetched copy or on what earlier tests left cached."""
|
||||
from litellm.anthropic_beta_headers_manager import reload_beta_headers_config
|
||||
|
||||
monkeypatch.setenv("LITELLM_LOCAL_ANTHROPIC_BETA_HEADERS", "True")
|
||||
reload_beta_headers_config()
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
monkeypatch.delenv("LITELLM_LOCAL_ANTHROPIC_BETA_HEADERS", raising=False)
|
||||
reload_beta_headers_config()
|
||||
|
||||
|
||||
def _run_coroutine_if_needed(result):
|
||||
if not asyncio.iscoroutine(result):
|
||||
return
|
||||
|
|
|
|||
|
|
@ -997,5 +997,54 @@ def test_shipped_claude_thinking_rules_backfill_only_anthropic(shipped_cost_map)
|
|||
assert match_fill_missing_generalizations("claude-sonnet-4-6", "anthropic") == {
|
||||
"supports_adaptive_thinking": True,
|
||||
"supports_legacy_thinking": True,
|
||||
"supports_tool_search": True,
|
||||
}
|
||||
assert match_fill_missing_generalizations("claude-sonnet-4-6", "perplexity") is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"model,provider,tool_search",
|
||||
[
|
||||
("us.anthropic.claude-opus-4-5", "bedrock", True),
|
||||
("claude-haiku-4-4", "anthropic", None),
|
||||
("claude-haiku-4-6", "anthropic", True),
|
||||
("claude-opus-4.5", "anthropic", True),
|
||||
("claude-opus-4_5", "anthropic", True),
|
||||
("claude-haiku-4-10", "anthropic", True),
|
||||
("claude-haiku-5-0", "anthropic", True),
|
||||
("claude-sonnet-5-1", "anthropic", True),
|
||||
("claude-newfam-6", "anthropic", True),
|
||||
("claude-haiku-4-20250514", "anthropic", None),
|
||||
],
|
||||
)
|
||||
def test_shipped_tool_search_rule_version_boundaries(shipped_cost_map, model, provider, tool_search):
|
||||
"""The claude-tool-search rule flags Claude 4.5 and newer in any family, bare major
|
||||
or major-minor with a dash, dot or underscore delimiter, and leaves 4.4 and
|
||||
date-suffixed 4.x ids without an opinion."""
|
||||
assert model not in litellm.model_cost
|
||||
info = litellm.get_model_info(model, custom_llm_provider=provider)
|
||||
assert info.get("supports_tool_search") is tool_search, model
|
||||
|
||||
|
||||
def test_shipped_tool_search_rule_fills_mapped_claude_entries_without_flag(shipped_cost_map):
|
||||
"""A mapped Claude 4.5+ entry with no supports_tool_search key gets it from the rule
|
||||
on Anthropic direct, Vertex and Bedrock, a mapped pre-4.5 entry stays without one,
|
||||
and Azure Foundry and reseller copies of the same model are not touched."""
|
||||
for key, model, provider in (
|
||||
("claude-opus-4-7", "claude-opus-4-7", "anthropic"),
|
||||
("vertex_ai/claude-opus-5", "claude-opus-5", "vertex_ai"),
|
||||
):
|
||||
assert "supports_tool_search" not in litellm.model_cost[key]
|
||||
assert litellm.get_model_info(model, custom_llm_provider=provider)["supports_tool_search"] is True
|
||||
|
||||
assert "supports_tool_search" not in litellm.model_cost["claude-opus-4-1"]
|
||||
opus_4_1_info = litellm.get_model_info("claude-opus-4-1", custom_llm_provider="anthropic")
|
||||
assert opus_4_1_info.get("supports_tool_search") is None
|
||||
|
||||
assert "supports_tool_search" not in litellm.model_cost["azure_ai/claude-opus-5"]
|
||||
azure_opus_5_info = litellm.get_model_info("claude-opus-5", custom_llm_provider="azure_ai")
|
||||
assert azure_opus_5_info.get("supports_tool_search") is None
|
||||
|
||||
assert match_fill_missing_generalizations("claude-opus-5", "bedrock")["supports_tool_search"] is True
|
||||
assert "supports_tool_search" not in match_fill_missing_generalizations("claude-opus-5", "azure_ai")
|
||||
assert match_fill_missing_generalizations("claude-opus-5", "perplexity") is None
|
||||
|
|
|
|||
|
|
@ -814,3 +814,48 @@ async def test_bedrock_invoke_claude_async_completion_inlines_document_url_sourc
|
|||
"type": "document",
|
||||
"source": {"type": "base64", "media_type": "application/pdf", "data": async_only_image_fetch.base64_png},
|
||||
} in captured["body"]["messages"][0]["content"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"model, expected_betas",
|
||||
[
|
||||
pytest.param("us.anthropic.claude-opus-4-8", ["tool-search-tool-2025-10-19"], id="opus_4_8"),
|
||||
pytest.param("us.anthropic.claude-opus-5", ["tool-search-tool-2025-10-19"], id="opus_5"),
|
||||
pytest.param("us.anthropic.claude-sonnet-5", ["tool-search-tool-2025-10-19"], id="sonnet_5"),
|
||||
pytest.param("us.anthropic.claude-haiku-4-5-20251001-v1:0", ["tool-search-tool-2025-10-19"], id="haiku_4_5"),
|
||||
pytest.param("us.anthropic.claude-opus-4-1-20250805-v1:0", None, id="opus_4_1_unsupported"),
|
||||
],
|
||||
)
|
||||
def test_bedrock_chat_invoke_tool_search_beta_follows_model_map(
|
||||
local_model_cost_map, local_beta_headers_config, model, expected_betas
|
||||
):
|
||||
"""LIT-5851: the chat Invoke path used to add the ``tool-search-tool-2025-10-19``
|
||||
beta whenever the id contained ``opus-4``, so Opus 5 and Sonnet 5 lost it, Haiku
|
||||
4.5 never had it, and Opus 4.1 got it without support. The gate now follows the
|
||||
model map's ``supports_tool_search`` flag, shared with the messages path."""
|
||||
result = AmazonAnthropicClaudeConfig().transform_request(
|
||||
model=model,
|
||||
messages=[{"role": "user", "content": "Add 2 and 3"}],
|
||||
optional_params={
|
||||
"max_tokens": 64,
|
||||
"tools": [
|
||||
{"type": "tool_search_tool_regex_20251119", "name": "tool_search_tool_regex"},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "add_numbers",
|
||||
"description": "Add two integers",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {"a": {"type": "integer"}, "b": {"type": "integer"}},
|
||||
"required": ["a", "b"],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
litellm_params={},
|
||||
headers={},
|
||||
)
|
||||
|
||||
assert result.get("anthropic_beta") == expected_betas
|
||||
|
|
|
|||
|
|
@ -2649,17 +2649,6 @@ def test_bedrock_clear_thinking_leaves_enabled_thinking_on_non_adaptive_model():
|
|||
assert "output_config" not in request
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def local_beta_headers_config(monkeypatch):
|
||||
from litellm.anthropic_beta_headers_manager import reload_beta_headers_config
|
||||
|
||||
monkeypatch.setenv("LITELLM_LOCAL_ANTHROPIC_BETA_HEADERS", "True")
|
||||
reload_beta_headers_config()
|
||||
yield
|
||||
monkeypatch.delenv("LITELLM_LOCAL_ANTHROPIC_BETA_HEADERS", raising=False)
|
||||
reload_beta_headers_config()
|
||||
|
||||
|
||||
def test_bedrock_messages_preserves_clear_tool_uses_context_management_and_adds_beta(
|
||||
local_beta_headers_config,
|
||||
):
|
||||
|
|
@ -2825,9 +2814,12 @@ def test_filter_and_transform_beta_headers_passes_context_management_for_bedrock
|
|||
"us.anthropic.claude-haiku-4-5-20251001-v1:0",
|
||||
"us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
"us.anthropic.claude-opus-4-7",
|
||||
"us.anthropic.claude-opus-4-8",
|
||||
"us.anthropic.claude-opus-5",
|
||||
"us.anthropic.claude-sonnet-5",
|
||||
],
|
||||
)
|
||||
def test_bedrock_messages_tool_search_adds_beta_header(local_beta_headers_config, model):
|
||||
def test_bedrock_messages_tool_search_adds_beta_header(local_model_cost_map, local_beta_headers_config, model):
|
||||
"""
|
||||
LIT-4522: Bedrock InvokeModel only admits ``tool_search_tool_*`` tool types
|
||||
when the request body carries the ``tool-search-tool-2025-10-19`` beta;
|
||||
|
|
@ -2837,6 +2829,11 @@ def test_bedrock_messages_tool_search_adds_beta_header(local_beta_headers_config
|
|||
Opus 4.7, so the beta was silently dropped for those models and every
|
||||
tool-search request failed. Verified live 2026-08-11: Bedrock returns 200
|
||||
with ``server_tool_use`` for all three models once the beta is sent.
|
||||
|
||||
LIT-5851: the same allowlist then missed Opus 4.8, Opus 5 and Sonnet 5, so
|
||||
the gate now reads the model map's ``supports_tool_search`` flag (explicit
|
||||
on the Bedrock entries, and the ``claude-tool-search`` rule for Claude 4.5
|
||||
and newer) instead of a per-model name list.
|
||||
"""
|
||||
from litellm.types.router import GenericLiteLLMParams
|
||||
|
||||
|
|
@ -2870,10 +2867,10 @@ def test_bedrock_messages_tool_search_adds_beta_header(local_beta_headers_config
|
|||
|
||||
|
||||
def test_bedrock_messages_tool_search_model_map_flag_is_authoritative(local_model_cost_map, monkeypatch):
|
||||
"""``supports_tool_search`` lives in the model map; the name patterns in
|
||||
``_supports_tool_search_on_bedrock`` are only a fallback for ids the map
|
||||
cannot resolve. Flipping the mapped entry's flag to ``False`` must win even
|
||||
though the model name still matches the ``haiku-4-5`` pattern."""
|
||||
"""``supports_tool_search`` lives in the model map; the ``claude-tool-search``
|
||||
rule only fills entries that carry no opinion. Flipping the mapped entry's
|
||||
flag to ``False`` must win even though the id is a Claude 4.5 the rule
|
||||
would flag."""
|
||||
import litellm
|
||||
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
|
||||
|
||||
|
|
@ -2892,19 +2889,43 @@ def test_bedrock_messages_tool_search_model_map_flag_is_authoritative(local_mode
|
|||
@pytest.mark.parametrize(
|
||||
"model, expected",
|
||||
[
|
||||
pytest.param("us.anthropic.claude-opus-4-6-v99:9", True, id="unmapped_id_falls_back_to_patterns"),
|
||||
pytest.param("anthropic.claude-3-5-sonnet-20240620-v1:0", False, id="mapped_entry_without_flag_no_pattern"),
|
||||
pytest.param("us.anthropic.claude-opus-4-6-v99:9", True, id="unmapped_4_6_variant"),
|
||||
pytest.param("us.anthropic.claude-haiku-5-2", True, id="unmapped_future_minor"),
|
||||
pytest.param(
|
||||
"arn:aws:bedrock:us-east-1:123456789012:inference-profile/us.anthropic.claude-opus-5",
|
||||
True,
|
||||
id="inference_profile_arn",
|
||||
),
|
||||
pytest.param("anthropic.claude-3-5-sonnet-20240620-v1:0", False, id="mapped_claude_3_5_without_flag"),
|
||||
pytest.param("us.anthropic.claude-opus-4-1-20250805-v1:0", False, id="mapped_opus_4_1_without_flag"),
|
||||
pytest.param("us.anthropic.claude-sonnet-4-20250514-v1:0", False, id="mapped_dated_sonnet_4_without_flag"),
|
||||
],
|
||||
)
|
||||
def test_bedrock_messages_tool_search_pattern_fallback(local_model_cost_map, model, expected):
|
||||
"""Ids the model map cannot resolve (or resolves without a
|
||||
``supports_tool_search`` opinion) fall through to the name patterns, so
|
||||
ARNs and unlisted regional variants of supported families keep working."""
|
||||
def test_bedrock_messages_tool_search_follows_claude_tool_search_rule(local_model_cost_map, model, expected):
|
||||
"""Ids the model map cannot resolve, or resolves without a ``supports_tool_search``
|
||||
opinion, take the ``claude-tool-search`` fallback rule: Claude 4.5 and newer get
|
||||
the beta, ARNs and unlisted regional variants included, and older Claudes do not."""
|
||||
cfg = AmazonAnthropicClaudeMessagesConfig()
|
||||
|
||||
assert cfg._supports_tool_search_on_bedrock(model) is expected
|
||||
|
||||
|
||||
def test_bedrock_messages_tool_search_rule_fills_mapped_entry_without_flag(local_model_cost_map, monkeypatch):
|
||||
"""LIT-5851: a Bedrock entry that is in the map but carries no ``supports_tool_search``
|
||||
key, the state Opus 4.8, Opus 5 and Sonnet 5 shipped in, is filled by the
|
||||
``claude-tool-search`` rule instead of resolving to ``None`` and losing the beta."""
|
||||
import litellm
|
||||
|
||||
model = "us.anthropic.claude-opus-5"
|
||||
cfg = AmazonAnthropicClaudeMessagesConfig()
|
||||
|
||||
monkeypatch.delitem(litellm.model_cost[model], "supports_tool_search")
|
||||
litellm.get_model_info.cache_clear()
|
||||
|
||||
assert litellm.get_model_info(model, custom_llm_provider="bedrock")["supports_tool_search"] is True
|
||||
assert cfg._supports_tool_search_on_bedrock(model) is True
|
||||
|
||||
|
||||
def test_bedrock_messages_thinking_shape_follows_exact_bedrock_entry_flag(
|
||||
local_model_cost_map, monkeypatch
|
||||
):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue