parent
fdb2be5ee5
commit
d25b43c9d9
@ -0,0 +1,895 @@
|
||||
import math
|
||||
from typing import List, Union, Dict
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from swarms.structs.agent import Agent
|
||||
from swarms.structs.omni_agent_types import AgentListType
|
||||
from swarms.structs.conversation import Conversation
|
||||
|
||||
|
||||
# Base Swarm class that all other swarm types will inherit from
|
||||
class BaseSwarm:
|
||||
def __init__(self, agents: AgentListType):
|
||||
# Ensure agents is a flat list of Agent objects
|
||||
self.agents = (
|
||||
[agent for sublist in agents for agent in sublist]
|
||||
if isinstance(agents[0], list)
|
||||
else agents
|
||||
)
|
||||
self.conversation = Conversation()
|
||||
|
||||
def run(
|
||||
self, tasks: List[str], return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the swarm with the given tasks
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not tasks:
|
||||
raise ValueError(
|
||||
"Agents and tasks lists cannot be empty."
|
||||
)
|
||||
|
||||
# Implementation will be overridden by child classes
|
||||
raise NotImplementedError(
|
||||
"This method should be implemented by child classes"
|
||||
)
|
||||
|
||||
def _format_return(
|
||||
self, return_type: str
|
||||
) -> Union[Dict, List, str]:
|
||||
"""Format the return value based on the return_type"""
|
||||
if return_type.lower() == "dict":
|
||||
return self.conversation.return_messages_as_dictionary()
|
||||
elif return_type.lower() == "list":
|
||||
return self.conversation.return_messages_as_list()
|
||||
elif return_type.lower() == "string":
|
||||
return self.conversation.return_history_as_string()
|
||||
else:
|
||||
raise ValueError(
|
||||
"return_type must be one of 'dict', 'list', or 'string'"
|
||||
)
|
||||
|
||||
|
||||
class CircularSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a circular swarm where agents pass tasks in a circular manner.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, tasks: List[str], return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the circular swarm with the given tasks
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not tasks:
|
||||
raise ValueError(
|
||||
"Agents and tasks lists cannot be empty."
|
||||
)
|
||||
|
||||
responses = []
|
||||
|
||||
for task in tasks:
|
||||
for agent in self.agents:
|
||||
response = agent.run(task)
|
||||
self.conversation.add(
|
||||
role=agent.agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class LinearSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a linear swarm where agents process tasks sequentially.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, tasks: List[str], return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the linear swarm with the given tasks
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not tasks:
|
||||
raise ValueError(
|
||||
"Agents and tasks lists cannot be empty."
|
||||
)
|
||||
|
||||
tasks_copy = tasks.copy()
|
||||
responses = []
|
||||
|
||||
for agent in self.agents:
|
||||
if tasks_copy:
|
||||
task = tasks_copy.pop(0)
|
||||
response = agent.run(task)
|
||||
self.conversation.add(
|
||||
role=agent.agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class StarSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a star swarm where a central agent processes all tasks, followed by others.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, tasks: List[str], return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the star swarm with the given tasks
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not tasks:
|
||||
raise ValueError(
|
||||
"Agents and tasks lists cannot be empty."
|
||||
)
|
||||
|
||||
responses = []
|
||||
center_agent = self.agents[0] # The central agent
|
||||
|
||||
for task in tasks:
|
||||
# Central agent processes the task
|
||||
center_response = center_agent.run(task)
|
||||
self.conversation.add(
|
||||
role=center_agent.agent_name,
|
||||
content=center_response,
|
||||
)
|
||||
responses.append(center_response)
|
||||
|
||||
# Other agents process the same task
|
||||
for agent in self.agents[1:]:
|
||||
response = agent.run(task)
|
||||
self.conversation.add(
|
||||
role=agent.agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class MeshSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a mesh swarm where agents work on tasks randomly from a task queue.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, tasks: List[str], return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the mesh swarm with the given tasks
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not tasks:
|
||||
raise ValueError(
|
||||
"Agents and tasks lists cannot be empty."
|
||||
)
|
||||
|
||||
task_queue = tasks.copy()
|
||||
responses = []
|
||||
|
||||
while task_queue:
|
||||
for agent in self.agents:
|
||||
if task_queue:
|
||||
task = task_queue.pop(0)
|
||||
response = agent.run(task)
|
||||
self.conversation.add(
|
||||
role=agent.agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class PyramidSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a pyramid swarm where agents are arranged in a pyramid structure.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, tasks: List[str], return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the pyramid swarm with the given tasks
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not tasks:
|
||||
raise ValueError(
|
||||
"Agents and tasks lists cannot be empty."
|
||||
)
|
||||
|
||||
tasks_copy = tasks.copy()
|
||||
responses = []
|
||||
|
||||
levels = int(
|
||||
(-1 + (1 + 8 * len(self.agents)) ** 0.5) / 2
|
||||
) # Number of levels in the pyramid
|
||||
|
||||
for i in range(levels):
|
||||
for j in range(i + 1):
|
||||
if tasks_copy:
|
||||
task = tasks_copy.pop(0)
|
||||
agent_index = int(i * (i + 1) / 2 + j)
|
||||
if agent_index < len(self.agents):
|
||||
response = self.agents[agent_index].run(task)
|
||||
self.conversation.add(
|
||||
role=self.agents[agent_index].agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class FibonacciSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a Fibonacci swarm where agents are arranged according to the Fibonacci sequence.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, tasks: List[str], return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the Fibonacci swarm with the given tasks
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not tasks:
|
||||
raise ValueError(
|
||||
"Agents and tasks lists cannot be empty."
|
||||
)
|
||||
|
||||
tasks_copy = tasks.copy()
|
||||
responses = []
|
||||
|
||||
fib = [1, 1]
|
||||
while len(fib) < len(self.agents):
|
||||
fib.append(fib[-1] + fib[-2])
|
||||
|
||||
for i in range(len(fib)):
|
||||
for j in range(fib[i]):
|
||||
agent_index = int(sum(fib[:i]) + j)
|
||||
if agent_index < len(self.agents) and tasks_copy:
|
||||
task = tasks_copy.pop(0)
|
||||
response = self.agents[agent_index].run(task)
|
||||
self.conversation.add(
|
||||
role=self.agents[agent_index].agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class PrimeSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a Prime swarm where agents at prime indices process tasks.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, tasks: List[str], return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the Prime swarm with the given tasks
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not tasks:
|
||||
raise ValueError(
|
||||
"Agents and tasks lists cannot be empty."
|
||||
)
|
||||
|
||||
tasks_copy = tasks.copy()
|
||||
responses = []
|
||||
|
||||
primes = [
|
||||
2,
|
||||
3,
|
||||
5,
|
||||
7,
|
||||
11,
|
||||
13,
|
||||
17,
|
||||
19,
|
||||
23,
|
||||
29,
|
||||
31,
|
||||
37,
|
||||
41,
|
||||
43,
|
||||
47,
|
||||
53,
|
||||
59,
|
||||
61,
|
||||
67,
|
||||
71,
|
||||
73,
|
||||
79,
|
||||
83,
|
||||
89,
|
||||
97,
|
||||
] # First 25 prime numbers
|
||||
|
||||
for prime in primes:
|
||||
if prime < len(self.agents) and tasks_copy:
|
||||
task = tasks_copy.pop(0)
|
||||
response = self.agents[prime].run(task)
|
||||
self.conversation.add(
|
||||
role=self.agents[prime].agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class PowerSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a Power swarm where agents at power-of-2 indices process tasks.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, tasks: List[str], return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the Power swarm with the given tasks
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not tasks:
|
||||
raise ValueError(
|
||||
"Agents and tasks lists cannot be empty."
|
||||
)
|
||||
|
||||
tasks_copy = tasks.copy()
|
||||
responses = []
|
||||
|
||||
powers = [2**i for i in range(int(len(self.agents) ** 0.5))]
|
||||
|
||||
for power in powers:
|
||||
if power < len(self.agents) and tasks_copy:
|
||||
task = tasks_copy.pop(0)
|
||||
response = self.agents[power].run(task)
|
||||
self.conversation.add(
|
||||
role=self.agents[power].agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class LogSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a Log swarm where agents at logarithmic indices process tasks.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, tasks: List[str], return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the Log swarm with the given tasks
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not tasks:
|
||||
raise ValueError(
|
||||
"Agents and tasks lists cannot be empty."
|
||||
)
|
||||
|
||||
tasks_copy = tasks.copy()
|
||||
responses = []
|
||||
|
||||
for i in range(len(self.agents)):
|
||||
index = 2**i
|
||||
if index < len(self.agents) and tasks_copy:
|
||||
task = tasks_copy.pop(0)
|
||||
response = self.agents[index].run(task)
|
||||
self.conversation.add(
|
||||
role=self.agents[index].agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class ExponentialSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements an Exponential swarm where agents at exponential indices process tasks.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, tasks: List[str], return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the Exponential swarm with the given tasks
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not tasks:
|
||||
raise ValueError(
|
||||
"Agents and tasks lists cannot be empty."
|
||||
)
|
||||
|
||||
tasks_copy = tasks.copy()
|
||||
responses = []
|
||||
|
||||
for i in range(len(self.agents)):
|
||||
index = min(int(2**i), len(self.agents) - 1)
|
||||
if tasks_copy:
|
||||
task = tasks_copy.pop(0)
|
||||
response = self.agents[index].run(task)
|
||||
self.conversation.add(
|
||||
role=self.agents[index].agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class GeometricSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a Geometric swarm where agents at geometrically increasing indices process tasks.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, tasks: List[str], return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the Geometric swarm with the given tasks
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not tasks:
|
||||
raise ValueError(
|
||||
"Agents and tasks lists cannot be empty."
|
||||
)
|
||||
|
||||
tasks_copy = tasks.copy()
|
||||
responses = []
|
||||
ratio = 2
|
||||
|
||||
for i in range(len(self.agents)):
|
||||
index = min(int(ratio**i), len(self.agents) - 1)
|
||||
if tasks_copy:
|
||||
task = tasks_copy.pop(0)
|
||||
response = self.agents[index].run(task)
|
||||
self.conversation.add(
|
||||
role=self.agents[index].agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class HarmonicSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a Harmonic swarm where agents at harmonically spaced indices process tasks.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, tasks: List[str], return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the Harmonic swarm with the given tasks
|
||||
|
||||
Args:
|
||||
tasks: List of tasks to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not tasks:
|
||||
raise ValueError(
|
||||
"Agents and tasks lists cannot be empty."
|
||||
)
|
||||
|
||||
tasks_copy = tasks.copy()
|
||||
responses = []
|
||||
|
||||
for i in range(1, len(self.agents) + 1):
|
||||
index = min(
|
||||
int(len(self.agents) / i), len(self.agents) - 1
|
||||
)
|
||||
if tasks_copy:
|
||||
task = tasks_copy.pop(0)
|
||||
response = self.agents[index].run(task)
|
||||
self.conversation.add(
|
||||
role=self.agents[index].agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class StaircaseSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a Staircase swarm where agents at staircase-patterned indices process a task.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, task: str, return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the Staircase swarm with the given task
|
||||
|
||||
Args:
|
||||
task: Task to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not task:
|
||||
raise ValueError("Agents and task cannot be empty.")
|
||||
|
||||
responses = []
|
||||
step = len(self.agents) // 5
|
||||
|
||||
for i in range(len(self.agents)):
|
||||
index = (i // step) * step
|
||||
if index < len(self.agents):
|
||||
response = self.agents[index].run(task)
|
||||
self.conversation.add(
|
||||
role=self.agents[index].agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class SigmoidSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a Sigmoid swarm where agents at sigmoid-distributed indices process a task.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, task: str, return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the Sigmoid swarm with the given task
|
||||
|
||||
Args:
|
||||
task: Task to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not task:
|
||||
raise ValueError("Agents and task cannot be empty.")
|
||||
|
||||
responses = []
|
||||
|
||||
for i in range(len(self.agents)):
|
||||
index = int(len(self.agents) / (1 + math.exp(-i)))
|
||||
if index < len(self.agents):
|
||||
response = self.agents[index].run(task)
|
||||
self.conversation.add(
|
||||
role=self.agents[index].agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
class SinusoidalSwarm(BaseSwarm):
|
||||
"""
|
||||
Implements a Sinusoidal swarm where agents at sinusoidally-distributed indices process a task.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self, task: str, return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the Sinusoidal swarm with the given task
|
||||
|
||||
Args:
|
||||
task: Task to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.agents or not task:
|
||||
raise ValueError("Agents and task cannot be empty.")
|
||||
|
||||
responses = []
|
||||
|
||||
for i in range(len(self.agents)):
|
||||
index = int((math.sin(i) + 1) / 2 * len(self.agents))
|
||||
if index < len(self.agents):
|
||||
response = self.agents[index].run(task)
|
||||
self.conversation.add(
|
||||
role=self.agents[index].agent_name,
|
||||
content=response,
|
||||
)
|
||||
responses.append(response)
|
||||
|
||||
return self._format_return(return_type)
|
||||
|
||||
|
||||
# Communication classes
|
||||
class OneToOne:
|
||||
"""
|
||||
Facilitates one-to-one communication between two agents.
|
||||
"""
|
||||
|
||||
def __init__(self, sender: Agent, receiver: Agent):
|
||||
self.sender = sender
|
||||
self.receiver = receiver
|
||||
self.conversation = Conversation()
|
||||
|
||||
def run(
|
||||
self, task: str, max_loops: int = 1, return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the one-to-one communication with the given task
|
||||
|
||||
Args:
|
||||
task: Task to be processed
|
||||
max_loops: Number of exchange iterations
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.sender or not self.receiver or not task:
|
||||
raise ValueError(
|
||||
"Sender, receiver, and task cannot be empty."
|
||||
)
|
||||
|
||||
responses = []
|
||||
|
||||
try:
|
||||
for loop in range(max_loops):
|
||||
# Sender processes the task
|
||||
sender_response = self.sender.run(task)
|
||||
self.conversation.add(
|
||||
role=self.sender.agent_name,
|
||||
content=sender_response,
|
||||
)
|
||||
responses.append(sender_response)
|
||||
|
||||
# Receiver processes the result of the sender
|
||||
receiver_response = self.receiver.run(sender_response)
|
||||
self.conversation.add(
|
||||
role=self.receiver.agent_name,
|
||||
content=receiver_response,
|
||||
)
|
||||
responses.append(receiver_response)
|
||||
|
||||
# Update task for next loop if needed
|
||||
if loop < max_loops - 1:
|
||||
task = receiver_response
|
||||
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"Error during one_to_one communication: {error}"
|
||||
)
|
||||
raise error
|
||||
|
||||
if return_type.lower() == "dict":
|
||||
return self.conversation.return_messages_as_dictionary()
|
||||
elif return_type.lower() == "list":
|
||||
return self.conversation.return_messages_as_list()
|
||||
elif return_type.lower() == "string":
|
||||
return self.conversation.return_history_as_string()
|
||||
else:
|
||||
raise ValueError(
|
||||
"return_type must be one of 'dict', 'list', or 'string'"
|
||||
)
|
||||
|
||||
|
||||
class Broadcast:
|
||||
"""
|
||||
Facilitates broadcasting from one agent to many agents.
|
||||
"""
|
||||
|
||||
def __init__(self, sender: Agent, receivers: AgentListType):
|
||||
self.sender = sender
|
||||
self.receivers = (
|
||||
[agent for sublist in receivers for agent in sublist]
|
||||
if isinstance(receivers[0], list)
|
||||
else receivers
|
||||
)
|
||||
self.conversation = Conversation()
|
||||
|
||||
def run(
|
||||
self, task: str, return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the broadcast communication with the given task
|
||||
|
||||
Args:
|
||||
task: Task to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.sender or not self.receivers or not task:
|
||||
raise ValueError(
|
||||
"Sender, receivers, and task cannot be empty."
|
||||
)
|
||||
|
||||
try:
|
||||
# First get the sender's broadcast message
|
||||
broadcast_message = self.sender.run(task)
|
||||
self.conversation.add(
|
||||
role=self.sender.agent_name,
|
||||
content=broadcast_message,
|
||||
)
|
||||
|
||||
# Then have all receivers process it
|
||||
for agent in self.receivers:
|
||||
response = agent.run(broadcast_message)
|
||||
self.conversation.add(
|
||||
role=agent.agent_name,
|
||||
content=response,
|
||||
)
|
||||
|
||||
if return_type.lower() == "dict":
|
||||
return (
|
||||
self.conversation.return_messages_as_dictionary()
|
||||
)
|
||||
elif return_type.lower() == "list":
|
||||
return self.conversation.return_messages_as_list()
|
||||
elif return_type.lower() == "string":
|
||||
return self.conversation.return_history_as_string()
|
||||
else:
|
||||
raise ValueError(
|
||||
"return_type must be one of 'dict', 'list', or 'string'"
|
||||
)
|
||||
|
||||
except Exception as error:
|
||||
logger.error(f"Error during broadcast: {error}")
|
||||
raise error
|
||||
|
||||
|
||||
class OneToThree:
|
||||
"""
|
||||
Facilitates one-to-three communication from one agent to exactly three agents.
|
||||
"""
|
||||
|
||||
def __init__(self, sender: Agent, receivers: AgentListType):
|
||||
if len(receivers) != 3:
|
||||
raise ValueError(
|
||||
"The number of receivers must be exactly 3."
|
||||
)
|
||||
|
||||
self.sender = sender
|
||||
self.receivers = receivers
|
||||
self.conversation = Conversation()
|
||||
|
||||
def run(
|
||||
self, task: str, return_type: str = "dict"
|
||||
) -> Union[Dict, List, str]:
|
||||
"""
|
||||
Run the one-to-three communication with the given task
|
||||
|
||||
Args:
|
||||
task: Task to be processed
|
||||
return_type: Type of return value, one of 'dict', 'list', or 'string'
|
||||
|
||||
Returns:
|
||||
Union[Dict, List, str]: The conversation history in the requested format
|
||||
"""
|
||||
if not self.sender or not task:
|
||||
raise ValueError("Sender and task cannot be empty.")
|
||||
|
||||
try:
|
||||
# Get sender's message
|
||||
sender_message = self.sender.run(task)
|
||||
self.conversation.add(
|
||||
role=self.sender.agent_name,
|
||||
content=sender_message,
|
||||
)
|
||||
|
||||
# Have each receiver process the message
|
||||
for i, agent in enumerate(self.receivers):
|
||||
response = agent.run(sender_message)
|
||||
self.conversation.add(
|
||||
role=agent.agent_name,
|
||||
content=response,
|
||||
)
|
||||
|
||||
if return_type.lower() == "dict":
|
||||
return (
|
||||
self.conversation.return_messages_as_dictionary()
|
||||
)
|
||||
elif return_type.lower() == "list":
|
||||
return self.conversation.return_messages_as_list()
|
||||
elif return_type.lower() == "string":
|
||||
return self.conversation.return_history_as_string()
|
||||
else:
|
||||
raise ValueError(
|
||||
"return_type must be one of 'dict', 'list', or 'string'"
|
||||
)
|
||||
|
||||
except Exception as error:
|
||||
logger.error(f"Error in one_to_three: {error}")
|
||||
raise error
|
Loading…
Reference in new issue