swarms 7.8.8__py3-none-any.whl → 7.9.0__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/cli/onboarding_process.py +1 -3
- swarms/prompts/collaborative_prompts.py +177 -0
- swarms/structs/agent.py +434 -128
- swarms/structs/concurrent_workflow.py +70 -196
- swarms/structs/conversation.py +6 -0
- swarms/structs/csv_to_agent.py +1 -3
- swarms/structs/interactive_groupchat.py +319 -12
- swarms/structs/ma_utils.py +25 -6
- swarms/structs/mixture_of_agents.py +88 -113
- swarms/structs/swarm_router.py +148 -187
- swarms/telemetry/__init__.py +4 -22
- swarms/telemetry/log_executions.py +43 -0
- swarms/telemetry/main.py +63 -325
- swarms/tools/__init__.py +10 -0
- swarms/tools/base_tool.py +15 -6
- swarms/tools/mcp_client_call.py +508 -0
- swarms/tools/py_func_to_openai_func_str.py +0 -1
- swarms/utils/auto_download_check_packages.py +4 -3
- swarms/utils/formatter.py +130 -13
- swarms/utils/history_output_formatter.py +2 -0
- swarms/utils/litellm_wrapper.py +5 -1
- swarms/utils/output_types.py +1 -1
- swarms-7.9.0.dist-info/METADATA +626 -0
- {swarms-7.8.8.dist-info → swarms-7.9.0.dist-info}/RECORD +27 -25
- swarms-7.8.8.dist-info/METADATA +0 -2119
- {swarms-7.8.8.dist-info → swarms-7.9.0.dist-info}/LICENSE +0 -0
- {swarms-7.8.8.dist-info → swarms-7.9.0.dist-info}/WHEEL +0 -0
- {swarms-7.8.8.dist-info → swarms-7.9.0.dist-info}/entry_points.txt +0 -0
@@ -1,13 +1,10 @@
|
|
1
|
+
import concurrent.futures
|
1
2
|
import os
|
2
|
-
import
|
3
|
-
from concurrent.futures import ThreadPoolExecutor
|
4
|
-
from functools import lru_cache
|
5
|
-
from typing import Any, Callable, Dict, List, Optional, Union
|
3
|
+
from typing import Callable, List, Optional, Union
|
6
4
|
|
7
5
|
from swarms.structs.agent import Agent
|
8
6
|
from swarms.structs.base_swarm import BaseSwarm
|
9
7
|
from swarms.structs.conversation import Conversation
|
10
|
-
from swarms.utils.formatter import formatter
|
11
8
|
from swarms.utils.history_output_formatter import (
|
12
9
|
history_output_formatter,
|
13
10
|
)
|
@@ -35,9 +32,7 @@ class ConcurrentWorkflow(BaseSwarm):
|
|
35
32
|
return_str_on (bool): Flag indicating whether to return the output as a string. Defaults to False.
|
36
33
|
auto_generate_prompts (bool): Flag indicating whether to auto-generate prompts for agents. Defaults to False.
|
37
34
|
return_entire_history (bool): Flag indicating whether to return the entire conversation history. Defaults to False.
|
38
|
-
|
39
|
-
max_retries (int): The maximum number of retry attempts. Defaults to 3.
|
40
|
-
retry_delay (float): The delay between retry attempts in seconds. Defaults to 1.0.
|
35
|
+
|
41
36
|
|
42
37
|
Raises:
|
43
38
|
ValueError: If the list of agents is empty or if the description is empty.
|
@@ -50,13 +45,7 @@ class ConcurrentWorkflow(BaseSwarm):
|
|
50
45
|
auto_save (bool): Flag indicating whether to automatically save the metadata.
|
51
46
|
output_type (str): The type of output format.
|
52
47
|
max_loops (int): The maximum number of loops for each agent.
|
53
|
-
return_str_on (bool): Flag indicating whether to return the output as a string.
|
54
48
|
auto_generate_prompts (bool): Flag indicating whether to auto-generate prompts for agents.
|
55
|
-
return_entire_history (bool): Flag indicating whether to return the entire conversation history.
|
56
|
-
cache_size (int): The size of the cache.
|
57
|
-
max_retries (int): The maximum number of retry attempts.
|
58
|
-
retry_delay (float): The delay between retry attempts in seconds.
|
59
|
-
_cache (dict): The cache for storing agent outputs.
|
60
49
|
"""
|
61
50
|
|
62
51
|
def __init__(
|
@@ -68,12 +57,7 @@ class ConcurrentWorkflow(BaseSwarm):
|
|
68
57
|
auto_save: bool = True,
|
69
58
|
output_type: str = "dict-all-except-first",
|
70
59
|
max_loops: int = 1,
|
71
|
-
return_str_on: bool = False,
|
72
60
|
auto_generate_prompts: bool = False,
|
73
|
-
return_entire_history: bool = False,
|
74
|
-
cache_size: int = 100,
|
75
|
-
max_retries: int = 3,
|
76
|
-
retry_delay: float = 1.0,
|
77
61
|
*args,
|
78
62
|
**kwargs,
|
79
63
|
):
|
@@ -90,63 +74,31 @@ class ConcurrentWorkflow(BaseSwarm):
|
|
90
74
|
self.metadata_output_path = metadata_output_path
|
91
75
|
self.auto_save = auto_save
|
92
76
|
self.max_loops = max_loops
|
93
|
-
self.return_str_on = return_str_on
|
94
77
|
self.auto_generate_prompts = auto_generate_prompts
|
95
|
-
self.max_workers = os.cpu_count()
|
96
78
|
self.output_type = output_type
|
97
|
-
self.return_entire_history = return_entire_history
|
98
|
-
self.tasks = [] # Initialize tasks list
|
99
|
-
self.cache_size = cache_size
|
100
|
-
self.max_retries = max_retries
|
101
|
-
self.retry_delay = retry_delay
|
102
|
-
self._cache = {}
|
103
79
|
|
104
80
|
self.reliability_check()
|
105
81
|
self.conversation = Conversation()
|
106
82
|
|
107
83
|
def reliability_check(self):
|
108
84
|
try:
|
109
|
-
|
110
|
-
content=f"\n 🏷️ Name: {self.name}\n 📝 Description: {self.description}\n 🤖 Agents: {len(self.agents)}\n 🔄 Max Loops: {self.max_loops}\n ",
|
111
|
-
title="⚙️ Concurrent Workflow Settings",
|
112
|
-
style="bold blue",
|
113
|
-
)
|
114
|
-
formatter.print_panel(
|
115
|
-
content="🔍 Starting reliability checks",
|
116
|
-
title="🔒 Reliability Checks",
|
117
|
-
style="bold blue",
|
118
|
-
)
|
119
|
-
|
120
|
-
if self.name is None:
|
121
|
-
logger.error("❌ A name is required for the swarm")
|
85
|
+
if self.agents is None:
|
122
86
|
raise ValueError(
|
123
|
-
"
|
87
|
+
"ConcurrentWorkflow: No agents provided"
|
124
88
|
)
|
125
89
|
|
126
|
-
if
|
127
|
-
logger.error(
|
128
|
-
"❌ The list of agents must not be empty."
|
129
|
-
)
|
90
|
+
if len(self.agents) == 0:
|
130
91
|
raise ValueError(
|
131
|
-
"
|
92
|
+
"ConcurrentWorkflow: No agents provided"
|
132
93
|
)
|
133
94
|
|
134
|
-
if
|
135
|
-
logger.
|
136
|
-
|
137
|
-
|
138
|
-
formatter.print_panel(
|
139
|
-
content="✅ Reliability checks completed successfully",
|
140
|
-
title="🎉 Reliability Checks",
|
141
|
-
style="bold green",
|
142
|
-
)
|
143
|
-
|
144
|
-
except ValueError as e:
|
145
|
-
logger.error(f"❌ Reliability check failed: {e}")
|
146
|
-
raise
|
95
|
+
if len(self.agents) == 1:
|
96
|
+
logger.warning(
|
97
|
+
"ConcurrentWorkflow: Only one agent provided. With ConcurrentWorkflow, you should use at least 2+ agents."
|
98
|
+
)
|
147
99
|
except Exception as e:
|
148
100
|
logger.error(
|
149
|
-
f"
|
101
|
+
f"ConcurrentWorkflow: Reliability check failed: {e}"
|
150
102
|
)
|
151
103
|
raise
|
152
104
|
|
@@ -163,162 +115,84 @@ class ConcurrentWorkflow(BaseSwarm):
|
|
163
115
|
for agent in self.agents:
|
164
116
|
agent.auto_generate_prompt = True
|
165
117
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
"""Validate input task"""
|
173
|
-
if not isinstance(task, str):
|
174
|
-
raise ValueError("Task must be a string")
|
175
|
-
if not task.strip():
|
176
|
-
raise ValueError("Task cannot be empty")
|
177
|
-
return True
|
178
|
-
|
179
|
-
def _run_with_retry(
|
180
|
-
self, agent: Agent, task: str, img: str = None
|
181
|
-
) -> Any:
|
182
|
-
"""Run agent with retry mechanism"""
|
183
|
-
for attempt in range(self.max_retries):
|
184
|
-
try:
|
185
|
-
output = agent.run(task=task, img=img)
|
186
|
-
self.conversation.add(agent.agent_name, output)
|
187
|
-
return output
|
188
|
-
except Exception as e:
|
189
|
-
if attempt == self.max_retries - 1:
|
190
|
-
logger.error(
|
191
|
-
f"Error running agent {agent.agent_name} after {self.max_retries} attempts: {e}"
|
192
|
-
)
|
193
|
-
raise
|
194
|
-
logger.warning(
|
195
|
-
f"Attempt {attempt + 1} failed for agent {agent.agent_name}: {e}"
|
196
|
-
)
|
197
|
-
time.sleep(
|
198
|
-
self.retry_delay * (attempt + 1)
|
199
|
-
) # Exponential backoff
|
200
|
-
|
201
|
-
def _process_agent(
|
202
|
-
self, agent: Agent, task: str, img: str = None
|
203
|
-
) -> Any:
|
118
|
+
def run(
|
119
|
+
self,
|
120
|
+
task: str,
|
121
|
+
img: Optional[str] = None,
|
122
|
+
imgs: Optional[List[str]] = None,
|
123
|
+
):
|
204
124
|
"""
|
205
|
-
|
125
|
+
Executes all agents in the workflow concurrently on the given task.
|
206
126
|
|
207
127
|
Args:
|
208
|
-
|
209
|
-
|
210
|
-
|
128
|
+
task (str): The task to be executed by all agents.
|
129
|
+
img (Optional[str]): Optional image path for agents that support image input.
|
130
|
+
imgs (Optional[List[str]]): Optional list of image paths for agents that support multiple image inputs.
|
211
131
|
|
212
132
|
Returns:
|
213
|
-
The
|
214
|
-
"""
|
215
|
-
try:
|
216
|
-
# Fast path - check cache first
|
217
|
-
cache_key = f"{task}_{agent.agent_name}"
|
218
|
-
if cache_key in self._cache:
|
219
|
-
output = self._cache[cache_key]
|
220
|
-
else:
|
221
|
-
# Slow path - run agent and update cache
|
222
|
-
output = self._run_with_retry(agent, task, img)
|
223
|
-
|
224
|
-
if len(self._cache) >= self.cache_size:
|
225
|
-
self._cache.pop(next(iter(self._cache)))
|
133
|
+
The formatted output based on the configured output_type.
|
226
134
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
logger.error(
|
232
|
-
f"Error running agent {agent.agent_name}: {e}"
|
233
|
-
)
|
234
|
-
raise
|
235
|
-
|
236
|
-
def _run(
|
237
|
-
self, task: str, img: str = None, *args, **kwargs
|
238
|
-
) -> Union[Dict[str, Any], str]:
|
239
|
-
"""
|
240
|
-
Enhanced run method with parallel execution.
|
135
|
+
Example:
|
136
|
+
>>> workflow = ConcurrentWorkflow(agents=[agent1, agent2])
|
137
|
+
>>> result = workflow.run("Analyze this financial data")
|
138
|
+
>>> print(result)
|
241
139
|
"""
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
140
|
+
self.conversation.add(role="User", content=task)
|
141
|
+
|
142
|
+
# Use 95% of available CPU cores for optimal performance
|
143
|
+
max_workers = int(os.cpu_count() * 0.95)
|
144
|
+
|
145
|
+
# Run agents concurrently using ThreadPoolExecutor
|
146
|
+
with concurrent.futures.ThreadPoolExecutor(
|
147
|
+
max_workers=max_workers
|
148
|
+
) as executor:
|
149
|
+
# Submit all agent tasks and store with their index
|
150
|
+
future_to_agent = {
|
151
|
+
executor.submit(
|
152
|
+
agent.run, task=task, img=img, imgs=imgs
|
153
|
+
): agent
|
154
|
+
for agent in self.agents
|
155
|
+
}
|
156
|
+
|
157
|
+
# Collect results and add to conversation in completion order
|
158
|
+
for future in concurrent.futures.as_completed(
|
159
|
+
future_to_agent
|
160
|
+
):
|
161
|
+
agent = future_to_agent[future]
|
162
|
+
output = future.result()
|
163
|
+
self.conversation.add(role=agent.name, content=output)
|
264
164
|
|
265
165
|
return history_output_formatter(
|
266
|
-
self.conversation,
|
267
|
-
|
166
|
+
conversation=self.conversation,
|
167
|
+
output_type=self.output_type,
|
268
168
|
)
|
269
169
|
|
270
|
-
def
|
170
|
+
def batch_run(
|
271
171
|
self,
|
272
|
-
|
172
|
+
tasks: List[str],
|
273
173
|
img: Optional[str] = None,
|
274
|
-
|
275
|
-
|
276
|
-
) -> Any:
|
174
|
+
imgs: Optional[List[str]] = None,
|
175
|
+
):
|
277
176
|
"""
|
278
|
-
Executes the
|
177
|
+
Executes the workflow on multiple tasks sequentially.
|
279
178
|
|
280
179
|
Args:
|
281
|
-
|
282
|
-
img (Optional[str]
|
283
|
-
|
284
|
-
**kwargs: Additional keyword arguments to be passed to the execution method.
|
180
|
+
tasks (List[str]): List of tasks to be executed by all agents.
|
181
|
+
img (Optional[str]): Optional image path for agents that support image input.
|
182
|
+
imgs (Optional[List[str]]): Optional list of image paths for agents that support multiple image inputs.
|
285
183
|
|
286
184
|
Returns:
|
287
|
-
|
288
|
-
|
289
|
-
Raises:
|
290
|
-
ValueError: If task validation fails.
|
291
|
-
Exception: If any other error occurs during execution.
|
292
|
-
"""
|
293
|
-
if task is not None:
|
294
|
-
self.tasks.append(task)
|
295
|
-
|
296
|
-
try:
|
297
|
-
outputs = self._run(task, img, *args, **kwargs)
|
298
|
-
return outputs
|
299
|
-
except Exception as e:
|
300
|
-
logger.error(f"An error occurred during execution: {e}")
|
301
|
-
raise e
|
185
|
+
List of results, one for each task.
|
302
186
|
|
303
|
-
|
304
|
-
|
305
|
-
|
187
|
+
Example:
|
188
|
+
>>> workflow = ConcurrentWorkflow(agents=[agent1, agent2])
|
189
|
+
>>> tasks = ["Task 1", "Task 2", "Task 3"]
|
190
|
+
>>> results = workflow.batch_run(tasks)
|
191
|
+
>>> print(len(results)) # 3
|
306
192
|
"""
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
return [self.run(task) for task in tasks]
|
311
|
-
|
312
|
-
def clear_cache(self):
|
313
|
-
"""Clear the task cache"""
|
314
|
-
self._cache.clear()
|
315
|
-
|
316
|
-
def get_cache_stats(self) -> Dict[str, int]:
|
317
|
-
"""Get cache statistics"""
|
318
|
-
return {
|
319
|
-
"cache_size": len(self._cache),
|
320
|
-
"max_cache_size": self.cache_size,
|
321
|
-
}
|
193
|
+
return [
|
194
|
+
self.run(task=task, img=img, imgs=imgs) for task in tasks
|
195
|
+
]
|
322
196
|
|
323
197
|
|
324
198
|
# if __name__ == "__main__":
|
swarms/structs/conversation.py
CHANGED
@@ -1326,6 +1326,12 @@ class Conversation(BaseStructure):
|
|
1326
1326
|
self.conversation_history[-1]["content"],
|
1327
1327
|
)
|
1328
1328
|
|
1329
|
+
def return_list_final(self):
|
1330
|
+
"""Return the final message as a list."""
|
1331
|
+
return [
|
1332
|
+
self.conversation_history[-1]["content"],
|
1333
|
+
]
|
1334
|
+
|
1329
1335
|
@classmethod
|
1330
1336
|
def list_conversations(
|
1331
1337
|
cls, conversations_dir: Optional[str] = None
|
swarms/structs/csv_to_agent.py
CHANGED
@@ -104,9 +104,7 @@ class AgentValidator:
|
|
104
104
|
model_name in model["model_name"]
|
105
105
|
for model in model_list
|
106
106
|
):
|
107
|
-
|
108
|
-
model["model_name"] for model in model_list
|
109
|
-
]
|
107
|
+
[model["model_name"] for model in model_list]
|
110
108
|
raise AgentValidationError(
|
111
109
|
"Invalid model name. Must be one of the supported litellm models",
|
112
110
|
"model_name",
|