-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcall_function.py
More file actions
158 lines (142 loc) · 4.95 KB
/
call_function.py
File metadata and controls
158 lines (142 loc) · 4.95 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
import json
from functions.get_files_info import get_files_info
from functions.get_file_content import get_file_content
from functions.write_file import write_file
from functions.run_python_file import run_python_file
# Mapping function names to implementation
function_map = {
"get_files_info": get_files_info,
"get_file_content": get_file_content,
"write_file": write_file,
"run_python_file": run_python_file,
}
# OpenAI Tool Definitions
tools_get_files_info = {
"type": "function",
"function": {
"name": "get_files_info",
"description": "Lists files in a specified directory relative to the working directory, providing file size and directory status",
"parameters": {
"type": "object",
"properties": {
"directory": {
"type": "string",
"description": "Directory path to list files from, relative to the working directory (default is the working directory itself)",
},
},
},
},
}
tools_get_file_content = {
"type": "function",
"function": {
"name": "get_file_content",
"description": "Reads the content of a file within the permitted working_directory, truncating it if it exceeds MAX_CHARS",
"parameters": {
"type": "object",
"properties": {
"file_path": {
"type": "string",
"description": "The path to the file to read, relative to the working directory",
},
},
"required": ["file_path"],
},
},
}
tools_write_file = {
"type": "function",
"function": {
"name": "write_file",
"description": "Writes content to a file within the permitted working_directory, creating parent directories if needed",
"parameters": {
"type": "object",
"properties": {
"file_path": {
"type": "string",
"description": "The path where the file should be written, relative to the working directory",
},
"content": {
"type": "string",
"description": "The text content to write to the file",
},
},
"required": ["file_path", "content"],
},
},
}
tools_run_python_file = {
"type": "function",
"function": {
"name": "run_python_file",
"description": "Executes a Python file within the permitted working_directory with a 30s timeout and output capture",
"parameters": {
"type": "object",
"properties": {
"file_path": {
"type": "string",
"description": "The path to the Python script to execute, relative to the working directory",
},
"args": {
"type": "array",
"items": {"type": "string"},
"description": "Optional list of command-line arguments to pass to the script",
},
},
"required": ["file_path"],
},
},
}
available_functions = [
tools_get_files_info,
tools_get_file_content,
tools_write_file,
tools_run_python_file,
]
# Classes to mimic the return structure requested by the assignment
class FunctionResponse:
def __init__(self, name, response):
self.name = name
self.response = response
class Part:
def __init__(self, function_response):
self.function_response = function_response
@classmethod
def from_function_response(cls, name, response):
return cls(FunctionResponse(name, response))
class Content:
def __init__(self, role, parts):
self.role = role
self.parts = parts
def call_function(tool_call, verbose=False):
"""
Dispatcher to execute the requested tool and return a structured response.
Injects working_directory="./calculator" for all calls.
"""
function_name = tool_call.function.name or ""
# Parse arguments
try:
raw_args = json.loads(tool_call.function.arguments)
args = dict(raw_args) if raw_args else {}
except (json.JSONDecodeError, TypeError):
args = {}
if verbose:
print(f"Calling function: {function_name}({args})")
else:
print(f" - Calling function: {function_name}")
# Inject working directory
args["working_directory"] = "./calculator"
# Execute function
if function_name in function_map:
try:
result = function_map[function_name](**args)
response_data = {"result": result}
except Exception as e:
response_data = {"error": str(e)}
else:
response_data = {"error": f"Unknown function: {function_name}"}
# Return mimicking the requested Content structure
return Content(
role="tool",
parts=[Part.from_function_response(function_name, response_data)]
)