Repository navigation
Expand file tree
/
Copy pathfunction_tool_with_max_exceptions.py
More file actions
187 lines (151 loc) · 6.54 KB
/
Copy pathfunction_tool_with_max_exceptions.py
File metadata and controls
187 lines (151 loc) · 6.54 KB
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from typing import Annotated
from agent_framework import Agent, tool
from agent_framework.openai import OpenAIChatClient
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
"""
Some tools are very expensive to run, so you may want to limit the number of times
it tries to call them and fails. This sample shows a tool that can only raise exceptions a
limited number of times.
"""
# we trick the AI into calling this function with 0 as denominator to trigger the exception
@tool(max_invocation_exceptions=1)
def safe_divide(
a: Annotated[int, "Numerator"],
b: Annotated[int, "Denominator"],
) -> str:
"""Divide two numbers can be used with 0 as denominator."""
try:
result = a / b # Will raise ZeroDivisionError
except ZeroDivisionError as exc:
print(f" Tool failed with error: {exc}")
raise
return f"{a} / {b} = {result}"
async def main():
# tools = Tools()
agent = Agent(
client=OpenAIChatClient(),
name="ToolAgent",
instructions="Use the provided tools.",
tools=[safe_divide],
)
session = agent.create_session()
print("=" * 60)
print("Step 1: Call divide(10, 0) - tool raises exception")
response = await agent.run("Divide 10 by 0", session=session)
print(f"Response: {response.text}")
print("=" * 60)
print("Step 2: Call divide(100, 0) - will refuse to execute due to max_invocation_exceptions")
response = await agent.run("Divide 100 by 0", session=session)
print(f"Response: {response.text}")
print("=" * 60)
print(f"Number of tool calls attempted: {safe_divide.invocation_count}")
print(f"Number of tool calls failed: {safe_divide.invocation_exception_count}")
# TODO: Use history providers to replay the conversation
# print("Replay the conversation:")
# for idx, msg in enumerate(messages):
# if msg.text:
# print(f"{idx + 1} {msg.author_name or msg.role}: {msg.text} ")
# for content in msg.contents:
# if content.type == "function_call":
# print(
# f"{idx + 1} {msg.author_name}: calling function: {content.name} with arguments: {content.arguments}"
# )
# if content.type == "function_result":
# print(f"{idx + 1} {msg.role}: {content.result if content.result else content.exception}")
"""
Expected Output:
============================================================
Step 1: Call divide(10, 0) - tool raises exception
Tool failed with error: division by zero
Response: Division by zero is undefined in standard arithmetic. There is no finite value for 10 ÷ 0.
If you want alternatives:
- A valid example: 10 ÷ 2 = 5.
- To handle safely in code, you can check the denominator first (e.g., in Python: if b == 0:
handle error else: compute a/b).
- If you’re curious about limits: as x → 0+, 10/x → +∞; as x → 0−, 10/x → −∞; there is no finite limit.
Would you like me to show a safe division snippet in a specific language, or compute something else?
============================================================
Step 2: Call divide(100, 0) - will refuse to execute due to max_invocations
Response: Division by zero is undefined in standard arithmetic, so 100 ÷ 0 has no finite value.
If you’re coding and want safe handling, here are quick patterns in a few languages:
- Python
def safe_divide(a, b):
if b == 0:
return None # or raise an exception
return a / b
safe_divide(100, 0) # -> None
- JavaScript
function safeDivide(a, b) {
if (b === 0) return undefined; // or throw
return a / b;
}
safeDivide(100, 0) // -> undefined
- Java
public static Double safeDivide(double a, double b) {
if (b == 0.0) throw new ArithmeticException("Divide by zero");
return a / b;
}
safeDivide(100, 0) // -> exception
- C/C++
double safeDivide(double a, double b) {
if (b == 0.0) return std::numeric_limits<double>::infinity(); // or handle error
return a / b;
}
Note: In many languages, dividing by zero with floating-point numbers yields Infinity (or -Infinity) or NaN,
but integer division typically raises an error.
Would you like a snippet in a specific language or to see a math explanation (limits) for what happens as the
divisor approaches zero?
============================================================
Number of tool calls attempted: 1
Number of tool calls failed: 1
Replay the conversation:
1 user: Divide 10 by 0
2 ToolAgent: calling function: safe_divide with arguments: {"a":10,"b":0}
3 tool: division by zero
4 ToolAgent: Division by zero is undefined in standard arithmetic. There is no finite value for 10 ÷ 0.
If you want alternatives:
- A valid example: 10 ÷ 2 = 5.
- To handle safely in code, you can check the denominator first (e.g., in Python: if b == 0:
handle error else: compute a/b).
- If you’re curious about limits: as x → 0+, 10/x → +∞; as x → 0−, 10/x → −∞; there is no finite limit.
Would you like me to show a safe division snippet in a specific language, or compute something else?
5 user: Divide 100 by 0
6 ToolAgent: calling function: safe_divide with arguments: {"a":100,"b":0}
7 tool: Function 'safe_divide' has reached its maximum exception limit, you tried to use this tool too many times
and it kept failing.
8 ToolAgent: Division by zero is undefined in standard arithmetic, so 100 ÷ 0 has no finite value.
If you’re coding and want safe handling, here are quick patterns in a few languages:
- Python
def safe_divide(a, b):
if b == 0:
return None # or raise an exception
return a / b
safe_divide(100, 0) # -> None
- JavaScript
function safeDivide(a, b) {
if (b === 0) return undefined; // or throw
return a / b;
}
safeDivide(100, 0) // -> undefined
- Java
public static Double safeDivide(double a, double b) {
if (b == 0.0) throw new ArithmeticException("Divide by zero");
return a / b;
}
safeDivide(100, 0) // -> exception
- C/C++
double safeDivide(double a, double b) {
if (b == 0.0) return std::numeric_limits<double>::infinity(); // or handle error
return a / b;
}
Note: In many languages, dividing by zero with floating-point numbers yields Infinity (or -Infinity) or NaN,
but integer division typically raises an error.
Would you like a snippet in a specific language or to see a math explanation (limits) for what happens as the
divisor approaches zero?
"""
if __name__ == "__main__":
asyncio.run(main())