From 5205a355803f3487711997f00a23e9bc87bcfd02 Mon Sep 17 00:00:00 2001 From: Mucheen <145200703+Mucheen@users.noreply.github.com> Date: Tue, 13 Oct 2026 11:17:50 +0800 Subject: [PATCH] fix(examples): handle numeric strings in async arithmetic tools --- examples/async-tools.py | 5 ++-- tests/test_async_tools_example.py | 44 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/test_async_tools_example.py diff --git a/examples/async-tools.py b/examples/async-tools.py index 11436659..f3b3d732 100644 --- a/examples/async-tools.py +++ b/examples/async-tools.py @@ -15,14 +15,15 @@ def add_two_numbers(a: int, b: int) -> int: Returns: int: The sum of the two numbers """ - return a + b + # Tool arguments may contain numeric strings even for integer parameters. + return int(a) + int(b) def subtract_two_numbers(a: int, b: int) -> int: """ Subtract two numbers """ - return a - b + return int(a) - int(b) # Tools can still be manually defined and passed into chat diff --git a/tests/test_async_tools_example.py b/tests/test_async_tools_example.py new file mode 100644 index 00000000..56f886b9 --- /dev/null +++ b/tests/test_async_tools_example.py @@ -0,0 +1,44 @@ +import runpy +from pathlib import Path +from unittest.mock import AsyncMock, patch + +import pytest + +from ollama import ChatResponse + + +@pytest.fixture +def anyio_backend(): + return 'asyncio' + + +@pytest.mark.anyio +@pytest.mark.parametrize( + ('function_name', 'arguments', 'expected'), + [ + ('add_two_numbers', {'a': '30', 'b': '12'}, '42'), + ('subtract_two_numbers', {'a': '30', 'b': '12'}, '18'), + ('add_two_numbers', {'a': 30, 'b': 12}, '42'), + ('subtract_two_numbers', {'a': 30, 'b': 12}, '18'), + ], +) +async def test_async_tools_example_returns_numeric_tool_results(function_name, arguments, expected): + example = runpy.run_path(str(Path(__file__).parents[1] / 'examples' / 'async-tools.py')) + tool_response = ChatResponse( + message={ + 'role': 'assistant', + 'tool_calls': [{'function': {'name': function_name, 'arguments': arguments}}], + }, + ) + chat = AsyncMock(side_effect=[tool_response, ChatResponse(message={'role': 'assistant', 'content': 'Done'})]) + + with patch('ollama.AsyncClient') as client: + client.return_value.chat = chat + await example['main']() + + assert chat.await_count == 2 + assert chat.await_args_list[1].kwargs['messages'] == [ + {'role': 'user', 'content': 'What is three plus one?'}, + tool_response.message, + {'role': 'tool', 'content': expected, 'tool_name': function_name}, + ]