-
Notifications
You must be signed in to change notification settings - Fork 895
/
Copy pathforcing_tool_use.py
99 lines (80 loc) · 3.24 KB
/
forcing_tool_use.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
from __future__ import annotations
import asyncio
from typing import Any, Literal
from pydantic import BaseModel
from agents import (
Agent,
FunctionToolResult,
ModelSettings,
RunContextWrapper,
Runner,
ToolsToFinalOutputFunction,
ToolsToFinalOutputResult,
function_tool,
)
"""
This example shows how to force the agent to use a tool. It uses `ModelSettings(tool_choice="required")`
to force the agent to use any tool.
You can run it with 3 options:
1. `default`: The default behavior, which is to send the tool output to the LLM. In this case,
`tool_choice` is not set, because otherwise it would result in an infinite loop - the LLM would
call the tool, the tool would run and send the results to the LLM, and that would repeat
(because the model is forced to use a tool every time.)
2. `first_tool_result`: The first tool result is used as the final output.
3. `custom`: A custom tool use behavior function is used. The custom function receives all the tool
results, and chooses to use the first tool result to generate the final output.
Usage:
python examples/agent_patterns/forcing_tool_use.py -t default
python examples/agent_patterns/forcing_tool_use.py -t first_tool
python examples/agent_patterns/forcing_tool_use.py -t custom
"""
class Weather(BaseModel):
city: str
temperature_range: str
conditions: str
@function_tool
def get_weather(city: str) -> Weather:
print("[debug] get_weather called")
return Weather(city=city, temperature_range="14-20C", conditions="Sunny with wind")
async def custom_tool_use_behavior(
context: RunContextWrapper[Any], results: list[FunctionToolResult]
) -> ToolsToFinalOutputResult:
weather: Weather = results[0].output
return ToolsToFinalOutputResult(
is_final_output=True, final_output=f"{weather.city} is {weather.conditions}."
)
async def main(tool_use_behavior: Literal["default", "first_tool", "custom"] = "default"):
if tool_use_behavior == "default":
behavior: Literal["run_llm_again", "stop_on_first_tool"] | ToolsToFinalOutputFunction = (
"run_llm_again"
)
elif tool_use_behavior == "first_tool":
behavior = "stop_on_first_tool"
elif tool_use_behavior == "custom":
behavior = custom_tool_use_behavior
agent = Agent(
name="Weather agent",
instructions="You are a helpful agent.",
tools=[get_weather],
tool_use_behavior=behavior,
model_settings=ModelSettings(
tool_choice="required" if tool_use_behavior != "default" else None
),
)
result = await Runner.run(agent, input="What's the weather in Tokyo?")
print(result.final_output)
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-t",
"--tool-use-behavior",
type=str,
required=True,
choices=["default", "first_tool", "custom"],
help="The behavior to use for tool use. Default will cause tool outputs to be sent to the model. "
"first_tool_result will cause the first tool result to be used as the final output. "
"custom will use a custom tool use behavior function.",
)
args = parser.parse_args()
asyncio.run(main(args.tool_use_behavior))