toolregistry 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Peng Ding
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,104 @@
1
+ Metadata-Version: 2.2
2
+ Name: toolregistry
3
+ Version: 0.2.0
4
+ Summary: A library for managing tool registries
5
+ Home-page: https://github.com/Oaklight/ToolRegistry
6
+ Author: Oaklight
7
+ Author-email: oaklight@gmx.com
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: pydantic>=1.5.1
21
+ Dynamic: author
22
+ Dynamic: author-email
23
+ Dynamic: classifier
24
+ Dynamic: description
25
+ Dynamic: description-content-type
26
+ Dynamic: home-page
27
+ Dynamic: requires-dist
28
+ Dynamic: requires-python
29
+ Dynamic: summary
30
+
31
+ # ToolRegistry
32
+
33
+ A Python library for managing and executing tools in a structured way.
34
+
35
+ ## Features
36
+
37
+ - Tool registration and management
38
+ - JSON Schema generation for tool parameters
39
+ - Tool execution and result handling
40
+ - Support for both synchronous and asynchronous tools
41
+
42
+ ## Installation
43
+
44
+ ```bash
45
+ pip install toolregistry
46
+ ```
47
+
48
+ ## Usage
49
+
50
+ ## Examples
51
+
52
+ ### OpenAI Implementation
53
+
54
+ The [openai_tool_usage_example.py](example/openai_tool_usage_example.py) shows how to integrate ToolRegistry with OpenAI's API.
55
+
56
+ ### Cicada Implementation
57
+
58
+ The [cicada_tool_usage_example.py](example/cicada_tool_usage_example.py) demonstrates how to use ToolRegistry with the Cicada MultiModalModel.
59
+
60
+ ## OpenAI Integration
61
+
62
+ The ToolRegistry integrates seamlessly with OpenAI's API. Here are some common usage patterns:
63
+
64
+ ### Getting Tools JSON for OpenAI
65
+
66
+ ```python
67
+ tools_json = registry.get_tools_json()
68
+ # Use this with OpenAI's API to provide available tools
69
+ ```
70
+
71
+ ### Executing Tool Calls
72
+
73
+ ```python
74
+ # Assuming tool_calls is received from OpenAI's API
75
+ tool_responses = registry.execute_tool_calls(tool_calls)
76
+ ```
77
+
78
+ ### Recovering Assistant Messages
79
+
80
+ ```python
81
+ # After executing tool calls
82
+ messages = registry.recover_tool_call_assistant_message(tool_calls, tool_responses)
83
+ # Use these messages to continue the conversation
84
+ ```
85
+
86
+ ### Manual Tool Execution
87
+
88
+ ```python
89
+ # Get a callable function
90
+ add_fn = registry.get_callable("add")
91
+ result = add_fn(a=1, b=2) # Output: 3
92
+ ```
93
+
94
+ ## Documentation
95
+
96
+ Full documentation is available at [https://github.com/Oaklight/ToolRegistry](https://github.com/Oaklight/ToolRegistry)
97
+
98
+ ## Contributing
99
+
100
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.
101
+
102
+ ## License
103
+
104
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,74 @@
1
+ # ToolRegistry
2
+
3
+ A Python library for managing and executing tools in a structured way.
4
+
5
+ ## Features
6
+
7
+ - Tool registration and management
8
+ - JSON Schema generation for tool parameters
9
+ - Tool execution and result handling
10
+ - Support for both synchronous and asynchronous tools
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pip install toolregistry
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ## Examples
21
+
22
+ ### OpenAI Implementation
23
+
24
+ The [openai_tool_usage_example.py](example/openai_tool_usage_example.py) shows how to integrate ToolRegistry with OpenAI's API.
25
+
26
+ ### Cicada Implementation
27
+
28
+ The [cicada_tool_usage_example.py](example/cicada_tool_usage_example.py) demonstrates how to use ToolRegistry with the Cicada MultiModalModel.
29
+
30
+ ## OpenAI Integration
31
+
32
+ The ToolRegistry integrates seamlessly with OpenAI's API. Here are some common usage patterns:
33
+
34
+ ### Getting Tools JSON for OpenAI
35
+
36
+ ```python
37
+ tools_json = registry.get_tools_json()
38
+ # Use this with OpenAI's API to provide available tools
39
+ ```
40
+
41
+ ### Executing Tool Calls
42
+
43
+ ```python
44
+ # Assuming tool_calls is received from OpenAI's API
45
+ tool_responses = registry.execute_tool_calls(tool_calls)
46
+ ```
47
+
48
+ ### Recovering Assistant Messages
49
+
50
+ ```python
51
+ # After executing tool calls
52
+ messages = registry.recover_tool_call_assistant_message(tool_calls, tool_responses)
53
+ # Use these messages to continue the conversation
54
+ ```
55
+
56
+ ### Manual Tool Execution
57
+
58
+ ```python
59
+ # Get a callable function
60
+ add_fn = registry.get_callable("add")
61
+ result = add_fn(a=1, b=2) # Output: 3
62
+ ```
63
+
64
+ ## Documentation
65
+
66
+ Full documentation is available at [https://github.com/Oaklight/ToolRegistry](https://github.com/Oaklight/ToolRegistry)
67
+
68
+ ## Contributing
69
+
70
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.
71
+
72
+ ## License
73
+
74
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,32 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ with open("README.md", "r", encoding="utf-8") as fh:
4
+ long_description = fh.read()
5
+
6
+ setup(
7
+ name="toolregistry",
8
+ version="0.2.0",
9
+ description="A library for managing tool registries",
10
+ long_description=long_description,
11
+ long_description_content_type="text/markdown",
12
+ author="Oaklight",
13
+ author_email="oaklight@gmx.com",
14
+ url="https://github.com/Oaklight/ToolRegistry",
15
+ packages=find_packages(where="src"),
16
+ package_dir={"": "src"},
17
+ install_requires=[
18
+ "pydantic>=1.5.1",
19
+ ],
20
+ python_requires=">=3.8",
21
+ classifiers=[
22
+ "Development Status :: 3 - Alpha",
23
+ "Intended Audience :: Developers",
24
+ "License :: OSI Approved :: MIT License",
25
+ "Programming Language :: Python :: 3",
26
+ "Programming Language :: Python :: 3.8",
27
+ "Programming Language :: Python :: 3.9",
28
+ "Programming Language :: Python :: 3.10",
29
+ "Programming Language :: Python :: 3.11",
30
+ "Topic :: Software Development :: Libraries :: Python Modules",
31
+ ],
32
+ )
@@ -0,0 +1,3 @@
1
+ from .tool_registry import *
2
+
3
+ __all__ = ["ToolRegistry", "Tool"]
@@ -0,0 +1,272 @@
1
+ import inspect
2
+ import json
3
+ from typing import Any, Callable, Dict, List, Optional
4
+
5
+ from pydantic import BaseModel
6
+
7
+
8
+ class Tool(BaseModel):
9
+ """
10
+ Represents a tool (function) that can be called by the language model.
11
+ """
12
+
13
+ name: str
14
+ description: str
15
+ parameters: Dict[str, Any]
16
+ callable: Callable
17
+
18
+
19
+ class ToolRegistry:
20
+ """
21
+ A registry for managing tools (functions) and their metadata.
22
+ """
23
+
24
+ def __init__(self):
25
+ self._tools: Dict[str, Tool] = {}
26
+
27
+ def __len__(self):
28
+ return len(self._tools)
29
+
30
+ def __contains__(self, name: str) -> bool:
31
+ """
32
+ Check if a tool with the given name is registered.
33
+ """
34
+ return name in self._tools
35
+
36
+ def register(self, func: Callable, description: Optional[str] = None):
37
+ """
38
+ Register a function as a tool.
39
+
40
+ Args:
41
+ func (Callable): The function to register.
42
+ description (str, optional): A description of the function. If not provided,
43
+ the function's docstring will be used.
44
+ """
45
+ # Generate the function's JSON schema based on its signature
46
+ parameters = self._generate_parameters_schema(func)
47
+ name = func.__name__
48
+ description = description or func.__doc__ or "No description provided."
49
+
50
+ # Create a Tool instance
51
+ tool = Tool(
52
+ name=name,
53
+ description=description,
54
+ parameters=parameters,
55
+ callable=func,
56
+ )
57
+
58
+ # Add the tool to the registry
59
+ self._tools[name] = tool
60
+
61
+ def merge(self, other: "ToolRegistry", keep_existing: bool = False):
62
+ """
63
+ Merge tools from another ToolRegistry into this one.
64
+
65
+ Args:
66
+ other (ToolRegistry): The other ToolRegistry to merge into this one.
67
+ """
68
+ if not isinstance(other, ToolRegistry):
69
+ raise TypeError("Can only merge with another ToolRegistry instance.")
70
+
71
+ if keep_existing:
72
+ for name, tool in other._tools.items():
73
+ if name not in self._tools:
74
+ self._tools[name] = tool
75
+ else:
76
+ self._tools.update(other._tools)
77
+
78
+ def _generate_parameters_schema(self, func: Callable) -> Dict[str, Any]:
79
+ """
80
+ Generate a JSON Schema-compliant schema for the function's parameters.
81
+
82
+ Args:
83
+ func (Callable): The function to generate the schema for.
84
+
85
+ Returns:
86
+ Dict[str, Any]: The JSON Schema for the function's parameters.
87
+ """
88
+ signature = inspect.signature(func)
89
+ properties = {}
90
+ required = []
91
+
92
+ for name, param in signature.parameters.items():
93
+ if name == "self":
94
+ continue # Skip 'self' for methods
95
+
96
+ # Map Python types to JSON Schema types
97
+ param_type = (
98
+ self._map_python_type_to_json_schema(param.annotation)
99
+ if param.annotation != inspect.Parameter.empty
100
+ else "string"
101
+ )
102
+
103
+ # Add the parameter to the properties
104
+ properties[name] = {
105
+ "type": param_type,
106
+ "description": f"The {name} parameter.",
107
+ }
108
+
109
+ # Check if the parameter is required
110
+ if param.default == inspect.Parameter.empty:
111
+ required.append(name)
112
+
113
+ return {
114
+ "type": "object",
115
+ "properties": properties,
116
+ "required": required,
117
+ "additionalProperties": False, # Enforce strict parameter validation
118
+ }
119
+
120
+ def _map_python_type_to_json_schema(self, python_type: Any) -> str:
121
+ """
122
+ Map Python types to JSON Schema types.
123
+
124
+ Args:
125
+ python_type (Any): The Python type to map.
126
+
127
+ Returns:
128
+ str: The corresponding JSON Schema type.
129
+ """
130
+ type_mapping = {
131
+ "str": "string",
132
+ "int": "integer",
133
+ "float": "number",
134
+ "bool": "boolean",
135
+ "list": "array",
136
+ "dict": "object",
137
+ }
138
+
139
+ # Handle cases where the type is a class (e.g., `int`, `str`)
140
+ if hasattr(python_type, "__name__"):
141
+ return type_mapping.get(python_type.__name__, "string")
142
+
143
+ # Default to "string" if the type is not recognized
144
+ return "string"
145
+
146
+ def get_tools_json(self) -> List[Dict[str, Any]]:
147
+ """
148
+ Get the JSON representation of all registered tools, following JSON Schema.
149
+
150
+ Returns:
151
+ List[Dict[str, Any]]: A list of tools in JSON format, compliant with JSON Schema.
152
+ """
153
+ return [
154
+ {
155
+ "type": "function",
156
+ "function": {
157
+ "name": tool.name,
158
+ "description": tool.description,
159
+ "parameters": tool.parameters,
160
+ },
161
+ }
162
+ for tool in self._tools.values()
163
+ ]
164
+
165
+ def get_callable(self, function_name: str) -> Callable:
166
+ """
167
+ Get a callable function by its name.
168
+
169
+ Args:
170
+ function_name (str): The name of the function.
171
+
172
+ Returns:
173
+ Callable: The function to call, or None if not found.
174
+ """
175
+ tool = self._tools.get(function_name)
176
+ return tool.callable if tool else None
177
+
178
+ def execute_tool_calls(self, tool_calls: List[Any]) -> Dict[str, str]:
179
+ """
180
+ Execute tool calls and return results.
181
+
182
+ Args:
183
+ tool_calls (List[Any]): List of tool calls
184
+
185
+ Returns:
186
+ Dict[str, str]: Dictionary mapping tool call IDs to results
187
+ """
188
+ tool_responses = {}
189
+ for tool_call in tool_calls:
190
+ tool_result = None
191
+ try:
192
+ function_name = tool_call.function.name
193
+ function_args = json.loads(tool_call.function.arguments)
194
+ tool_call_id = tool_call.id
195
+
196
+ # Get the tool from registry
197
+ tool = self.get_callable(function_name)
198
+ if tool:
199
+ function_response = tool(**function_args)
200
+ tool_result = f"{function_name} -> {function_response}"
201
+ else:
202
+ tool_result = f"Error: Tool '{function_name}' not found"
203
+ except Exception as e:
204
+ tool_result = f"Error executing {function_name}: {str(e)}"
205
+
206
+ tool_responses[tool_call_id] = tool_result
207
+
208
+ return tool_responses
209
+
210
+ def recover_tool_call_assistant_message(
211
+ self, tool_calls: List[Any], tool_responses: Dict[str, str]
212
+ ) -> List[Dict[str, Any]]:
213
+ """
214
+ Construct assistant messages with tool call results.
215
+
216
+ Args:
217
+ tool_calls (List[Any]): List of tool calls
218
+ tool_responses (Dict[str, str]): Tool execution results
219
+
220
+ Returns:
221
+ List[Dict[str, Any]]: List of message dictionaries
222
+ """
223
+ messages = []
224
+ for tool_call in tool_calls:
225
+ messages.append(
226
+ {
227
+ "role": "assistant",
228
+ "content": None,
229
+ "tool_calls": [
230
+ {
231
+ "id": tool_call.id,
232
+ "type": "function",
233
+ "function": {
234
+ "name": tool_call.function.name,
235
+ "arguments": tool_call.function.arguments,
236
+ },
237
+ }
238
+ ],
239
+ }
240
+ )
241
+ messages.append(
242
+ {
243
+ "role": "tool",
244
+ "content": tool_responses[tool_call.id],
245
+ "tool_call_id": tool_call.id,
246
+ }
247
+ )
248
+ return messages
249
+
250
+ def __repr__(self):
251
+ """
252
+ Return the JSON representation of the registry for debugging purposes.
253
+ """
254
+ return json.dumps(self.get_tools_json(), indent=2)
255
+
256
+ def __str__(self):
257
+ """
258
+ Return the JSON representation of the registry as a string.
259
+ """
260
+ return json.dumps(self.get_tools_json(), indent=2)
261
+
262
+ def __getitem__(self, key: str) -> Callable:
263
+ """
264
+ Enable key-value access to retrieve callables.
265
+
266
+ Args:
267
+ key (str): The name of the function.
268
+
269
+ Returns:
270
+ Callable: The function to call, or None if not found.
271
+ """
272
+ return self.get_callable(key)
@@ -0,0 +1,104 @@
1
+ Metadata-Version: 2.2
2
+ Name: toolregistry
3
+ Version: 0.2.0
4
+ Summary: A library for managing tool registries
5
+ Home-page: https://github.com/Oaklight/ToolRegistry
6
+ Author: Oaklight
7
+ Author-email: oaklight@gmx.com
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: pydantic>=1.5.1
21
+ Dynamic: author
22
+ Dynamic: author-email
23
+ Dynamic: classifier
24
+ Dynamic: description
25
+ Dynamic: description-content-type
26
+ Dynamic: home-page
27
+ Dynamic: requires-dist
28
+ Dynamic: requires-python
29
+ Dynamic: summary
30
+
31
+ # ToolRegistry
32
+
33
+ A Python library for managing and executing tools in a structured way.
34
+
35
+ ## Features
36
+
37
+ - Tool registration and management
38
+ - JSON Schema generation for tool parameters
39
+ - Tool execution and result handling
40
+ - Support for both synchronous and asynchronous tools
41
+
42
+ ## Installation
43
+
44
+ ```bash
45
+ pip install toolregistry
46
+ ```
47
+
48
+ ## Usage
49
+
50
+ ## Examples
51
+
52
+ ### OpenAI Implementation
53
+
54
+ The [openai_tool_usage_example.py](example/openai_tool_usage_example.py) shows how to integrate ToolRegistry with OpenAI's API.
55
+
56
+ ### Cicada Implementation
57
+
58
+ The [cicada_tool_usage_example.py](example/cicada_tool_usage_example.py) demonstrates how to use ToolRegistry with the Cicada MultiModalModel.
59
+
60
+ ## OpenAI Integration
61
+
62
+ The ToolRegistry integrates seamlessly with OpenAI's API. Here are some common usage patterns:
63
+
64
+ ### Getting Tools JSON for OpenAI
65
+
66
+ ```python
67
+ tools_json = registry.get_tools_json()
68
+ # Use this with OpenAI's API to provide available tools
69
+ ```
70
+
71
+ ### Executing Tool Calls
72
+
73
+ ```python
74
+ # Assuming tool_calls is received from OpenAI's API
75
+ tool_responses = registry.execute_tool_calls(tool_calls)
76
+ ```
77
+
78
+ ### Recovering Assistant Messages
79
+
80
+ ```python
81
+ # After executing tool calls
82
+ messages = registry.recover_tool_call_assistant_message(tool_calls, tool_responses)
83
+ # Use these messages to continue the conversation
84
+ ```
85
+
86
+ ### Manual Tool Execution
87
+
88
+ ```python
89
+ # Get a callable function
90
+ add_fn = registry.get_callable("add")
91
+ result = add_fn(a=1, b=2) # Output: 3
92
+ ```
93
+
94
+ ## Documentation
95
+
96
+ Full documentation is available at [https://github.com/Oaklight/ToolRegistry](https://github.com/Oaklight/ToolRegistry)
97
+
98
+ ## Contributing
99
+
100
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.
101
+
102
+ ## License
103
+
104
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ README.md
3
+ setup.py
4
+ src/toolregistry/__init__.py
5
+ src/toolregistry/tool_registry.py
6
+ src/toolregistry.egg-info/PKG-INFO
7
+ src/toolregistry.egg-info/SOURCES.txt
8
+ src/toolregistry.egg-info/dependency_links.txt
9
+ src/toolregistry.egg-info/requires.txt
10
+ src/toolregistry.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ pydantic>=1.5.1
@@ -0,0 +1 @@
1
+ toolregistry