diff --git a/playground/demos/logistics/logistics.py b/playground/demos/logistics/logistics.py index fefe78d3..0e09f910 100644 --- a/playground/demos/logistics/logistics.py +++ b/playground/demos/logistics/logistics.py @@ -11,6 +11,7 @@ from swarms.prompts.logistics import ( Sustainability_Agent_Prompt, Efficiency_Agent_Prompt, ) + # from swarms.utils.phoenix_handler import phoenix_trace_decorator # from swarms.utils.banana_wrapper import banana @@ -33,7 +34,7 @@ health_security_agent = Agent( multi_modal=True, ) -#@phoenix_trace_decorator("This function is an agent and is traced by Phoenix.") +# @phoenix_trace_decorator("This function is an agent and is traced by Phoenix.") quality_control_agent = Agent( llm=llm, sop=Quality_Control_Agent_Prompt, @@ -41,7 +42,7 @@ quality_control_agent = Agent( multi_modal=True, ) -#@phoenix_trace_decorator("This function is an agent and is traced by Phoenix.") +# @phoenix_trace_decorator("This function is an agent and is traced by Phoenix.") productivity_agent = Agent( llm=llm, sop=Productivity_Agent_Prompt, @@ -49,17 +50,17 @@ productivity_agent = Agent( multi_modal=True, ) -#@phoenix_trace_decorator("This function is an agent and is traced by Phoenix.") +# @phoenix_trace_decorator("This function is an agent and is traced by Phoenix.") safety_agent = Agent( llm=llm, sop=Safety_Agent_Prompt, max_loops=1, multi_modal=True ) -#@phoenix_trace_decorator("This function is an agent and is traced by Phoenix.") +# @phoenix_trace_decorator("This function is an agent and is traced by Phoenix.") security_agent = Agent( llm=llm, sop=Security_Agent_Prompt, max_loops=1, multi_modal=True ) -#@phoenix_trace_decorator("This function is an agent and is traced by Phoenix.") +# @phoenix_trace_decorator("This function is an agent and is traced by Phoenix.") sustainability_agent = Agent( llm=llm, sop=Sustainability_Agent_Prompt, @@ -67,7 +68,7 @@ sustainability_agent = Agent( multi_modal=True, ) -#@phoenix_trace_decorator("This function is an agent and is traced by Phoenix.") +# @phoenix_trace_decorator("This function is an agent and is traced by Phoenix.") efficiency_agent = Agent( llm=llm, sop=Efficiency_Agent_Prompt, diff --git a/playground/demos/optimize_llm_stack/vortex.py b/playground/demos/optimize_llm_stack/vortex.py index 5f48b2b6..438c1451 100644 --- a/playground/demos/optimize_llm_stack/vortex.py +++ b/playground/demos/optimize_llm_stack/vortex.py @@ -5,6 +5,7 @@ from dotenv import load_dotenv from swarms.models import OpenAIChat from swarms.structs import Agent + # from swarms.utils.phoenix_handler import phoenix_trace_decorator # import modal @@ -32,5 +33,8 @@ agent = Agent( autosave=True, dashboard=True, ) -out = agent.run("Generate a 5,000 word blog on how swarms of autonomous agents can be used to solve the world's problems.") -print(out) \ No newline at end of file +out = agent.run( + "Generate a 5,000 word blog on how swarms of autonomous agents" + " can be used to solve the world's problems." +) +print(out) diff --git a/swarms/memory/__init__.py b/swarms/memory/__init__.py index 284b9b4f..66639678 100644 --- a/swarms/memory/__init__.py +++ b/swarms/memory/__init__.py @@ -1,4 +1,3 @@ - from swarms.memory.base_vectordb import VectorDatabase __all__ = [ diff --git a/swarms/structs/agent.py b/swarms/structs/agent.py index ac5f2413..1ad6f8ca 100644 --- a/swarms/structs/agent.py +++ b/swarms/structs/agent.py @@ -583,10 +583,10 @@ class Agent: return agent_system_prompt_2(self.agent_name) def run( - self, - task: Optional[str] = None, - img: Optional[str] = None, - **kwargs + self, + task: Optional[str] = None, + img: Optional[str] = None, + **kwargs, ): """ Run the autonomous agent loop diff --git a/swarms/swarms/base.py b/swarms/swarms/base.py index 15238a8a..2f65bf86 100644 --- a/swarms/swarms/base.py +++ b/swarms/swarms/base.py @@ -1,82 +1,56 @@ +import asyncio +import concurrent.futures +import time from abc import ABC, abstractmethod -from typing import Optional, List, Dict, Any -from swarms.workers.base import AbstractWorker +from typing import Any, Dict, List, Optional +from swarms.structs.agent import Agent +from swarms.agents.base import AbstractWorker class AbstractSwarm(ABC): """ - Abstract class for swarm simulation architectures + Abstract Swarm Class for multi-agent systems + Attributes: + agents (List[Agent]): A list of agents + max_loops (int): The maximum number of loops to run - Methods: - --------- - - communicate() - Communicate with the swarm through the orchestrator, protocols, and the universal communication layer - - run() - Run the swarm - - arun() - Run the swarm Asynchronously - - add_worker(worker: "AbstractWorker") - Add a worker to the swarm - - remove_worker(worker: "AbstractWorker") - Remove a worker from the swarm - - broadcast(message: str, sender: Optional["AbstractWorker"] = None) - Broadcast a message to all workers - - reset() - Reset the swarm - - plan(task: str) - Workers must individually plan using a workflow or pipeline - - direct_message(message: str, sender: "AbstractWorker", recipient: "AbstractWorker") - Send a direct message to a worker - - autoscaler(num_workers: int, worker: ["AbstractWorker"]) - Autoscaler that acts like kubernetes for autonomous agents - - get_worker_by_id(id: str) -> "AbstractWorker" - Locate a worker by id - - get_worker_by_name(name: str) -> "AbstractWorker" - Locate a worker by name - - assign_task(worker: "AbstractWorker", task: Any) -> Dict - Assign a task to a worker - - get_all_tasks(worker: "AbstractWorker", task: Any) - Get all tasks - - get_finished_tasks() -> List[Dict] - Get all finished tasks - - get_pending_tasks() -> List[Dict] - Get all pending tasks - - pause_worker(worker: "AbstractWorker", worker_id: str) - Pause a worker - - resume_worker(worker: "AbstractWorker", worker_id: str) - Resume a worker - - stop_worker(worker: "AbstractWorker", worker_id: str) - Stop a worker - - restart_worker(worker: "AbstractWorker") - Restart worker - - scale_up(num_worker: int) - Scale up the number of workers - - scale_down(num_worker: int) - Scale down the number of workers + Methods: + communicate: Communicate with the swarm through the orchestrator, protocols, and the universal communication layer + run: Run the swarm + step: Step the swarm + add_worker: Add a worker to the swarm + remove_worker: Remove a worker from the swarm + broadcast: Broadcast a message to all agents + reset: Reset the swarm + plan: agents must individually plan using a workflow or pipeline + direct_message: Send a direct message to a worker + autoscaler: Autoscaler that acts like kubernetes for autonomous agents + get_worker_by_id: Locate a worker by id + get_worker_by_name: Locate a worker by name + assign_task: Assign a task to a worker + get_all_tasks: Get all tasks + get_finished_tasks: Get all finished tasks + get_pending_tasks: Get all pending tasks + pause_worker: Pause a worker + resume_worker: Resume a worker + stop_worker: Stop a worker + restart_worker: Restart worker + scale_up: Scale up the number of agents + scale_down: Scale down the number of agents + scale_to: Scale to a specific number of agents + get_all_agents: Get all agents + get_swarm_size: Get the size of the swarm + get_swarm_status: Get the status of the swarm + save_swarm_state: Save the swarm state + loop: Loop through the swarm + run_async: Run the swarm asynchronously + run_batch_async: Run the swarm asynchronously + run_batch: Run the swarm asynchronously + batched_run: Run the swarm asynchronously + abatch_run: Asynchronous batch run with language model + arun: Asynchronous run """ @@ -86,54 +60,71 @@ class AbstractSwarm(ABC): # TODO: Add RLHF Data collection, ask user how the swarm is performing # TODO: Create an onboarding process if not settings are preconfigured like `from swarms import Swarm, Swarm()` => then initiate onboarding name your swarm + provide purpose + etc - @abstractmethod - def __init__(self, workers: List["AbstractWorker"]): - """Initialize the swarm with workers""" + # @abstractmethod + def __init__(self, agents: List[Agent], max_loops: int = 200): + """Initialize the swarm with agents""" + self.agents = agents + self.max_loops = max_loops pass - @abstractmethod + # @abstractmethod def communicate(self): """Communicate with the swarm through the orchestrator, protocols, and the universal communication layer""" pass - @abstractmethod + # @abstractmethod def run(self): """Run the swarm""" pass - @abstractmethod - def arun(self): - """Run the swarm Asynchronously""" + def __call__( + self, + task, + *args, + **kwargs, + ): + """Call self as a function + + Args: + task (_type_): _description_ + + Returns: + _type_: _description_ + """ + return self.run(task, *args, **kwargs) + + def step(self): + """Step the swarm""" pass - @abstractmethod + # @abstractmethod def add_worker(self, worker: "AbstractWorker"): """Add a worker to the swarm""" pass - @abstractmethod + # @abstractmethod def remove_worker(self, worker: "AbstractWorker"): """Remove a worker from the swarm""" pass - @abstractmethod + # @abstractmethod def broadcast( self, message: str, sender: Optional["AbstractWorker"] = None ): - """Broadcast a message to all workers""" + """Broadcast a message to all agents""" pass - @abstractmethod + # @abstractmethod def reset(self): """Reset the swarm""" pass - @abstractmethod + # @abstractmethod def plan(self, task: str): - """Workers must individually plan using a workflow or pipeline""" + """agents must individually plan using a workflow or pipeline""" pass - @abstractmethod + # @abstractmethod def direct_message( self, message: str, @@ -143,95 +134,231 @@ class AbstractSwarm(ABC): """Send a direct message to a worker""" pass - @abstractmethod - def autoscaler( - self, num_workers: int, worker: ["AbstractWorker"] - ): + # @abstractmethod + def autoscaler(self, num_agents: int, worker: ["AbstractWorker"]): """Autoscaler that acts like kubernetes for autonomous agents""" pass - @abstractmethod + # @abstractmethod def get_worker_by_id(self, id: str) -> "AbstractWorker": """Locate a worker by id""" pass - @abstractmethod + # @abstractmethod def get_worker_by_name(self, name: str) -> "AbstractWorker": """Locate a worker by name""" pass - @abstractmethod + # @abstractmethod def assign_task( self, worker: "AbstractWorker", task: Any ) -> Dict: """Assign a task to a worker""" pass - @abstractmethod + # @abstractmethod def get_all_tasks(self, worker: "AbstractWorker", task: Any): """Get all tasks""" - @abstractmethod + # @abstractmethod def get_finished_tasks(self) -> List[Dict]: """Get all finished tasks""" pass - @abstractmethod + # @abstractmethod def get_pending_tasks(self) -> List[Dict]: """Get all pending tasks""" pass - @abstractmethod + # @abstractmethod def pause_worker(self, worker: "AbstractWorker", worker_id: str): """Pause a worker""" pass - @abstractmethod + # @abstractmethod def resume_worker(self, worker: "AbstractWorker", worker_id: str): """Resume a worker""" pass - @abstractmethod + # @abstractmethod def stop_worker(self, worker: "AbstractWorker", worker_id: str): """Stop a worker""" pass - @abstractmethod + # @abstractmethod def restart_worker(self, worker: "AbstractWorker"): """Restart worker""" pass - @abstractmethod + # @abstractmethod def scale_up(self, num_worker: int): - """Scale up the number of workers""" + """Scale up the number of agents""" pass - @abstractmethod + # @abstractmethod def scale_down(self, num_worker: int): - """Scale down the number of workers""" + """Scale down the number of agents""" pass - @abstractmethod + # @abstractmethod def scale_to(self, num_worker: int): - """Scale to a specific number of workers""" + """Scale to a specific number of agents""" pass - @abstractmethod - def get_all_workers(self) -> List["AbstractWorker"]: - """Get all workers""" + # @abstractmethod + def get_all_agents(self) -> List["AbstractWorker"]: + """Get all agents""" pass - @abstractmethod + # @abstractmethod def get_swarm_size(self) -> int: """Get the size of the swarm""" pass - @abstractmethod + # #@abstractmethod def get_swarm_status(self) -> Dict: """Get the status of the swarm""" pass - @abstractmethod + # #@abstractmethod def save_swarm_state(self): """Save the swarm state""" pass + + def batched_run(self, tasks: List[Any], *args, **kwargs): + """_summary_ + + Args: + tasks (List[Any]): _description_ + """ + # Implement batched run + return [self.run(task, *args, **kwargs) for task in tasks] + + async def abatch_run(self, tasks: List[str], *args, **kwargs): + """Asynchronous batch run with language model + + Args: + tasks (List[str]): _description_ + + Returns: + _type_: _description_ + """ + return await asyncio.gather( + *(self.arun(task, *args, **kwargs) for task in tasks) + ) + + async def arun(self, task: Optional[str] = None, *args, **kwargs): + """Asynchronous run + + Args: + task (Optional[str], optional): _description_. Defaults to None. + """ + loop = asyncio.get_event_loop() + result = await loop.run_in_executor( + None, self.run, task, *args, **kwargs + ) + return result + + def loop( + self, + task: Optional[str] = None, + *args, + **kwargs, + ): + """Loop through the swarm + + Args: + task (Optional[str], optional): _description_. Defaults to None. + """ + # Loop through the self.max_loops + for i in range(self.max_loops): + self.run(task, *args, **kwargs) + + async def aloop( + self, + task: Optional[str] = None, + *args, + **kwargs, + ): + """Asynchronous loop through the swarm + + Args: + task (Optional[str], optional): _description_. Defaults to None. + """ + # Async Loop through the self.max_loops + loop = asyncio.get_event_loop() + result = await loop.run_in_executor( + None, self.loop, task, *args, **kwargs + ) + return result + + def run_async(self, task: Optional[str] = None, *args, **kwargs): + """Run the swarm asynchronously + + Args: + task (Optional[str], optional): _description_. Defaults to None. + """ + loop = asyncio.get_event_loop() + result = loop.run_until_complete( + self.arun(task, *args, **kwargs) + ) + return result + + def run_batch_async(self, tasks: List[str], *args, **kwargs): + """Run the swarm asynchronously + + Args: + task (Optional[str], optional): _description_. Defaults to None. + """ + loop = asyncio.get_event_loop() + result = loop.run_until_complete( + self.abatch_run(tasks, *args, **kwargs) + ) + return result + + def run_batch(self, tasks: List[str], *args, **kwargs): + """Run the swarm asynchronously + + Args: + task (Optional[str], optional): _description_. Defaults to None. + """ + return self.batched_run(tasks, *args, **kwargs) + + def reset_all_agents(self): + """Reset all agents + + Returns: + + """ + for agent in self.agents: + agent.reset() + + def select_agent(self, agent_id: str): + """ + Select an agent through their id + """ + # Find agent with id + for agent in self.agents: + if agent.id == agent_id: + return agent + + def select_agent_by_name(self, agent_name: str): + """ + Select an agent through their name + """ + # Find agent with id + for agent in self.agents: + if agent.name == agent_name: + return agent + + def task_assignment_by_id( + self, task: str, agent_id: str, *args, **kwargs + ): + """ + Assign a task to an agent + """ + # Assign task to agent by their agent id + agent = self.select_agent(agent_id) + return agent.run(task, *args, **kwargs) + + \ No newline at end of file diff --git a/swarms/utils/__init__.py b/swarms/utils/__init__.py index 018f1818..7c3ef717 100644 --- a/swarms/utils/__init__.py +++ b/swarms/utils/__init__.py @@ -4,6 +4,7 @@ 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.phoenix_handler import phoenix_trace_decorator __all__ = [ diff --git a/tests/models/test_huggingface.py b/tests/models/test_huggingface.py index 17a89535..7e19a056 100644 --- a/tests/models/test_huggingface.py +++ b/tests/models/test_huggingface.py @@ -39,16 +39,16 @@ def test_llm_bad_model_initialization(): HuggingfaceLLM(model_id="unknown-model") -# Mocking the tokenizer and model to test run method -@patch("swarms.models.huggingface.AutoTokenizer.from_pretrained") -@patch( - "swarms.models.huggingface.AutoModelForCausalLM.from_pretrained" -) -def test_llm_run(mock_model, mock_tokenizer, llm_instance): - mock_model.return_value.generate.return_value = "mocked output" - mock_tokenizer.return_value.encode.return_value = "mocked input" - result = llm_instance.run("test task") - assert result == "mocked output" +# # Mocking the tokenizer and model to test run method +# @patch("swarms.models.huggingface.AutoTokenizer.from_pretrained") +# @patch( +# "swarms.models.huggingface.AutoModelForCausalLM.from_pretrained" +# ) +# def test_llm_run(mock_model, mock_tokenizer, llm_instance): +# mock_model.return_value.generate.return_value = "mocked output" +# mock_tokenizer.return_value.encode.return_value = "mocked input" +# result = llm_instance.run("test task") +# assert result == "mocked output" # Async test (requires pytest-asyncio plugin)