forked from openai/openai-agents-python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_function_tool_decorator.py
144 lines (98 loc) · 4.01 KB
/
test_function_tool_decorator.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
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
import asyncio
import json
from typing import Any
import pytest
from agents import function_tool
from agents.run_context import RunContextWrapper
class DummyContext:
def __init__(self):
self.data = "something"
def ctx_wrapper() -> RunContextWrapper[DummyContext]:
return RunContextWrapper(DummyContext())
@function_tool
def sync_no_context_no_args() -> str:
return "test_1"
@pytest.mark.asyncio
async def test_sync_no_context_no_args_invocation():
tool = sync_no_context_no_args
output = await tool.on_invoke_tool(ctx_wrapper(), "")
assert output == "test_1"
@function_tool
def sync_no_context_with_args(a: int, b: int) -> int:
return a + b
@pytest.mark.asyncio
async def test_sync_no_context_with_args_invocation():
tool = sync_no_context_with_args
input_data = {"a": 5, "b": 7}
output = await tool.on_invoke_tool(ctx_wrapper(), json.dumps(input_data))
assert int(output) == 12
@function_tool
def sync_with_context(ctx: RunContextWrapper[DummyContext], name: str) -> str:
return f"{name}_{ctx.context.data}"
@pytest.mark.asyncio
async def test_sync_with_context_invocation():
tool = sync_with_context
input_data = {"name": "Alice"}
output = await tool.on_invoke_tool(ctx_wrapper(), json.dumps(input_data))
assert output == "Alice_something"
@function_tool
async def async_no_context(a: int, b: int) -> int:
await asyncio.sleep(0) # Just to illustrate async
return a * b
@pytest.mark.asyncio
async def test_async_no_context_invocation():
tool = async_no_context
input_data = {"a": 3, "b": 4}
output = await tool.on_invoke_tool(ctx_wrapper(), json.dumps(input_data))
assert int(output) == 12
@function_tool
async def async_with_context(ctx: RunContextWrapper[DummyContext], prefix: str, num: int) -> str:
await asyncio.sleep(0)
return f"{prefix}-{num}-{ctx.context.data}"
@pytest.mark.asyncio
async def test_async_with_context_invocation():
tool = async_with_context
input_data = {"prefix": "Value", "num": 42}
output = await tool.on_invoke_tool(ctx_wrapper(), json.dumps(input_data))
assert output == "Value-42-something"
@function_tool(name_override="my_custom_tool", description_override="custom desc")
def sync_no_context_override() -> str:
return "override_result"
@pytest.mark.asyncio
async def test_sync_no_context_override_invocation():
tool = sync_no_context_override
assert tool.name == "my_custom_tool"
assert tool.description == "custom desc"
output = await tool.on_invoke_tool(ctx_wrapper(), "")
assert output == "override_result"
@function_tool(failure_error_function=None)
def will_fail_on_bad_json(x: int) -> int:
return x * 2 # pragma: no cover
@pytest.mark.asyncio
async def test_error_on_invalid_json():
tool = will_fail_on_bad_json
# Passing an invalid JSON string
with pytest.raises(Exception) as exc_info:
await tool.on_invoke_tool(ctx_wrapper(), "{not valid json}")
assert "Invalid JSON input for tool" in str(exc_info.value)
def sync_error_handler(ctx: RunContextWrapper[Any], error: Exception) -> str:
return f"error_{error.__class__.__name__}"
@function_tool(failure_error_function=sync_error_handler)
def will_not_fail_on_bad_json(x: int) -> int:
return x * 2 # pragma: no cover
@pytest.mark.asyncio
async def test_no_error_on_invalid_json():
tool = will_not_fail_on_bad_json
# Passing an invalid JSON string
result = await tool.on_invoke_tool(ctx_wrapper(), "{not valid json}")
assert result == "error_ModelBehaviorError"
def async_error_handler(ctx: RunContextWrapper[Any], error: Exception) -> str:
return f"error_{error.__class__.__name__}"
@function_tool(failure_error_function=sync_error_handler)
def will_not_fail_on_bad_json_async(x: int) -> int:
return x * 2 # pragma: no cover
@pytest.mark.asyncio
async def test_no_error_on_invalid_json_async():
tool = will_not_fail_on_bad_json_async
result = await tool.on_invoke_tool(ctx_wrapper(), "{not valid json}")
assert result == "error_ModelBehaviorError"