Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
Sequence,
)
from itertools import chain
from typing import Any, ClassVar, Generic, TypedDict
from typing import Any, ClassVar, Generic, TypedDict, cast

from agent_framework import (
BaseChatClient,
Expand All @@ -31,6 +31,7 @@
FunctionTool,
Message,
ResponseStream,
ToolMode,
UsageDetails,
)
from agent_framework._settings import load_settings
Expand Down Expand Up @@ -407,7 +408,7 @@ def _prepare_options(self, messages: Sequence[Message], options: Mapping[str, An
messages = prepend_instructions_to_messages(list(messages), instructions, role="system")

# Keys to exclude from processing
exclude_keys = {"instructions", "tool_choice"}
exclude_keys = {"instructions", "tool_choice", "tools"}

# Build run_options and model_options separately
run_options: dict[str, Any] = {}
Expand Down Expand Up @@ -454,7 +455,9 @@ def _prepare_options(self, messages: Sequence[Message], options: Mapping[str, An

# tools
tools = options.get("tools")
if tools is not None and (prepared_tools := self._prepare_tools_for_ollama(tools)):
tool_choice = options.get("tool_choice")
tool_mode = cast(ToolMode, tool_choice).get("mode") if isinstance(tool_choice, Mapping) else tool_choice
if tool_mode != "none" and tools is not None and (prepared_tools := self._prepare_tools_for_ollama(tools)):
run_options["tools"] = prepared_tools

return run_options
Expand Down
103 changes: 103 additions & 0 deletions python/packages/ollama/tests/test_ollama_chat_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -907,3 +907,106 @@ def test_prepare_options_single_stop_string_becomes_list(ollama_unit_test_env: d
request = client._prepare_options(messages, {"stop": "END"})

assert request["options"]["stop"] == ["END"]


def test_prepare_options_omits_tools_when_tool_choice_is_none(
ollama_unit_test_env: dict[str, str],
) -> None:
"""Tools are omitted when tool_choice explicitly disables tool use."""
client = OllamaChatClient()
messages = [Message(role="user", contents=[Content.from_text(text="hello")])]
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"},
},
"required": ["city"],
},
},
}
]

request = client._prepare_options(
messages,
{
"tools": tools,
"tool_choice": "none",
},
)

assert "tools" not in request


def test_prepare_options_omits_tools_when_tool_choice_mode_is_none(
ollama_unit_test_env: dict[str, str],
) -> None:
"""Tools are omitted when ToolMode mapping explicitly disables tool use."""
client = OllamaChatClient()
messages = [Message(role="user", contents=[Content.from_text(text="hello")])]
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"},
},
"required": ["city"],
},
},
}
]

request = client._prepare_options(
messages,
{
"tools": tools,
"tool_choice": {"mode": "none"},
},
)

assert "tools" not in request


def test_prepare_options_includes_tools_when_tool_choice_is_auto(
ollama_unit_test_env: dict[str, str],
) -> None:
"""Tools remain available when automatic tool selection is enabled."""
client = OllamaChatClient()
messages = [Message(role="user", contents=[Content.from_text(text="hello")])]
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"},
},
"required": ["city"],
},
},
}
]

request = client._prepare_options(
messages,
{
"tools": tools,
"tool_choice": "auto",
},
)

assert "tools" in request
assert request["tools"] == tools
Loading