swarms 7.7.1__py3-none-any.whl → 7.7.3__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/prompts/ag_prompt.py +51 -19
- swarms/prompts/agent_system_prompts.py +13 -4
- swarms/prompts/multi_agent_collab_prompt.py +18 -0
- swarms/prompts/prompt.py +6 -10
- swarms/schemas/__init__.py +0 -3
- swarms/structs/__init__.py +3 -8
- swarms/structs/agent.py +211 -163
- swarms/structs/aop.py +8 -1
- swarms/structs/auto_swarm_builder.py +271 -210
- swarms/structs/conversation.py +23 -56
- swarms/structs/hiearchical_swarm.py +93 -122
- swarms/structs/ma_utils.py +96 -0
- swarms/structs/mixture_of_agents.py +20 -103
- swarms/structs/{multi_agent_orchestrator.py → multi_agent_router.py} +32 -95
- swarms/structs/output_types.py +3 -16
- swarms/structs/stopping_conditions.py +30 -0
- swarms/structs/swarm_router.py +57 -5
- swarms/structs/swarming_architectures.py +576 -185
- swarms/telemetry/main.py +6 -2
- swarms/tools/mcp_client.py +209 -53
- swarms/tools/mcp_integration.py +1 -53
- swarms/utils/formatter.py +15 -1
- swarms/utils/generate_keys.py +64 -0
- swarms/utils/history_output_formatter.py +2 -0
- {swarms-7.7.1.dist-info → swarms-7.7.3.dist-info}/METADATA +98 -263
- {swarms-7.7.1.dist-info → swarms-7.7.3.dist-info}/RECORD +29 -38
- swarms/schemas/agent_input_schema.py +0 -149
- swarms/structs/agents_available.py +0 -87
- swarms/structs/async_workflow.py +0 -818
- swarms/structs/graph_swarm.py +0 -612
- swarms/structs/octotools.py +0 -844
- swarms/structs/pulsar_swarm.py +0 -469
- swarms/structs/queue_swarm.py +0 -193
- swarms/structs/swarm_builder.py +0 -395
- swarms/structs/swarm_load_balancer.py +0 -344
- swarms/structs/swarm_output_type.py +0 -23
- swarms/structs/talk_hier.py +0 -729
- {swarms-7.7.1.dist-info → swarms-7.7.3.dist-info}/LICENSE +0 -0
- {swarms-7.7.1.dist-info → swarms-7.7.3.dist-info}/WHEEL +0 -0
- {swarms-7.7.1.dist-info → swarms-7.7.3.dist-info}/entry_points.txt +0 -0
@@ -1,59 +1,20 @@
|
|
1
1
|
import asyncio
|
2
2
|
import os
|
3
|
-
import
|
4
|
-
from typing import Any, Dict, List, Optional
|
3
|
+
from typing import List, Optional
|
5
4
|
|
6
|
-
from pydantic import BaseModel, Field
|
7
5
|
|
8
6
|
from swarms.structs.agent import Agent
|
9
|
-
from swarms.
|
10
|
-
from swarms.schemas.agent_step_schemas import ManySteps
|
11
|
-
from swarms.prompts.ag_prompt import aggregator_system_prompt
|
7
|
+
from swarms.prompts.ag_prompt import aggregator_system_prompt_main
|
12
8
|
from swarms.utils.loguru_logger import initialize_logger
|
13
9
|
import concurrent.futures
|
14
10
|
from swarms.structs.output_types import OutputType
|
15
11
|
from swarms.structs.conversation import Conversation
|
12
|
+
from swarms.utils.history_output_formatter import (
|
13
|
+
history_output_formatter,
|
14
|
+
)
|
16
15
|
|
17
16
|
logger = initialize_logger(log_folder="mixture_of_agents")
|
18
17
|
|
19
|
-
time_stamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
20
|
-
|
21
|
-
|
22
|
-
class MixtureOfAgentsInput(BaseModel):
|
23
|
-
name: str = "MixtureOfAgents"
|
24
|
-
description: str = (
|
25
|
-
"A class to run a mixture of agents and aggregate their responses."
|
26
|
-
)
|
27
|
-
agents: List[Dict[str, Any]]
|
28
|
-
aggregator_agent: Any = Field(
|
29
|
-
...,
|
30
|
-
description="An aggregator agent to be used in the mixture.",
|
31
|
-
)
|
32
|
-
aggregator_system_prompt: str = Field(
|
33
|
-
default=aggregator_system_prompt.get_prompt(),
|
34
|
-
description=aggregator_system_prompt.description,
|
35
|
-
)
|
36
|
-
layers: int = 3
|
37
|
-
time_created: str = Field(
|
38
|
-
time_stamp,
|
39
|
-
description="The time the mixture of agents was created.",
|
40
|
-
)
|
41
|
-
|
42
|
-
|
43
|
-
class MixtureOfAgentsOutput(BaseModel):
|
44
|
-
id: str = Field(
|
45
|
-
..., description="The ID of the mixture of agents."
|
46
|
-
)
|
47
|
-
task: str = Field(..., description="None")
|
48
|
-
InputConfig: MixtureOfAgentsInput
|
49
|
-
# output: List[ManySteps]
|
50
|
-
normal_agent_outputs: List[ManySteps]
|
51
|
-
aggregator_agent_summary: str
|
52
|
-
time_completed: str = Field(
|
53
|
-
time_stamp,
|
54
|
-
description="The time the mixture of agents was completed.",
|
55
|
-
)
|
56
|
-
|
57
18
|
|
58
19
|
class MixtureOfAgents:
|
59
20
|
"""
|
@@ -66,7 +27,7 @@ class MixtureOfAgents:
|
|
66
27
|
description: str = "A class to run a mixture of agents and aggregate their responses.",
|
67
28
|
agents: List[Agent] = [],
|
68
29
|
aggregator_agent: Agent = None,
|
69
|
-
aggregator_system_prompt: str =
|
30
|
+
aggregator_system_prompt: str = aggregator_system_prompt_main,
|
70
31
|
layers: int = 3,
|
71
32
|
max_loops: int = 1,
|
72
33
|
return_str_on: bool = False,
|
@@ -85,31 +46,13 @@ class MixtureOfAgents:
|
|
85
46
|
"""
|
86
47
|
self.name = name
|
87
48
|
self.description = description
|
88
|
-
self.agents
|
89
|
-
self.aggregator_agent
|
90
|
-
self.aggregator_system_prompt
|
91
|
-
self.layers
|
92
|
-
self.max_loops
|
93
|
-
self.return_str_on
|
94
|
-
self.output_type
|
95
|
-
|
96
|
-
self.input_schema = MixtureOfAgentsInput(
|
97
|
-
name=name,
|
98
|
-
description=description,
|
99
|
-
agents=[agent.to_dict() for agent in self.agents],
|
100
|
-
aggregator_agent=aggregator_agent.to_dict(),
|
101
|
-
aggregator_system_prompt=self.aggregator_system_prompt,
|
102
|
-
layers=self.layers,
|
103
|
-
time_created=time_stamp,
|
104
|
-
)
|
105
|
-
|
106
|
-
self.output_schema = MixtureOfAgentsOutput(
|
107
|
-
id="MixtureOfAgents",
|
108
|
-
InputConfig=self.input_schema.model_dump(),
|
109
|
-
normal_agent_outputs=[],
|
110
|
-
aggregator_agent_summary="",
|
111
|
-
task="",
|
112
|
-
)
|
49
|
+
self.agents = agents
|
50
|
+
self.aggregator_agent = aggregator_agent
|
51
|
+
self.aggregator_system_prompt = aggregator_system_prompt_main
|
52
|
+
self.layers = layers
|
53
|
+
self.max_loops = max_loops
|
54
|
+
self.return_str_on = return_str_on
|
55
|
+
self.output_type = output_type
|
113
56
|
|
114
57
|
self.reliability_check()
|
115
58
|
|
@@ -182,9 +125,6 @@ class MixtureOfAgents:
|
|
182
125
|
Returns:
|
183
126
|
str: The response from the agent.
|
184
127
|
"""
|
185
|
-
# Update the task in the output schema
|
186
|
-
self.output_schema.task = task
|
187
|
-
|
188
128
|
# If there are previous responses, update the agent's system prompt
|
189
129
|
if prev_responses:
|
190
130
|
system_prompt_with_responses = (
|
@@ -197,9 +137,7 @@ class MixtureOfAgents:
|
|
197
137
|
# Run the agent asynchronously
|
198
138
|
response = await asyncio.to_thread(agent.run, task)
|
199
139
|
|
200
|
-
self.
|
201
|
-
agent.agent_output
|
202
|
-
)
|
140
|
+
self.conversation.add(agent.agent_name, response)
|
203
141
|
|
204
142
|
# Log the agent's response
|
205
143
|
print(f"Agent {agent.agent_name} response: {response}")
|
@@ -235,7 +173,6 @@ class MixtureOfAgents:
|
|
235
173
|
final_result = await self._run_agent_async(
|
236
174
|
self.aggregator_agent, task, prev_responses=results
|
237
175
|
)
|
238
|
-
self.output_schema.aggregator_agent_summary = final_result
|
239
176
|
|
240
177
|
print(f"Final Aggregated Response: {final_result}")
|
241
178
|
|
@@ -248,38 +185,18 @@ class MixtureOfAgents:
|
|
248
185
|
"""
|
249
186
|
try:
|
250
187
|
self.conversation.add("user", task)
|
251
|
-
prev_context = None
|
252
188
|
|
253
189
|
for _ in range(self.max_loops):
|
254
190
|
# Add previous context to task if available
|
255
|
-
|
256
|
-
f"{task}\n\nPrevious context:\n{prev_context}"
|
257
|
-
if prev_context
|
258
|
-
else task
|
259
|
-
)
|
191
|
+
prompt = f"History: {self.conversation.get_str()}\n\nTask: {task}"
|
260
192
|
|
261
193
|
# Run async process
|
262
|
-
asyncio.run(self._run_async(
|
194
|
+
asyncio.run(self._run_async(prompt))
|
263
195
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
self.output_schema.task = task
|
270
|
-
|
271
|
-
log_agent_data(self.output_schema.model_dump())
|
272
|
-
|
273
|
-
if self.return_str_on or self.output_type == "str":
|
274
|
-
return self.conversation.get_str()
|
275
|
-
elif self.output_type == "dict":
|
276
|
-
return (
|
277
|
-
self.conversation.return_messages_as_dictionary()
|
278
|
-
)
|
279
|
-
elif self.output_type == "list":
|
280
|
-
return self.conversation.return_messages_as_list()
|
281
|
-
else:
|
282
|
-
return self.output_schema.model_dump_json(indent=4)
|
196
|
+
return history_output_formatter(
|
197
|
+
conversation=self.conversation,
|
198
|
+
type=self.output_type,
|
199
|
+
)
|
283
200
|
|
284
201
|
except Exception as e:
|
285
202
|
logger.error(f"Error running mixture of agents: {str(e)}")
|
@@ -9,8 +9,6 @@ Todo:
|
|
9
9
|
"""
|
10
10
|
|
11
11
|
import os
|
12
|
-
import uuid
|
13
|
-
from datetime import datetime
|
14
12
|
from typing import List, Optional
|
15
13
|
|
16
14
|
from loguru import logger
|
@@ -20,6 +18,10 @@ from swarms.structs.agent import Agent
|
|
20
18
|
from swarms.structs.conversation import Conversation
|
21
19
|
from swarms.structs.output_types import OutputType
|
22
20
|
from swarms.utils.any_to_str import any_to_str
|
21
|
+
from swarms.utils.history_output_formatter import (
|
22
|
+
history_output_formatter,
|
23
|
+
)
|
24
|
+
from swarms.utils.formatter import formatter
|
23
25
|
|
24
26
|
|
25
27
|
class AgentResponse(BaseModel):
|
@@ -62,7 +64,7 @@ class MultiAgentRouter:
|
|
62
64
|
temperature: float = 0.1,
|
63
65
|
shared_memory_system: callable = None,
|
64
66
|
output_type: OutputType = "dict",
|
65
|
-
|
67
|
+
if_print: bool = True,
|
66
68
|
):
|
67
69
|
"""
|
68
70
|
Initializes the MultiAgentRouter with a list of agents and configuration options.
|
@@ -80,15 +82,15 @@ class MultiAgentRouter:
|
|
80
82
|
self.description = description
|
81
83
|
self.shared_memory_system = shared_memory_system
|
82
84
|
self.output_type = output_type
|
83
|
-
self.execute_task = execute_task
|
84
85
|
self.model = model
|
85
86
|
self.temperature = temperature
|
86
|
-
|
87
|
+
self.if_print = if_print
|
87
88
|
# Initialize Agents
|
88
89
|
self.agents = {agent.name: agent for agent in agents}
|
89
90
|
self.conversation = Conversation()
|
90
91
|
|
91
92
|
self.api_key = os.getenv("OPENAI_API_KEY")
|
93
|
+
|
92
94
|
if not self.api_key:
|
93
95
|
raise ValueError("OpenAI API key must be provided")
|
94
96
|
|
@@ -99,6 +101,7 @@ class MultiAgentRouter:
|
|
99
101
|
system_prompt=self.boss_system_prompt,
|
100
102
|
api_key=self.api_key,
|
101
103
|
temperature=temperature,
|
104
|
+
base_model=AgentResponse,
|
102
105
|
)
|
103
106
|
|
104
107
|
def __repr__(self):
|
@@ -140,21 +143,6 @@ class MultiAgentRouter:
|
|
140
143
|
Always select exactly one agent that best matches the task requirements.
|
141
144
|
"""
|
142
145
|
|
143
|
-
def find_agent_in_list(self, agent_name: str) -> Optional[Agent]:
|
144
|
-
"""
|
145
|
-
Find an agent by name in a list of agents.
|
146
|
-
|
147
|
-
Args:
|
148
|
-
agent_name (str): The name of the agent to find.
|
149
|
-
|
150
|
-
Returns:
|
151
|
-
Optional[Agent]: The agent object if found, otherwise None.
|
152
|
-
"""
|
153
|
-
for agent in self.agent_list:
|
154
|
-
if agent.name == agent_name:
|
155
|
-
return agent
|
156
|
-
return None
|
157
|
-
|
158
146
|
def route_task(self, task: str) -> dict:
|
159
147
|
"""
|
160
148
|
Routes a task to the appropriate agent and returns their response.
|
@@ -167,15 +155,21 @@ class MultiAgentRouter:
|
|
167
155
|
"""
|
168
156
|
try:
|
169
157
|
self.conversation.add(role="user", content=task)
|
170
|
-
start_time = datetime.now()
|
171
158
|
|
172
159
|
# Get boss decision using function calling
|
173
|
-
boss_response = self.function_caller.
|
174
|
-
|
160
|
+
boss_response = self.function_caller.run(task)
|
175
161
|
boss_response_str = any_to_str(boss_response)
|
176
162
|
|
163
|
+
if self.if_print:
|
164
|
+
formatter.print_panel(
|
165
|
+
boss_response_str,
|
166
|
+
title="Multi-Agent Router Decision",
|
167
|
+
)
|
168
|
+
else:
|
169
|
+
pass
|
170
|
+
|
177
171
|
self.conversation.add(
|
178
|
-
role="
|
172
|
+
role="Agent Router", content=boss_response_str
|
179
173
|
)
|
180
174
|
|
181
175
|
# Validate that the selected agent exists
|
@@ -190,60 +184,16 @@ class MultiAgentRouter:
|
|
190
184
|
# Use the modified task if provided, otherwise use original task
|
191
185
|
final_task = boss_response.modified_task or task
|
192
186
|
|
193
|
-
#
|
194
|
-
|
195
|
-
agent_response = None
|
196
|
-
execution_time = 0
|
187
|
+
# Use the agent's run method directly
|
188
|
+
agent_response = selected_agent.run(final_task)
|
197
189
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
self.conversation.add(
|
202
|
-
role=selected_agent.name, content=agent_response
|
203
|
-
)
|
204
|
-
execution_time = (
|
205
|
-
datetime.now() - execution_start
|
206
|
-
).total_seconds()
|
207
|
-
else:
|
208
|
-
logger.info(
|
209
|
-
"Task execution skipped (execute_task=False)"
|
210
|
-
)
|
190
|
+
self.conversation.add(
|
191
|
+
role=selected_agent.name, content=agent_response
|
192
|
+
)
|
211
193
|
|
212
|
-
|
213
|
-
|
214
|
-
result = {
|
215
|
-
"id": str(uuid.uuid4()),
|
216
|
-
"timestamp": datetime.now().isoformat(),
|
217
|
-
"task": {
|
218
|
-
"original": task,
|
219
|
-
"modified": (
|
220
|
-
final_task
|
221
|
-
if boss_response.modified_task
|
222
|
-
else None
|
223
|
-
),
|
224
|
-
},
|
225
|
-
"boss_decision": {
|
226
|
-
"selected_agent": boss_response.selected_agent,
|
227
|
-
"reasoning": boss_response.reasoning,
|
228
|
-
},
|
229
|
-
"execution": {
|
230
|
-
"agent_name": selected_agent.name,
|
231
|
-
"agent_id": selected_agent.id,
|
232
|
-
"was_executed": self.execute_task,
|
233
|
-
"response": (
|
234
|
-
agent_response if self.execute_task else None
|
235
|
-
),
|
236
|
-
"execution_time": (
|
237
|
-
execution_time if self.execute_task else None
|
238
|
-
),
|
239
|
-
},
|
240
|
-
"total_time": total_time,
|
241
|
-
}
|
242
|
-
|
243
|
-
logger.info(
|
244
|
-
f"Successfully routed task to {selected_agent.name}"
|
194
|
+
return history_output_formatter(
|
195
|
+
conversation=self.conversation, type=self.output_type
|
245
196
|
)
|
246
|
-
return result
|
247
197
|
|
248
198
|
except Exception as e:
|
249
199
|
logger.error(f"Error routing task: {str(e)}")
|
@@ -312,31 +262,18 @@ class MultiAgentRouter:
|
|
312
262
|
# ),
|
313
263
|
# ]
|
314
264
|
|
315
|
-
# # Initialize
|
316
|
-
#
|
317
|
-
# # router_no_execute = MultiAgentRouter(agents=agents, execute_task=False)
|
265
|
+
# # Initialize router
|
266
|
+
# router = MultiAgentRouter(agents=agents)
|
318
267
|
|
319
268
|
# # Example task
|
320
269
|
# task = "Write a Python function to calculate fibonacci numbers"
|
321
270
|
|
322
271
|
# try:
|
323
|
-
# # Process the task
|
324
|
-
#
|
325
|
-
#
|
326
|
-
# print(
|
327
|
-
#
|
328
|
-
# )
|
329
|
-
# print(
|
330
|
-
# f"Reasoning: {result_execute['boss_decision']['reasoning']}"
|
331
|
-
# )
|
332
|
-
# if result_execute["execution"]["response"]:
|
333
|
-
# print(
|
334
|
-
# f"Response Preview: {result_execute['execution']['response'][:200]}..."
|
335
|
-
# )
|
336
|
-
# print(
|
337
|
-
# f"Execution Time: {result_execute['execution']['execution_time']:.2f}s"
|
338
|
-
# )
|
339
|
-
# print(f"Total Time: {result_execute['total_time']:.2f}s")
|
272
|
+
# # Process the task
|
273
|
+
# result = router.route_task(task)
|
274
|
+
# print(f"Selected Agent: {result['boss_decision']['selected_agent']}")
|
275
|
+
# print(f"Reasoning: {result['boss_decision']['reasoning']}")
|
276
|
+
# print(f"Total Time: {result['total_time']:.2f}s")
|
340
277
|
|
341
278
|
# except Exception as e:
|
342
279
|
# print(f"Error occurred: {str(e)}")
|
swarms/structs/output_types.py
CHANGED
@@ -1,19 +1,6 @@
|
|
1
|
-
from
|
2
|
-
|
3
|
-
|
4
|
-
OutputType = Literal[
|
5
|
-
"all",
|
6
|
-
"final",
|
7
|
-
"list",
|
8
|
-
"dict",
|
9
|
-
".json",
|
10
|
-
".md",
|
11
|
-
".txt",
|
12
|
-
".yaml",
|
13
|
-
".toml",
|
14
|
-
"string",
|
15
|
-
"str",
|
16
|
-
]
|
1
|
+
from swarms.utils.history_output_formatter import (
|
2
|
+
HistoryOutputType as OutputType,
|
3
|
+
)
|
17
4
|
|
18
5
|
# Use the OutputType for type annotations
|
19
6
|
output_type: OutputType
|
@@ -36,3 +36,33 @@ def check_exit(s):
|
|
36
36
|
|
37
37
|
def check_end(s):
|
38
38
|
return "end" in s
|
39
|
+
|
40
|
+
|
41
|
+
def check_stopping_conditions(input: str) -> str:
|
42
|
+
"""
|
43
|
+
Checks a string against all stopping conditions and returns an appropriate message.
|
44
|
+
|
45
|
+
Args:
|
46
|
+
s (str): The input string to check
|
47
|
+
|
48
|
+
Returns:
|
49
|
+
str: A message indicating which stopping condition was met, or None if no condition was met
|
50
|
+
"""
|
51
|
+
conditions = [
|
52
|
+
(check_done, "Task is done"),
|
53
|
+
(check_finished, "Task is finished"),
|
54
|
+
(check_complete, "Task is complete"),
|
55
|
+
(check_success, "Task succeeded"),
|
56
|
+
(check_failure, "Task failed"),
|
57
|
+
(check_error, "Task encountered an error"),
|
58
|
+
(check_stopped, "Task was stopped"),
|
59
|
+
(check_cancelled, "Task was cancelled"),
|
60
|
+
(check_exit, "Task exited"),
|
61
|
+
(check_end, "Task ended"),
|
62
|
+
]
|
63
|
+
|
64
|
+
for check_func, message in conditions:
|
65
|
+
if check_func(input):
|
66
|
+
return message
|
67
|
+
|
68
|
+
return None
|
swarms/structs/swarm_router.py
CHANGED
@@ -5,7 +5,9 @@ from typing import Any, Callable, Dict, List, Literal, Optional, Union
|
|
5
5
|
|
6
6
|
from pydantic import BaseModel, Field
|
7
7
|
|
8
|
-
from swarms.prompts.
|
8
|
+
from swarms.prompts.multi_agent_collab_prompt import (
|
9
|
+
MULTI_AGENT_COLLAB_PROMPT_TWO,
|
10
|
+
)
|
9
11
|
from swarms.structs.agent import Agent
|
10
12
|
from swarms.structs.concurrent_workflow import ConcurrentWorkflow
|
11
13
|
from swarms.structs.csv_to_agent import AgentLoader
|
@@ -13,7 +15,7 @@ from swarms.structs.groupchat import GroupChat
|
|
13
15
|
from swarms.structs.hiearchical_swarm import HierarchicalSwarm
|
14
16
|
from swarms.structs.majority_voting import MajorityVoting
|
15
17
|
from swarms.structs.mixture_of_agents import MixtureOfAgents
|
16
|
-
from swarms.structs.
|
18
|
+
from swarms.structs.multi_agent_router import MultiAgentRouter
|
17
19
|
from swarms.structs.rearrange import AgentRearrange
|
18
20
|
from swarms.structs.sequential_workflow import SequentialWorkflow
|
19
21
|
from swarms.structs.spreadsheet_swarm import SpreadSheetSwarm
|
@@ -66,6 +68,38 @@ class SwarmLog(BaseModel):
|
|
66
68
|
documents: List[Document] = []
|
67
69
|
|
68
70
|
|
71
|
+
class SwarmRouterConfig(BaseModel):
|
72
|
+
"""Configuration model for SwarmRouter."""
|
73
|
+
|
74
|
+
name: str = Field(
|
75
|
+
description="Name identifier for the SwarmRouter instance",
|
76
|
+
)
|
77
|
+
description: str = Field(
|
78
|
+
description="Description of the SwarmRouter's purpose",
|
79
|
+
)
|
80
|
+
# max_loops: int = Field(
|
81
|
+
# description="Maximum number of execution loops"
|
82
|
+
# )
|
83
|
+
swarm_type: SwarmType = Field(
|
84
|
+
description="Type of swarm to use",
|
85
|
+
)
|
86
|
+
rearrange_flow: Optional[str] = Field(
|
87
|
+
description="Flow configuration string"
|
88
|
+
)
|
89
|
+
rules: Optional[str] = Field(
|
90
|
+
description="Rules to inject into every agent"
|
91
|
+
)
|
92
|
+
multi_agent_collab_prompt: bool = Field(
|
93
|
+
description="Whether to enable multi-agent collaboration prompts",
|
94
|
+
)
|
95
|
+
task: str = Field(
|
96
|
+
description="The task to be executed by the swarm",
|
97
|
+
)
|
98
|
+
|
99
|
+
class Config:
|
100
|
+
arbitrary_types_allowed = True
|
101
|
+
|
102
|
+
|
69
103
|
class SwarmRouter:
|
70
104
|
"""
|
71
105
|
A class that dynamically routes tasks to different swarm types based on user selection or automatic matching.
|
@@ -157,6 +191,7 @@ class SwarmRouter:
|
|
157
191
|
load_agents_from_csv: bool = False,
|
158
192
|
csv_file_path: str = None,
|
159
193
|
return_entire_history: bool = True,
|
194
|
+
multi_agent_collab_prompt: bool = True,
|
160
195
|
*args,
|
161
196
|
**kwargs,
|
162
197
|
):
|
@@ -179,14 +214,18 @@ class SwarmRouter:
|
|
179
214
|
self.load_agents_from_csv = load_agents_from_csv
|
180
215
|
self.csv_file_path = csv_file_path
|
181
216
|
self.return_entire_history = return_entire_history
|
217
|
+
self.multi_agent_collab_prompt = multi_agent_collab_prompt
|
182
218
|
|
219
|
+
# Reliability check
|
220
|
+
self.reliability_check()
|
221
|
+
|
222
|
+
# Load agents from CSV
|
183
223
|
if self.load_agents_from_csv:
|
184
224
|
self.agents = AgentLoader(
|
185
225
|
csv_path=self.csv_file_path
|
186
226
|
).load_agents()
|
187
227
|
|
188
|
-
|
189
|
-
|
228
|
+
# Log initialization
|
190
229
|
self._log(
|
191
230
|
"info",
|
192
231
|
f"SwarmRouter initialized with swarm type: {swarm_type}",
|
@@ -345,7 +384,6 @@ class SwarmRouter:
|
|
345
384
|
name=self.name,
|
346
385
|
description=self.description,
|
347
386
|
agents=self.agents,
|
348
|
-
aggregator_system_prompt=aggregator_system_prompt.get_prompt(),
|
349
387
|
aggregator_agent=self.agents[-1],
|
350
388
|
layers=self.max_loops,
|
351
389
|
output_type=self.output_type,
|
@@ -421,6 +459,17 @@ class SwarmRouter:
|
|
421
459
|
f"Invalid swarm type: {self.swarm_type} try again with a valid swarm type such as 'SequentialWorkflow' or 'ConcurrentWorkflow' or 'auto' or 'AgentRearrange' or 'MixtureOfAgents' or 'SpreadSheetSwarm'"
|
422
460
|
)
|
423
461
|
|
462
|
+
def update_system_prompt_for_agent_in_swarm(self):
|
463
|
+
# Use list comprehension for faster iteration
|
464
|
+
[
|
465
|
+
setattr(
|
466
|
+
agent,
|
467
|
+
"system_prompt",
|
468
|
+
agent.system_prompt + MULTI_AGENT_COLLAB_PROMPT_TWO,
|
469
|
+
)
|
470
|
+
for agent in self.agents
|
471
|
+
]
|
472
|
+
|
424
473
|
def _log(
|
425
474
|
self,
|
426
475
|
level: str,
|
@@ -464,6 +513,9 @@ class SwarmRouter:
|
|
464
513
|
"""
|
465
514
|
self.swarm = self._create_swarm(task, *args, **kwargs)
|
466
515
|
|
516
|
+
if self.multi_agent_collab_prompt is True:
|
517
|
+
self.update_system_prompt_for_agent_in_swarm()
|
518
|
+
|
467
519
|
try:
|
468
520
|
logger.info(
|
469
521
|
f"Running task on {self.swarm_type} swarm with task: {task}"
|