-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtool_data.py
More file actions
145 lines (122 loc) · 5.4 KB
/
tool_data.py
File metadata and controls
145 lines (122 loc) · 5.4 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
import inspect
from dataclasses import dataclass, field
from typing import get_type_hints, List, Callable, Dict, Any
tools = {}
tools_by_tag = {}
def to_openai_tools(tools_metadata: List[dict]):
openai_tools = [
{
"type": "function",
"function": {
"name": t['tool_name'],
# Include up to 1024 characters of the description
"description": t.get('description',"")[:1024],
"parameters": t.get('parameters',{}),
},
} for t in tools_metadata
]
return openai_tools
def get_tool_metadata(func, tool_name=None, description=None, parameters_override=None, terminal=False, tags=None):
"""
Extracts metadata for a function to use in tool registration.
Parameters:
func (function): The function to extract metadata from.
tool_name (str, optional): The name of the tool. Defaults to the function name.
description (str, optional): Description of the tool. Defaults to the function's docstring.
parameters_override (dict, optional): Override for the argument schema. Defaults to dynamically inferred schema.
terminal (bool, optional): Whether the tool is terminal. Defaults to False.
tags (List[str], optional): List of tags to associate with the tool.
Returns:
dict: A dictionary containing metadata about the tool, including description, args schema, and the function.
"""
# Default tool_name to the function name if not provided
tool_name = tool_name or func.__name__
# Default description to the function's docstring if not provided
description = description or (func.__doc__.strip() if func.__doc__ else "No description provided.")
# Discover the function's signature and type hints if no args_override is provided
if parameters_override is None:
signature = inspect.signature(func)
type_hints = get_type_hints(func)
# Build the arguments schema dynamically
args_schema = {
"type": "object",
"properties": {},
"required": []
}
for param_name, param in signature.parameters.items():
if param_name in ["action_context", "action_agent"]:
continue # Skip these parameters
def get_json_type(param_type):
if param_type == str:
return "string"
elif param_type == int:
return "integer"
elif param_type == float:
return "number"
elif param_type == bool:
return "boolean"
elif param_type == list:
return "array"
elif param_type == dict:
return "object"
else:
return "string"
# Add parameter details
param_type = type_hints.get(param_name, str) # Default to string if type is not annotated
param_schema = {"type": get_json_type(param_type)} # Convert Python types to JSON schema types
args_schema["properties"][param_name] = param_schema
# Add to required if not defaulted
if param.default == inspect.Parameter.empty:
args_schema["required"].append(param_name)
else:
args_schema = parameters_override
# Return the metadata as a dictionary
return {
"tool_name": tool_name,
"description": description,
"parameters": args_schema,
"function": func,
"terminal": terminal,
"tags": tags or []
}
def register_tool(tool_name=None, description=None, parameters_override=None, terminal=False, tags=None):
"""
A decorator to dynamically register a function in the tools dictionary with its parameters, schema, and docstring.
Parameters:
tool_name (str, optional): The name of the tool to register. Defaults to the function name.
description (str, optional): Override for the tool's description. Defaults to the function's docstring.
parameters_override (dict, optional): Override for the argument schema. Defaults to dynamically inferred schema.
terminal (bool, optional): Whether the tool is terminal. Defaults to False.
tags (List[str], optional): List of tags to associate with the tool.
Returns:
function: The wrapped function.
"""
def decorator(func):
# Use the reusable function to extract metadata
metadata = get_tool_metadata(
func=func,
tool_name=tool_name,
description=description,
parameters_override=parameters_override,
terminal=terminal,
tags=tags
)
# Register the tool in the global dictionary
tools[metadata["tool_name"]] = {
"description": metadata["description"],
"parameters": metadata["parameters"],
"function": metadata["function"],
"terminal": metadata["terminal"],
"tags": metadata["tags"] or []
}
for tag in metadata["tags"]:
if tag not in tools_by_tag:
tools_by_tag[tag] = []
tools_by_tag[tag].append(metadata["tool_name"])
return func
return decorator
@dataclass
class Prompt:
messages: List[Dict] = field(default_factory=list)
tools: List[Dict] = field(default_factory=list)
metadata: dict = field(default_factory=dict)