swarms 7.9.7__py3-none-any.whl → 7.9.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- swarms/agents/consistency_agent.py +246 -64
- swarms/agents/reasoning_agents.py +136 -35
- swarms/prompts/collaborative_prompts.py +92 -53
- swarms/prompts/hiearchical_system_prompt.py +159 -0
- swarms/structs/__init__.py +3 -0
- swarms/structs/agent.py +59 -235
- swarms/structs/conversation.py +48 -38
- swarms/structs/hiearchical_swarm.py +553 -523
- swarms/structs/ma_utils.py +34 -14
- swarms/utils/lite_utils.py +5 -0
- swarms/utils/litellm_wrapper.py +154 -82
- {swarms-7.9.7.dist-info → swarms-7.9.9.dist-info}/METADATA +139 -28
- {swarms-7.9.7.dist-info → swarms-7.9.9.dist-info}/RECORD +16 -14
- {swarms-7.9.7.dist-info → swarms-7.9.9.dist-info}/LICENSE +0 -0
- {swarms-7.9.7.dist-info → swarms-7.9.9.dist-info}/WHEEL +0 -0
- {swarms-7.9.7.dist-info → swarms-7.9.9.dist-info}/entry_points.txt +0 -0
@@ -1,22 +1,33 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
"""
|
2
|
+
Flow:
|
3
|
+
|
4
|
+
1. User provides a task
|
5
|
+
2. Director creates a plan
|
6
|
+
3. Director distributes orders to agents individually or multiple tasks at once
|
7
|
+
4. Agents execute tasks and report back to the director
|
8
|
+
5. Director evaluates results and issues new orders if needed (up to max_loops)
|
9
|
+
6. All context and conversation history is preserved throughout the process
|
10
|
+
|
11
|
+
"""
|
12
|
+
|
13
|
+
import traceback
|
14
|
+
from typing import Any, Callable, List, Literal, Optional, Union
|
4
15
|
|
5
16
|
from pydantic import BaseModel, Field
|
6
17
|
|
18
|
+
from swarms.prompts.hiearchical_system_prompt import (
|
19
|
+
HIEARCHICAL_SWARM_SYSTEM_PROMPT,
|
20
|
+
)
|
7
21
|
from swarms.structs.agent import Agent
|
8
22
|
from swarms.structs.base_swarm import BaseSwarm
|
9
23
|
from swarms.structs.conversation import Conversation
|
10
|
-
from swarms.
|
11
|
-
from swarms.
|
12
|
-
from swarms.utils.formatter import formatter
|
13
|
-
|
14
|
-
from swarms.utils.function_caller_model import OpenAIFunctionCaller
|
15
|
-
from swarms.utils.loguru_logger import initialize_logger
|
24
|
+
from swarms.structs.ma_utils import list_all_agents
|
25
|
+
from swarms.tools.base_tool import BaseTool
|
16
26
|
from swarms.utils.history_output_formatter import (
|
17
27
|
history_output_formatter,
|
18
28
|
)
|
19
|
-
from swarms.
|
29
|
+
from swarms.utils.loguru_logger import initialize_logger
|
30
|
+
from swarms.utils.output_types import OutputType
|
20
31
|
|
21
32
|
logger = initialize_logger(log_folder="hierarchical_swarm")
|
22
33
|
|
@@ -33,204 +44,49 @@ class HierarchicalOrder(BaseModel):
|
|
33
44
|
|
34
45
|
|
35
46
|
class SwarmSpec(BaseModel):
|
36
|
-
goals: str = Field(
|
37
|
-
...,
|
38
|
-
description="The goal of the swarm. This is the overarching objective that the swarm is designed to achieve. It guides the swarm's plan and the tasks assigned to the agents.",
|
39
|
-
)
|
40
47
|
plan: str = Field(
|
41
48
|
...,
|
42
49
|
description="Outlines the sequence of actions to be taken by the swarm. This plan is a detailed roadmap that guides the swarm's behavior and decision-making.",
|
43
50
|
)
|
44
|
-
rules: str = Field(
|
45
|
-
...,
|
46
|
-
description="Defines the governing principles for swarm behavior and decision-making. These rules are the foundation of the swarm's operations and ensure that the swarm operates in a coordinated and efficient manner.",
|
47
|
-
)
|
48
51
|
orders: List[HierarchicalOrder] = Field(
|
49
52
|
...,
|
50
53
|
description="A collection of task assignments to specific agents within the swarm. These orders are the specific instructions that guide the agents in their task execution and are a key element in the swarm's plan.",
|
51
54
|
)
|
52
55
|
|
53
56
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
- **Dynamic Reassignment:** Allow for real-time reassignments based on the evolving state of the system. If an agent encounters issues or delays, reassign tasks to ensure continuity.
|
78
|
-
|
79
|
-
4. **Adherence to Rules and Safety Protocols:**
|
80
|
-
- **Operational Rules:** Every task must be executed in strict compliance with the “rules” provided in the SwarmSpec. These rules are non-negotiable and serve as the ethical and operational foundation for all decisions.
|
81
|
-
- **Fail-Safe Mechanisms:** Incorporate safety protocols that monitor agent performance and task progress. If an anomaly or failure is detected, trigger a reallocation of tasks or an escalation process to mitigate risks.
|
82
|
-
- **Auditability:** Ensure that every decision and task assignment is logged for auditing purposes. This enables traceability and accountability in system operations.
|
83
|
-
|
84
|
-
---
|
85
|
-
|
86
|
-
**III. Detailed Task Assignment Process**
|
87
|
-
|
88
|
-
1. **Input Analysis and Context Setting:**
|
89
|
-
- **Goal Review:** Begin by carefully reading the “goals” string within the SwarmSpec. This is your north star for every decision you make.
|
90
|
-
- **Plan Comprehension:** Analyze the “plan” string for detailed instructions. Identify key milestones, deliverables, and dependencies within the roadmap.
|
91
|
-
- **Rule Enforcement:** Read through the “rules” string to understand the non-negotiable guidelines that govern task assignments. Consider potential edge cases and ensure that your task breakdown respects these boundaries.
|
92
|
-
|
93
|
-
2. **Task Breakdown and Subtask Identification:**
|
94
|
-
- **Decompose the Plan:** Using a systematic approach, decompose the overall plan into discrete tasks. For each major phase, identify the specific actions required. Document dependencies among tasks, and note any potential bottlenecks.
|
95
|
-
- **Task Granularity:** Ensure that tasks are broken down to a level of granularity that makes them actionable. Overly broad tasks must be subdivided further until they can be executed by an individual worker agent.
|
96
|
-
- **Inter-Agent Dependencies:** Clearly specify any dependencies that exist between tasks assigned to different agents. This ensures that the workflow remains coherent and that agents collaborate effectively.
|
97
|
-
|
98
|
-
3. **Agent Selection Strategy:**
|
99
|
-
- **Capabilities Matching:** For each identified task, analyze the capabilities required. Compare these against the registry of available worker agents. Factor in specialized skills, past performance, current load, and any situational awareness that might influence the assignment.
|
100
|
-
- **Task Suitability:** Consider both the technical requirements of the task and any contextual subtleties noted in the “plan” and “rules.” Ensure that the chosen agent has a proven track record with similar tasks.
|
101
|
-
- **Adaptive Assignments:** Build in flexibility to allow for agent reassignment in real-time. Monitor ongoing tasks and reallocate resources as needed, especially if an agent experiences unexpected delays or issues.
|
102
|
-
|
103
|
-
4. **Constructing Hierarchical Orders:**
|
104
|
-
- **Order Creation:** For each task, generate a HierarchicalOrder object that specifies the agent’s name and the task details. The task description should be unambiguous and detailed enough to guide the agent’s execution without requiring additional clarification.
|
105
|
-
- **Order Validation:** Prior to finalizing each order, cross-reference the task requirements against the agent’s profile. Validate that the order adheres to the “rules” of the SwarmSpec and that it fits within the broader operational context.
|
106
|
-
- **Order Prioritization:** Clearly mark high-priority tasks so that agents understand the urgency. In cases where multiple tasks are assigned to a single agent, provide a sequence or ranking to ensure proper execution order.
|
107
|
-
|
108
|
-
5. **Feedback and Iteration:**
|
109
|
-
- **Real-Time Monitoring:** Establish feedback loops with worker agents to track the progress of each task. This allows for early detection of issues and facilitates dynamic reassignment if necessary.
|
110
|
-
- **Continuous Improvement:** Regularly review task execution data and agent performance metrics. Use this feedback to refine the task decomposition and agent selection process in future iterations.
|
111
|
-
|
112
|
-
---
|
113
|
-
|
114
|
-
**IV. Execution Guidelines and Best Practices**
|
115
|
-
|
116
|
-
1. **Communication Clarity:**
|
117
|
-
- Use clear, concise language in every HierarchicalOrder. Avoid ambiguity by detailing both the “what” and the “how” of the task.
|
118
|
-
- Provide contextual notes when necessary, especially if the task involves dependencies or coordination with other agents.
|
119
|
-
|
120
|
-
2. **Documentation and Traceability:**
|
121
|
-
- Record every task assignment in a centralized log. This log should include the agent’s name, task details, time of assignment, and any follow-up actions taken.
|
122
|
-
- Ensure that the entire decision-making process is documented. This aids in post-operation analysis and helps in refining future assignments.
|
123
|
-
|
124
|
-
3. **Error Handling and Escalation:**
|
125
|
-
- If an agent is unable to complete a task due to unforeseen challenges, immediately trigger the escalation protocol. Reassign the task to a qualified backup agent while flagging the incident for further review.
|
126
|
-
- Document all deviations from the plan along with the corrective measures taken. This helps in identifying recurring issues and improving the system’s robustness.
|
127
|
-
|
128
|
-
4. **Ethical and Operational Compliance:**
|
129
|
-
- Adhere strictly to the rules outlined in the SwarmSpec. Any action that violates these rules is unacceptable, regardless of the potential gains in efficiency.
|
130
|
-
- Maintain transparency in all operations. If a decision or task assignment is questioned, be prepared to justify the choice based on objective criteria such as agent capability, historical performance, and task requirements.
|
131
|
-
|
132
|
-
5. **Iterative Refinement:**
|
133
|
-
- After the completion of each mission cycle, perform a thorough debriefing. Analyze the success and shortcomings of the task assignments.
|
134
|
-
- Use these insights to iterate on your hierarchical ordering process. Update agent profiles and adjust your selection strategies based on real-world performance data.
|
135
|
-
|
136
|
-
---
|
137
|
-
|
138
|
-
**V. Exemplary Use Case and Order Breakdown**
|
139
|
-
|
140
|
-
Imagine that the swarm’s overarching goal is to perform a comprehensive analysis of market trends for a large-scale enterprise. The “goals” field might read as follows:
|
141
|
-
*“To conduct an in-depth market analysis that identifies emerging trends, competitive intelligence, and actionable insights for strategic decision-making.”*
|
142
|
-
|
143
|
-
The “plan” could outline a multi-phase approach:
|
144
|
-
- Phase 1: Data Collection and Preprocessing
|
145
|
-
- Phase 2: Trend Analysis and Pattern Recognition
|
146
|
-
- Phase 3: Report Generation and Presentation of Findings
|
147
|
-
|
148
|
-
The “rules” may specify that all data processing must comply with privacy regulations, and that results must be validated against multiple data sources.
|
149
|
-
|
150
|
-
For Phase 1, the Director breaks down tasks such as “Identify data sources,” “Extract relevant market data,” and “Preprocess raw datasets.” For each task, the director selects agents with expertise in data mining, natural language processing, and data cleaning. A series of HierarchicalOrder objects are created, for example:
|
151
|
-
|
152
|
-
1. HierarchicalOrder for Data Collection:
|
153
|
-
- **agent_name:** “DataMiner_Agent”
|
154
|
-
- **task:** “Access external APIs and scrape structured market data from approved financial news sources.”
|
155
|
-
|
156
|
-
2. HierarchicalOrder for Data Preprocessing:
|
157
|
-
- **agent_name:** “Preprocess_Expert”
|
158
|
-
- **task:** “Clean and normalize the collected datasets, ensuring removal of duplicate records and compliance with data privacy rules.”
|
159
|
-
|
160
|
-
3. HierarchicalOrder for Preliminary Trend Analysis:
|
161
|
-
- **agent_name:** “TrendAnalyst_Pro”
|
162
|
-
- **task:** “Apply statistical models to identify initial trends and anomalies in the market data.”
|
163
|
-
|
164
|
-
Each order is meticulously validated against the rules provided in the SwarmSpec and prioritized according to the project timeline. The director ensures that if any of these tasks are delayed, backup agents are identified and the orders are reissued in real time.
|
165
|
-
|
166
|
-
---
|
167
|
-
|
168
|
-
**VI. Detailed Hierarchical Order Construction and Validation**
|
169
|
-
|
170
|
-
1. **Order Structuring:**
|
171
|
-
- Begin by constructing a template that includes placeholders for the agent’s name and a detailed description of the task.
|
172
|
-
- Ensure that the task description is unambiguous. For instance, rather than stating “analyze data,” specify “analyze the temporal patterns in consumer sentiment from Q1 and Q2, and identify correlations with economic indicators.”
|
173
|
-
|
174
|
-
2. **Validation Workflow:**
|
175
|
-
- Prior to dispatch, each HierarchicalOrder must undergo a validation check. This includes verifying that the agent’s capabilities align with the task, that the task does not conflict with any other orders, and that the task is fully compliant with the operational rules.
|
176
|
-
- If a validation error is detected, the order should be revised. The director may consult with relevant experts or consult historical data to refine the task’s description and ensure it is actionable.
|
177
|
-
|
178
|
-
3. **Order Finalization:**
|
179
|
-
- Once validated, finalize the HierarchicalOrder and insert it into the “orders” list of the SwarmSpec.
|
180
|
-
- Dispatch the order immediately, ensuring that the worker agent acknowledges receipt and provides an estimated time of completion.
|
181
|
-
- Continuously monitor the progress, and if any agent’s status changes (e.g., they become overloaded or unresponsive), trigger a reallocation process based on the predefined agent selection strategy.
|
182
|
-
|
183
|
-
---
|
184
|
-
|
185
|
-
**VII. Continuous Monitoring, Feedback, and Dynamic Reassignment**
|
186
|
-
|
187
|
-
1. **Real-Time Status Tracking:**
|
188
|
-
- Use real-time dashboards to monitor each agent’s progress on the assigned tasks.
|
189
|
-
- Update the hierarchical ordering system dynamically if a task is delayed, incomplete, or requires additional resources.
|
190
|
-
|
191
|
-
2. **Feedback Loop Integration:**
|
192
|
-
- Each worker agent must provide periodic status updates, including intermediate results, encountered issues, and resource usage.
|
193
|
-
- The director uses these updates to adjust task priorities and reassign tasks if necessary. This dynamic feedback loop ensures the overall swarm remains agile and responsive.
|
194
|
-
|
195
|
-
3. **Performance Metrics and Analysis:**
|
196
|
-
- At the conclusion of every mission, aggregate performance metrics and conduct a thorough review of task efficiency.
|
197
|
-
- Identify any tasks that repeatedly underperform or cause delays, and adjust the agent selection criteria accordingly for future orders.
|
198
|
-
- Document lessons learned and integrate them into the operating procedures for continuous improvement.
|
199
|
-
|
200
|
-
---
|
201
|
-
|
202
|
-
**VIII. Final Directives and Implementation Mandate**
|
203
|
-
|
204
|
-
As the Hierarchical Agent Director, your mandate is clear: you must orchestrate the operation with precision, clarity, and unwavering adherence to the overarching goals and rules specified in the SwarmSpec. You are empowered to deconstruct complex objectives into manageable tasks and to assign these tasks to the worker agents best equipped to execute them.
|
205
|
-
|
206
|
-
Your decisions must always be data-driven, relying on agent profiles, historical performance, and real-time feedback. Ensure that every HierarchicalOrder is constructed with a clear task description and assigned to an agent whose expertise aligns perfectly with the requirements. Maintain strict compliance with all operational rules, and be ready to adapt dynamically as conditions change.
|
207
|
-
|
208
|
-
This production-grade prompt is your operational blueprint. Utilize it to break down orders efficiently, assign tasks intelligently, and steer the swarm toward achieving the defined goals with optimal efficiency and reliability. Every decision you make should reflect a deep commitment to excellence, safety, and operational integrity.
|
209
|
-
|
210
|
-
Remember: the success of the swarm depends on your ability to manage complexity, maintain transparency, and dynamically adapt to the evolving operational landscape. Execute your role with diligence, precision, and a relentless focus on performance excellence.
|
211
|
-
|
212
|
-
"""
|
213
|
-
|
214
|
-
|
215
|
-
class TeamUnit(BaseModel):
|
216
|
-
"""Represents a team within a department."""
|
217
|
-
|
218
|
-
name: Optional[str] = Field(
|
219
|
-
None, description="The name of the team."
|
220
|
-
)
|
221
|
-
description: Optional[str] = Field(
|
222
|
-
None, description="A brief description of the team's purpose."
|
223
|
-
)
|
224
|
-
agents: Optional[List[Union[Agent, Any]]] = Field(
|
225
|
-
None,
|
226
|
-
description="A list of agents that are part of the team.",
|
57
|
+
SwarmType = Literal[
|
58
|
+
"AgentRearrange",
|
59
|
+
"MixtureOfAgents",
|
60
|
+
"SpreadSheetSwarm",
|
61
|
+
"SequentialWorkflow",
|
62
|
+
"ConcurrentWorkflow",
|
63
|
+
"GroupChat",
|
64
|
+
"MultiAgentRouter",
|
65
|
+
"AutoSwarmBuilder",
|
66
|
+
"HiearchicalSwarm",
|
67
|
+
"auto",
|
68
|
+
"MajorityVoting",
|
69
|
+
"MALT",
|
70
|
+
"DeepResearchSwarm",
|
71
|
+
"CouncilAsAJudge",
|
72
|
+
"InteractiveGroupChat",
|
73
|
+
]
|
74
|
+
|
75
|
+
|
76
|
+
class SwarmRouterCall(BaseModel):
|
77
|
+
goal: str = Field(
|
78
|
+
...,
|
79
|
+
description="The goal of the swarm router call. This is the goal that the swarm router will use to determine the best swarm to use.",
|
227
80
|
)
|
228
|
-
|
229
|
-
|
81
|
+
swarm_type: SwarmType = Field(
|
82
|
+
...,
|
83
|
+
description="The type of swarm to use. This is the type of swarm that the swarm router will use to determine the best swarm to use.",
|
230
84
|
)
|
231
85
|
|
232
|
-
|
233
|
-
|
86
|
+
task: str = Field(
|
87
|
+
...,
|
88
|
+
description="The task to be executed by the swarm router. This is the task that the swarm router will use to determine the best swarm to use.",
|
89
|
+
)
|
234
90
|
|
235
91
|
|
236
92
|
class HierarchicalSwarm(BaseSwarm):
|
@@ -248,13 +104,19 @@ class HierarchicalSwarm(BaseSwarm):
|
|
248
104
|
self,
|
249
105
|
name: str = "HierarchicalAgentSwarm",
|
250
106
|
description: str = "Distributed task swarm",
|
251
|
-
director: Optional[Union[Agent, Any]] = None,
|
252
|
-
agents: List[Union[Agent, Any]] = None,
|
107
|
+
director: Optional[Union[Agent, Callable, Any]] = None,
|
108
|
+
agents: List[Union[Agent, Callable, Any]] = None,
|
253
109
|
max_loops: int = 1,
|
254
110
|
output_type: OutputType = "dict-all-except-first",
|
255
|
-
|
256
|
-
|
257
|
-
|
111
|
+
feedback_director_model_name: str = "gpt-4o-mini",
|
112
|
+
director_name: str = "Director",
|
113
|
+
director_model_name: str = "gpt-4o-mini",
|
114
|
+
verbose: bool = False,
|
115
|
+
add_collaboration_prompt: bool = True,
|
116
|
+
planning_director_agent: Optional[
|
117
|
+
Union[Agent, Callable, Any]
|
118
|
+
] = None,
|
119
|
+
director_feedback_on: bool = True,
|
258
120
|
*args,
|
259
121
|
**kwargs,
|
260
122
|
):
|
@@ -267,441 +129,609 @@ class HierarchicalSwarm(BaseSwarm):
|
|
267
129
|
:param agents: A list of agents within the swarm.
|
268
130
|
:param max_loops: The maximum number of feedback loops between the director and agents.
|
269
131
|
:param output_type: The format in which to return the output (dict, str, or list).
|
132
|
+
:param verbose: Enable detailed logging with loguru.
|
270
133
|
"""
|
271
134
|
super().__init__(
|
272
135
|
name=name,
|
273
136
|
description=description,
|
274
137
|
agents=agents,
|
275
138
|
)
|
139
|
+
self.name = name
|
276
140
|
self.director = director
|
277
141
|
self.agents = agents
|
278
142
|
self.max_loops = max_loops
|
279
143
|
self.output_type = output_type
|
144
|
+
self.feedback_director_model_name = (
|
145
|
+
feedback_director_model_name
|
146
|
+
)
|
147
|
+
self.director_name = director_name
|
148
|
+
self.verbose = verbose
|
280
149
|
self.director_model_name = director_model_name
|
281
|
-
self.
|
282
|
-
self.
|
150
|
+
self.add_collaboration_prompt = add_collaboration_prompt
|
151
|
+
self.planning_director_agent = planning_director_agent
|
152
|
+
self.director_feedback_on = director_feedback_on
|
283
153
|
|
284
|
-
self.
|
285
|
-
self.current_loop = 0
|
286
|
-
self.agent_outputs = {} # Store agent outputs for each loop
|
154
|
+
self.init_swarm()
|
287
155
|
|
288
|
-
|
156
|
+
def init_swarm(self):
|
157
|
+
"""
|
158
|
+
Initializes the swarm.
|
159
|
+
"""
|
160
|
+
# Initialize logger only if verbose is enabled
|
161
|
+
if self.verbose:
|
162
|
+
logger.info(
|
163
|
+
f"🚀 Initializing HierarchicalSwarm: {self.name}"
|
164
|
+
)
|
165
|
+
logger.info(
|
166
|
+
f"📊 Configuration - Max loops: {self.max_loops}"
|
167
|
+
)
|
168
|
+
|
169
|
+
self.conversation = Conversation(time_enabled=False)
|
289
170
|
|
290
171
|
# Reliability checks
|
291
172
|
self.reliability_checks()
|
292
173
|
|
293
|
-
# Handle teams
|
294
|
-
self.handle_teams()
|
295
|
-
|
296
|
-
# List all agents
|
297
|
-
list_all_agents(self.agents, self.conversation, self.name)
|
298
|
-
|
299
174
|
self.director = self.setup_director()
|
300
175
|
|
301
|
-
|
302
|
-
if not self.teams:
|
303
|
-
return
|
176
|
+
self.add_context_to_director()
|
304
177
|
|
305
|
-
|
306
|
-
|
178
|
+
if self.verbose:
|
179
|
+
logger.success(
|
180
|
+
f"✅ HierarchicalSwarm initialized successfully: Name {self.name}"
|
181
|
+
)
|
307
182
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
183
|
+
def add_context_to_director(self):
|
184
|
+
"""Add agent context to the director's conversation."""
|
185
|
+
try:
|
186
|
+
if self.verbose:
|
187
|
+
logger.info("📝 Adding agent context to director")
|
188
|
+
|
189
|
+
list_all_agents(
|
190
|
+
agents=self.agents,
|
191
|
+
conversation=self.conversation,
|
192
|
+
add_to_conversation=True,
|
193
|
+
add_collaboration_prompt=self.add_collaboration_prompt,
|
194
|
+
)
|
312
195
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
196
|
+
if self.verbose:
|
197
|
+
logger.success(
|
198
|
+
"✅ Agent context added to director successfully"
|
199
|
+
)
|
200
|
+
|
201
|
+
except Exception as e:
|
202
|
+
error_msg = (
|
203
|
+
f"❌ Failed to add context to director: {str(e)}"
|
204
|
+
)
|
205
|
+
logger.error(
|
206
|
+
f"{error_msg}\n🔍 Traceback: {traceback.format_exc()}"
|
207
|
+
)
|
318
208
|
|
319
209
|
def setup_director(self):
|
320
|
-
director
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
210
|
+
"""Set up the director agent with proper configuration."""
|
211
|
+
try:
|
212
|
+
if self.verbose:
|
213
|
+
logger.info("🎯 Setting up director agent")
|
214
|
+
|
215
|
+
schema = BaseTool().base_model_to_dict(SwarmSpec)
|
216
|
+
|
217
|
+
if self.verbose:
|
218
|
+
logger.debug(f"📋 Director schema: {schema}")
|
219
|
+
|
220
|
+
# if self.director is not None:
|
221
|
+
# # if litellm_check_for_tools(self.director.model_name) is True:
|
222
|
+
# self.director.add_tool_schema([schema])
|
223
|
+
|
224
|
+
# if self.verbose:
|
225
|
+
# logger.success(
|
226
|
+
# "✅ Director agent setup completed successfully"
|
227
|
+
# )
|
228
|
+
|
229
|
+
# return self.director
|
230
|
+
# else:
|
231
|
+
return Agent(
|
232
|
+
agent_name=self.director_name,
|
233
|
+
agent_description="A director agent that can create a plan and distribute orders to agents",
|
234
|
+
model_name=self.director_model_name,
|
235
|
+
max_loops=1,
|
236
|
+
base_model=SwarmSpec,
|
237
|
+
tools_list_dictionary=[schema],
|
238
|
+
output_type="dict-all-except-first",
|
239
|
+
)
|
328
240
|
|
329
|
-
|
241
|
+
except Exception as e:
|
242
|
+
error_msg = f"❌ Failed to setup director: {str(e)}\n🔍 Traceback: {traceback.format_exc()}\n🐛 If this issue persists, please report it at: https://github.com/kyegomez/swarms/issues"
|
243
|
+
logger.error(error_msg)
|
330
244
|
|
331
245
|
def reliability_checks(self):
|
332
246
|
"""
|
333
247
|
Checks if there are any agents and a director set for the swarm.
|
334
248
|
Raises ValueError if either condition is not met.
|
335
249
|
"""
|
250
|
+
try:
|
251
|
+
if self.verbose:
|
252
|
+
logger.info(
|
253
|
+
f"🔍 Running reliability checks for swarm: {self.name}"
|
254
|
+
)
|
336
255
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
"No agents found in the swarm. At least one agent must be provided to create a hierarchical swarm."
|
342
|
-
)
|
256
|
+
if not self.agents or len(self.agents) == 0:
|
257
|
+
raise ValueError(
|
258
|
+
"No agents found in the swarm. At least one agent must be provided to create a hierarchical swarm."
|
259
|
+
)
|
343
260
|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
261
|
+
if self.max_loops <= 0:
|
262
|
+
raise ValueError(
|
263
|
+
"Max loops must be greater than 0. Please set a valid number of loops."
|
264
|
+
)
|
348
265
|
|
349
|
-
|
350
|
-
|
266
|
+
if not self.director:
|
267
|
+
raise ValueError(
|
268
|
+
"Director not set for the swarm. A director agent is required to coordinate and orchestrate tasks among the agents."
|
269
|
+
)
|
351
270
|
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
271
|
+
if self.verbose:
|
272
|
+
logger.success(
|
273
|
+
f"✅ Reliability checks passed for swarm: {self.name}"
|
274
|
+
)
|
275
|
+
logger.info(
|
276
|
+
f"📊 Swarm stats - Agents: {len(self.agents)}, Max loops: {self.max_loops}"
|
277
|
+
)
|
356
278
|
|
357
|
-
|
279
|
+
except Exception as e:
|
280
|
+
error_msg = f"❌ Failed to setup director: {str(e)}\n🔍 Traceback: {traceback.format_exc()}\n🐛 If this issue persists, please report it at: https://github.com/kyegomez/swarms/issues"
|
281
|
+
logger.error(error_msg)
|
358
282
|
|
359
283
|
def run_director(
|
360
|
-
self,
|
284
|
+
self,
|
285
|
+
task: str,
|
286
|
+
img: str = None,
|
361
287
|
) -> SwarmSpec:
|
362
288
|
"""
|
363
289
|
Runs a task through the director agent with the current conversation context.
|
364
290
|
|
365
291
|
:param task: The task to be executed by the director.
|
366
|
-
:param loop_context: Additional context specific to the current loop.
|
367
292
|
:param img: Optional image to be used with the task.
|
368
293
|
:return: The SwarmSpec containing the director's orders.
|
369
294
|
"""
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
director_context += f"\n\nYour Task: {task}"
|
377
|
-
|
378
|
-
# Run the director with the context
|
379
|
-
function_call = self.director.run(task=director_context)
|
380
|
-
|
381
|
-
formatter.print_panel(
|
382
|
-
f"Director Output (Loop {self.current_loop}/{self.max_loops}):\n{function_call}",
|
383
|
-
title="Director's Orders",
|
384
|
-
)
|
385
|
-
|
386
|
-
# Add director's output to the conversation
|
387
|
-
self.conversation.add(
|
388
|
-
role="Director",
|
389
|
-
content=f"Loop {self.current_loop}/{self.max_loops}: {function_call}",
|
390
|
-
)
|
391
|
-
|
392
|
-
return function_call
|
393
|
-
|
394
|
-
def run(
|
395
|
-
self, task: str, img: str = None, *args, **kwargs
|
396
|
-
) -> Union[str, Dict, List]:
|
397
|
-
"""
|
398
|
-
Runs a task through the swarm, involving the director and agents through multiple loops.
|
399
|
-
|
400
|
-
:param task: The task to be executed by the swarm.
|
401
|
-
:param img: Optional image to be used with the task.
|
402
|
-
:return: The output of the swarm's task execution in the specified format.
|
403
|
-
"""
|
404
|
-
# Add the initial task to the conversation
|
405
|
-
self.conversation.add(role="User", content=f"Task: {task}")
|
406
|
-
|
407
|
-
# Reset loop counter and agent outputs
|
408
|
-
self.current_loop = 0
|
409
|
-
self.agent_outputs = {}
|
295
|
+
try:
|
296
|
+
if self.verbose:
|
297
|
+
logger.info(
|
298
|
+
f"🎯 Running director with task: {task[:100]}..."
|
299
|
+
)
|
410
300
|
|
411
|
-
|
412
|
-
|
301
|
+
if self.planning_director_agent is not None:
|
302
|
+
plan = self.planning_director_agent.run(
|
303
|
+
task=f"History: {self.conversation.get_str()} \n\n Create a detailed step by step comprehensive plan for the director to execute the task: {task}",
|
304
|
+
img=img,
|
305
|
+
)
|
413
306
|
|
414
|
-
|
415
|
-
for loop_idx in range(self.max_loops):
|
416
|
-
self.current_loop = loop_idx + 1
|
307
|
+
task += plan
|
417
308
|
|
418
|
-
#
|
419
|
-
|
420
|
-
f"
|
309
|
+
# Run the director with the context
|
310
|
+
function_call = self.director.run(
|
311
|
+
task=f"History: {self.conversation.get_str()} \n\n Task: {task}",
|
312
|
+
img=img,
|
421
313
|
)
|
422
314
|
|
423
|
-
|
424
|
-
|
425
|
-
task=task, loop_context=loop_context, img=img
|
315
|
+
self.conversation.add(
|
316
|
+
role="Director", content=function_call
|
426
317
|
)
|
427
318
|
|
428
|
-
|
429
|
-
|
319
|
+
if self.verbose:
|
320
|
+
logger.success("✅ Director execution completed")
|
321
|
+
logger.debug(
|
322
|
+
f"📋 Director output type: {type(function_call)}"
|
323
|
+
)
|
430
324
|
|
431
|
-
|
432
|
-
orders_list = self.parse_swarm_spec(swarm_spec)
|
325
|
+
return function_call
|
433
326
|
|
434
|
-
|
435
|
-
|
327
|
+
except Exception as e:
|
328
|
+
error_msg = f"❌ Failed to setup director: {str(e)}\n🔍 Traceback: {traceback.format_exc()}\n🐛 If this issue persists, please report it at: https://github.com/kyegomez/swarms/issues"
|
329
|
+
logger.error(error_msg)
|
436
330
|
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
331
|
+
def step(self, task: str, img: str = None, *args, **kwargs):
|
332
|
+
"""
|
333
|
+
Runs a single step of the hierarchical swarm.
|
334
|
+
"""
|
335
|
+
try:
|
336
|
+
if self.verbose:
|
337
|
+
logger.info(
|
338
|
+
f"👣 Executing single step for task: {task[:100]}..."
|
443
339
|
)
|
444
340
|
|
445
|
-
|
446
|
-
self.agent_outputs[self.current_loop][
|
447
|
-
order.agent_name
|
448
|
-
] = agent_output
|
449
|
-
|
450
|
-
# Prepare context for the next loop
|
451
|
-
loop_context = self.compile_loop_context(
|
452
|
-
self.current_loop
|
453
|
-
)
|
341
|
+
output = self.run_director(task=task, img=img)
|
454
342
|
|
455
|
-
#
|
456
|
-
|
457
|
-
break
|
343
|
+
# Parse the orders
|
344
|
+
plan, orders = self.parse_orders(output)
|
458
345
|
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
346
|
+
if self.verbose:
|
347
|
+
logger.info(
|
348
|
+
f"📋 Parsed plan and {len(orders)} orders"
|
349
|
+
)
|
463
350
|
|
464
|
-
|
465
|
-
|
466
|
-
Compiles the context for a specific loop, including all agent outputs.
|
351
|
+
# Execute the orders
|
352
|
+
outputs = self.execute_orders(orders)
|
467
353
|
|
468
|
-
|
469
|
-
|
470
|
-
"""
|
471
|
-
if loop_number not in self.agent_outputs:
|
472
|
-
return "No agent outputs available for this loop."
|
354
|
+
if self.verbose:
|
355
|
+
logger.info(f"⚡ Executed {len(outputs)} orders")
|
473
356
|
|
474
|
-
|
357
|
+
if self.director_feedback_on is True:
|
358
|
+
feedback = self.feedback_director(outputs)
|
359
|
+
else:
|
360
|
+
feedback = outputs
|
475
361
|
|
476
|
-
|
477
|
-
|
478
|
-
].items():
|
479
|
-
context += f"\n--- {agent_name}'s Output ---\n{output}\n"
|
362
|
+
if self.verbose:
|
363
|
+
logger.success("✅ Step completed successfully")
|
480
364
|
|
481
|
-
|
365
|
+
return feedback
|
482
366
|
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
"""
|
487
|
-
self.conversation.add(
|
488
|
-
role="System",
|
489
|
-
content=f"\n\nSwarm Name: {self.name}\n\nSwarm Description: {self.description}",
|
490
|
-
)
|
367
|
+
except Exception as e:
|
368
|
+
error_msg = f"❌ Failed to setup director: {str(e)}\n🔍 Traceback: {traceback.format_exc()}\n🐛 If this issue persists, please report it at: https://github.com/kyegomez/swarms/issues"
|
369
|
+
logger.error(error_msg)
|
491
370
|
|
492
|
-
def
|
371
|
+
def run(self, task: str, img: str = None, *args, **kwargs):
|
493
372
|
"""
|
494
|
-
|
373
|
+
Executes the hierarchical swarm for a specified number of feedback loops.
|
495
374
|
|
496
|
-
:param
|
497
|
-
:
|
498
|
-
:
|
375
|
+
:param task: The initial task to be processed by the swarm.
|
376
|
+
:param img: Optional image input for the agents.
|
377
|
+
:param args: Additional positional arguments.
|
378
|
+
:param kwargs: Additional keyword arguments.
|
379
|
+
:return: The formatted conversation history as output.
|
499
380
|
"""
|
500
381
|
try:
|
501
|
-
|
502
|
-
|
503
|
-
agent
|
504
|
-
for agent in self.agents
|
505
|
-
if agent.agent_name == name
|
506
|
-
]
|
507
|
-
|
508
|
-
if not matching_agents:
|
509
|
-
error_msg = f"Agent '{name}' not found in the swarm '{self.name}'"
|
510
|
-
logger.error(error_msg)
|
511
|
-
return None
|
382
|
+
current_loop = 0
|
383
|
+
last_output = None
|
512
384
|
|
513
|
-
|
385
|
+
if self.verbose:
|
386
|
+
logger.info(
|
387
|
+
f"🚀 Starting hierarchical swarm run: {self.name}"
|
388
|
+
)
|
389
|
+
logger.info(
|
390
|
+
f"📊 Configuration - Max loops: {self.max_loops}"
|
391
|
+
)
|
514
392
|
|
515
|
-
|
516
|
-
|
517
|
-
|
393
|
+
while current_loop < self.max_loops:
|
394
|
+
if self.verbose:
|
395
|
+
logger.info(
|
396
|
+
f"🔄 Loop {current_loop + 1}/{self.max_loops} - Processing task"
|
397
|
+
)
|
398
|
+
|
399
|
+
# For the first loop, use the original task.
|
400
|
+
# For subsequent loops, use the feedback from the previous loop as context.
|
401
|
+
if current_loop == 0:
|
402
|
+
loop_task = task
|
403
|
+
else:
|
404
|
+
loop_task = (
|
405
|
+
f"Previous loop results: {last_output}\n\n"
|
406
|
+
f"Original task: {task}\n\n"
|
407
|
+
"Based on the previous results and any feedback, continue with the next iteration of the task. "
|
408
|
+
"Refine, improve, or complete any remaining aspects of the analysis."
|
409
|
+
)
|
410
|
+
|
411
|
+
# Execute one step of the swarm
|
412
|
+
try:
|
413
|
+
last_output = self.step(
|
414
|
+
task=loop_task, img=img, *args, **kwargs
|
415
|
+
)
|
416
|
+
|
417
|
+
if self.verbose:
|
418
|
+
logger.success(
|
419
|
+
f"✅ Loop {current_loop + 1} completed successfully"
|
420
|
+
)
|
421
|
+
|
422
|
+
except Exception as e:
|
423
|
+
error_msg = f"❌ Failed to setup director: {str(e)}\n🔍 Traceback: {traceback.format_exc()}\n🐛 If this issue persists, please report it at: https://github.com/kyegomez/swarms/issues"
|
424
|
+
logger.error(error_msg)
|
425
|
+
|
426
|
+
current_loop += 1
|
427
|
+
|
428
|
+
# Add loop completion marker to conversation
|
429
|
+
self.conversation.add(
|
430
|
+
role="System",
|
431
|
+
content=f"--- Loop {current_loop}/{self.max_loops} completed ---",
|
432
|
+
)
|
518
433
|
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
434
|
+
if self.verbose:
|
435
|
+
logger.success(
|
436
|
+
f"🎉 Hierarchical swarm run completed: {self.name}"
|
437
|
+
)
|
438
|
+
logger.info(
|
439
|
+
f"📊 Total loops executed: {current_loop}"
|
440
|
+
)
|
524
441
|
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
442
|
+
return history_output_formatter(
|
443
|
+
conversation=self.conversation, type=self.output_type
|
444
|
+
)
|
445
|
+
|
446
|
+
except Exception as e:
|
447
|
+
error_msg = f"❌ Failed to setup director: {str(e)}\n🔍 Traceback: {traceback.format_exc()}\n🐛 If this issue persists, please report it at: https://github.com/kyegomez/swarms/issues"
|
448
|
+
logger.error(error_msg)
|
449
|
+
|
450
|
+
def feedback_director(self, outputs: list):
|
451
|
+
"""Provide feedback from the director based on agent outputs."""
|
530
452
|
try:
|
531
|
-
|
453
|
+
if self.verbose:
|
454
|
+
logger.info("📝 Generating director feedback")
|
532
455
|
|
533
|
-
|
534
|
-
agent_context = (
|
535
|
-
f"Loop: {self.current_loop}/{self.max_loops}\n"
|
536
|
-
f"History: {self.conversation.get_str()}\n"
|
537
|
-
f"Your Task: {task}"
|
538
|
-
)
|
456
|
+
task = f"History: {self.conversation.get_str()} \n\n"
|
539
457
|
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
458
|
+
feedback_director = Agent(
|
459
|
+
agent_name="Director",
|
460
|
+
agent_description="Director module that provides feedback to the worker agents",
|
461
|
+
model_name=self.director_model_name,
|
462
|
+
max_loops=1,
|
463
|
+
system_prompt=HIEARCHICAL_SWARM_SYSTEM_PROMPT,
|
544
464
|
)
|
545
465
|
|
546
|
-
|
547
|
-
|
548
|
-
|
466
|
+
output = feedback_director.run(
|
467
|
+
task=(
|
468
|
+
"You are the Director. Carefully review the outputs generated by all the worker agents in the previous step. "
|
469
|
+
"Provide specific, actionable feedback for each agent, highlighting strengths, weaknesses, and concrete suggestions for improvement. "
|
470
|
+
"If any outputs are unclear, incomplete, or could be enhanced, explain exactly how. "
|
471
|
+
f"Your feedback should help the agents refine their work in the next iteration. "
|
472
|
+
f"Worker Agent Responses: {task}"
|
473
|
+
)
|
474
|
+
)
|
549
475
|
self.conversation.add(
|
550
|
-
role=agent_name,
|
551
|
-
content=f"Loop {self.current_loop}/{self.max_loops}: {out}",
|
476
|
+
role=self.director.agent_name, content=output
|
552
477
|
)
|
553
478
|
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
479
|
+
if self.verbose:
|
480
|
+
logger.success(
|
481
|
+
"✅ Director feedback generated successfully"
|
482
|
+
)
|
483
|
+
|
484
|
+
return output
|
558
485
|
|
559
|
-
return out
|
560
486
|
except Exception as e:
|
561
|
-
error_msg = (
|
562
|
-
f"Error running agent '{agent_name}': {str(e)}"
|
563
|
-
)
|
487
|
+
error_msg = f"❌ Failed to setup director: {str(e)}\n🔍 Traceback: {traceback.format_exc()}\n🐛 If this issue persists, please report it at: https://github.com/kyegomez/swarms/issues"
|
564
488
|
logger.error(error_msg)
|
565
|
-
return error_msg
|
566
489
|
|
567
|
-
def
|
490
|
+
def call_single_agent(
|
491
|
+
self, agent_name: str, task: str, *args, **kwargs
|
492
|
+
):
|
568
493
|
"""
|
569
|
-
|
570
|
-
|
571
|
-
:param swarm_spec: The SwarmSpec containing the orders to be parsed.
|
572
|
-
:return: A list of agent outputs.
|
494
|
+
Calls a single agent with the given task.
|
573
495
|
"""
|
574
|
-
self.add_goal_and_more_in_conversation(swarm_spec)
|
575
|
-
orders_list = self.parse_swarm_spec(swarm_spec)
|
576
|
-
outputs = []
|
577
|
-
|
578
496
|
try:
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
497
|
+
if self.verbose:
|
498
|
+
logger.info(f"📞 Calling agent: {agent_name}")
|
499
|
+
|
500
|
+
# Find agent by name
|
501
|
+
agent = None
|
502
|
+
for a in self.agents:
|
503
|
+
if (
|
504
|
+
hasattr(a, "agent_name")
|
505
|
+
and a.agent_name == agent_name
|
506
|
+
):
|
507
|
+
agent = a
|
508
|
+
break
|
509
|
+
|
510
|
+
if agent is None:
|
511
|
+
available_agents = [
|
512
|
+
a.agent_name
|
513
|
+
for a in self.agents
|
514
|
+
if hasattr(a, "agent_name")
|
515
|
+
]
|
516
|
+
raise ValueError(
|
517
|
+
f"Agent '{agent_name}' not found in swarm. Available agents: {available_agents}"
|
583
518
|
)
|
584
|
-
outputs.append(output)
|
585
519
|
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
520
|
+
output = agent.run(
|
521
|
+
task=f"History: {self.conversation.get_str()} \n\n Task: {task}",
|
522
|
+
*args,
|
523
|
+
**kwargs,
|
590
524
|
)
|
525
|
+
self.conversation.add(role=agent_name, content=output)
|
526
|
+
|
527
|
+
if self.verbose:
|
528
|
+
logger.success(
|
529
|
+
f"✅ Agent {agent_name} completed task successfully"
|
530
|
+
)
|
531
|
+
|
532
|
+
return output
|
533
|
+
|
534
|
+
except Exception as e:
|
535
|
+
error_msg = f"❌ Failed to setup director: {str(e)}\n🔍 Traceback: {traceback.format_exc()}\n🐛 If this issue persists, please report it at: https://github.com/kyegomez/swarms/issues"
|
591
536
|
logger.error(error_msg)
|
592
|
-
return [error_msg]
|
593
537
|
|
594
|
-
def
|
595
|
-
self, swarm_spec: SwarmSpec
|
596
|
-
) -> List[HierarchicalOrder]:
|
538
|
+
def parse_orders(self, output):
|
597
539
|
"""
|
598
|
-
Parses the
|
599
|
-
|
600
|
-
:param swarm_spec: The SwarmSpec to be parsed.
|
601
|
-
:return: The list of orders extracted from the SwarmSpec.
|
540
|
+
Parses the orders from the director's output.
|
602
541
|
"""
|
603
542
|
try:
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
543
|
+
if self.verbose:
|
544
|
+
logger.info("📋 Parsing director orders")
|
545
|
+
logger.debug(f"📊 Output type: {type(output)}")
|
546
|
+
|
547
|
+
import json
|
548
|
+
|
549
|
+
# Handle different output formats from the director
|
550
|
+
if isinstance(output, list):
|
551
|
+
# If output is a list, look for function call data
|
552
|
+
for item in output:
|
553
|
+
if isinstance(item, dict):
|
554
|
+
# Check if it's a conversation format with role/content
|
555
|
+
if "content" in item and isinstance(
|
556
|
+
item["content"], list
|
557
|
+
):
|
558
|
+
for content_item in item["content"]:
|
559
|
+
if (
|
560
|
+
isinstance(content_item, dict)
|
561
|
+
and "function" in content_item
|
562
|
+
):
|
563
|
+
function_data = content_item[
|
564
|
+
"function"
|
565
|
+
]
|
566
|
+
if "arguments" in function_data:
|
567
|
+
try:
|
568
|
+
args = json.loads(
|
569
|
+
function_data[
|
570
|
+
"arguments"
|
571
|
+
]
|
572
|
+
)
|
573
|
+
if (
|
574
|
+
"plan" in args
|
575
|
+
and "orders" in args
|
576
|
+
):
|
577
|
+
plan = args["plan"]
|
578
|
+
orders = [
|
579
|
+
HierarchicalOrder(
|
580
|
+
**order
|
581
|
+
)
|
582
|
+
for order in args[
|
583
|
+
"orders"
|
584
|
+
]
|
585
|
+
]
|
586
|
+
|
587
|
+
if self.verbose:
|
588
|
+
logger.success(
|
589
|
+
f"✅ Successfully parsed plan and {len(orders)} orders"
|
590
|
+
)
|
591
|
+
|
592
|
+
return plan, orders
|
593
|
+
except (
|
594
|
+
json.JSONDecodeError
|
595
|
+
) as json_err:
|
596
|
+
if self.verbose:
|
597
|
+
logger.warning(
|
598
|
+
f"⚠️ JSON decode error: {json_err}"
|
599
|
+
)
|
600
|
+
pass
|
601
|
+
# Check if it's a direct function call format
|
602
|
+
elif "function" in item:
|
603
|
+
function_data = item["function"]
|
604
|
+
if "arguments" in function_data:
|
605
|
+
try:
|
606
|
+
args = json.loads(
|
607
|
+
function_data["arguments"]
|
608
|
+
)
|
609
|
+
if (
|
610
|
+
"plan" in args
|
611
|
+
and "orders" in args
|
612
|
+
):
|
613
|
+
plan = args["plan"]
|
614
|
+
orders = [
|
615
|
+
HierarchicalOrder(**order)
|
616
|
+
for order in args[
|
617
|
+
"orders"
|
618
|
+
]
|
619
|
+
]
|
620
|
+
|
621
|
+
if self.verbose:
|
622
|
+
logger.success(
|
623
|
+
f"✅ Successfully parsed plan and {len(orders)} orders"
|
624
|
+
)
|
625
|
+
|
626
|
+
return plan, orders
|
627
|
+
except (
|
628
|
+
json.JSONDecodeError
|
629
|
+
) as json_err:
|
630
|
+
if self.verbose:
|
631
|
+
logger.warning(
|
632
|
+
f"⚠️ JSON decode error: {json_err}"
|
633
|
+
)
|
634
|
+
pass
|
635
|
+
# If no function call found, raise error
|
636
|
+
raise ValueError(
|
637
|
+
f"Unable to parse orders from director output: {output}"
|
638
|
+
)
|
639
|
+
elif isinstance(output, dict):
|
640
|
+
# Handle direct dictionary format
|
641
|
+
if "plan" in output and "orders" in output:
|
642
|
+
plan = output["plan"]
|
643
|
+
orders = [
|
644
|
+
HierarchicalOrder(**order)
|
645
|
+
for order in output["orders"]
|
646
|
+
]
|
647
|
+
|
648
|
+
if self.verbose:
|
649
|
+
logger.success(
|
650
|
+
f"✅ Successfully parsed plan and {len(orders)} orders"
|
651
|
+
)
|
652
|
+
|
653
|
+
return plan, orders
|
654
|
+
else:
|
655
|
+
raise ValueError(
|
656
|
+
f"Missing 'plan' or 'orders' in director output: {output}"
|
657
|
+
)
|
658
|
+
else:
|
659
|
+
raise ValueError(
|
660
|
+
f"Unexpected output format from director: {type(output)}"
|
661
|
+
)
|
662
|
+
|
610
663
|
except Exception as e:
|
611
|
-
|
612
|
-
|
664
|
+
error_msg = f"❌ Failed to setup director: {str(e)}\n🔍 Traceback: {traceback.format_exc()}\n🐛 If this issue persists, please report it at: https://github.com/kyegomez/swarms/issues"
|
665
|
+
logger.error(error_msg)
|
613
666
|
|
614
|
-
def
|
615
|
-
self, agent_outputs: Dict[str, str]
|
616
|
-
) -> Dict[str, str]:
|
667
|
+
def execute_orders(self, orders: list):
|
617
668
|
"""
|
618
|
-
|
619
|
-
|
620
|
-
:param agent_outputs: A dictionary mapping agent names to their outputs.
|
621
|
-
:return: A dictionary of feedback for each agent.
|
669
|
+
Executes the orders from the director's output.
|
622
670
|
"""
|
623
|
-
|
671
|
+
try:
|
672
|
+
if self.verbose:
|
673
|
+
logger.info(f"⚡ Executing {len(orders)} orders")
|
674
|
+
|
675
|
+
outputs = []
|
676
|
+
for i, order in enumerate(orders):
|
677
|
+
if self.verbose:
|
678
|
+
logger.info(
|
679
|
+
f"📋 Executing order {i+1}/{len(orders)}: {order.agent_name}"
|
680
|
+
)
|
681
|
+
|
682
|
+
output = self.call_single_agent(
|
683
|
+
order.agent_name, order.task
|
684
|
+
)
|
685
|
+
outputs.append(output)
|
624
686
|
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
)
|
687
|
+
if self.verbose:
|
688
|
+
logger.success(
|
689
|
+
f"✅ All {len(orders)} orders executed successfully"
|
690
|
+
)
|
630
691
|
|
631
|
-
|
632
|
-
feedback_task = (
|
633
|
-
f"Review the following agent outputs and provide feedback for each agent.\n\n"
|
634
|
-
f"{agent_outputs_str}"
|
635
|
-
)
|
692
|
+
return outputs
|
636
693
|
|
637
|
-
|
638
|
-
|
694
|
+
except Exception as e:
|
695
|
+
error_msg = f"❌ Failed to setup director: {str(e)}\n🔍 Traceback: {traceback.format_exc()}\n🐛 If this issue persists, please report it at: https://github.com/kyegomez/swarms/issues"
|
696
|
+
logger.error(error_msg)
|
639
697
|
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
698
|
+
def batched_run(
|
699
|
+
self, tasks: List[str], img: str = None, *args, **kwargs
|
700
|
+
):
|
701
|
+
"""
|
702
|
+
Executes the hierarchical swarm for a list of tasks.
|
703
|
+
"""
|
704
|
+
try:
|
705
|
+
if self.verbose:
|
706
|
+
logger.info(
|
707
|
+
f"🚀 Starting batched hierarchical swarm run: {self.name}"
|
708
|
+
)
|
709
|
+
logger.info(
|
710
|
+
f"📊 Configuration - Max loops: {self.max_loops}"
|
711
|
+
)
|
646
712
|
|
647
|
-
#
|
648
|
-
|
713
|
+
# Initialize a list to store the results
|
714
|
+
results = []
|
649
715
|
|
650
|
-
#
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
)
|
716
|
+
# Process each task in parallel
|
717
|
+
for task in tasks:
|
718
|
+
result = self.run(task, img, *args, **kwargs)
|
719
|
+
results.append(result)
|
655
720
|
|
656
|
-
|
721
|
+
if self.verbose:
|
722
|
+
logger.success(
|
723
|
+
f"🎉 Batched hierarchical swarm run completed: {self.name}"
|
724
|
+
)
|
725
|
+
logger.info(f"📊 Total tasks processed: {len(tasks)}")
|
657
726
|
|
658
|
-
|
659
|
-
self, swarm_spec: SwarmSpec
|
660
|
-
) -> None:
|
661
|
-
"""
|
662
|
-
Adds the swarm's goals, plan, and rules to the conversation.
|
727
|
+
return results
|
663
728
|
|
664
|
-
:param swarm_spec: The SwarmSpec containing the goals, plan, and rules.
|
665
|
-
"""
|
666
|
-
try:
|
667
|
-
# Directly access and format attributes in one line
|
668
|
-
self.conversation.add(
|
669
|
-
role="Director",
|
670
|
-
content=f"Goals:\n{swarm_spec.goals}\n\nPlan:\n{swarm_spec.plan}\n\nRules:\n{swarm_spec.rules}",
|
671
|
-
)
|
672
729
|
except Exception as e:
|
673
|
-
|
674
|
-
f"
|
730
|
+
error_msg = (
|
731
|
+
f"❌ Batched hierarchical swarm run failed: {str(e)}"
|
675
732
|
)
|
676
|
-
|
677
|
-
|
678
|
-
self, tasks: List[str], img: str = None
|
679
|
-
) -> List[Union[str, Dict, List]]:
|
680
|
-
"""
|
681
|
-
Runs multiple tasks sequentially through the swarm.
|
682
|
-
|
683
|
-
:param tasks: The list of tasks to be executed.
|
684
|
-
:param img: Optional image to be used with the tasks.
|
685
|
-
:return: A list of outputs from each task execution.
|
686
|
-
"""
|
687
|
-
return [self.run(task, img) for task in tasks]
|
688
|
-
|
689
|
-
def check_director_agent_output(self, output: any) -> dict:
|
690
|
-
if isinstance(output, dict):
|
691
|
-
return output
|
692
|
-
elif isinstance(output, str):
|
693
|
-
try:
|
694
|
-
# Attempt to parse the string as JSON
|
695
|
-
return json.loads(output)
|
696
|
-
except json.JSONDecodeError as e:
|
697
|
-
# Log an error if the string cannot be parsed
|
733
|
+
if self.verbose:
|
734
|
+
logger.error(error_msg)
|
698
735
|
logger.error(
|
699
|
-
f"
|
736
|
+
f"🔍 Traceback: {traceback.format_exc()}"
|
700
737
|
)
|
701
|
-
return {}
|
702
|
-
else:
|
703
|
-
# Log an error if the output is neither a dict nor a string
|
704
|
-
logger.error(
|
705
|
-
"Output is neither a dictionary nor a string."
|
706
|
-
)
|
707
|
-
return {}
|