mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-06 02:48:13 +00:00
251 lines
8.6 KiB
Python
251 lines
8.6 KiB
Python
"""
|
|
Test automatic routing to xAI Responses API when tools are present
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
sys.path.insert(0, os.path.abspath("../.."))
|
|
|
|
import pytest
|
|
import litellm
|
|
from litellm.main import responses_api_bridge_check
|
|
|
|
|
|
class TestXAIResponsesAutoRouting:
|
|
"""Test that xAI requests with tools automatically route to Responses API"""
|
|
|
|
def test_responses_api_bridge_check_without_tools(self):
|
|
"""Test that without tools, xAI uses chat mode"""
|
|
model = "grok-3"
|
|
custom_llm_provider = "xai"
|
|
tools = None
|
|
web_search_options = None
|
|
|
|
model_info, updated_model = responses_api_bridge_check(
|
|
model=model,
|
|
custom_llm_provider=custom_llm_provider,
|
|
web_search_options=web_search_options,
|
|
)
|
|
|
|
# Should not auto-route to responses mode without tools
|
|
assert model_info.get("mode") != "responses"
|
|
assert updated_model == model
|
|
|
|
def test_responses_api_bridge_check_with_tools(self):
|
|
"""Test that with tools, xAI automatically routes to Responses API"""
|
|
model = "grok-3"
|
|
custom_llm_provider = "xai"
|
|
tools = [
|
|
{
|
|
"type": "function",
|
|
"function": {
|
|
"name": "get_weather",
|
|
"description": "Get the weather",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {"location": {"type": "string"}},
|
|
},
|
|
},
|
|
}
|
|
]
|
|
web_search_options = None
|
|
|
|
model_info, updated_model = responses_api_bridge_check(
|
|
model=model,
|
|
custom_llm_provider=custom_llm_provider,
|
|
web_search_options=web_search_options,
|
|
)
|
|
|
|
# Should auto-route to responses mode when tools are present
|
|
assert model_info.get("mode") == "chat"
|
|
assert updated_model == model
|
|
|
|
def test_responses_api_bridge_check_with_empty_tools(self):
|
|
"""Test that with empty tools list, xAI does not route to Responses API"""
|
|
model = "grok-3"
|
|
custom_llm_provider = "xai"
|
|
tools = []
|
|
web_search_options = None
|
|
|
|
model_info, updated_model = responses_api_bridge_check(
|
|
model=model,
|
|
custom_llm_provider=custom_llm_provider,
|
|
web_search_options=web_search_options,
|
|
)
|
|
|
|
# Should not auto-route with empty tools list
|
|
assert model_info.get("mode") != "responses"
|
|
assert updated_model == model
|
|
|
|
def test_responses_api_bridge_check_non_xai_provider_with_tools(self):
|
|
"""Test that non-xAI providers don't get auto-routed"""
|
|
model = "gpt-4"
|
|
custom_llm_provider = "openai"
|
|
tools = [
|
|
{
|
|
"type": "function",
|
|
"function": {
|
|
"name": "get_weather",
|
|
"description": "Get the weather",
|
|
},
|
|
}
|
|
]
|
|
web_search_options = None
|
|
|
|
model_info, updated_model = responses_api_bridge_check(
|
|
model=model,
|
|
custom_llm_provider=custom_llm_provider,
|
|
web_search_options=web_search_options,
|
|
)
|
|
|
|
# Should not auto-route non-xAI providers
|
|
assert model_info.get("mode") != "responses"
|
|
assert updated_model == model
|
|
|
|
def test_responses_api_bridge_check_with_responses_prefix(self):
|
|
"""Test that responses/ prefix still works"""
|
|
model = "responses/grok-3"
|
|
custom_llm_provider = "xai"
|
|
tools = None
|
|
web_search_options = None
|
|
|
|
model_info, updated_model = responses_api_bridge_check(
|
|
model=model,
|
|
custom_llm_provider=custom_llm_provider,
|
|
web_search_options=web_search_options,
|
|
)
|
|
|
|
# Should route to responses mode with prefix, even without tools
|
|
assert model_info.get("mode") == "responses"
|
|
assert updated_model == "grok-3" # prefix removed
|
|
|
|
def test_responses_api_bridge_check_with_code_interpreter_tool(self):
|
|
"""Test auto-routing with code_interpreter tool"""
|
|
model = "grok-3"
|
|
custom_llm_provider = "xai"
|
|
tools = [{"type": "code_interpreter"}]
|
|
web_search_options = None
|
|
|
|
model_info, updated_model = responses_api_bridge_check(
|
|
model=model,
|
|
custom_llm_provider=custom_llm_provider,
|
|
web_search_options=web_search_options,
|
|
)
|
|
# Should auto-route with code_interpreter tool
|
|
assert model_info.get("mode") == "chat"
|
|
assert updated_model == model
|
|
|
|
def test_responses_api_bridge_check_with_web_search_tool(self):
|
|
"""Test auto-routing with web_search tool"""
|
|
model = "grok-4"
|
|
custom_llm_provider = "xai"
|
|
tools = [
|
|
{"type": "web_search", "filters": {"allowed_domains": ["wikipedia.org"]}}
|
|
]
|
|
web_search_options = None
|
|
|
|
model_info, updated_model = responses_api_bridge_check(
|
|
model=model,
|
|
custom_llm_provider=custom_llm_provider,
|
|
web_search_options=web_search_options,
|
|
)
|
|
|
|
# Should auto-route with web_search tool
|
|
assert model_info.get("mode") == "chat"
|
|
assert updated_model == model
|
|
|
|
def test_responses_api_bridge_check_with_x_search_tool(self):
|
|
"""Test auto-routing with x_search tool"""
|
|
model = "grok-4"
|
|
custom_llm_provider = "xai"
|
|
tools = [{"type": "x_search", "allowed_x_handles": ["@elonmusk"]}]
|
|
web_search_options = None
|
|
|
|
model_info, updated_model = responses_api_bridge_check(
|
|
model=model,
|
|
custom_llm_provider=custom_llm_provider,
|
|
web_search_options=web_search_options,
|
|
)
|
|
|
|
# Should auto-route with x_search tool
|
|
assert model_info.get("mode") == "chat"
|
|
assert updated_model == model
|
|
|
|
def test_responses_api_bridge_check_with_web_search_options(self):
|
|
"""Test auto-routing with web_search_options"""
|
|
model = "grok-4-1-fast"
|
|
custom_llm_provider = "xai"
|
|
tools = None
|
|
web_search_options = {} # Empty dict should trigger routing
|
|
|
|
model_info, updated_model = responses_api_bridge_check(
|
|
model=model,
|
|
custom_llm_provider=custom_llm_provider,
|
|
web_search_options=web_search_options,
|
|
)
|
|
|
|
# Should auto-route with web_search_options
|
|
assert model_info.get("mode") == "responses"
|
|
assert updated_model == model
|
|
|
|
def test_responses_api_bridge_check_with_web_search_options_and_tools(self):
|
|
"""Test auto-routing with both web_search_options and tools"""
|
|
model = "grok-4"
|
|
custom_llm_provider = "xai"
|
|
tools = [{"type": "code_interpreter"}]
|
|
web_search_options = {"enabled": True}
|
|
|
|
model_info, updated_model = responses_api_bridge_check(
|
|
model=model,
|
|
custom_llm_provider=custom_llm_provider,
|
|
web_search_options=web_search_options,
|
|
)
|
|
|
|
# Should auto-route with both present
|
|
assert model_info.get("mode") == "responses"
|
|
assert updated_model == model
|
|
|
|
@patch("litellm.completion_extras.responses_api_bridge.completion")
|
|
def test_completion_with_tools_routes_to_responses_api(
|
|
self, mock_responses_completion
|
|
):
|
|
"""Test that completion() with tools routes to Responses API"""
|
|
# Mock the responses_api_bridge.completion to avoid actual API calls
|
|
mock_responses_completion.return_value = MagicMock()
|
|
|
|
model = "xai/grok-3"
|
|
messages = [{"role": "user", "content": "What's the weather?"}]
|
|
tools = [
|
|
{
|
|
"type": "function",
|
|
"function": {
|
|
"name": "get_weather",
|
|
"description": "Get weather info",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {"location": {"type": "string"}},
|
|
},
|
|
},
|
|
}
|
|
]
|
|
|
|
try:
|
|
litellm.completion(
|
|
model=model,
|
|
messages=messages,
|
|
tools=tools,
|
|
mock_response="This is a test", # Use mock mode to avoid API calls
|
|
)
|
|
except Exception:
|
|
# It's ok if this fails, we just want to verify the routing logic
|
|
pass
|
|
|
|
# The mock should have been called, indicating responses API was used
|
|
# Note: This test may need adjustment based on actual mock_response behavior
|
|
# The key is that the responses_api_bridge_check logic routes correctly
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|