"""
Test script for tool calling methods to ensure proper handling of different LLM method arguments.
"""
from unittest.mock import Mock
import pytest
from langchain_core.language_models.chat_models import BaseChatModel
from browser_use.agent.service import Agent
class TestToolCallingMethods:
"""Tests for different tool calling methods handling."""
@pytest.fixture
def mock_llm_with_structured_output(self):
"""Create a mock LLM that tracks with_structured_output calls."""
mock_llm = Mock(spec=BaseChatModel)
# Track calls to with_structured_output
structured_output_calls = []
def mock_with_structured_output(schema, include_raw=True, method=None):
structured_output_calls.append({'schema': schema, 'include_raw': include_raw, 'method': method})
# Return a mock that can be invoked
mock_structured = Mock()
mock_structured.invoke = Mock(return_value={'parsed': None, 'raw': Mock(content='test')})
mock_structured.ainvoke = Mock(return_value={'parsed': None, 'raw': Mock(content='test')})
return mock_structured
mock_llm.with_structured_output = mock_with_structured_output
mock_llm.structured_output_calls = structured_output_calls
mock_llm.invoke = Mock(return_value=Mock(content='{"answer": "paris"}'))
return mock_llm
async def test_tools_method_error(self, mock_llm_with_structured_output):
"""Test that 'tools' method causes the expected error."""
# Create agent with 'tools' method
agent = Agent(
task='Test task',
llm=mock_llm_with_structured_output,
tool_calling_method='tools',
)
# The error should occur during initialization when _test_tool_calling_method is called
# Check that with_structured_output was called with 'tools' method
assert len(mock_llm_with_structured_output.structured_output_calls) > 0
# Find the call that used 'tools' method
tools_call = next(
(call for call in mock_llm_with_structured_output.structured_output_calls if call['method'] == 'tools'), None
)
assert tools_call is not None, "Expected with_structured_output to be called with method='tools'"
async def test_function_calling_method_works(self, mock_llm_with_structured_output):
"""Test that 'function_calling' method works correctly."""
# Create agent with 'function_calling' method
agent = Agent(
task='Test task',
llm=mock_llm_with_structured_output,
tool_calling_method='function_calling',
)
# Check that with_structured_output was called with 'function_calling' method
assert len(mock_llm_with_structured_output.structured_output_calls) > 0
# Find the call that used 'function_calling' method
fc_call = next(
(call for call in mock_llm_with_structured_output.structured_output_calls if call['method'] == 'function_calling'),
None,
)
assert fc_call is not None, "Expected with_structured_output to be called with method='function_calling'"
async def test_json_mode_method_works(self, mock_llm_with_structured_output):
"""Test that 'json_mode' method works correctly."""
# Create agent with 'json_mode' method
agent = Agent(
task='Test task',
llm=mock_llm_with_structured_output,
tool_calling_method='json_mode',
)
# For json_mode, it should not call with_structured_output during testing
# because it uses raw mode
# Check the calls
json_mode_calls = [
call for call in mock_llm_with_structured_output.structured_output_calls if call['method'] == 'json_mode'
]
# json_mode is handled specially and doesn't use with_structured_output in _test_tool_calling_method
assert len(json_mode_calls) == 0
async def test_raw_method_works(self, mock_llm_with_structured_output):
"""Test that 'raw' method works correctly."""
# Create agent with 'raw' method
agent = Agent(
task='Test task',
llm=mock_llm_with_structured_output,
tool_calling_method='raw',
)
# For raw mode, it should not call with_structured_output during testing
# Check the calls
raw_calls = [call for call in mock_llm_with_structured_output.structured_output_calls if call['method'] == 'raw']
# raw is handled specially and doesn't use with_structured_output in _test_tool_calling_method
assert len(raw_calls) == 0
async def test_auto_method_selection(self, mock_llm_with_structured_output):
"""Test that 'auto' method selects appropriate method based on LLM."""
# Mock the agent to simulate Azure OpenAI with GPT-4
agent = Agent(
task='Test task',
llm=mock_llm_with_structured_output,
tool_calling_method='auto',
)
# Monkey patch to simulate Azure OpenAI
agent.chat_model_library = 'AzureChatOpenAI'
agent.chat_model_name = 'gpt-4-1106-preview'
# Call _get_tool_calling_method_for_model to see what it returns
method = agent._get_tool_calling_method_for_model()
# For Azure OpenAI with GPT-4, it should return 'tools'
assert method == 'tools'