Skip to content

Commit

Permalink
feat: add swarm output schemas and agent fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Occupying-Mars committed Jan 10, 2025
1 parent b408faf commit 738891c
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 0 deletions.
79 changes: 79 additions & 0 deletions swarms/schemas/swarm_output_schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from typing import List, Dict, Any, Optional
from pydantic import BaseModel, Field

Check failure

Code scanning / Pyre

Undefined import Error

Undefined import [21]: Could not find a module corresponding to import pydantic.
from datetime import datetime

class AgentStep(BaseModel):

Check failure

Code scanning / Pyre

Undefined or invalid type Error

Undefined or invalid type [11]: Annotation BaseModel is not defined as a type.
"""Schema for individual agent execution steps"""
role: str = Field(description="Role of the agent in this step")
content: str = Field(description="Content/response from the agent")

class AgentOutput(BaseModel):
"""Schema for individual agent outputs"""
agent_name: str = Field(description="Name of the agent")
steps: List[AgentStep] = Field(description="List of execution steps by this agent")
metadata: Optional[Dict[str, Any]] = Field(default=None, description="Additional metadata about the agent's execution")

class SwarmInput(BaseModel):
"""Schema for swarm input configuration"""
swarm_id: str = Field(description="Unique identifier for the swarm execution")
name: str = Field(description="Name of the swarm type")
flow: str = Field(description="Agent execution flow configuration")
description: Optional[str] = Field(default=None, description="Description of the swarm execution")

class SwarmOutput(BaseModel):
"""Unified schema for all swarm type outputs"""
input: SwarmInput = Field(description="Input configuration for the swarm")
outputs: List[AgentOutput] = Field(description="List of outputs from all agents")
time: float = Field(description="Timestamp of execution")
execution_time: Optional[float] = Field(default=None, description="Total execution time in seconds")
metadata: Optional[Dict[str, Any]] = Field(default=None, description="Additional swarm execution metadata")

def format_output(self) -> str:
"""Format the swarm output into a readable string"""
output = f"Workflow Execution Details\n\n"
output += f"Swarm ID: `{self.input.swarm_id}`\n"
output += f"Swarm Name: `{self.input.name}`\n"
output += f"Agent Flow: `{self.input.flow}`\n\n---\n"
output += f"Agent Task Execution\n\n"

for i, agent_output in enumerate(self.outputs, start=1):
output += f"Run {i} (Agent: `{agent_output.agent_name}`)\n\n"

for j, step in enumerate(agent_output.steps, start=1):
if step.role.strip() != "System:":
output += f"Step {j}:\n"
output += f"Response: {step.content}\n\n"

if self.execution_time:
output += f"Overall Execution Time: `{self.execution_time:.2f}s`"

return output

class MixtureOfAgentsOutput(SwarmOutput):
"""Schema specific to MixtureOfAgents output"""
aggregator_summary: Optional[str] = Field(default=None, description="Aggregated summary from all agents")

def format_output(self) -> str:
"""Format MixtureOfAgents output"""
output = super().format_output()
if self.aggregator_summary:
output += f"\nAggregated Summary:\n{self.aggregator_summary}\n{'=' * 50}\n"
return output

class SpreadsheetSwarmOutput(SwarmOutput):
"""Schema specific to SpreadsheetSwarm output"""
csv_data: List[List[str]] = Field(description="CSV data in list format")

def format_output(self) -> str:
"""Format SpreadsheetSwarm output"""
output = "### Spreadsheet Swarm Output ###\n\n"
if self.csv_data:
# Create markdown table
header = self.csv_data[0]
output += "| " + " | ".join(header) + " |\n"
output += "| " + " | ".join(["---"] * len(header)) + " |\n"

for row in self.csv_data[1:]:
output += "| " + " | ".join(row) + " |\n"

return output
70 changes: 70 additions & 0 deletions swarms/structs/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@
ChatCompletionResponseChoice,
ChatMessageResponse,
)
from swarms.schemas.swarm_output_schemas import (
SwarmOutput,
SwarmInput,
AgentOutput,
AgentStep,
MixtureOfAgentsOutput,
SpreadsheetSwarmOutput
)
from swarms.structs.concat import concat_strings
from swarms.structs.conversation import Conversation
from swarms.structs.safe_loading import (
Expand Down Expand Up @@ -210,6 +218,7 @@ class Agent:
run_async_concurrent: Run the agent asynchronously and concurrently
construct_dynamic_prompt: Construct the dynamic prompt
handle_artifacts: Handle artifacts
create_swarm_output: Create standardized swarm output
Examples:
Expand Down Expand Up @@ -2596,3 +2605,64 @@ def showcase_config(self):
return formatter.print_table(
f"Agent: {self.agent_name} Configuration", config_dict
)

def create_swarm_output(
self,
swarm_type: str,
swarm_id: str,
agent_outputs: List[Dict[str, Any]],
flow: Optional[str] = None,
execution_time: Optional[float] = None,
metadata: Optional[Dict[str, Any]] = None
) -> SwarmOutput:
"""Create standardized swarm output"""

# Create input config
input_config = SwarmInput(
swarm_id=swarm_id,
name=swarm_type,
flow=flow or "->".join([out["agent_name"] for out in agent_outputs]),
)

Check failure

Code scanning / Pyre

Unexpected keyword Error

Unexpected keyword [28]: Unexpected keyword argument swarm\_id to call object.\_\_init\_\_.

# Create agent outputs
formatted_outputs = []
for agent_out in agent_outputs:
steps = [
AgentStep(role=step["role"], content=step["content"])

Check failure

Code scanning / Pyre

Unexpected keyword Error

Unexpected keyword [28]: Unexpected keyword argument role to call object.\_\_init\_\_.
for step in agent_out.get("steps", [])
]
formatted_outputs.append(
AgentOutput(
agent_name=agent_out["agent_name"],
steps=steps,
metadata=agent_out.get("metadata")
)

Check failure

Code scanning / Pyre

Unexpected keyword Error

Unexpected keyword [28]: Unexpected keyword argument agent\_name to call object.\_\_init\_\_.
)

# Create appropriate output type based on swarm_type
if swarm_type == "MixtureOfAgents":
return MixtureOfAgentsOutput(
input=input_config,
outputs=formatted_outputs,
time=time.time(),
execution_time=execution_time,
metadata=metadata,
aggregator_summary=metadata.get("aggregator_summary") if metadata else None
)

Check failure

Code scanning / Pyre

Unexpected keyword Error

Unexpected keyword [28]: Unexpected keyword argument input to call object.\_\_init\_\_.
elif swarm_type == "SpreadSheetSwarm":
return SpreadsheetSwarmOutput(
input=input_config,
outputs=formatted_outputs,
time=time.time(),
execution_time=execution_time,
metadata=metadata,
csv_data=metadata.get("csv_data", []) if metadata else []
)

Check failure

Code scanning / Pyre

Unexpected keyword Error

Unexpected keyword [28]: Unexpected keyword argument input to call object.\_\_init\_\_.
else:
return SwarmOutput(
input=input_config,
outputs=formatted_outputs,
time=time.time(),
execution_time=execution_time,
metadata=metadata
)

Check failure

Code scanning / Pyre

Unexpected keyword Error

Unexpected keyword [28]: Unexpected keyword argument input to call object.\_\_init\_\_.

0 comments on commit 738891c

Please sign in to comment.