parent
4fbd2281f4
commit
d572cafce6
@ -0,0 +1,41 @@
|
|||||||
|
from swarms import Anthropic, Agent, SequentialWorkflow
|
||||||
|
|
||||||
|
|
||||||
|
# Initialize the language model agent (e.g., GPT-3)
|
||||||
|
|
||||||
|
llm = Anthropic()
|
||||||
|
|
||||||
|
|
||||||
|
# Initialize agents for individual tasks
|
||||||
|
|
||||||
|
agent1 = Agent(
|
||||||
|
agent_name="Blog generator", llm=llm, max_loops=1, dashboard=False
|
||||||
|
)
|
||||||
|
|
||||||
|
agent2 = Agent(
|
||||||
|
agent_name="summarizer", llm=llm, max_loops=1, dashboard=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Create the Sequential workflow
|
||||||
|
|
||||||
|
workflow = SequentialWorkflow(
|
||||||
|
max_loops=1, objective="Create a full blog and then summarize it"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Add tasks to the workflow
|
||||||
|
|
||||||
|
workflow.add(
|
||||||
|
"Generate a 10,000 word blog on health and wellness.", agent1
|
||||||
|
) # this task will be executed task,
|
||||||
|
|
||||||
|
workflow.add(
|
||||||
|
"Summarize the generated blog", agent2
|
||||||
|
) # then the next agent will accomplish this task
|
||||||
|
|
||||||
|
|
||||||
|
# Run the workflow
|
||||||
|
|
||||||
|
out = workflow.run()
|
||||||
|
print(f"{out}")
|
@ -1,203 +1,134 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, field
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from termcolor import colored
|
|
||||||
|
|
||||||
# from swarms.utils.logger import logger
|
|
||||||
from swarms.structs.agent import Agent
|
from swarms.structs.agent import Agent
|
||||||
from swarms.structs.conversation import Conversation
|
from swarms.structs.conversation import Conversation
|
||||||
from swarms.structs.task import Task
|
|
||||||
from swarms.utils.loguru_logger import logger
|
from swarms.utils.loguru_logger import logger
|
||||||
|
from swarms.utils.try_except_wrapper import try_except_wrapper
|
||||||
|
|
||||||
|
|
||||||
# SequentialWorkflow class definition using dataclasses
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class SequentialWorkflow:
|
class SequentialWorkflow:
|
||||||
"""
|
name: str = "Sequential Workflow"
|
||||||
SequentialWorkflow class for running a sequence of task_pool using N number of autonomous agents.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
max_loops (int): The maximum number of times to run the workflow.
|
|
||||||
dashboard (bool): Whether to display the dashboard for the workflow.
|
|
||||||
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
task_pool (List[Task]): The list of task_pool to execute.
|
|
||||||
max_loops (int): The maximum number of times to run the workflow.
|
|
||||||
dashboard (bool): Whether to display the dashboard for the workflow.
|
|
||||||
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
>>> from swarms.models import OpenAIChat
|
|
||||||
>>> from swarms.structs import SequentialWorkflow
|
|
||||||
>>> llm = OpenAIChat(openai_api_key="")
|
|
||||||
>>> workflow = SequentialWorkflow(max_loops=1)
|
|
||||||
>>> workflow.add("What's the weather in miami", llm)
|
|
||||||
>>> workflow.add("Create a report on these metrics", llm)
|
|
||||||
>>> workflow.run()
|
|
||||||
>>> workflow.task_pool
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
name: str = None
|
|
||||||
description: str = None
|
description: str = None
|
||||||
task_pool: List[Task] = None
|
objective: str = None
|
||||||
max_loops: int = 1
|
max_loops: int = 1
|
||||||
autosave: bool = False
|
autosave: bool = False
|
||||||
saved_state_filepath: Optional[str] = "sequential_workflow_state.json"
|
saved_state_filepath: Optional[str] = "sequential_workflow_state.json"
|
||||||
restore_state_filepath: Optional[str] = None
|
restore_state_filepath: Optional[str] = None
|
||||||
dashboard: bool = False
|
dashboard: bool = False
|
||||||
agents: List[Agent] = None
|
agent_pool: List[Agent] = field(default_factory=list)
|
||||||
|
# task_pool: List[str] = field(
|
||||||
|
# default_factory=list
|
||||||
|
# ) # List to store tasks
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
self.conversation = Conversation(
|
self.conversation = Conversation(
|
||||||
system_prompt=f"Objective: {self.description}",
|
|
||||||
time_enabled=True,
|
time_enabled=True,
|
||||||
autosave=True,
|
autosave=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Logging
|
# If objective exists then set it
|
||||||
logger.info("Number of agents activated:")
|
if self.objective is not None:
|
||||||
if self.agents:
|
self.conversation.system_prompt = self.objective
|
||||||
logger.info(f"Agents: {len(self.agents)}")
|
|
||||||
else:
|
def workflow_bootup(self):
|
||||||
logger.info("No agents activated.")
|
logger.info(f"{self.name} is activating...")
|
||||||
|
|
||||||
if self.task_pool:
|
for agent in self.agent_pool:
|
||||||
logger.info(f"Task Pool Size: {len(self.task_pool)}")
|
logger.info(f"Agent {agent.agent_name} Activated")
|
||||||
else:
|
|
||||||
logger.info("Task Pool is empty.")
|
@try_except_wrapper
|
||||||
|
def add(self, task: str, agent: Agent, *args, **kwargs):
|
||||||
def add(
|
self.agent_pool.append(agent)
|
||||||
self,
|
# self.task_pool.append(
|
||||||
task: Optional[Task] = None,
|
# task
|
||||||
tasks: Optional[List[Task]] = None,
|
# ) # Store tasks corresponding to each agent
|
||||||
*args,
|
|
||||||
**kwargs,
|
return self.conversation.add(
|
||||||
) -> None:
|
role=agent.agent_name, content=task, *args, **kwargs
|
||||||
"""
|
)
|
||||||
Add a task to the workflow.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
agent (Union[Callable, Agent]): The model or agent to execute the task.
|
|
||||||
task (str): The task description or the initial input for the Agent.
|
|
||||||
|
|
||||||
*args: Additional arguments to pass to the task execution.
|
|
||||||
**kwargs: Additional keyword arguments to pass to the task execution.
|
|
||||||
"""
|
|
||||||
for agent in self.agents:
|
|
||||||
out = agent(str(self.description))
|
|
||||||
self.conversation.add(agent.agent_name, out)
|
|
||||||
prompt = self.conversation.return_history_as_string()
|
|
||||||
out = agent(prompt)
|
|
||||||
|
|
||||||
return out
|
|
||||||
|
|
||||||
def reset_workflow(self) -> None:
|
def reset_workflow(self) -> None:
|
||||||
"""Resets the workflow by clearing the results of each task."""
|
self.conversation = {}
|
||||||
try:
|
|
||||||
for task in self.task_pool:
|
# @try_except_wrapper
|
||||||
task.result = None
|
# WITH TASK POOL
|
||||||
logger.info(
|
# def run(self):
|
||||||
f"[INFO][SequentialWorkflow] Reset task {task} in"
|
# if not self.agent_pool:
|
||||||
" workflow"
|
# raise ValueError("No agents have been added to the workflow.")
|
||||||
)
|
|
||||||
except Exception as error:
|
# self.workflow_bootup()
|
||||||
logger.error(
|
# loops = 0
|
||||||
colored(f"Error resetting workflow: {error}", "red"),
|
# prompt = None # Initialize prompt to None; will be updated with the output of each agent
|
||||||
)
|
# while loops < self.max_loops:
|
||||||
|
# for i, agent in enumerate(self.agent_pool):
|
||||||
def get_task_results(self) -> Dict[str, Any]:
|
# task = (
|
||||||
"""
|
# self.task_pool[i] if prompt is None else prompt
|
||||||
Returns the results of each task in the workflow.
|
# ) # Use initial task or the output from the previous agent
|
||||||
|
# logger.info(
|
||||||
Returns:
|
# f"Agent: {agent.agent_name} {i+1} is executing the task"
|
||||||
Dict[str, Any]: The results of each task in the workflow
|
# )
|
||||||
"""
|
# logger.info("\n")
|
||||||
try:
|
# output = agent.run(task)
|
||||||
return {
|
# if output is None:
|
||||||
task.description: task.result for task in self.task_pool
|
# logger.error(
|
||||||
}
|
# f"Agent {i+1} returned None for task: {task}"
|
||||||
except Exception as error:
|
# )
|
||||||
logger.error(
|
# raise ValueError(f"Agent {i+1} returned None.")
|
||||||
colored(f"Error getting task results: {error}", "red"),
|
# self.conversation.add(agent.agent_name, output)
|
||||||
)
|
# prompt = output # Update prompt with current agent's output to pass to the next agent
|
||||||
|
# logger.info(f"Prompt: {prompt}")
|
||||||
def remove_task(self, task: Task) -> None:
|
# loops += 1
|
||||||
"""Remove task_pool from sequential workflow"""
|
# return self.conversation.return_history_as_string()
|
||||||
try:
|
@try_except_wrapper
|
||||||
self.task_pool.remove(task)
|
def run(self):
|
||||||
logger.info(
|
if not self.agent_pool:
|
||||||
f"[INFO][SequentialWorkflow] Removed task {task} from"
|
raise ValueError("No agents have been added to the workflow.")
|
||||||
" workflow"
|
|
||||||
)
|
|
||||||
except Exception as error:
|
|
||||||
logger.error(
|
|
||||||
colored(
|
|
||||||
f"Error removing task from workflow: {error}",
|
|
||||||
"red",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
def run(self) -> None:
|
|
||||||
"""
|
|
||||||
Run the workflow.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
ValueError: If an Agent instance is used as a task and the 'task' argument is not provided.
|
|
||||||
|
|
||||||
"""
|
|
||||||
self.workflow_bootup()
|
self.workflow_bootup()
|
||||||
loops = 0
|
loops = 0
|
||||||
while loops < self.max_loops:
|
while loops < self.max_loops:
|
||||||
for i, agent in enumerate(self.agents):
|
previous_output = None # Initialize to None; will hold the output of the previous agent
|
||||||
logger.info(f"Agent {i+1} is executing the task.")
|
for i, agent in enumerate(self.agent_pool):
|
||||||
out = agent(self.description)
|
# Fetch the last task specific to this agent from the conversation history
|
||||||
self.conversation.add(agent.agent_name, str(out))
|
tasks_for_agent = [
|
||||||
prompt = self.conversation.return_history_as_string()
|
msg["content"]
|
||||||
print(prompt)
|
for msg in self.conversation.conversation_history
|
||||||
print("Next agent...........")
|
if msg["role"] == agent.agent_name
|
||||||
out = agent(prompt)
|
]
|
||||||
|
task = tasks_for_agent[-1] if tasks_for_agent else None
|
||||||
return out
|
|
||||||
# try:
|
if task is None and previous_output is not None:
|
||||||
# self.workflow_bootup()
|
# If no specific task for this agent, use the output from the previous agent
|
||||||
# loops = 0
|
task = previous_output
|
||||||
# while loops < self.max_loops:
|
|
||||||
# for i in range(len(self.task_pool)):
|
if task is None:
|
||||||
# task = self.task_pool[i]
|
# If no initial task is found, and there's no previous output, log error and skip this agent
|
||||||
# # Check if the current task can be executed
|
logger.error(
|
||||||
# if task.result is None:
|
f"No initial task found for agent {agent.agent_name}, and no previous output to use."
|
||||||
# # Get the inputs for the current task
|
)
|
||||||
# task.context(task)
|
continue
|
||||||
|
|
||||||
# result = task.execute()
|
logger.info(
|
||||||
|
f" \n Agent {i+1} ({agent.agent_name}) is executing the task: {task} \n"
|
||||||
# # Pass the inputs to the next task
|
)
|
||||||
# if i < len(self.task_pool) - 1:
|
|
||||||
# next_task = self.task_pool[i + 1]
|
# Space the log
|
||||||
# next_task.description = result
|
|
||||||
|
output = agent.run(task)
|
||||||
# # Execute the current task
|
if output is None:
|
||||||
# task.execute()
|
logger.error(
|
||||||
|
f"Agent {agent.agent_name} returned None for task: {task}"
|
||||||
# # Autosave the workflow state
|
)
|
||||||
# if self.autosave:
|
raise ValueError(
|
||||||
# self.save_workflow_state(
|
f"Agent {agent.agent_name} returned None."
|
||||||
# "sequential_workflow_state.json"
|
)
|
||||||
# )
|
|
||||||
|
# Update the conversation history with the new output using agent's role
|
||||||
# self.workflow_shutdown()
|
self.conversation.add(
|
||||||
# loops += 1
|
role=agent.agent_name, content=output
|
||||||
# except Exception as e:
|
)
|
||||||
# logger.error(
|
previous_output = output # Update the previous_output to pass to the next agent
|
||||||
# colored(
|
|
||||||
# (
|
loops += 1
|
||||||
# "Error initializing the Sequential workflow:"
|
return self.conversation.return_history_as_string()
|
||||||
# f" {e} try optimizing your inputs like the"
|
|
||||||
# " agent class and task description"
|
|
||||||
# ),
|
|
||||||
# "red",
|
|
||||||
# attrs=["bold", "underline"],
|
|
||||||
# )
|
|
||||||
# )
|
|
||||||
|
Loading…
Reference in new issue