mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-17 04:34:25 +00:00
fix(guardrails): keep OpenAI tool_search out of the Responses guardrail tool scan
The scan translated tool_search into Anthropic's regex search tool on every route, so a guardrail returning only function tools removed tool_search from native OpenAI requests and OpenAI answered 400 for the deferred tools
This commit is contained in:
parent
063a87296f
commit
d9da2df0d3
2 changed files with 25 additions and 1 deletions
|
|
@ -64,6 +64,7 @@ from litellm.llms.base_llm.guardrail_translation.utils import (
|
|||
)
|
||||
from litellm.llms.openai.responses.guardrail_translation.tool_merge import merge_guardrailed_tools
|
||||
from litellm.responses.litellm_completion_transformation.custom_tools import without_malformed_tool_flags
|
||||
from litellm.responses.litellm_completion_transformation.tool_search import is_server_tool_search_tool
|
||||
from litellm.responses.litellm_completion_transformation.transformation import (
|
||||
LiteLLMCompletionResponsesConfig,
|
||||
)
|
||||
|
|
@ -570,7 +571,12 @@ class OpenAIResponsesHandler(BaseTranslation):
|
|||
)
|
||||
scanned_tools: Final = tuple(without_malformed_tool_flags(tool) for tool in original_tools)
|
||||
flattened_tool_groups: Final = tuple(
|
||||
form.chat_tools for form in LiteLLMCompletionResponsesConfig.responses_tools_to_chat_forms(scanned_tools)
|
||||
() if is_server_tool_search_tool(tool) else form.chat_tools
|
||||
for tool, form in zip(
|
||||
scanned_tools,
|
||||
LiteLLMCompletionResponsesConfig.responses_tools_to_chat_forms(scanned_tools),
|
||||
strict=True,
|
||||
)
|
||||
)
|
||||
extracted: Final = self._extract_guardrail_inputs(
|
||||
data, input_data, flattened_tool_groups, skip_system=skip_system
|
||||
|
|
|
|||
|
|
@ -3216,6 +3216,24 @@ class TestOpenAIResponsesHandlerNamespaceTools:
|
|||
"apply_patch",
|
||||
]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_a_function_only_guardrail_keeps_the_tool_search_tool_it_never_scans(self):
|
||||
data: Final = _codex_request("hi")
|
||||
data["tools"] = [{"type": "tool_search"}, {**data["tools"][0], "defer_loading": True}]
|
||||
expected_tools: Final = copy.deepcopy(data["tools"])
|
||||
scanned: Final[list[list[dict]]] = []
|
||||
|
||||
def keep_functions(tools):
|
||||
scanned.append(copy.deepcopy(tools))
|
||||
return [tool for tool in tools if tool["type"] == "function"]
|
||||
|
||||
result: Final = await OpenAIResponsesHandler().process_input_messages(
|
||||
data, ToolEditingGuardrail(edit=keep_functions, guardrail_name="test")
|
||||
)
|
||||
|
||||
assert result["tools"] == expected_tools
|
||||
assert [tool["type"] for tool in scanned[0]] == ["function"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_appending_guardrail_keeps_namespace_and_adds_tool(self):
|
||||
data = _codex_request("hi")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue