mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-18 02:23:44 +00:00
Fix greptile review
This commit is contained in:
@@ -907,6 +907,7 @@ def responses(
|
||||
"extra_body": extra_body,
|
||||
"timeout": timeout,
|
||||
"custom_llm_provider": custom_llm_provider,
|
||||
**({"use_responses_api_bridge": True} if use_responses_api_bridge else {}),
|
||||
**{k: v for k, v in kwargs.items() if k not in _internal_skip},
|
||||
}
|
||||
if _is_async:
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
"""
|
||||
Tests for the `use_responses_api_bridge` flag that allows openai/ models
|
||||
with custom api_base to opt-in to the /responses → /chat/completions bridge.
|
||||
|
||||
Includes file_search emulation: the flag must be forwarded on inner aresponses
|
||||
calls so routed requests do not hit a custom api_base /v1/responses endpoint.
|
||||
"""
|
||||
|
||||
import os
|
||||
@@ -12,6 +15,7 @@ sys.path.insert(
|
||||
) # Adds the parent directory to the system path
|
||||
|
||||
import litellm
|
||||
from litellm.types.llms.openai import ResponseAPIUsage, ResponsesAPIResponse
|
||||
|
||||
|
||||
class TestUseResponsesApiBridgeFlag:
|
||||
@@ -105,3 +109,154 @@ class TestUseResponsesApiBridgeFlag:
|
||||
)
|
||||
|
||||
mock_bridge_handler.assert_called_once()
|
||||
|
||||
@patch("litellm.responses.file_search.emulated_handler._call_aresponses")
|
||||
@patch(
|
||||
"litellm.responses.main.ProviderConfigManager.get_provider_responses_api_config"
|
||||
)
|
||||
async def test_bridge_flag_forwarded_to_file_search_emulation(
|
||||
self, mock_get_config, mock_call_aresponses
|
||||
):
|
||||
"""When use_responses_api_bridge=True and file_search tool is present,
|
||||
the flag should be forwarded to the inner aresponses call in the
|
||||
file_search emulation path."""
|
||||
# Setup: provider has native responses API support
|
||||
mock_get_config.return_value = litellm.OpenAIResponsesAPIConfig()
|
||||
|
||||
# Mock the inner aresponses call to return a valid response
|
||||
mock_response = ResponsesAPIResponse(
|
||||
id="resp_123",
|
||||
model="openai/my-custom-model",
|
||||
created_at=1234567890,
|
||||
output=[
|
||||
{"type": "message", "content": [{"type": "text", "text": "Answer"}]}
|
||||
],
|
||||
usage=ResponseAPIUsage(
|
||||
input_tokens=10, output_tokens=5, total_tokens=15
|
||||
),
|
||||
)
|
||||
mock_call_aresponses.return_value = mock_response
|
||||
|
||||
await litellm.aresponses(
|
||||
model="openai/my-custom-model",
|
||||
input="Search for information",
|
||||
tools=[{"type": "file_search"}],
|
||||
use_responses_api_bridge=True,
|
||||
litellm_logging_obj=MagicMock(),
|
||||
)
|
||||
|
||||
# Verify _call_aresponses was called with use_responses_api_bridge=True
|
||||
mock_call_aresponses.assert_called_once()
|
||||
call_kwargs = mock_call_aresponses.call_args.kwargs
|
||||
assert (
|
||||
call_kwargs.get("use_responses_api_bridge") is True
|
||||
), "use_responses_api_bridge flag should be forwarded to inner aresponses call"
|
||||
|
||||
@patch(
|
||||
"litellm.responses.main.litellm_completion_transformation_handler.response_api_handler"
|
||||
)
|
||||
@patch("litellm.vector_stores.main.asearch")
|
||||
@patch(
|
||||
"litellm.responses.main.ProviderConfigManager.get_provider_responses_api_config"
|
||||
)
|
||||
async def test_bridge_flag_prevents_native_responses_endpoint_call(
|
||||
self, mock_get_config, mock_asearch, mock_bridge_handler
|
||||
):
|
||||
"""
|
||||
Concrete failing scenario: native OpenAI responses config + bridge flag +
|
||||
file_search → emulation must still route inner calls through the bridge
|
||||
(chat completions), not POST to api_base /v1/responses.
|
||||
"""
|
||||
mock_get_config.return_value = litellm.OpenAIResponsesAPIConfig()
|
||||
mock_asearch.return_value = []
|
||||
|
||||
first_response = ResponsesAPIResponse(
|
||||
id="resp_first",
|
||||
model="openai/my-local-model",
|
||||
created_at=1234567890,
|
||||
output=[
|
||||
{
|
||||
"type": "function_call",
|
||||
"name": "litellm_file_search",
|
||||
"call_id": "call_123",
|
||||
"arguments": '{"queries": ["test query"]}',
|
||||
}
|
||||
],
|
||||
usage=ResponseAPIUsage(
|
||||
input_tokens=10, output_tokens=5, total_tokens=15
|
||||
),
|
||||
)
|
||||
second_response = ResponsesAPIResponse(
|
||||
id="resp_second",
|
||||
model="openai/my-local-model",
|
||||
created_at=1234567891,
|
||||
output=[
|
||||
{
|
||||
"type": "message",
|
||||
"content": [{"type": "text", "text": "Final answer"}],
|
||||
}
|
||||
],
|
||||
usage=ResponseAPIUsage(
|
||||
input_tokens=20, output_tokens=10, total_tokens=30
|
||||
),
|
||||
)
|
||||
mock_bridge_handler.side_effect = [first_response, second_response]
|
||||
|
||||
result = await litellm.aresponses(
|
||||
model="openai/my-local-model",
|
||||
input="Search for information",
|
||||
tools=[
|
||||
{
|
||||
"type": "file_search",
|
||||
"file_search": {"vector_store_ids": ["vs_123"]},
|
||||
}
|
||||
],
|
||||
use_responses_api_bridge=True,
|
||||
api_base="http://localhost:8080/v1",
|
||||
litellm_logging_obj=MagicMock(),
|
||||
)
|
||||
|
||||
assert mock_bridge_handler.call_count == 2, (
|
||||
"Bridge handler should be called twice: initial function-tool call "
|
||||
"and follow-up with tool results"
|
||||
)
|
||||
for call in mock_bridge_handler.call_args_list:
|
||||
all_kwargs = call.kwargs if call.kwargs else {}
|
||||
assert "use_responses_api_bridge" not in all_kwargs
|
||||
assert result is not None
|
||||
assert result.id is not None
|
||||
|
||||
@patch("litellm.responses.main.base_llm_http_handler.response_api_handler")
|
||||
@patch("litellm.vector_stores.main.asearch")
|
||||
@patch(
|
||||
"litellm.responses.main.ProviderConfigManager.get_provider_responses_api_config"
|
||||
)
|
||||
async def test_without_bridge_flag_uses_native_endpoint(
|
||||
self, mock_get_config, mock_asearch, mock_native_handler
|
||||
):
|
||||
"""Without the bridge flag, openai/ with native config uses the native handler."""
|
||||
mock_get_config.return_value = litellm.OpenAIResponsesAPIConfig()
|
||||
mock_asearch.return_value = []
|
||||
mock_native_handler.return_value = ResponsesAPIResponse(
|
||||
id="resp_native",
|
||||
model="openai/gpt-4o",
|
||||
created_at=1234567890,
|
||||
output=[
|
||||
{
|
||||
"type": "message",
|
||||
"content": [{"type": "text", "text": "Native response"}],
|
||||
}
|
||||
],
|
||||
usage=ResponseAPIUsage(
|
||||
input_tokens=10, output_tokens=5, total_tokens=15
|
||||
),
|
||||
)
|
||||
|
||||
result = await litellm.aresponses(
|
||||
model="openai/gpt-4o",
|
||||
input="Hello",
|
||||
litellm_logging_obj=MagicMock(),
|
||||
)
|
||||
|
||||
mock_native_handler.assert_called_once()
|
||||
assert result is not None
|
||||
|
||||
Reference in New Issue
Block a user