mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-18 04:44:37 +00:00
fix(bedrock): answer 400 for the OpenAI tool_search tool on Converse unless drop_params is set
This commit is contained in:
parent
266c4aa924
commit
9b22785887
3 changed files with 77 additions and 11 deletions
|
|
@ -327,6 +327,23 @@ DROP_UNSUPPORTED_TOOL_SEARCH_WARNING: Final = (
|
|||
)
|
||||
|
||||
|
||||
def tools_without_unsupported_tool_search(
|
||||
tools: Sequence[object], model: str, route: str, drop_params: bool
|
||||
) -> Sequence[object]:
|
||||
if not any(_is_openai_tool_search_tool(tool) for tool in tools):
|
||||
return tools
|
||||
if not (litellm.drop_params or drop_params):
|
||||
raise litellm.utils.UnsupportedParamsError(
|
||||
message=(
|
||||
f"{model} on {route} cannot run the OpenAI `tool_search` tool. To drop it "
|
||||
"and the `defer_loading` of the other tools, set `litellm.drop_params = True`."
|
||||
),
|
||||
status_code=400,
|
||||
)
|
||||
litellm.verbose_logger.warning(DROP_UNSUPPORTED_TOOL_SEARCH_WARNING, model, route)
|
||||
return [_without_deferral(tool) for tool in tools if not _is_openai_tool_search_tool(tool)]
|
||||
|
||||
|
||||
class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
||||
"""
|
||||
Reference: https://docs.anthropic.com/claude/reference/messages_post
|
||||
|
|
@ -1045,16 +1062,9 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
model, self._resolved_provider
|
||||
):
|
||||
return [anthropic_tool_search_chat_tool() if _is_openai_tool_search_tool(tool) else tool for tool in tools]
|
||||
if not (litellm.drop_params or drop_params):
|
||||
raise litellm.utils.UnsupportedParamsError(
|
||||
message=(
|
||||
f"{model} on {self._resolved_provider} cannot run the OpenAI `tool_search` tool. To drop it "
|
||||
"and the `defer_loading` of the other tools, set `litellm.drop_params = True`."
|
||||
),
|
||||
status_code=400,
|
||||
)
|
||||
litellm.verbose_logger.warning(DROP_UNSUPPORTED_TOOL_SEARCH_WARNING, model, self._resolved_provider)
|
||||
return [_without_deferral(tool) for tool in tools if not _is_openai_tool_search_tool(tool)]
|
||||
return tools_without_unsupported_tool_search(
|
||||
tools=tools, model=model, route=self._resolved_provider, drop_params=drop_params
|
||||
)
|
||||
|
||||
def _map_tools(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ from litellm.llms.anthropic.chat.transformation import (
|
|||
DROP_UNSUPPORTED_OUTPUT_CONFIG_WARNING,
|
||||
REASONING_EFFORT_TO_OUTPUT_CONFIG_EFFORT,
|
||||
AnthropicConfig,
|
||||
tools_without_unsupported_tool_search,
|
||||
)
|
||||
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
|
||||
from litellm.llms.base_llm.chat.transformation import BaseConfig, BaseLLMException
|
||||
|
|
@ -136,6 +137,7 @@ UNSUPPORTED_BEDROCK_CONVERSE_BETA_PATTERNS: Final = [
|
|||
|
||||
|
||||
_TOOLS_AS_SENT: Final = TypeAdapter(tuple[Mapping[str, object], ...])
|
||||
_TOOLS_AS_RECEIVED: Final = TypeAdapter(list[object])
|
||||
|
||||
|
||||
def _tools_the_model_accepts(
|
||||
|
|
@ -1085,7 +1087,17 @@ class AmazonConverseConfig(BaseConfig):
|
|||
optional_params["topP" if param == "top_p" else param] = value
|
||||
if param == "tools" and isinstance(value, list):
|
||||
self._apply_tool_call_transformation(
|
||||
tools=cast(list[OpenAIChatCompletionToolParam], value),
|
||||
tools=cast(
|
||||
list[OpenAIChatCompletionToolParam],
|
||||
list(
|
||||
tools_without_unsupported_tool_search(
|
||||
tools=_TOOLS_AS_RECEIVED.validate_python(value),
|
||||
model=model,
|
||||
route="bedrock converse",
|
||||
drop_params=drop_params,
|
||||
)
|
||||
),
|
||||
),
|
||||
model=model,
|
||||
non_default_params=non_default_params,
|
||||
optional_params=optional_params,
|
||||
|
|
|
|||
|
|
@ -10145,3 +10145,47 @@ async def test_bedrock_user_file_element_becomes_document_block(sync_mode: bool)
|
|||
assert content[0] == {"text": "Summarize this report"}
|
||||
assert content[1]["document"]["source"] == {"bytes": base64.b64encode(pdf_bytes).decode()}
|
||||
assert content[1]["document"]["format"] == "pdf"
|
||||
|
||||
|
||||
def _openai_tool_search_with_deferred_functions() -> list[dict[str, object]]:
|
||||
return [
|
||||
{"type": "tool_search", "execution": "server"},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {"name": "get_weather", "parameters": {"type": "object", "properties": {}}},
|
||||
"defer_loading": True,
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_stock_price",
|
||||
"parameters": {"type": "object", "properties": {}},
|
||||
"defer_loading": True,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def test_map_openai_params_answers_400_for_the_openai_tool_search_tool_without_drop_params(monkeypatch):
|
||||
monkeypatch.setattr(litellm, "drop_params", False)
|
||||
with pytest.raises(litellm.utils.UnsupportedParamsError) as raised:
|
||||
AmazonConverseConfig().map_openai_params(
|
||||
non_default_params={"tools": _openai_tool_search_with_deferred_functions()},
|
||||
optional_params={},
|
||||
model="us.anthropic.claude-sonnet-5-5",
|
||||
drop_params=False,
|
||||
)
|
||||
assert raised.value.status_code == 400
|
||||
assert "tool_search" in str(raised.value)
|
||||
|
||||
|
||||
def test_map_openai_params_drops_the_openai_tool_search_tool_and_every_deferral_under_drop_params(monkeypatch):
|
||||
monkeypatch.setattr(litellm, "drop_params", False)
|
||||
mapped: Final = AmazonConverseConfig().map_openai_params(
|
||||
non_default_params={"tools": _openai_tool_search_with_deferred_functions()},
|
||||
optional_params={},
|
||||
model="us.anthropic.claude-sonnet-5-5",
|
||||
drop_params=True,
|
||||
)
|
||||
assert [tool["function"]["name"] for tool in mapped["tools"]] == ["get_weather", "get_stock_price"]
|
||||
assert all("defer_loading" not in tool and "defer_loading" not in tool["function"] for tool in mapped["tools"])
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue