wip: add tools to agent control and improve tool class
This commit is contained in:
1 parent
6134c026a6
commit
9585008433
7 files changed
+144
-13
No files matched your search
+74
-8
@@ -1,3 +1,6 @@
|
||||
import inspect
|
||||
from typing import get_type_hints
|
||||
|
||||
class ToolParameter:
|
||||
"""Describes a single input parameter for a tool.
|
||||
|
||||
@@ -55,6 +58,14 @@ class ToolSpec:
|
||||
self.description = description
|
||||
self.parameters = parameters or []
|
||||
self.func = func
|
||||
|
||||
def clone (self):
|
||||
return ToolSpec(
|
||||
name = self.name,
|
||||
description = self.description,
|
||||
parameters = self.parameters,
|
||||
func = self.func,
|
||||
)
|
||||
|
||||
# -- serialization helpers -------------------------------------------
|
||||
|
||||
@@ -119,26 +130,81 @@ class Tool:
|
||||
"""Base class for tools that implement their logic in a 'run' method.
|
||||
|
||||
Subclasses should override 'run' to provide the tool's functionality.
|
||||
|
||||
The Tool class provides a method to_spec() that automatically generates
|
||||
a ToolSpec from the class name, docstring, and run method signature.
|
||||
This allows tools to be used with LLM function calling without manually
|
||||
creating ToolSpec objects. The generated ToolSpec is cached at initialization.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
def __init__(self, name=None):
|
||||
# Generate and cache the ToolSpec during initialization
|
||||
self.name = name or self.__class__.tool_name()
|
||||
self._spec = self._generate_spec()
|
||||
|
||||
def run(self, **kwargs):
|
||||
"""Execute the tool. To be overridden by subclasses."""
|
||||
raise NotImplementedError("Tool subclasses must override the 'run' method.")
|
||||
|
||||
@classmethod
|
||||
def tool_name(cls):
|
||||
return ''.join(['_'+c.lower() if c.isupper() else c for c in cls.__name__]).lstrip('_')
|
||||
|
||||
def to_spec(self):
|
||||
"""Generate a ToolSpec from this tool instance."""
|
||||
|
||||
def _generate_spec(self):
|
||||
"""Generate a ToolSpec from this tool instance.
|
||||
|
||||
Automatically creates a ToolSpec by:
|
||||
- Using the class name (converted to snake_case) as the tool name
|
||||
- Using the class docstring as the description
|
||||
- Inspecting the run method signature to create parameters
|
||||
"""
|
||||
|
||||
# Use the class docstring as the description
|
||||
description = inspect.getdoc(self.__class__) or ""
|
||||
|
||||
# Get parameters from the run method signature
|
||||
parameters = []
|
||||
run_signature = inspect.signature(self.run)
|
||||
type_hints = get_type_hints(self.run)
|
||||
|
||||
for param_name, param in run_signature.parameters.items():
|
||||
# Skip 'self' parameter
|
||||
if param_name == 'self':
|
||||
continue
|
||||
|
||||
# Get type information
|
||||
param_type = type_hints.get(param_name, "string")
|
||||
if isinstance(param_type, type):
|
||||
type_name = param_type.__name__.lower()
|
||||
else:
|
||||
type_name = str(param_type).lower()
|
||||
|
||||
# Check if parameter is required (no default or default is None)
|
||||
is_required = param.default is inspect.Parameter.empty or param.default is None
|
||||
|
||||
# Create ToolParameter
|
||||
tool_param = ToolParameter(
|
||||
name=param_name,
|
||||
type=type_name,
|
||||
description="",
|
||||
required=is_required
|
||||
)
|
||||
parameters.append(tool_param)
|
||||
|
||||
return ToolSpec(
|
||||
name=None, # TODO: Computed from class name, or from class attribute
|
||||
description=None, # TODO: From class doc comment
|
||||
parameters=None, # TODO: Class attribute
|
||||
name=self.name,
|
||||
description=description,
|
||||
parameters=parameters,
|
||||
func=self.run,
|
||||
)
|
||||
|
||||
def get_spec(self):
|
||||
"""Return the cached ToolSpec for this tool."""
|
||||
return self._spec
|
||||
|
||||
def __repr__(self):
|
||||
return f"Tool(name={self.name!r}, params={[p.name for p in self.parameters]})"
|
||||
return f"Tool(name={self._spec.name!r}, params={[p.name for p in self._spec.parameters]})"
|
||||
|
||||
class ToolCall:
|
||||
"""Represents a single tool invocation request emitted by the model.
|
||||
|
||||
Reference in new issue
Block a user