jarvis/tools.py

85 lines
2.7 KiB
Python

import duckduckgo_search
import requests
from readability.readability import Document
from markdownify import markdownify as md
class Tool:
def __init__(self, name: str, description: str, arguments: str, returns: str):
self.name = name
self.description = description
self.arguments = arguments
self.returns = returns
def execute(self, arguments: str) -> str:
pass
class ToolManager:
def __init__(self):
self.tools = []
def add_tool(self, tool: Tool):
self.tools.append(tool)
def get_tool(self, name: str) -> Tool:
for tool in self.tools:
if tool.name == name:
return tool
return None
def get_tools_and_descriptions_for_prompt(self):
return "\n".join([f"{tool.name}: {tool.description}" for tool in self.tools])
class DefaultToolManager(ToolManager):
def __init__(self):
super().__init__()
self.add_tool(SearchTool())
self.add_tool(GetReadablePageContentsTool())
self.add_tool(CalculatorTool())
self.add_tool(PythonCodeTool())
class SearchTool(Tool):
def __init__(self):
super().__init__("search_web", "Search the internet for information -- Takes a search query as an argument", "query:string", "results:list[string]")
def execute(self, arg: str) -> str:
res = duckduckgo_search.DDGS().text(arg, max_results=5)
return [f"{r['title']}\n{r['body']}\n{r['href']}" for r in res]
def get_readable_page_contents(url: str) -> str:
try:
response = requests.get(url)
response.raise_for_status()
doc = Document(response.content)
content = doc.summary()
return md(content)
except Exception as e:
return f"Error fetching readable content: {str(e)}"
class GetReadablePageContentsTool(Tool):
def __init__(self):
super().__init__("get_readable_page_contents", "Get the contents of a web page in a readable format -- Takes a url as an argument", "url:string", "contents:string")
def execute(self, arg: str) -> str:
return get_readable_page_contents(arg[0])
class CalculatorTool(Tool):
def __init__(self):
super().__init__("calculator", "Perform a calculation -- Takes a python mathematical expression as an argument", "expression:string", "result:string")
def execute(self, arg: str) -> str:
return str(eval(arg[0]))
class PythonCodeTool(Tool):
def __init__(self):
super().__init__("python_code", "Execute python code -- Takes a python code as an argument, code must be a single line of valid python", "code:string", "result:string")
def execute(self, arg: str) -> str:
return str(eval(arg[0]))