101 lines
2.7 KiB
Python
Executable File
101 lines
2.7 KiB
Python
Executable File
"""
|
|
Base Tool Class
|
|
All tools inherit from this class.
|
|
"""
|
|
from abc import ABC, abstractmethod
|
|
from typing import Dict, Any, Optional
|
|
from pydantic import BaseModel
|
|
from loguru import logger
|
|
|
|
|
|
class ToolResult:
|
|
"""Result from a tool execution."""
|
|
|
|
def __init__(
|
|
self,
|
|
success: bool,
|
|
data: Any = None,
|
|
error: Optional[str] = None
|
|
):
|
|
self.success = success
|
|
self.data = data
|
|
self.error = error
|
|
|
|
def to_string(self) -> str:
|
|
"""Convert result to string for LLM consumption."""
|
|
if self.success:
|
|
if isinstance(self.data, str):
|
|
return self.data
|
|
elif isinstance(self.data, dict):
|
|
return str(self.data)
|
|
else:
|
|
return str(self.data)
|
|
else:
|
|
return f"Error: {self.error}"
|
|
|
|
|
|
class BaseTool(ABC):
|
|
"""
|
|
Abstract base class for all tools.
|
|
|
|
Each tool must implement:
|
|
- name: The tool's identifier
|
|
- description: What the tool does
|
|
- parameters: JSON schema for parameters
|
|
- execute: The actual tool logic
|
|
"""
|
|
|
|
def __init__(self, config: Optional[Dict] = None):
|
|
self.config = config or {}
|
|
self._validate_config()
|
|
|
|
@property
|
|
@abstractmethod
|
|
def name(self) -> str:
|
|
"""Tool name used in function calls."""
|
|
pass
|
|
|
|
@property
|
|
@abstractmethod
|
|
def description(self) -> str:
|
|
"""Tool description shown to the LLM."""
|
|
pass
|
|
|
|
@property
|
|
@abstractmethod
|
|
def parameters(self) -> Dict[str, Any]:
|
|
"""JSON schema for tool parameters."""
|
|
pass
|
|
|
|
def get_definition(self) -> Dict[str, Any]:
|
|
"""Get the OpenAI-style tool definition."""
|
|
return {
|
|
"type": "function",
|
|
"function": {
|
|
"name": self.name,
|
|
"description": self.description,
|
|
"parameters": self.parameters,
|
|
}
|
|
}
|
|
|
|
@abstractmethod
|
|
async def execute(self, **kwargs) -> ToolResult:
|
|
"""Execute the tool with given parameters."""
|
|
pass
|
|
|
|
def _validate_config(self) -> None:
|
|
"""Validate tool configuration. Override in subclasses."""
|
|
pass
|
|
|
|
def _log_execution(self, kwargs: Dict) -> None:
|
|
"""Log tool execution."""
|
|
logger.info(f"Executing tool: {self.name} with args: {kwargs}")
|
|
|
|
def _log_success(self, result: Any) -> None:
|
|
"""Log successful execution."""
|
|
logger.debug(f"Tool {self.name} completed successfully")
|
|
|
|
def _log_error(self, error: str) -> None:
|
|
"""Log execution error."""
|
|
logger.error(f"Tool {self.name} failed: {error}")
|