[FEAT][SwarmRouter in YAML]

pull/606/merge
Your Name 3 months ago
parent 520bd5f6c2
commit 75938ae274

@ -609,7 +609,7 @@ You can now easily plug this custom Griptape agent into the **Swarms Framework**
### What is a Swarm?
A swarm, in the context of multi-agent systems, refers to a group of more than two agents working collaboratively to achieve a common goal. These agents can be software entities, such as llms that interact with each other to perform complex tasks. The concept of a swarm is inspired by natural systems like ant colonies or bird flocks, where simple individual behaviors lead to complex group dynamics and problem-solving capabilities.
A swarm refers to a group of more than two agents working collaboratively to achieve a common goal. These agents can be software entities, such as llms that interact with each other to perform complex tasks. The concept of a swarm is inspired by natural systems like ant colonies or bird flocks, where simple individual behaviors lead to complex group dynamics and problem-solving capabilities.
### How Swarm Architectures Facilitate Communication

@ -1,9 +1,9 @@
agents:
- agent_name: "Delaware-C-Corp-Tax-Deduction-Agent"
model:
model_name: "gpt-4o-mini"
temperature: 0.1
max_tokens: 2500
# model:
# model_name: "gpt-4o-mini"
# temperature: 0.1
# max_tokens: 2500
system_prompt: |
You are a highly specialized financial analysis agent focused on Delaware C Corps tax deductions. Your task is to provide expert advice on optimizing tax strategies for Delaware C Corps, ensuring compliance with all relevant tax laws and regulations. You should be well-versed in Delaware state tax codes and federal tax laws affecting C Corps. Your responses should include detailed explanations of tax deductions available to Delaware C Corps, including but not limited to:
- Research and Development (R&D) tax credits
@ -26,10 +26,10 @@ agents:
task: "What are the most effective tax deduction strategies for a Delaware C Corp in the technology industry?"
- agent_name: "Delaware-C-Corp-Tax-Optimization-Agent"
model:
model_name: "gpt-4o-mini"
temperature: 0.2
max_tokens: 2000
# model:
# model_name: "gpt-4o-mini"
# temperature: 0.2
# max_tokens: 2000
system_prompt: |
You are a highly specialized financial analysis agent focused on Delaware C Corps tax optimization. Your task is to provide expert advice on optimizing tax strategies for Delaware C Corps, ensuring compliance with all relevant tax laws and regulations. You should be well-versed in Delaware state tax codes and federal tax laws affecting C Corps. Your responses should include detailed explanations of tax optimization strategies available to Delaware C Corps, including but not limited to:
- Entity structure optimization

@ -0,0 +1,53 @@
agents:
- agent_name: "Delaware-C-Corp-Tax-Deduction-Agent"
system_prompt: |
You are a highly specialized financial analysis agent focused on Delaware C Corps tax deductions. Your task is to provide expert advice on optimizing tax strategies for Delaware C Corps, ensuring compliance with all relevant tax laws and regulations. You should be well-versed in Delaware state tax codes and federal tax laws affecting C Corps. Your responses should include detailed explanations of tax deductions available to Delaware C Corps, including but not limited to:
- Research and Development (R&D) tax credits
- Depreciation and amortization
- Business expense deductions
- Charitable contributions
- State-specific tax incentives
- Federal tax deductions applicable to C Corps
max_loops: 1
autosave: true
dashboard: false
verbose: true
dynamic_temperature_enabled: true
saved_state_path: "delaware_c_corp_tax_deduction_agent.json"
user_name: "swarms_corp"
retry_attempts: 1
context_length: 250000
return_step_meta: false
output_type: "str" # Can be "json" or any other format
task: "What are the most effective tax deduction strategies for a Delaware C Corp in the technology industry?"
- agent_name: "Delaware-C-Corp-Tax-Optimization-Agent"
system_prompt: |
You are a highly specialized financial analysis agent focused on Delaware C Corps tax optimization. Your task is to provide expert advice on optimizing tax strategies for Delaware C Corps, ensuring compliance with all relevant tax laws and regulations. You should be well-versed in Delaware state tax codes and federal tax laws affecting C Corps. Your responses should include detailed explanations of tax optimization strategies available to Delaware C Corps, including but not limited to:
- Entity structure optimization
- Income shifting strategies
- Loss utilization and carryovers
- Tax-efficient supply chain management
- State-specific tax planning
- Federal tax planning applicable to C Corps
max_loops: 2
autosave: true
dashboard: false
verbose: true
dynamic_temperature_enabled: false
saved_state_path: "delaware_c_corp_tax_optimization_agent.json"
user_name: "tax_optimization_user"
retry_attempts: 3
context_length: 200000
return_step_meta: true
output_type: "str"
task: "How can a Delaware C Corp in the finance industry optimize its tax strategy for maximum savings?"
swarm_architecture:
name: "MySwarm"
description: "A swarm for collaborative task solving"
max_loops: 5
swarm_type: "ConcurrentWorkflow"
task: "How can we trademark concepts as a delaware C CORP for free"

@ -59,10 +59,10 @@ The function relies on a YAML file for defining agents and tasks. Below is an ex
```yaml
agents:
- agent_name: "Financial-Analysis-Agent"
model:
model_name: "gpt-4o-mini"
temperature: 0.1
max_tokens: 2000
# model:
# model_name: "gpt-4o-mini"
# temperature: 0.1
# max_tokens: 2000
system_prompt: "Your full system prompt here"
max_loops: 1
autosave: true
@ -78,10 +78,10 @@ agents:
task: "How can I establish a ROTH IRA to buy stocks and get a tax break?"
- agent_name: "Stock-Analysis-Agent"
model:
model_name: "gpt-4o-mini"
temperature: 0.2
max_tokens: 1500
# model:
# model_name: "gpt-4o-mini"
# temperature: 0.2
# max_tokens: 1500
system_prompt: "Your full system prompt here"
max_loops: 2
autosave: true
@ -112,44 +112,45 @@ agents:
---
# Example: Creating Agents and Running Tasks
### Full Code Example
### Example 1: Creating and Returning Agents
```python
from swarms import create_agents_from_yaml
import os
yaml_file = 'agents_config.yaml'
agents = create_agents_from_yaml(yaml_file, return_type="agents")
from dotenv import load_dotenv
from loguru import logger
from swarm_models import OpenAIChat # any model from swarm_models
for agent in agents:
print(f"Agent {agent.agent_name} created.")
```
from swarms.agents.create_agents_from_yaml import (
create_agents_from_yaml,
)
### Example 2: Creating Agents and Returning Task Results
```python
from swarms import create_agents_from_yaml
# Load environment variables
load_dotenv()
yaml_file = 'agents_config.yaml'
task_results = create_agents_from_yaml(yaml_file, return_type="tasks")
# Path to your YAML file
yaml_file = "agents.yaml"
for result in task_results:
print(f"Agent {result['agent_name']} executed task '{result['task']}': {result['output']}")
```
# Get the OpenAI API key from the environment variable
api_key = os.getenv("OPENAI_API_KEY")
### Example 3: Returning Both Agents and Task Results
```python
from swarms import create_agents_from_yaml
# Create an instance of the OpenAIChat class
model = OpenAIChat(
openai_api_key=api_key, model_name="gpt-4o-mini", temperature=0.1
)
try:
# Create agents and run tasks (using 'both' to return agents and task results)
task_results = create_agents_from_yaml(
model=model, yaml_file=yaml_file, return_type="tasks"
)
yaml_file = 'agents_config.yaml'
agents, task_results = create_agents_from_yaml(yaml_file, return_type="both")
logger.info(f"Results from agents: {task_results}")
except Exception as e:
logger.error(f"An error occurred: {e}")
# Handling agents
for agent in agents:
print(f"Agent {agent.agent_name} created.")
# Handling task results
for result in task_results:
print(f"Agent {result['agent_name']} executed task '{result['task']}': {result['output']}")
```
---

@ -1,7 +1,7 @@
# Swarm Architectures
### What is a Swarm?
A swarm, in the context of multi-agent systems, refers to a group of more than two agents working collaboratively to achieve a common goal. These agents can be software entities, such as llms that interact with each other to perform complex tasks. The concept of a swarm is inspired by natural systems like ant colonies or bird flocks, where simple individual behaviors lead to complex group dynamics and problem-solving capabilities.
A swarm refers to a group of more than two agents working collaboratively to achieve a common goal. These agents can be software entities, such as llms that interact with each other to perform complex tasks. The concept of a swarm is inspired by natural systems like ant colonies or bird flocks, where simple individual behaviors lead to complex group dynamics and problem-solving capabilities.
### How Swarm Architectures Facilitate Communication

@ -133,26 +133,40 @@ Now, create the main Python script that will use the `create_agents_from_yaml` f
### `main.py`:
```python
import os
from loguru import logger
from dotenv import load_dotenv
from swarms import create_agents_from_yaml
from loguru import logger
from swarm_models import OpenAIChat
from swarms.agents.create_agents_from_yaml import (
create_agents_from_yaml,
)
# Load environment variables
load_dotenv()
# Path to your YAML file
yaml_file = 'agents_config.yaml'
yaml_file = "agents.yaml"
# Get the OpenAI API key from the environment variable
api_key = os.getenv("OPENAI_API_KEY")
# Create an instance of the OpenAIChat class
model = OpenAIChat(
openai_api_key=api_key, model_name="gpt-4o-mini", temperature=0.1
)
try:
# Create agents and run tasks (using 'both' to return agents and task results)
agents, task_results = create_agents_from_yaml(yaml_file, return_type="both")
# Print the results of the tasks
for result in task_results:
print(f"Agent: {result['agent_name']} | Task: {result['task']} | Output: {result.get('output', 'Error encountered')}")
task_results = create_agents_from_yaml(
model=model, yaml_file=yaml_file, return_type="tasks"
)
logger.info(f"Results from agents: {task_results}")
except Exception as e:
logger.error(f"An error occurred: {e}")
```
### Example Run:

@ -1,5 +1,9 @@
from loguru import logger
import os
from dotenv import load_dotenv
from loguru import logger
from swarm_models import OpenAIChat
from swarms.agents.create_agents_from_yaml import (
create_agents_from_yaml,
)
@ -10,10 +14,19 @@ load_dotenv()
# Path to your YAML file
yaml_file = "agents.yaml"
# Get the OpenAI API key from the environment variable
api_key = os.getenv("OPENAI_API_KEY")
# Create an instance of the OpenAIChat class
model = OpenAIChat(
openai_api_key=api_key, model_name="gpt-4o-mini", temperature=0.1
)
try:
# Create agents and run tasks (using 'both' to return agents and task results)
task_results = create_agents_from_yaml(
yaml_file, return_type="tasks"
model=model, yaml_file=yaml_file, return_type="tasks"
)
logger.info(f"Results from agents: {task_results}")

@ -0,0 +1,37 @@
import os
from dotenv import load_dotenv
from loguru import logger
from swarm_models import OpenAIChat
from swarms.agents.create_agents_from_yaml import (
create_agents_from_yaml,
)
# Load environment variables
load_dotenv()
# Path to your YAML file
yaml_file = "agents_multi_agent.yaml"
# Get the OpenAI API key from the environment variable
api_key = os.getenv("GROQ_API_KEY")
# Model
model = OpenAIChat(
openai_api_base="https://api.groq.com/openai/v1",
openai_api_key=api_key,
model_name="llama-3.1-70b-versatile",
temperature=0.1,
)
try:
# Create agents and run tasks (using 'both' to return agents and task results)
task_results = create_agents_from_yaml(
model=model, yaml_file=yaml_file, return_type="run_swarm"
)
logger.info(f"Results from agents: {task_results}")
except Exception as e:
logger.error(f"An error occurred: {e}")

@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "swarms"
version = "5.8.4"
version = "5.8.5"
description = "Swarms - Pytorch"
license = "MIT"
authors = ["Kye Gomez <kye@apac.ai>"]

@ -0,0 +1,205 @@
import os
from swarms import Agent, AgentRearrange
from swarm_models import OpenAIChat
# model = Anthropic(anthropic_api_key=os.getenv("ANTHROPIC_API_KEY"))
company = "TGSC"
# Get the OpenAI API key from the environment variable
api_key = os.getenv("GROQ_API_KEY")
# Model
model = OpenAIChat(
openai_api_base="https://api.groq.com/openai/v1",
openai_api_key=api_key,
model_name="llama-3.1-70b-versatile",
temperature=0.1,
)
# Initialize the Managing Director agent
managing_director = Agent(
agent_name="Managing-Director",
system_prompt=f"""
As the Managing Director at Blackstone, your role is to oversee the entire investment analysis process for potential acquisitions.
Your responsibilities include:
1. Setting the overall strategy and direction for the analysis
2. Coordinating the efforts of the various team members and ensuring a comprehensive evaluation
3. Reviewing the findings and recommendations from each team member
4. Making the final decision on whether to proceed with the acquisition
For the current potential acquisition of {company}, direct the tasks for the team to thoroughly analyze all aspects of the company, including its financials, industry position, technology, market potential, and regulatory compliance. Provide guidance and feedback as needed to ensure a rigorous and unbiased assessment.
""",
llm=model,
max_loops=1,
dashboard=False,
streaming_on=True,
verbose=True,
stopping_token="<DONE>",
state_save_file_type="json",
saved_state_path="managing-director.json",
)
# Initialize the Vice President of Finance
vp_finance = Agent(
agent_name="VP-Finance",
system_prompt=f"""
As the Vice President of Finance at Blackstone, your role is to lead the financial analysis of potential acquisitions.
For the current potential acquisition of {company}, your tasks include:
1. Conducting a thorough review of {company}' financial statements, including income statements, balance sheets, and cash flow statements
2. Analyzing key financial metrics such as revenue growth, profitability margins, liquidity ratios, and debt levels
3. Assessing the company's historical financial performance and projecting future performance based on assumptions and market conditions
4. Identifying any financial risks or red flags that could impact the acquisition decision
5. Providing a detailed report on your findings and recommendations to the Managing Director
Be sure to consider factors such as the sustainability of {company}' business model, the strength of its customer base, and its ability to generate consistent cash flows. Your analysis should be data-driven, objective, and aligned with Blackstone's investment criteria.
""",
llm=model,
max_loops=1,
dashboard=False,
streaming_on=True,
verbose=True,
stopping_token="<DONE>",
state_save_file_type="json",
saved_state_path="vp-finance.json",
)
# Initialize the Industry Analyst
industry_analyst = Agent(
agent_name="Industry-Analyst",
system_prompt=f"""
As the Industry Analyst at Blackstone, your role is to provide in-depth research and analysis on the industries and markets relevant to potential acquisitions.
For the current potential acquisition of {company}, your tasks include:
1. Conducting a comprehensive analysis of the industrial robotics and automation solutions industry, including market size, growth rates, key trends, and future prospects
2. Identifying the major players in the industry and assessing their market share, competitive strengths and weaknesses, and strategic positioning
3. Evaluating {company}' competitive position within the industry, including its market share, differentiation, and competitive advantages
4. Analyzing the key drivers and restraints for the industry, such as technological advancements, labor costs, regulatory changes, and economic conditions
5. Identifying potential risks and opportunities for {company} based on the industry analysis, such as disruptive technologies, emerging markets, or shifts in customer preferences
Your analysis should provide a clear and objective assessment of the attractiveness and future potential of the industrial robotics industry, as well as {company}' positioning within it. Consider both short-term and long-term factors, and provide evidence-based insights to inform the investment decision.
""",
llm=model,
max_loops=1,
dashboard=False,
streaming_on=True,
verbose=True,
stopping_token="<DONE>",
state_save_file_type="json",
saved_state_path="industry-analyst.json",
)
# Initialize the Technology Expert
tech_expert = Agent(
agent_name="Tech-Expert",
system_prompt=f"""
As the Technology Expert at Blackstone, your role is to assess the technological capabilities, competitive advantages, and potential risks of companies being considered for acquisition.
For the current potential acquisition of {company}, your tasks include:
1. Conducting a deep dive into {company}' proprietary technologies, including its robotics platforms, automation software, and AI capabilities
2. Assessing the uniqueness, scalability, and defensibility of {company}' technology stack and intellectual property
3. Comparing {company}' technologies to those of its competitors and identifying any key differentiators or technology gaps
4. Evaluating {company}' research and development capabilities, including its innovation pipeline, engineering talent, and R&D investments
5. Identifying any potential technology risks or disruptive threats that could impact {company}' long-term competitiveness, such as emerging technologies or expiring patents
Your analysis should provide a comprehensive assessment of {company}' technological strengths and weaknesses, as well as the sustainability of its competitive advantages. Consider both the current state of its technology and its future potential in light of industry trends and advancements.
""",
llm=model,
max_loops=1,
dashboard=False,
streaming_on=True,
verbose=True,
stopping_token="<DONE>",
state_save_file_type="json",
saved_state_path="tech-expert.json",
)
# Initialize the Market Researcher
market_researcher = Agent(
agent_name="Market-Researcher",
system_prompt=f"""
As the Market Researcher at Blackstone, your role is to analyze the target company's customer base, market share, and growth potential to assess the commercial viability and attractiveness of the potential acquisition.
For the current potential acquisition of {company}, your tasks include:
1. Analyzing {company}' current customer base, including customer segmentation, concentration risk, and retention rates
2. Assessing {company}' market share within its target markets and identifying key factors driving its market position
3. Conducting a detailed market sizing and segmentation analysis for the industrial robotics and automation markets, including identifying high-growth segments and emerging opportunities
4. Evaluating the demand drivers and sales cycles for {company}' products and services, and identifying any potential risks or limitations to adoption
5. Developing financial projections and estimates for {company}' revenue growth potential based on the market analysis and assumptions around market share and penetration
Your analysis should provide a data-driven assessment of the market opportunity for {company} and the feasibility of achieving our investment return targets. Consider both bottom-up and top-down market perspectives, and identify any key sensitivities or assumptions in your projections.
""",
llm=model,
max_loops=1,
dashboard=False,
streaming_on=True,
verbose=True,
stopping_token="<DONE>",
state_save_file_type="json",
saved_state_path="market-researcher.json",
)
# Initialize the Regulatory Specialist
regulatory_specialist = Agent(
agent_name="Regulatory-Specialist",
system_prompt=f"""
As the Regulatory Specialist at Blackstone, your role is to identify and assess any regulatory risks, compliance requirements, and potential legal liabilities associated with potential acquisitions.
For the current potential acquisition of {company}, your tasks include:
1. Identifying all relevant regulatory bodies and laws that govern the operations of {company}, including industry-specific regulations, labor laws, and environmental regulations
2. Reviewing {company}' current compliance policies, procedures, and track record to identify any potential gaps or areas of non-compliance
3. Assessing the potential impact of any pending or proposed changes to relevant regulations that could affect {company}' business or create additional compliance burdens
4. Evaluating the potential legal liabilities and risks associated with {company}' products, services, and operations, including product liability, intellectual property, and customer contracts
5. Providing recommendations on any regulatory or legal due diligence steps that should be taken as part of the acquisition process, as well as any post-acquisition integration considerations
Your analysis should provide a comprehensive assessment of the regulatory and legal landscape surrounding {company}, and identify any material risks or potential deal-breakers. Consider both the current state and future outlook, and provide practical recommendations to mitigate identified risks.
""",
llm=model,
max_loops=1,
dashboard=False,
streaming_on=True,
verbose=True,
stopping_token="<DONE>",
state_save_file_type="json",
saved_state_path="regulatory-specialist.json",
)
# Create a list of agents
agents = [
managing_director,
vp_finance,
industry_analyst,
tech_expert,
market_researcher,
regulatory_specialist,
]
# Define multiple flow patterns
flows = [
"Industry-Analyst -> Tech-Expert -> Market-Researcher -> Regulatory-Specialist -> Managing-Director -> VP-Finance",
"Managing-Director -> VP-Finance -> Industry-Analyst -> Tech-Expert -> Market-Researcher -> Regulatory-Specialist",
"Tech-Expert -> Market-Researcher -> Regulatory-Specialist -> Industry-Analyst -> Managing-Director -> VP-Finance",
]
# Create instances of AgentRearrange for each flow pattern
blackstone_acquisition_analysis = AgentRearrange(
name="Blackstone-Acquisition-Analysis",
description="A system for analyzing potential acquisitions",
agents=agents,
flow=flows[0],
)
blackstone_investment_strategy = AgentRearrange(
name="Blackstone-Investment-Strategy",
description="A system for evaluating investment opportunities",
agents=agents,
flow=flows[1],
)
blackstone_market_analysis = AgentRearrange(
name="Blackstone-Market-Analysis",
description="A system for analyzing market trends and opportunities",
agents=agents,
flow=flows[2],
)
# Example of running each system
# output = blackstone_acquisition_analysis.run(
# f"Analyze the potential acquisition of {company}, a leading manufacturer of industrial robots and automation solutions."
# )
# print(output)

@ -0,0 +1,363 @@
import threading
import time
import uuid
from typing import Any, Callable, Dict, List, Optional
from swarms.utils.loguru_logger import logger
def swarm_id():
return uuid.uuid4().hex
class SwarmArrangeInput:
id: str = uuid.uuid4().hex
time_stamp: str = time.strftime("%Y-%m-%d %H:%M:%S")
name: str
description: str
swarms: List[Callable] = []
output_type: str
flow: str = ""
class SwarmArrangeOutput:
input_config: SwarmArrangeInput = None
class SwarmRearrange:
"""
A class representing a swarm of swarms for rearranging tasks.
Attributes:
swarms (dict): A dictionary of swarms, where the key is the swarm's name and the value is the swarm object.
flow (str): The flow pattern of the tasks.
Methods:
__init__(swarms: List[swarm] = None, flow: str = None): Initializes the SwarmRearrange object.
add_swarm(swarm: swarm): Adds an swarm to the swarm.
remove_swarm(swarm_name: str): Removes an swarm from the swarm.
add_swarms(swarms: List[swarm]): Adds multiple swarms to the swarm.
validate_flow(): Validates the flow pattern.
run(task): Runs the swarm to rearrange the tasks.
"""
def __init__(
self,
id: str = swarm_id(),
name: str = "SwarmRearrange",
description: str = "A swarm of swarms for rearranging tasks.",
swarms: List[Any] = [],
flow: str = None,
max_loops: int = 1,
verbose: bool = True,
human_in_the_loop: bool = False,
custom_human_in_the_loop: Optional[
Callable[[str], str]
] = None,
return_json: bool = False,
*args,
**kwargs,
):
"""
Initializes the SwarmRearrange object.
Args:
swarms (List[swarm], optional): A list of swarm objects. Defaults to None.
flow (str, optional): The flow pattern of the tasks. Defaults to None.
"""
self.id = id
self.name = name
self.description = description
self.swarms = {swarm.name: swarm for swarm in swarms}
self.flow = flow if flow is not None else ""
self.verbose = verbose
self.max_loops = max_loops if max_loops > 0 else 1
self.human_in_the_loop = human_in_the_loop
self.custom_human_in_the_loop = custom_human_in_the_loop
self.return_json = return_json
self.swarm_history = {swarm.name: [] for swarm in swarms}
self.lock = threading.Lock()
self.id = uuid.uuid4().hex if id is None else id
# Run the relianility checks
self.reliability_checks()
# # Output schema
# self.input_config = SwarmRearrangeInput(
# swarm_id=self.id,
# name=self.name,
# description=self.description,
# flow=self.flow,
# max_loops=self.max_loops,
# )
# # Output schema
# self.output_schema = SwarmRearrangeOutput(
# Input=self.input_config,
# outputs=[],
# )
def reliability_checks(self):
logger.info("Running reliability checks.")
if self.swarms is None:
raise ValueError("No swarms found in the swarm.")
if self.flow is None:
raise ValueError("No flow found in the swarm.")
if self.max_loops is None:
raise ValueError("No max_loops found in the swarm.")
logger.info(
"SwarmRearrange initialized with swarms: {}".format(
list(self.swarms.keys())
)
)
# Verbose is True
if self.verbose is True:
logger.add("swarm_rearrange.log")
def set_custom_flow(self, flow: str):
self.flow = flow
logger.info(f"Custom flow set: {flow}")
def add_swarm(self, swarm: Any):
"""
Adds an swarm to the swarm.
Args:
swarm (swarm): The swarm to be added.
"""
logger.info(f"Adding swarm {swarm.name} to the swarm.")
self.swarms[swarm.name] = swarm
def track_history(
self,
swarm_name: str,
result: str,
):
self.swarm_history[swarm_name].append(result)
def remove_swarm(self, swarm_name: str):
"""
Removes an swarm from the swarm.
Args:
swarm_name (str): The name of the swarm to be removed.
"""
del self.swarms[swarm_name]
def add_swarms(self, swarms: List[Any]):
"""
Adds multiple swarms to the swarm.
Args:
swarms (List[swarm]): A list of swarm objects.
"""
for swarm in swarms:
self.swarms[swarm.name] = swarm
def validate_flow(self):
"""
Validates the flow pattern.
Raises:
ValueError: If the flow pattern is incorrectly formatted or contains duplicate swarm names.
Returns:
bool: True if the flow pattern is valid.
"""
if "->" not in self.flow:
raise ValueError(
"Flow must include '->' to denote the direction of the task."
)
swarms_in_flow = []
# Arrow
tasks = self.flow.split("->")
# For the task in tasks
for task in tasks:
swarm_names = [name.strip() for name in task.split(",")]
# Loop over the swarm names
for swarm_name in swarm_names:
if (
swarm_name not in self.swarms
and swarm_name != "H"
):
raise ValueError(
f"swarm '{swarm_name}' is not registered."
)
swarms_in_flow.append(swarm_name)
# If the length of the swarms does not equal the length of the swarms in flow
if len(set(swarms_in_flow)) != len(swarms_in_flow):
raise ValueError(
"Duplicate swarm names in the flow are not allowed."
)
print("Flow is valid.")
return True
def run(
self,
task: str = None,
img: str = None,
custom_tasks: Optional[Dict[str, str]] = None,
*args,
**kwargs,
):
"""
Runs the swarm to rearrange the tasks.
Args:
task: The initial task to be processed.
img: An optional image input.
custom_tasks: A dictionary of custom tasks for specific swarms.
Returns:
str: The final processed task.
"""
try:
if not self.validate_flow():
return "Invalid flow configuration."
tasks = self.flow.split("->")
current_task = task
# Check if custom_tasks is a dictionary and not empty
if isinstance(custom_tasks, dict) and custom_tasks:
c_swarm_name, c_task = next(
iter(custom_tasks.items())
)
# Find the position of the custom swarm in the tasks list
if c_swarm_name in tasks:
position = tasks.index(c_swarm_name)
# If there is a previous swarm, merge its task with the custom tasks
if position > 0:
tasks[position - 1] += "->" + c_task
else:
# If there is no previous swarm, just insert the custom tasks
tasks.insert(position, c_task)
# Set the loop counter
loop_count = 0
while loop_count < self.max_loops:
for task in tasks:
swarm_names = [
name.strip() for name in task.split(",")
]
if len(swarm_names) > 1:
# Parallel processing
logger.info(
f"Running swarms in parallel: {swarm_names}"
)
results = []
for swarm_name in swarm_names:
if swarm_name == "H":
# Human in the loop intervention
if (
self.human_in_the_loop
and self.custom_human_in_the_loop
):
current_task = (
self.custom_human_in_the_loop(
current_task
)
)
else:
current_task = input(
"Enter your response: "
)
else:
swarm = self.swarms[swarm_name]
result = swarm.run(
current_task, img, *args, **kwargs
)
logger.info(
f"Swarm {swarm_name} returned result of type: {type(result)}"
)
if isinstance(result, bool):
logger.warning(
f"Swarm {swarm_name} returned a boolean value: {result}"
)
result = str(
result
) # Convert boolean to string
results.append(result)
current_task = "; ".join(
str(r) for r in results if r is not None
)
else:
# Sequential processing
logger.info(
f"Running swarms sequentially: {swarm_names}"
)
swarm_name = swarm_names[0]
if swarm_name == "H":
# Human-in-the-loop intervention
if (
self.human_in_the_loop
and self.custom_human_in_the_loop
):
current_task = (
self.custom_human_in_the_loop(
current_task
)
)
else:
current_task = input(
"Enter the next task: "
)
else:
swarm = self.swarms[swarm_name]
result = swarm.run(
current_task, img, *args, **kwargs
)
logger.info(
f"Swarm {swarm_name} returned result of type: {type(result)}"
)
if isinstance(result, bool):
logger.warning(
f"Swarm {swarm_name} returned a boolean value: {result}"
)
result = str(
result
) # Convert boolean to string
current_task = (
result
if result is not None
else current_task
)
loop_count += 1
return current_task
except Exception as e:
logger.error(f"An error occurred: {e}")
return str(e)
def swarm_arrange(
name: str = "SwarmArrange-01",
description: str = "Combine multiple swarms and execute them sequentially",
swarms: List[Callable] = None,
output_type: str = "json",
flow: str = None,
task: str = None,
*args,
**kwargs,
):
return SwarmRearrange(
name,
description,
swarms,
output_type,
flow,
).run(task, *args, **kwargs)

@ -0,0 +1,21 @@
from swarm_arange import SwarmRearrange
from rearrange_example_blackstone import (
blackstone_acquisition_analysis,
blackstone_investment_strategy,
blackstone_market_analysis,
)
swarm_arrange = SwarmRearrange(
swarms=[
blackstone_acquisition_analysis,
blackstone_investment_strategy,
blackstone_market_analysis,
],
flow=f"{blackstone_acquisition_analysis.name} -> {blackstone_investment_strategy.name} -> {blackstone_market_analysis.name}",
)
print(
swarm_arrange.run(
"Analyze swarms, 150k revenue with 45m+ agents build, with 1.4m downloads since march 2024"
)
)

@ -1,46 +1,65 @@
import os
import yaml
from dotenv import load_dotenv
from loguru import logger
from swarm_models import OpenAIChat
from typing import Callable, List, Union, Tuple, Dict, Any
from swarms.structs.agent import Agent
from swarms.structs.swarm_router import SwarmRouter
load_dotenv()
# Function to create and optionally run agents from a YAML file
def create_agents_from_yaml(
yaml_file: str, return_type: str = "agents", *args, **kwargs
):
model: Callable = None,
yaml_file: str = "agents.yaml",
return_type: str = "auto",
*args,
**kwargs,
) -> Union[
SwarmRouter,
Agent,
List[Agent],
Tuple[Union[SwarmRouter, Agent], List[Agent]],
List[Dict[str, Any]],
]:
"""
Create agents based on configurations defined in a YAML file.
If a 'task' is provided in the YAML, the agent will execute the task after creation.
Create agents and/or SwarmRouter based on configurations defined in a YAML file.
This function dynamically creates agents and a SwarmRouter (if specified) based on the
configuration in the YAML file. It adapts its behavior based on the presence of a
swarm architecture and the number of agents defined.
Args:
yaml_file (str): Path to the YAML file containing agent configurations.
return_type (str): Determines the return value. "agents" to return agent list,
"tasks" to return task results, "both" to return both agents and tasks.
*args: Additional positional arguments for agent customization.
**kwargs: Additional keyword arguments for agent customization.
model (Callable): The language model to be used by the agents.
yaml_file (str): Path to the YAML file containing agent and swarm configurations.
return_type (str): Determines the return value. Options are:
"auto" (default): Automatically determine the most appropriate return type.
"swarm": Return SwarmRouter if present, otherwise a single agent or list of agents.
"agents": Return a list of agents (or a single agent if only one is defined).
"both": Return both SwarmRouter (or single agent) and list of agents.
"tasks": Return task results if any tasks were executed.
"run_swarm": Run the swarm and return its output.
*args: Additional positional arguments for agent or SwarmRouter customization.
**kwargs: Additional keyword arguments for agent or SwarmRouter customization.
Returns:
List[Agent] or List[Task Results] or Tuple(List[Agent], List[Task Results])
Union[SwarmRouter, Agent, List[Agent], Tuple[Union[SwarmRouter, Agent], List[Agent]], List[Dict[str, Any]]]:
The return type depends on the 'return_type' argument and the configuration in the YAML file.
Raises:
FileNotFoundError: If the specified YAML file is not found.
ValueError: If the YAML configuration is invalid or if an invalid return_type is specified.
"""
logger.info(f"Checking if the YAML file {yaml_file} exists...")
# Check if the YAML file exists
if not os.path.exists(yaml_file):
logger.error(f"YAML file {yaml_file} not found.")
raise FileNotFoundError(f"YAML file {yaml_file} not found.")
# Load the YAML configuration
logger.info(f"Loading YAML file {yaml_file}")
with open(yaml_file, "r") as file:
config = yaml.safe_load(file)
# Ensure agents key exists
if "agents" not in config:
logger.error(
"The YAML configuration does not contain 'agents'."
@ -49,39 +68,13 @@ def create_agents_from_yaml(
"The YAML configuration does not contain 'agents'."
)
# List to store created agents and task results
agents = []
task_results = []
# Iterate over each agent configuration and create agents
# Create agents
for agent_config in config["agents"]:
logger.info(f"Creating agent: {agent_config['agent_name']}")
# # Get the OpenAI API key from environment or YAML config
# api_key = (
# os.getenv("OPENAI_API_KEY")
# )
# Create an instance of OpenAIChat model
# model = OpenAIChat(
# openai_api_key=api_key,
# model_name=agent_config["model"]["model_name"],
# temperature=agent_config["model"]["temperature"],
# max_tokens=agent_config["model"]["max_tokens"],
# *args,
# **kwargs, # Pass any additional arguments to the model
# )
# Model
api_key = os.getenv("GROQ_API_KEY")
model = OpenAIChat(
openai_api_base="https://api.groq.com/openai/v1",
openai_api_key=api_key,
model_name="llama-3.1-70b-versatile",
temperature=0.1,
)
# Ensure the system prompt is provided
if "system_prompt" not in agent_config:
logger.error(
f"System prompt is missing for agent: {agent_config['agent_name']}"
@ -90,7 +83,6 @@ def create_agents_from_yaml(
f"System prompt is missing for agent: {agent_config['agent_name']}"
)
# Initialize the agent using the configuration
agent = Agent(
agent_name=agent_config["agent_name"],
system_prompt=agent_config["system_prompt"],
@ -111,7 +103,7 @@ def create_agents_from_yaml(
),
output_type=agent_config.get("output_type", "str"),
*args,
**kwargs, # Pass any additional arguments to the agent
**kwargs,
)
logger.info(
@ -119,43 +111,85 @@ def create_agents_from_yaml(
)
agents.append(agent)
# Check if a task is provided, and if so, run the agent
task = agent_config.get("task")
if task:
logger.info(
f"Running task '{task}' with agent {agent_config['agent_name']}"
)
# Create SwarmRouter if swarm_architecture is present
swarm_router = None
if "swarm_architecture" in config:
swarm_config = config["swarm_architecture"]
swarm_router = SwarmRouter(
name=swarm_config["name"],
description=swarm_config["description"],
max_loops=swarm_config["max_loops"],
agents=agents,
swarm_type=swarm_config["swarm_type"],
task=swarm_config.get("task"),
*args,
**kwargs,
)
logger.info(
f"SwarmRouter '{swarm_config['name']}' created successfully."
)
# Define function to run SwarmRouter
def run_swarm_router(
task: str = (
swarm_config.get("task")
if "swarm_architecture" in config
else None
),
):
if swarm_router:
try:
output = agent.run(task)
output = swarm_router.run(task)
print(output)
logger.info(
f"Output for agent {agent_config['agent_name']}: {output}"
)
task_results.append(
{
"agent_name": agent_config["agent_name"],
"task": task,
"output": output,
}
f"Output for SwarmRouter '{swarm_config['name']}': {output}"
)
return output
except Exception as e:
logger.error(
f"Error running task for agent {agent_config['agent_name']}: {e}"
)
task_results.append(
{
"agent_name": agent_config["agent_name"],
"task": task,
"error": str(e),
}
f"Error running task for SwarmRouter '{swarm_config['name']}': {e}"
)
# Return results based on the `return_type`
if return_type == "agents":
return agents
raise e
else:
logger.error("SwarmRouter not created.")
raise ValueError("SwarmRouter not created.")
# Handle return types
if return_type == "auto":
if swarm_router:
return swarm_router
elif len(agents) == 1:
return agents[0]
else:
return agents
elif return_type == "swarm":
return (
swarm_router
if swarm_router
else (agents[0] if len(agents) == 1 else agents)
)
elif return_type == "agents":
return agents[0] if len(agents) == 1 else agents
elif return_type == "both":
return (
swarm_router
if swarm_router
else agents[0] if len(agents) == 1 else agents
), agents
elif return_type == "tasks":
if not task_results:
logger.warning(
"No tasks were executed. Returning empty list."
)
return task_results
elif return_type == "both":
return agents, task_results
elif return_type == "run_swarm":
if swarm_router:
return run_swarm_router()
else:
logger.error("Cannot run swarm: SwarmRouter not created.")
raise ValueError(
"Cannot run swarm: SwarmRouter not created."
)
else:
logger.error(f"Invalid return_type: {return_type}")
raise ValueError(f"Invalid return_type: {return_type}")

@ -164,7 +164,7 @@ class Prompt(BaseModel):
Returns:
str: The current prompt content.
"""
logger.debug(f"Returning prompt {self.id} as a string.")
# logger.debug(f"Returning prompt {self.id} as a string.")
self.log_telemetry()
return self.content

@ -523,15 +523,6 @@ class Agent:
# Telemetry Processor to log agent data
threading.Thread(target=self.log_agent_data).start()
if load_yaml_path is not None:
from swarms.agents.create_agents_from_yaml import (
create_agents_from_yaml,
)
create_agents_from_yaml(
load_yaml_path, return_type="tasks"
)
def set_system_prompt(self, system_prompt: str):
"""Set the system prompt"""
self.system_prompt = system_prompt

@ -0,0 +1,336 @@
from typing import Callable, List, Dict, Any
from swarms.structs.base_swarm import BaseSwarm
from loguru import logger
import time
import uuid
class SwarmArrangeInput:
id: str = uuid.uuid4().hex
time_stamp: str = time.strftime("%Y-%m-%d %H:%M:%S")
name: str
description: str
swarms: List[Callable] = []
output_type: str
flow: str = ""
class SwarmArrangeOutput:
input_config: SwarmArrangeInput = None
class SwarmArrange:
"""
A class for arranging and executing multiple swarms sequentially.
Attributes:
name (str): The name of the SwarmArrange instance.
description (str): A description of the SwarmArrange instance.
swarms (List[Callable]): A list of swarms to be arranged and executed.
output_type (str): The type of output expected from the SwarmArrange instance.
flow (str): The flow pattern of the swarms to be executed.
"""
def __init__(
self,
name: str = "SwarmArrange-01",
description: str = "Combine multiple swarms and execute them sequentially",
swarms: List[Any] = [],
output_type: str = "json",
flow: str = None,
):
"""
Initializes the SwarmArrange instance.
Args:
name (str, optional): The name of the SwarmArrange instance. Defaults to "SwarmArrange-01".
description (str, optional): A description of the SwarmArrange instance. Defaults to "Combine multiple swarms and execute them sequentially".
swarms (List[Callable], optional): A list of swarms to be arranged and executed. Defaults to None.
output_type (str, optional): The type of output expected from the SwarmArrange instance. Defaults to "json".
flow (str, optional): The flow pattern of the swarms to be executed. Defaults to None.
Raises:
ValueError: If the name or description is None.
"""
if not name:
raise ValueError("Name cannot be None")
if not description:
raise ValueError("Description cannot be None")
self.name = name
self.description = description
self.swarms = swarms
self.output_type = output_type
self.flow = flow
self.reliability_check()
# self.log = SwarmArrangeInput(
# name=name,
# description=description,
# swarms=swarms,
# output_type=output_type,
# flow=flow,
# )
def reliability_check(self):
"""
Performs a reliability check on the SwarmArrange instance.
This method checks if the swarms provided are valid and logs the results.
"""
logger.info(
f"Initializing the SwarmArrange with name: {self.name} and description: {self.description}"
)
if self.swarms is None:
logger.warning(
"No swarms detected. Please input a callable with a .run(task: str) method for reliable operation."
)
else:
logger.info(
"SwarmArrange initialized with swarms. Proceeding with reliability check."
)
# Additional logging for reliability check
logger.info(
"Checking if all swarms are callable or instances of BaseSwarm."
)
for swarm in self.swarms:
if not callable(swarm) and not isinstance(
swarm, BaseSwarm
):
logger.error(
f"Swarm {swarm} is not a callable or an instance of BaseSwarm. This may cause reliability issues."
)
return False
logger.info("All swarms are valid. SwarmArrange is reliable.")
return True
def set_custom_flow(self, flow: str):
"""
Sets a custom flow pattern for the SwarmArrange instance.
Args:
flow (str): The custom flow pattern to be set.
"""
self.flow = flow
logger.info(f"Custom flow set: {flow}")
def add_swarm(self, swarm: Callable):
"""
Adds an swarm to the SwarmArrange instance.
Args:
swarm (swarm): The swarm to be added.
"""
logger.info(f"Adding swarm {swarm.name} to the swarm.")
self.swarms[swarm.name] = swarm
def track_history(
self,
swarm_name: str,
result: str,
):
"""
Tracks the history of a swarm's execution.
Args:
swarm_name (str): The name of the swarm.
result (str): The result of the swarm's execution.
"""
self.swarm_history[swarm_name].append(result)
def remove_swarm(self, swarm_name: str):
"""
Removes an swarm from the SwarmArrange instance.
Args:
swarm_name (str): The name of the swarm to be removed.
"""
del self.swarms[swarm_name]
def add_swarms(self, swarms: List[Callable]):
"""
Adds multiple swarms to the SwarmArrange instance.
Args:
swarms (List[swarm]): A list of swarm objects.
"""
self.swarms.extend(swarms)
def validate_flow(self):
"""
Validates the flow pattern of the SwarmArrange instance.
Raises:
ValueError: If the flow pattern is incorrectly formatted or contains duplicate swarm names.
Returns:
bool: True if the flow pattern is valid.
"""
if "->" not in self.flow:
raise ValueError(
"Flow must include '->' to denote the direction of the task."
)
swarms_in_flow = []
# Split the flow into tasks
tasks = self.flow.split("->")
# For each task in the tasks
for task in tasks:
swarm_names = [name.strip() for name in task.split(",")]
# Loop over the swarm names
for swarm_name in swarm_names:
if (
swarm_name not in self.swarms
and swarm_name != "H"
):
raise ValueError(
f"swarm '{swarm_name}' is not registered."
)
swarms_in_flow.append(swarm_name)
# Check for duplicate swarm names in the flow
if len(set(swarms_in_flow)) != len(swarms_in_flow):
raise ValueError(
"Duplicate swarm names in the flow are not allowed."
)
logger.info("Flow is valid.")
return True
def run(
self,
task: str = None,
img: str = None,
custom_tasks: Dict[str, str] = None,
*args,
**kwargs,
):
"""
Runs the SwarmArrange instance to rearrange and execute the swarms.
Args:
task (str, optional): The initial task to be processed. Defaults to None.
img (str, optional): The image to be processed. Defaults to None.
custom_tasks (Dict[str, str], optional): Custom tasks to be executed. Defaults to None.
Returns:
str: The final processed task.
"""
try:
if not self.validate_flow():
return "Invalid flow configuration."
tasks = self.flow.split("->")
current_task = task
# If custom_tasks have the swarms name and tasks then combine them
if custom_tasks is not None:
c_swarm_name, c_task = next(
iter(custom_tasks.items())
)
# Find the position of the custom swarm in the tasks list
position = tasks.index(c_swarm_name)
# If there is a previous swarm merge its task with the custom tasks
if position > 0:
tasks[position - 1] += "->" + c_task
else:
# If there is no previous swarm just insert the custom tasks
tasks.insert(position, c_task)
# Set the loop counter
loop_count = 0
while loop_count < self.max_loops:
for task in tasks:
is_last = task == tasks[-1]
swarm_names = [
name.strip() for name in task.split(",")
]
if len(swarm_names) > 1:
# Parallel processing
logger.info(
f"Running swarms in parallel: {swarm_names}"
)
results = []
for swarm_name in swarm_names:
if swarm_name == "H":
# Human in the loop intervention
if (
self.human_in_the_loop
and self.custom_human_in_the_loop
):
current_task = (
self.custom_human_in_the_loop(
current_task
)
)
else:
current_task = input(
"Enter your response:"
)
else:
swarm = self.swarms[swarm_name]
result = swarm.run(
current_task,
# img,
# is_last,
*args,
**kwargs,
)
results.append(result)
self.output_schema.outputs.append(
swarm.swarm_output
)
current_task = "; ".join(results)
else:
# Sequential processing
logger.info(
f"Running swarms sequentially: {swarm_names}"
)
swarm_name = swarm_names[0]
if swarm_name == "H":
# Human-in-the-loop intervention
if (
self.human_in_the_loop
and self.custom_human_in_the_loop
):
current_task = (
self.custom_human_in_the_loop(
current_task
)
)
else:
current_task = input(
"Enter the next task: "
)
else:
swarm = self.swarms[swarm_name]
current_task = swarm.run(
current_task,
# img,
# is_last,
*args,
**kwargs,
)
self.output_schema.outputs.append(
swarm.swarm_output
)
loop_count += 1
# return current_task
if self.return_json:
return self.output_schema.model_dump_json(indent=4)
else:
return current_task
except Exception as e:
logger.error(f"An error occurred: {e}")
return e
Loading…
Cancel
Save