diff --git a/chat.py b/chat.py new file mode 100644 index 00000000..134f7f16 --- /dev/null +++ b/chat.py @@ -0,0 +1,11 @@ +from swarms import Orchestrator, Worker + +# Instantiate the Orchestrator with 10 agents +orchestrator = Orchestrator( + Worker, + agent_list=[Worker]*10, + task_queue=[] +) + +# Agent 1 sends a message to Agent 2 +orchestrator.chat(sender_id=1, receiver_id=2, message="Hello, Agent 2!") \ No newline at end of file diff --git a/swarms/__init__.py b/swarms/__init__.py index 8c105356..fcd31eb2 100644 --- a/swarms/__init__.py +++ b/swarms/__init__.py @@ -4,6 +4,7 @@ print(logo2) # worker import swarms.workers +from swarms.workers.worker import Worker #boss # from swarms.boss.boss_node import Boss @@ -16,6 +17,6 @@ import swarms.structs # swarms import swarms.swarms - +from swarms.swarms.orchestrate import Orchestrator #agents import swarms.agents \ No newline at end of file diff --git a/swarms/agents/__init__.py b/swarms/agents/__init__.py index 6a1cfea3..24c0ae9e 100644 --- a/swarms/agents/__init__.py +++ b/swarms/agents/__init__.py @@ -2,7 +2,6 @@ ########### -# #tools # from swarms.tools.base import BaseTool, Tool, StructuredTool, ToolWrapper, BaseToolSet, ToolCreator, GlobalToolsCreator, SessionToolsCreator, ToolsFactory # from swarms.tools.autogpt import pushd, process_csv, async_load_playwright, run_async, browse_web_page, WebpageQATool, web_search, query_website_tool # from swarms.tools.exit_conversation import ExitConversation @@ -15,7 +14,7 @@ #agents -from swarms.agents.profitpilot import ProfitPilot +# from swarms.agents.profitpilot import ProfitPilot from swarms.agents.aot import AoTAgent -from swarms.agents.multi_modal_agent import MultiModalVisualAgent -from swarms.agents.omni_modal_agent import OmniModalAgent \ No newline at end of file +# from swarms.agents.multi_modal_agent import MultiModalVisualAgent +# from swarms.agents.omni_modal_agent import OmniModalAgent \ No newline at end of file diff --git a/swarms/swarms/orchestrate.py b/swarms/swarms/orchestrate.py index fde746b7..083a8f7b 100644 --- a/swarms/swarms/orchestrate.py +++ b/swarms/swarms/orchestrate.py @@ -2,8 +2,8 @@ import logging import queue import threading from concurrent.futures import ThreadPoolExecutor -from typing import Any, Dict, List from enum import Enum +from typing import Any, Dict, List import chromadb from chromadb.utils import embedding_functions @@ -71,7 +71,7 @@ class Orchestrator: ###Usage ``` - from exa import Orchestrator + from swarms import Orchestrator # Instantiate the Orchestrator with 10 agents orchestrator = Orchestrator(llm, agent_list=[llm]*10, task_queue=[]) diff --git a/swarms/swarms/scable_groupchat.py b/swarms/swarms/scable_groupchat.py new file mode 100644 index 00000000..9c59882e --- /dev/null +++ b/swarms/swarms/scable_groupchat.py @@ -0,0 +1,213 @@ +import logging +from enum import Enum +from typing import Any + +from chromadb.utils import embedding_functions + +from swarms.workers.worker import Worker + + +class TaskStatus(Enum): + QUEUED = 1 + RUNNING = 2 + COMPLETED = 3 + FAILED = 4 + +class ScalableGroupChat: + """ + The Orchestrator takes in an agent, worker, or boss as input + then handles all the logic for + - task creation, + - task assignment, + - and task compeletion. + + And, the communication for millions of agents to chat with eachother through + a vector database that each agent has access to chat with. + + Each LLM agent chats with the orchestrator through a dedicated + communication layer. The orchestrator assigns tasks to each LLM agent, + which the agents then complete and return. + + This setup allows for a high degree of flexibility, scalability, and robustness. + + In the context of swarm LLMs, one could consider an **Omni-Vector Embedding Database + for communication. This database could store and manage + the high-dimensional vectors produced by each LLM agent. + + Strengths: This approach would allow for similarity-based lookup and matching of + LLM-generated vectors, which can be particularly useful for tasks that involve finding similar outputs or recognizing patterns. + + Weaknesses: An Omni-Vector Embedding Database might add complexity to the system in terms of setup and maintenance. + It might also require significant computational resources, + depending on the volume of data being handled and the complexity of the vectors. + The handling and transmission of high-dimensional vectors could also pose challenges + in terms of network load. + + # Orchestrator + * Takes in an agent class with vector store, + then handles all the communication and scales + up a swarm with number of agents and handles task assignment and task completion + + from swarms import OpenAI, Orchestrator, Swarm + + orchestrated = Orchestrate(OpenAI, nodes=40) #handles all the task assignment and allocation and agent communication using a vectorstore as a universal communication layer and also handlles the task completion logic + + Objective = "Make a business website for a marketing consultancy" + + Swarms = Swarms(orchestrated, auto=True, Objective)) + ``` + + In terms of architecture, the swarm might look something like this: + + ``` + (Orchestrator) + / \ + Tools + Vector DB -- (LLM Agent)---(Communication Layer) (Communication Layer)---(LLM Agent)-- Tools + Vector DB + / | | \ + (Task Assignment) (Task Completion) (Task Assignment) (Task Completion) + + + ###Usage + ``` + from swarms import Orchestrator + + # Instantiate the Orchestrator with 10 agents + orchestrator = Orchestrator(llm, agent_list=[llm]*10, task_queue=[]) + + # Add tasks to the Orchestrator + tasks = [{"content": f"Write a short story about a {animal}."} for animal in ["cat", "dog", "bird", "fish", "lion", "tiger", "elephant", "giraffe", "monkey", "zebra"]] + orchestrator.assign_tasks(tasks) + + # Run the Orchestrator + orchestrator.run() + + # Retrieve the results + for task in tasks: + print(orchestrator.retrieve_result(id(task))) + ``` + """ + def __init__( + self, + worker_count: int = 5, + collection_name: str = "swarm", + api_key: str = None, + model_name: str = None, + worker = None + ): + self.workers = [] + self.worker_count = worker_count + + # Create a list of Worker instances with unique names + for i in range(worker_count): + self.workers.append(Worker(openai_api_key="", ai_name=f"Worker-{i}")) + + def embed(self, input, api_key, model_name): + openai = embedding_functions.OpenAIEmbeddingFunction( + api_key=api_key, + model_name=model_name + ) + embedding = openai(input) + return embedding + + + # @abstractmethod + def retrieve_results( + self, + agent_id: int + ) -> Any: + """Retrieve results from a specific agent""" + + try: + #Query the vector database for documents created by the agents + results = self.collection.query( + query_texts=[str(agent_id)], + n_results=10 + ) + + return results + except Exception as e: + logging.error(f"Failed to retrieve results from agent {agent_id}. Error {e}") + raise + + # @abstractmethod + def update_vector_db(self, data) -> None: + """Update the vector database""" + + try: + self.collection.add( + embeddings=[data["vector"]], + documents=[str(data["task_id"])], + ids=[str(data["task_id"])] + ) + + except Exception as e: + logging.error(f"Failed to update the vector database. Error: {e}") + raise + + + # @abstractmethod + def get_vector_db(self): + """Retrieve the vector database""" + return self.collection + + + def append_to_db( + self, + result: str + ): + """append the result of the swarm to a specifici collection in the database""" + + try: + self.collection.add( + documents=[result], + ids=[str(id(result))] + ) + + except Exception as e: + logging.error(f"Failed to append the agent output to database. Error: {e}") + raise + + + + def chat( + self, + sender_id: int, + receiver_id: int, + message: str + ): + """ + + Allows the agents to chat with eachother thrught the vectordatabase + + # Instantiate the Orchestrator with 10 agents + orchestrator = Orchestrator( + llm, + agent_list=[llm]*10, + task_queue=[] + ) + + # Agent 1 sends a message to Agent 2 + orchestrator.chat(sender_id=1, receiver_id=2, message="Hello, Agent 2!") + + """ + if sender_id < 0 or sender_id >= self.worker_count or receiver_id < 0 or receiver_id >= self.worker_count: + raise ValueError("Invalid sender or receiver ID") + + message_vector = self.embed( + message, + self.api_key, + self.model_name + ) + + #store the mesage in the vector database + self.collection.add( + embeddings=[message_vector], + documents=[message], + ids=[f"{sender_id}_to_{receiver_id}"] + ) + + self.run( + objective=f"chat with agent {receiver_id} about {message}" + ) + +