import os import sys import importlib import inspect import traceback from typing import Dict, Any, List, Tuple class Initializer: def __init__(self, enabled_tools: List[str] = [], model_string: str = None, api_key: str = None): self.toolbox_metadata = {} self.available_tools = [] self.enabled_tools = enabled_tools self.model_string = model_string # llm model string self.api_key = api_key print("\nInitializing OpenTools...") print(f"Enabled tools: {self.enabled_tools}") print(f"LLM model string: {self.model_string}") self._set_up_tools() def get_project_root(self): current_dir = os.path.dirname(os.path.abspath(__file__)) while current_dir != '/': if os.path.exists(os.path.join(current_dir, 'opentools')): return os.path.join(current_dir, 'opentools') current_dir = os.path.dirname(current_dir) raise Exception("Could not find project root") def load_tools_and_get_metadata(self) -> Dict[str, Any]: # Implementation of load_tools_and_get_metadata function print("Loading tools and getting metadata...") self.toolbox_metadata = {} opentools_dir = self.get_project_root() tools_dir = os.path.join(opentools_dir, 'tools') print(f"OpenTools directory: {opentools_dir}") print(f"Tools directory: {tools_dir}") # Add the OpenTools directory and its parent to the Python path sys.path.insert(0, opentools_dir) sys.path.insert(0, os.path.dirname(opentools_dir)) print(f"Updated Python path: {sys.path}") if not os.path.exists(tools_dir): print(f"Error: Tools directory does not exist: {tools_dir}") return self.toolbox_metadata for root, dirs, files in os.walk(tools_dir): # print(f"\nScanning directory: {root}") if 'tool.py' in files and os.path.basename(root) in self.available_tools: file = 'tool.py' module_path = os.path.join(root, file) module_name = os.path.splitext(file)[0] relative_path = os.path.relpath(module_path, opentools_dir) import_path = '.'.join(os.path.split(relative_path)).replace(os.sep, '.')[:-3] print(f"\nAttempting to import: {import_path}") try: module = importlib.import_module(import_path) for name, obj in inspect.getmembers(module): if inspect.isclass(obj) and name.endswith('Tool') and name != 'BaseTool': print(f"Found tool class: {name}") # print(f"Class attributes: {dir(obj)}") # print(f"Class __dict__: {obj.__dict__}") try: # Check if the tool requires an LLM engine inputs = {} if hasattr(obj, 'require_llm_engine') and obj.require_llm_engine: inputs['model_string'] = self.model_string if hasattr(obj, 'require_api_key') and obj.require_api_key: inputs['api_key'] = self.api_key tool_instance = obj(**inputs) # print(f"\nInstance attributes: {dir(tool_instance)}") # print(f"\nInstance __dict__: {tool_instance.__dict__}") self.toolbox_metadata[name] = { 'tool_name': getattr(tool_instance, 'tool_name', 'Unknown'), 'tool_description': getattr(tool_instance, 'tool_description', 'No description'), 'tool_version': getattr(tool_instance, 'tool_version', 'Unknown'), 'input_types': getattr(tool_instance, 'input_types', {}), 'output_type': getattr(tool_instance, 'output_type', 'Unknown'), 'demo_commands': getattr(tool_instance, 'demo_commands', []), 'user_metadata': getattr(tool_instance, 'user_metadata', {}), # NOTE: This is a placeholder for user-defined metadata 'require_llm_engine': getattr(obj, 'require_llm_engine', False), } print(f"\nMetadata for {name}: {self.toolbox_metadata[name]}") except Exception as e: print(f"Error instantiating {name}: {str(e)}") except Exception as e: print(f"Error loading module {module_name}: {str(e)}") print(f"\nTotal number of tools loaded: {len(self.toolbox_metadata)}") return self.toolbox_metadata def run_demo_commands(self) -> List[str]: print("\nRunning demo commands for each tool...") self.available_tools = [] for tool_name, tool_data in self.toolbox_metadata.items(): print(f"\nChecking availability of {tool_name}...") try: # Import the tool module module_name = f"tools.{tool_name.lower().replace('_tool', '')}.tool" module = importlib.import_module(module_name) # Get the tool class tool_class = getattr(module, tool_name) # Instantiate the tool tool_instance = tool_class() # FIXME This is a temporary workaround to avoid running demo commands self.available_tools.append(tool_name) # # TODO Run the first demo command if available # demo_commands = tool_data.get('demo_commands', []) # if demo_commands: # print(f"Running demo command: {demo_commands[0]['command']}") # # Extract the arguments from the demo command # command = demo_commands[0]['command'] # args_start = command.index('(') + 1 # args_end = command.rindex(')') # args_str = command[args_start:args_end] # # Create a dictionary of arguments # args_dict = eval(f"dict({args_str})") # # Execute the demo command # result = tool_instance.execute(**args_dict) # print(f"Demo command executed successfully. Result: {result}") # self.available_tools.append(tool_name) # else: # print(f"No demo commands available for {tool_name}") # # If no demo commands, we'll assume the tool is available # self.available_tools.append(tool_name) except Exception as e: print(f"Error checking availability of {tool_name}: {str(e)}") print(traceback.format_exc()) # update the toolmetadata with the available tools self.toolbox_metadata = {tool: self.toolbox_metadata[tool] for tool in self.available_tools} print(f"\nUpdated total number of available tools: {len(self.toolbox_metadata)}") print(f"\nAvailable tools: {self.available_tools}") return self.available_tools def _set_up_tools(self) -> None: print("Setting up tools...") # Keep enabled tools self.available_tools = [tool.lower().replace('_tool', '') for tool in self.enabled_tools] # Load tools and get metadata self.load_tools_and_get_metadata() # Run demo commands to determine available tools self.run_demo_commands() # Filter toolbox_metadata to include only available tools self.toolbox_metadata = {tool: self.toolbox_metadata[tool] for tool in self.available_tools} print(f"\nTotal number of available tools: {len(self.available_tools)}") print(f"Available tools: {self.available_tools}") print(f"Enabled tools: {self.enabled_tools}") if __name__ == "__main__": enabled_tools = ["Generalist_Solution_Generator_Tool"] initializer = Initializer(enabled_tools=enabled_tools) print("\nAvailable tools:") print(initializer.available_tools) print("\nToolbox metadata for available tools:") print(initializer.toolbox_metadata)