mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: [BREAKING] Replace Hosted*Tool classes with tool methods (#3634)
* Replace Hosted*Tool classes with client static factory methods * fixed failing test * mypy fix * mypy fix 2 * declarative mypy fix * addressed comments * ToolProtocol removal * fixed test * agents mypy fix * fix failing tests * mypy fix * addressed comments * fixed tests * addressed comments + added factory method overrides for azureai v2 client * mypy fix * added kwargs to azureai tool methods * fixed in test * _sessions fix * test fix
This commit is contained in:
@@ -9,7 +9,6 @@ from collections.abc import (
|
||||
Awaitable,
|
||||
Callable,
|
||||
Mapping,
|
||||
MutableMapping,
|
||||
Sequence,
|
||||
)
|
||||
from itertools import chain
|
||||
@@ -26,10 +25,8 @@ from agent_framework import (
|
||||
FunctionInvocationConfiguration,
|
||||
FunctionInvocationLayer,
|
||||
FunctionTool,
|
||||
HostedWebSearchTool,
|
||||
Message,
|
||||
ResponseStream,
|
||||
ToolProtocol,
|
||||
UsageDetails,
|
||||
get_logger,
|
||||
)
|
||||
@@ -343,7 +340,7 @@ class OllamaChatClient(
|
||||
self.model_id = ollama_settings.model_id
|
||||
self.client = client or AsyncClient(host=ollama_settings.host)
|
||||
# Save Host URL for serialization with to_dict()
|
||||
self.host = str(self.client._client.base_url)
|
||||
self.host = str(self.client._client.base_url) # pyright: ignore[reportUnknownMemberType,reportPrivateUsage,reportUnknownArgumentType]
|
||||
|
||||
super().__init__(
|
||||
middleware=middleware,
|
||||
@@ -559,21 +556,22 @@ class OllamaChatClient(
|
||||
resp.append(fcc)
|
||||
return resp
|
||||
|
||||
def _prepare_tools_for_ollama(self, tools: list[ToolProtocol | MutableMapping[str, Any]]) -> list[dict[str, Any]]:
|
||||
chat_tools: list[dict[str, Any]] = []
|
||||
def _prepare_tools_for_ollama(self, tools: list[Any]) -> list[Any]:
|
||||
"""Prepare tools for the Ollama API.
|
||||
|
||||
Converts FunctionTool to JSON schema format. All other tools pass through unchanged.
|
||||
|
||||
Args:
|
||||
tools: List of tools to prepare.
|
||||
|
||||
Returns:
|
||||
List of tool definitions ready for the Ollama API.
|
||||
"""
|
||||
chat_tools: list[Any] = []
|
||||
for tool in tools:
|
||||
if isinstance(tool, ToolProtocol):
|
||||
match tool:
|
||||
case FunctionTool():
|
||||
chat_tools.append(tool.to_json_schema_spec())
|
||||
case HostedWebSearchTool():
|
||||
raise ServiceInvalidRequestError("HostedWebSearchTool is not supported by the Ollama client.")
|
||||
case _:
|
||||
raise ServiceInvalidRequestError(
|
||||
"Unsupported tool type '"
|
||||
f"{type(tool).__name__}"
|
||||
"' for Ollama client. Supported tool types: FunctionTool."
|
||||
)
|
||||
if isinstance(tool, FunctionTool):
|
||||
chat_tools.append(tool.to_json_schema_spec())
|
||||
else:
|
||||
chat_tools.append(tool if isinstance(tool, dict) else dict(tool))
|
||||
# Pass through all other tools unchanged
|
||||
chat_tools.append(tool)
|
||||
return chat_tools
|
||||
|
||||
@@ -10,7 +10,6 @@ from agent_framework import (
|
||||
BaseChatClient,
|
||||
ChatResponseUpdate,
|
||||
Content,
|
||||
HostedWebSearchTool,
|
||||
Message,
|
||||
chat_middleware,
|
||||
tool,
|
||||
@@ -384,27 +383,30 @@ async def test_cmc_streaming_with_tool_call(
|
||||
assert text_result.text == "test"
|
||||
|
||||
|
||||
async def test_cmc_with_hosted_tool_call(
|
||||
@patch.object(AsyncClient, "chat", new_callable=AsyncMock)
|
||||
async def test_cmc_with_dict_tool_passthrough(
|
||||
mock_chat: AsyncMock,
|
||||
ollama_unit_test_env: dict[str, str],
|
||||
chat_history: list[Message],
|
||||
mock_chat_completion_response: OllamaChatResponse,
|
||||
) -> None:
|
||||
with pytest.raises(ServiceInvalidRequestError):
|
||||
additional_properties = {
|
||||
"user_location": {
|
||||
"country": "US",
|
||||
"city": "Seattle",
|
||||
}
|
||||
}
|
||||
"""Test that dict-based tools are passed through to Ollama."""
|
||||
mock_chat.return_value = mock_chat_completion_response
|
||||
chat_history.append(Message(text="hello world", role="user"))
|
||||
|
||||
chat_history.append(Message(text="hello world", role="user"))
|
||||
ollama_client = OllamaChatClient()
|
||||
await ollama_client.get_response(
|
||||
messages=chat_history,
|
||||
options={
|
||||
"tools": [{"type": "function", "function": {"name": "custom_tool", "parameters": {}}}],
|
||||
},
|
||||
)
|
||||
|
||||
ollama_client = OllamaChatClient()
|
||||
await ollama_client.get_response(
|
||||
messages=chat_history,
|
||||
options={
|
||||
"tools": HostedWebSearchTool(additional_properties=additional_properties),
|
||||
},
|
||||
)
|
||||
# Verify the tool was passed through to the Ollama client
|
||||
mock_chat.assert_called_once()
|
||||
call_kwargs = mock_chat.call_args.kwargs
|
||||
assert "tools" in call_kwargs
|
||||
assert call_kwargs["tools"] == [{"type": "function", "function": {"name": "custom_tool", "parameters": {}}}]
|
||||
|
||||
|
||||
@patch.object(AsyncClient, "chat", new_callable=AsyncMock)
|
||||
|
||||
Reference in New Issue
Block a user