Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Imporve the UX of CLI and Add onboard examples #745

Merged
merged 1 commit into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions examples/onboard/agents.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
agents:
- agent_name: "Financial-Analysis-Agent"
model:
model_name: "gpt-4"
temperature: 0.1
max_tokens: 2000
system_prompt: "financial_agent_sys_prompt"
max_loops: 1
autosave: true
dashboard: false
verbose: true
dynamic_temperature_enabled: true
saved_state_path: "finance_agent.json"
user_name: "swarms_corp"
retry_attempts: 1
context_length: 4000
return_step_meta: false
output_type: "str"
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-4"
temperature: 0.2
max_tokens: 1500
system_prompt: "stock_agent_sys_prompt"
max_loops: 2
autosave: true
dashboard: false
verbose: true
dynamic_temperature_enabled: false
saved_state_path: "stock_agent.json"
user_name: "stock_user"
retry_attempts: 3
context_length: 4000
return_step_meta: true
output_type: "json"
task: "What is the best strategy for long-term stock investment?"

swarm_architecture:
name: "Financial-Advisory-Swarm"
description: "A swarm of agents working together to provide comprehensive financial advice"
swarm_type: "SequentialWorkflow"
max_loops: 2
task: "Analyze ROTH IRA setup requirements and provide a comprehensive long-term investment strategy"
autosave: true
return_json: false
rules: |
1. Financial-Analysis-Agent first explains ROTH IRA setup process and requirements
2. Stock-Analysis-Agent then provides specific investment strategies suitable for ROTH IRA
3. Both agents should ensure advice is tax-aware and compliant with retirement account regulations
4. Focus on practical, actionable steps the user can take
37 changes: 37 additions & 0 deletions examples/onboard/onboard-basic.py
Original file line number Diff line number Diff line change
@@ -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.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
)

print(model)

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="agents"
)

print(task_results)
logger.info(f"Results from agents: {task_results}")
except Exception as e:
logger.error(f"An error occurred: {e}")
print(e)
92 changes: 76 additions & 16 deletions swarms/agents/create_agents_from_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,21 +178,38 @@ def create_agents_from_yaml(
swarm_router = None

try:
logger.info("Starting agent creation process...")

# Load and validate configuration
if yaml_file:
logger.info(f"Loading configuration from {yaml_file}")
config = load_yaml_safely(yaml_file, yaml_string)

if not config.get("agents"):
raise ValueError(
"No agents defined in the YAML configuration. "
"Please add at least one agent under the 'agents' section."
)

logger.info(f"Found {len(config['agents'])} agent(s) to create")

# Create agents with retry logic
for agent_config in config["agents"]:
for idx, agent_config in enumerate(config["agents"], 1):
if not agent_config.get("agent_name"):
agent_config["agent_name"] = f"Agent_{idx}"

logger.info(
f"Creating agent: {agent_config['agent_name']}"
f"Creating agent {idx}/{len(config['agents'])}: {agent_config['agent_name']}"
)

if "model_name" in agent_config:
logger.info(f"Using specified model: {agent_config['model_name']}")
model_instance = LiteLLM(
model_name=agent_config["model_name"]
)
else:
model_name = "gpt-4o"
model_name = "gpt-4"
logger.info(f"No model specified, using default: {model_name}")
model_instance = LiteLLM(model_name=model_name)

agent = create_agent_with_retry(
Expand All @@ -203,12 +220,29 @@ def create_agents_from_yaml(
)
agents.append(agent)

logger.info(f"Successfully created {len(agents)} agent(s)")

# Create SwarmRouter if specified
if "swarm_architecture" in config:
logger.info("Setting up swarm architecture...")
try:
if not isinstance(config["swarm_architecture"], dict):
raise ValueError(
"swarm_architecture must be a dictionary containing swarm configuration"
)

required_fields = {"name", "description", "swarm_type"}
missing_fields = required_fields - set(config["swarm_architecture"].keys())
if missing_fields:
raise ValueError(
f"SwarmRouter creation failed: Missing required fields in swarm_architecture: {', '.join(missing_fields)}"
)

swarm_config = SwarmConfig(
**config["swarm_architecture"]
)

logger.info(f"Creating SwarmRouter with type: {swarm_config.swarm_type}")
swarm_router = SwarmRouter(
name=swarm_config.name,
description=swarm_config.description,
Expand All @@ -226,8 +260,14 @@ def create_agents_from_yaml(
)
except Exception as e:
logger.error(f"Error creating SwarmRouter: {str(e)}")
if "swarm_type" in str(e) and "valid_types" in str(e):
raise ValueError(
"Invalid swarm_type. Must be one of: SequentialWorkflow, ConcurrentWorkflow, "
"AgentRearrange, MixtureOfAgents, or auto"
)
raise ValueError(
f"Failed to create SwarmRouter: {str(e)}"
f"Failed to create SwarmRouter: {str(e)}. Make sure your YAML file "
"has a valid swarm_architecture section with required fields."
)

# Handle return types with improved error checking
Expand All @@ -244,12 +284,29 @@ def create_agents_from_yaml(
f"Invalid return_type. Must be one of: {valid_return_types}"
)

if return_type == "run_swarm" or "swarm":
logger.info(f"Processing with return type: {return_type}")

if return_type in ("run_swarm", "swarm"):
if not swarm_router:
if "swarm_architecture" not in config:
raise ValueError(
"Cannot run swarm: No swarm_architecture section found in YAML configuration.\n"
"Please add a swarm_architecture section with:\n"
" - name: your_swarm_name\n"
" - description: your_swarm_description\n"
" - swarm_type: one of [SequentialWorkflow, ConcurrentWorkflow, AgentRearrange, MixtureOfAgents, auto]\n"
" - task: your_task_description"
)
raise ValueError(
"Cannot run swarm: SwarmRouter not created."
"Cannot run swarm: SwarmRouter creation failed. Check the previous error messages."
)
try:
if not config["swarm_architecture"].get("task"):
raise ValueError(
"No task specified in swarm_architecture. Please add a 'task' field "
"to define what the swarm should do."
)
logger.info(f"Running swarm with task: {config['swarm_architecture']['task']}")
return swarm_router.run(
config["swarm_architecture"]["task"]
)
Expand All @@ -259,30 +316,33 @@ def create_agents_from_yaml(

# Return appropriate type based on configuration
if return_type == "auto":
return (
result = (
swarm_router
if swarm_router
else (agents[0] if len(agents) == 1 else agents)
)
elif return_type == "swarm":
return (
result = (
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
result = 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
result = (
(swarm_router if swarm_router else agents[0] if len(agents) == 1 else agents),
agents
)
elif return_type == "tasks":
return task_results
result = task_results

logger.info("Process completed successfully")
return result

except Exception as e:
logger.error(
f"Critical error in create_agents_from_yaml: {str(e)}"
f"Critical error in create_agents_from_yaml: {str(e)}\n"
"Please check your YAML configuration and try again."
)
raise
84 changes: 81 additions & 3 deletions swarms/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,87 @@ def main():
elif args.command == "check-login":
check_login()
elif args.command == "run-agents":
create_agents_from_yaml(
yaml_file=args.yaml_file, return_type="tasks"
)
try:
console.print(f"[yellow]Loading agents from {args.yaml_file}...[/yellow]")

if not os.path.exists(args.yaml_file):
raise FileNotFoundError(
f"YAML file not found: {args.yaml_file}\n"
"Please make sure the file exists and you're in the correct directory."
)

# Create progress display
progress = Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
console=console,
)

with progress:
# Add initial task
init_task = progress.add_task("Initializing...", total=None)

# Load and validate YAML
progress.update(init_task, description="Loading YAML configuration...")

# Create agents
progress.update(init_task, description="Creating agents...")
result = create_agents_from_yaml(
yaml_file=args.yaml_file,
return_type="run_swarm"
)

# Update progress on completion
progress.update(init_task, description="Processing complete!", completed=True)

if result:
# Format and display the results
if isinstance(result, str):
console.print("\n[bold green]Results:[/bold green]")
console.print(Panel(result, title="Agent Output", border_style="green"))
elif isinstance(result, dict):
console.print("\n[bold green]Results:[/bold green]")
for key, value in result.items():
console.print(f"[cyan]{key}:[/cyan] {value}")
else:
console.print("[green]✓ Agents completed their tasks successfully![/green]")
else:
console.print("[yellow]⚠ Agents completed but returned no results.[/yellow]")

except FileNotFoundError as e:
show_error("File Error", str(e))
except ValueError as e:
show_error(
"Configuration Error",
str(e) + "\n\nPlease check your agents.yaml file format."
)
except Exception as e:
# Enhanced error handling
error_msg = str(e)
if "context_length_exceeded" in error_msg:
show_error(
"Context Length Error",
"The model's context length was exceeded. Try:\n"
"1. Reducing max_tokens in your YAML config\n"
"2. Reducing context_length in your YAML config\n"
"3. Using a model with larger context window"
)
elif "api_key" in error_msg.lower():
show_error(
"API Key Error",
"There seems to be an issue with the API key. Please:\n"
"1. Check if your API key is set correctly\n"
"2. Verify the API key is valid\n"
"3. Run 'swarms get-api-key' to get a new key"
)
else:
show_error(
"Execution Error",
f"An unexpected error occurred: {error_msg}\n"
"1. Check your YAML configuration\n"
"2. Verify your API keys are set\n"
"3. Check network connectivity"
)
elif args.command == "book-call":
webbrowser.open(
"https://cal.com/swarms/swarms-strategy-session"
Expand Down
Loading