feat: update agent to include tools

pull/298/head
Zack 1 year ago
parent 74cf494e23
commit a7c1c2bcb2

@ -1,2 +1,12 @@
Created a temporary directory at /tmp/tmpy1_589mf Traceback (most recent call last):
Writing /tmp/tmpy1_589mf/_remote_module_non_scriptable.py File "/home/zack/code/swarms/app.py", line 15, in <module>
from swarms.modelui.modules.block_requests import OpenMonkeyPatch, RequestBlocker
File "/home/zack/code/swarms/swarms/__init__.py", line 6, in <module>
from swarms.swarms import * # noqa: E402, F403
File "/home/zack/code/swarms/swarms/swarms/__init__.py", line 1, in <module>
from swarms.structs.autoscaler import AutoScaler
File "/home/zack/code/swarms/swarms/structs/__init__.py", line 1, in <module>
from swarms.structs.agent import Agent
File "/home/zack/code/swarms/swarms/structs/agent.py", line 25, in <module>
from swarms.tools.tool import BaseTool
ImportError: cannot import name 'BaseTool' from 'swarms.tools.tool' (/home/zack/code/swarms/swarms/tools/tool.py)

@ -19,19 +19,26 @@ from swarms.prompts.agent_system_prompts import (
from swarms.prompts.multi_modal_autonomous_instruction_prompt import ( from swarms.prompts.multi_modal_autonomous_instruction_prompt import (
MULTI_MODAL_AUTO_AGENT_SYSTEM_PROMPT_1, MULTI_MODAL_AUTO_AGENT_SYSTEM_PROMPT_1,
) )
from swarms.prompts.tools import ( from swarms.prompts.tools import SCENARIOS
SCENARIOS,
) #TODO temp removed to test new tool system revert fro old system and rename tool.old to tools
from swarms.tools.tool import BaseTool # from swarms.prompts.tools import (
from swarms.tools.tool_func_doc_scraper import scrape_tool_func_docs # SCENARIOS,
from swarms.utils.code_interpreter import SubprocessCodeInterpreter # )
from swarms.utils.parse_code import ( # from swarms.tools.tool import BaseTool
extract_code_in_backticks_in_string, # from swarms.tools.tool_func_doc_scraper import scrape_tool_func_docs
) # from swarms.utils.code_interpreter import SubprocessCodeInterpreter
from swarms.utils.pdf_to_text import pdf_to_text # from swarms.utils.parse_code import (
# extract_code_in_backticks_in_string,
# )
# from swarms.utils.pdf_to_text import pdf_to_text
# from swarms.utils.token_count_tiktoken import limit_tokens_from_string
from swarms.tools.tools_controller import load_valid_tools, tools_mappings
from swarms.utils import pdf_to_text
from swarms.utils.parse_code import extract_code_in_backticks_in_string
from swarms.utils.token_count_tiktoken import limit_tokens_from_string from swarms.utils.token_count_tiktoken import limit_tokens_from_string
# Utils # Utils
# Custom stopping condition # Custom stopping condition
def stop_when_repeats(response: str) -> bool: def stop_when_repeats(response: str) -> bool:
@ -176,7 +183,7 @@ class Agent:
agent_name: str = "Autonomous-Agent-XYZ1B", agent_name: str = "Autonomous-Agent-XYZ1B",
agent_description: str = None, agent_description: str = None,
system_prompt: str = AGENT_SYSTEM_PROMPT_3, system_prompt: str = AGENT_SYSTEM_PROMPT_3,
tools: List[BaseTool] = None, # tools: List[BaseTool] = None,
dynamic_temperature_enabled: Optional[bool] = False, dynamic_temperature_enabled: Optional[bool] = False,
sop: Optional[str] = None, sop: Optional[str] = None,
sop_list: Optional[List[str]] = None, sop_list: Optional[List[str]] = None,
@ -344,72 +351,72 @@ class Agent:
return "\n".join(params_str_list) return "\n".join(params_str_list)
def get_tool_description(self): #TODO deprecated moving to new system delete if not used
"""Get the tool description""" # def get_tool_description(self):
if self.tools: # """Get the tool description"""
try: # if self.tools:
tool_descriptions = [] # try:
for tool in self.tools: # tool_descriptions = []
description = f"{tool.name}: {tool.description}" # for tool in self.tools:
tool_descriptions.append(description) # description = f"{tool.name}: {tool.description}"
return "\n".join(tool_descriptions) # tool_descriptions.append(description)
except Exception as error: # return "\n".join(tool_descriptions)
print( # except Exception as error:
f"Error getting tool description: {error} try" # print(
" adding a description to the tool or removing" # f"Error getting tool description: {error} try"
" the tool" # " adding a description to the tool or removing"
) # " the tool"
else: # )
return "No tools available" # else:
# return "No tools available"
def find_tool_by_name(self, name: str): # def find_tool_by_name(self, name: str):
"""Find a tool by name""" # """Find a tool by name"""
for tool in self.tools: # for tool in self.tools:
if tool.name == name: # if tool.name == name:
return tool # return tool
def extract_tool_commands(self, text: str): # def extract_tool_commands(self, text: str):
""" # """
Extract the tool commands from the text # Extract the tool commands from the text
Example: # Example:
```json # ```json
{ # {
"tool": "tool_name", # "tool": "tool_name",
"params": { # "params": {
"tool1": "inputs", # "tool1": "inputs",
"param2": "value2" # "param2": "value2"
} # }
} # }
``` # ```
""" # """
# Regex to find JSON like strings # # Regex to find JSON like strings
pattern = r"```json(.+?)```" # pattern = r"```json(.+?)```"
matches = re.findall(pattern, text, re.DOTALL) # matches = re.findall(pattern, text, re.DOTALL)
json_commands = [] # json_commands = []
for match in matches: # for match in matches:
try: # try:
json_commands = json.loads(match) # json_commands = json.loads(match)
json_commands.append(json_commands) # json_commands.append(json_commands)
except Exception as error: # except Exception as error:
print(f"Error parsing JSON command: {error}") # print(f"Error parsing JSON command: {error}")
def execute_tools(self, tool_name, params): # def execute_tools(self, tool_name, params):
"""Execute the tool with the provided params""" # """Execute the tool with the provided params"""
tool = self.tool_find_by_name(tool_name) # tool = self.tool_find_by_name(tool_name)
if tool: # if tool:
# Execute the tool with the provided parameters # # Execute the tool with the provided parameters
tool_result = tool.run(**params) # tool_result = tool.run(**params)
print(tool_result) # print(tool_result)
def parse_and_execute_tools(self, response: str): # def parse_and_execute_tools(self, response: str):
"""Parse and execute the tools""" # """Parse and execute the tools"""
json_commands = self.extract_tool_commands(response) # json_commands = self.extract_tool_commands(response)
for command in json_commands: # for command in json_commands:
tool_name = command.get("tool") # tool_name = command.get("tool")
params = command.get("parmas", {}) # params = command.get("parmas", {})
self.execute_tools(tool_name, params) # self.execute_tools(tool_name, params)
def truncate_history(self): def truncate_history(self):
""" """
@ -454,11 +461,11 @@ class Agent:
self.short_memory[-1].append(message) self.short_memory[-1].append(message)
self.truncate_history() self.truncate_history()
def parse_tool_docs(self): # def parse_tool_docs(self):
"""Parse the tool docs""" # """Parse the tool docs"""
for tool in self.tools: # for tool in self.tools:
docs = self.tool_docs.append(scrape_tool_func_docs(tool)) # docs = self.tool_docs.append(scrape_tool_func_docs(tool))
return str(docs) # return str(docs)
def print_dashboard(self, task: str): def print_dashboard(self, task: str):
"""Print dashboard""" """Print dashboard"""
@ -1213,16 +1220,17 @@ class Agent:
def generate_reply(self, history: str, **kwargs) -> str: def generate_reply(self, history: str, **kwargs) -> str:
""" """
Generate a response based on initial or task Generate a reply using the LLM and the tools.
""" """
prompt = f""" # Generate a response using the LLM
response = self.llm.generate_reply(history, **kwargs)
SYSTEM_PROMPT: {self.system_prompt} # Execute the tools
for tool in self.tools:
if tool.command in response:
response = tool.execute(response)
History: {history} return response
"""
response = self.llm(prompt, **kwargs)
return {"role": self.agent_name, "content": response}
def update_system_prompt(self, system_prompt: str): def update_system_prompt(self, system_prompt: str):
"""Upddate the system message""" """Upddate the system message"""
@ -1350,3 +1358,4 @@ class Agent:
""" """
return PROMPT return PROMPT

@ -19,17 +19,6 @@ logger = get_logger(__name__)
tools_mappings = {} tools_mappings = {}
# data = json.load(open('openai.json'))
# items = data['items']
# for plugin in items:
# url = plugin['manifest']['api']['url']
# tool_name = plugin['namespace']
# tools_mappings[tool_name] = url[:-len('/.well-known/openai.yaml')]
# print(tools_mappings)
# all_tools_list = []
def load_valid_tools(tools_mappings): def load_valid_tools(tools_mappings):
tools_to_config = {} tools_to_config = {}
for key in tools_mappings: for key in tools_mappings:
@ -46,14 +35,10 @@ def load_valid_tools(tools_mappings):
return tools_to_config return tools_to_config
# Read the model/ directory and get the list of models
model_dir = Path("./models/") model_dir = Path("./models/")
available_models = ["ChatGPT", "GPT-3.5"] + [f.name for f in model_dir.iterdir() if f.is_dir()] available_models = ["ChatGPT", "GPT-3.5"] + [f.name for f in model_dir.iterdir() if f.is_dir()]
class MTQuestionAnswerer: class MTQuestionAnswerer:
"""Use multiple tools to answer a question. Basically pass a natural question to"""
def __init__(self, openai_api_key, all_tools, stream_output=False, llm="ChatGPT", model_path=None): def __init__(self, openai_api_key, all_tools, stream_output=False, llm="ChatGPT", model_path=None):
if len(openai_api_key) < 3: # not valid key (TODO: more rigorous checking) if len(openai_api_key) < 3: # not valid key (TODO: more rigorous checking)
openai_api_key = os.environ.get("OPENAI_API_KEY") openai_api_key = os.environ.get("OPENAI_API_KEY")
@ -106,12 +91,9 @@ class MTQuestionAnswerer:
.replace("}", "}}"), .replace("}", "}}"),
func=subagent, func=subagent,
) )
tool.tool_logo_md = tool_logo_md
self.tools_pool.append(tool) self.tools_pool.append(tool)
def build_runner( def build_runner(self):
self,
):
from langchain.vectorstores import FAISS from langchain.vectorstores import FAISS
from langchain.docstore import InMemoryDocstore from langchain.docstore import InMemoryDocstore
from langchain.embeddings import OpenAIEmbeddings from langchain.embeddings import OpenAIEmbeddings
@ -125,7 +107,6 @@ class MTQuestionAnswerer:
embeddings_model.embed_query, index, InMemoryDocstore({}), {} embeddings_model.embed_query, index, InMemoryDocstore({}), {}
) )
# TODO refactor to use the flow
from swarms.tools.agent.autogptmulti.agent import AutoGPT from swarms.tools.agent.autogptmulti.agent import AutoGPT
from langchain.chat_models import ChatOpenAI from langchain.chat_models import ChatOpenAI
@ -136,6 +117,8 @@ class MTQuestionAnswerer:
llm=ChatOpenAI(temperature=0), llm=ChatOpenAI(temperature=0),
memory=vectorstore.as_retriever(), memory=vectorstore.as_retriever(),
) )
''' '''
# You can modify the prompt to improve the model's performance, or modify the tool's doc # You can modify the prompt to improve the model's performance, or modify the tool's doc
prefix = """Answer the following questions as best you can. In this level, you are calling the tools in natural language format, since the tools are actually an intelligent agent like you, but they expert only in one area. Several things to remember. (1) Remember to follow the format of passing natural language as the Action Input. (2) DO NOT use your imagination, only use concrete information given by the tools. (3) If the observation contains images or urls which has useful information, YOU MUST INCLUDE ALL USEFUL IMAGES and links in your Answer and Final Answers using format ![img](url). BUT DO NOT provide any imaginary links. (4) The information in your Final Answer should include ALL the informations returned by the tools. (5) If a user's query is a language other than English, please translate it to English without tools, and translate it back to the source language in Final Answer. You have access to the following tools (Only use these tools we provide you):""" prefix = """Answer the following questions as best you can. In this level, you are calling the tools in natural language format, since the tools are actually an intelligent agent like you, but they expert only in one area. Several things to remember. (1) Remember to follow the format of passing natural language as the Action Input. (2) DO NOT use your imagination, only use concrete information given by the tools. (3) If the observation contains images or urls which has useful information, YOU MUST INCLUDE ALL USEFUL IMAGES and links in your Answer and Final Answers using format ![img](url). BUT DO NOT provide any imaginary links. (4) The information in your Final Answer should include ALL the informations returned by the tools. (5) If a user's query is a language other than English, please translate it to English without tools, and translate it back to the source language in Final Answer. You have access to the following tools (Only use these tools we provide you):"""

@ -5,8 +5,8 @@ import sys
def disable_logging(): def disable_logging():
log_file = open("errors.txt", "w") # log_file = open("errors.txt", "w")
sys.stderr = log_file # sys.stderr = log_file
warnings.filterwarnings("ignore", category=UserWarning) warnings.filterwarnings("ignore", category=UserWarning)

Loading…
Cancel
Save