swarms 7.8.9__py3-none-any.whl → 7.9.1__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/__init__.py +11 -1
- swarms/structs/agent.py +488 -127
- swarms/structs/concurrent_workflow.py +70 -196
- swarms/structs/conversation.py +103 -25
- swarms/structs/interactive_groupchat.py +815 -108
- swarms/structs/ma_utils.py +25 -6
- swarms/structs/mixture_of_agents.py +88 -113
- swarms/structs/swarm_router.py +155 -195
- swarms/telemetry/__init__.py +4 -18
- swarms/telemetry/log_executions.py +43 -0
- swarms/telemetry/main.py +53 -217
- swarms/tools/base_tool.py +8 -3
- swarms/utils/formatter.py +130 -13
- swarms/utils/litellm_wrapper.py +7 -1
- swarms/utils/retry_func.py +66 -0
- swarms-7.9.1.dist-info/METADATA +626 -0
- {swarms-7.8.9.dist-info → swarms-7.9.1.dist-info}/RECORD +22 -19
- swarms-7.8.9.dist-info/METADATA +0 -2119
- {swarms-7.8.9.dist-info → swarms-7.9.1.dist-info}/LICENSE +0 -0
- {swarms-7.8.9.dist-info → swarms-7.9.1.dist-info}/WHEEL +0 -0
- {swarms-7.8.9.dist-info → swarms-7.9.1.dist-info}/entry_points.txt +0 -0
swarms/structs/swarm_router.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
import concurrent.futures
|
2
|
+
import json
|
1
3
|
import os
|
2
|
-
import
|
3
|
-
from datetime import datetime
|
4
|
+
import traceback
|
4
5
|
from typing import Any, Callable, Dict, List, Literal, Optional, Union
|
5
6
|
|
6
7
|
from pydantic import BaseModel, Field
|
@@ -20,13 +21,15 @@ from swarms.structs.rearrange import AgentRearrange
|
|
20
21
|
from swarms.structs.sequential_workflow import SequentialWorkflow
|
21
22
|
from swarms.structs.spreadsheet_swarm import SpreadSheetSwarm
|
22
23
|
from swarms.structs.swarm_matcher import swarm_matcher
|
24
|
+
from swarms.telemetry.log_executions import log_execution
|
23
25
|
from swarms.utils.output_types import OutputType
|
24
26
|
from swarms.utils.loguru_logger import initialize_logger
|
25
27
|
from swarms.structs.malt import MALT
|
26
28
|
from swarms.structs.deep_research_swarm import DeepResearchSwarm
|
27
29
|
from swarms.structs.council_judge import CouncilAsAJudge
|
28
30
|
from swarms.structs.interactive_groupchat import InteractiveGroupChat
|
29
|
-
|
31
|
+
from swarms.structs.ma_utils import list_all_agents
|
32
|
+
from swarms.utils.generate_keys import generate_api_key
|
30
33
|
|
31
34
|
logger = initialize_logger(log_folder="swarm_router")
|
32
35
|
|
@@ -54,25 +57,6 @@ class Document(BaseModel):
|
|
54
57
|
data: str
|
55
58
|
|
56
59
|
|
57
|
-
class SwarmLog(BaseModel):
|
58
|
-
"""
|
59
|
-
A Pydantic model to capture log entries.
|
60
|
-
"""
|
61
|
-
|
62
|
-
id: Optional[str] = Field(
|
63
|
-
default_factory=lambda: str(uuid.uuid4())
|
64
|
-
)
|
65
|
-
timestamp: Optional[datetime] = Field(
|
66
|
-
default_factory=datetime.utcnow
|
67
|
-
)
|
68
|
-
level: Optional[str] = None
|
69
|
-
message: Optional[str] = None
|
70
|
-
swarm_type: Optional[SwarmType] = None
|
71
|
-
task: Optional[str] = ""
|
72
|
-
metadata: Optional[Dict[str, Any]] = Field(default_factory=dict)
|
73
|
-
documents: List[Document] = []
|
74
|
-
|
75
|
-
|
76
60
|
class SwarmRouterConfig(BaseModel):
|
77
61
|
"""Configuration model for SwarmRouter."""
|
78
62
|
|
@@ -172,12 +156,11 @@ class SwarmRouter:
|
|
172
156
|
concurrent_batch_run(tasks: List[str], *args, **kwargs) -> List[Any]:
|
173
157
|
Executes multiple tasks concurrently
|
174
158
|
|
175
|
-
get_logs() -> List[SwarmLog]:
|
176
|
-
Retrieves execution logs
|
177
159
|
"""
|
178
160
|
|
179
161
|
def __init__(
|
180
162
|
self,
|
163
|
+
id: str = generate_api_key(prefix="swarm-router"),
|
181
164
|
name: str = "swarm-router",
|
182
165
|
description: str = "Routes your task to the desired swarm",
|
183
166
|
max_loops: int = 1,
|
@@ -191,15 +174,19 @@ class SwarmRouter:
|
|
191
174
|
rules: str = None,
|
192
175
|
documents: List[str] = [], # A list of docs file paths
|
193
176
|
output_type: OutputType = "dict-all-except-first",
|
194
|
-
no_cluster_ops: bool = False,
|
195
177
|
speaker_fn: callable = None,
|
196
178
|
load_agents_from_csv: bool = False,
|
197
179
|
csv_file_path: str = None,
|
198
180
|
return_entire_history: bool = True,
|
199
181
|
multi_agent_collab_prompt: bool = True,
|
182
|
+
list_all_agents: bool = False,
|
183
|
+
conversation: Any = None,
|
184
|
+
agents_config: Optional[Dict[Any, Any]] = None,
|
185
|
+
speaker_function: str = None,
|
200
186
|
*args,
|
201
187
|
**kwargs,
|
202
188
|
):
|
189
|
+
self.id = id
|
203
190
|
self.name = name
|
204
191
|
self.description = description
|
205
192
|
self.max_loops = max_loops
|
@@ -213,13 +200,16 @@ class SwarmRouter:
|
|
213
200
|
self.rules = rules
|
214
201
|
self.documents = documents
|
215
202
|
self.output_type = output_type
|
216
|
-
self.no_cluster_ops = no_cluster_ops
|
217
203
|
self.speaker_fn = speaker_fn
|
218
204
|
self.logs = []
|
219
205
|
self.load_agents_from_csv = load_agents_from_csv
|
220
206
|
self.csv_file_path = csv_file_path
|
221
207
|
self.return_entire_history = return_entire_history
|
222
208
|
self.multi_agent_collab_prompt = multi_agent_collab_prompt
|
209
|
+
self.list_all_agents = list_all_agents
|
210
|
+
self.conversation = conversation
|
211
|
+
self.agents_config = agents_config
|
212
|
+
self.speaker_function = speaker_function
|
223
213
|
|
224
214
|
# Reliability check
|
225
215
|
self.reliability_check()
|
@@ -230,6 +220,8 @@ class SwarmRouter:
|
|
230
220
|
csv_path=self.csv_file_path
|
231
221
|
).load_agents()
|
232
222
|
|
223
|
+
self.agent_config = self.agent_config()
|
224
|
+
|
233
225
|
def setup(self):
|
234
226
|
if self.auto_generate_prompts is True:
|
235
227
|
self.activate_ape()
|
@@ -276,15 +268,12 @@ class SwarmRouter:
|
|
276
268
|
logger.info(
|
277
269
|
f"Successfully activated APE for {activated_count} agents"
|
278
270
|
)
|
279
|
-
self._log(
|
280
|
-
"info",
|
281
|
-
f"Activated automatic prompt engineering for {activated_count} agents",
|
282
|
-
)
|
283
271
|
|
284
272
|
except Exception as e:
|
285
273
|
error_msg = f"Error activating automatic prompt engineering: {str(e)}"
|
286
|
-
logger.error(
|
287
|
-
|
274
|
+
logger.error(
|
275
|
+
f"Error activating automatic prompt engineering in SwarmRouter: {str(e)}"
|
276
|
+
)
|
288
277
|
raise RuntimeError(error_msg) from e
|
289
278
|
|
290
279
|
def reliability_check(self):
|
@@ -293,48 +282,24 @@ class SwarmRouter:
|
|
293
282
|
Validates essential swarm parameters and configuration before execution.
|
294
283
|
Handles special case for CouncilAsAJudge which may not require agents.
|
295
284
|
"""
|
296
|
-
logger.info(
|
297
|
-
"🔍 [SYSTEM] Initializing advanced swarm reliability diagnostics..."
|
298
|
-
)
|
299
|
-
logger.info(
|
300
|
-
"⚡ [SYSTEM] Running pre-flight checks and system validation..."
|
301
|
-
)
|
302
285
|
|
303
286
|
# Check swarm type first since it affects other validations
|
304
287
|
if self.swarm_type is None:
|
305
|
-
|
306
|
-
"
|
288
|
+
raise ValueError(
|
289
|
+
"SwarmRouter: Swarm type cannot be 'none'."
|
307
290
|
)
|
308
|
-
raise ValueError("Swarm type cannot be 'none'.")
|
309
291
|
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
logger.warning(
|
314
|
-
"⚠️ [ADVISORY] CouncilAsAJudge detected with agents - this is atypical"
|
315
|
-
)
|
316
|
-
elif not self.agents:
|
317
|
-
logger.error(
|
318
|
-
"❌ [CRITICAL] Agent validation failed - no agents detected in swarm"
|
292
|
+
if self.agents is None:
|
293
|
+
raise ValueError(
|
294
|
+
"SwarmRouter: No agents provided for the swarm."
|
319
295
|
)
|
320
|
-
raise ValueError("No agents provided for the swarm.")
|
321
296
|
|
322
297
|
# Validate max_loops
|
323
298
|
if self.max_loops == 0:
|
324
|
-
|
325
|
-
"❌ [CRITICAL] Loop validation failed - max_loops cannot be 0"
|
326
|
-
)
|
327
|
-
raise ValueError("max_loops cannot be 0.")
|
299
|
+
raise ValueError("SwarmRouter: max_loops cannot be 0.")
|
328
300
|
|
329
|
-
# Setup other functionality
|
330
|
-
logger.info("🔄 [SYSTEM] Initializing swarm subsystems...")
|
331
301
|
self.setup()
|
332
302
|
|
333
|
-
logger.info(
|
334
|
-
"✅ [SYSTEM] All reliability checks passed successfully"
|
335
|
-
)
|
336
|
-
logger.info("🚀 [SYSTEM] Swarm is ready for deployment")
|
337
|
-
|
338
303
|
def _create_swarm(self, task: str = None, *args, **kwargs):
|
339
304
|
"""
|
340
305
|
Dynamically create and return the specified swarm type or automatically match the best swarm type for a given task.
|
@@ -395,6 +360,7 @@ class SwarmRouter:
|
|
395
360
|
agents=self.agents,
|
396
361
|
max_loops=self.max_loops,
|
397
362
|
output_type=self.output_type,
|
363
|
+
speaker_function=self.speaker_function,
|
398
364
|
)
|
399
365
|
|
400
366
|
elif self.swarm_type == "DeepResearchSwarm":
|
@@ -500,46 +466,24 @@ class SwarmRouter:
|
|
500
466
|
|
501
467
|
def update_system_prompt_for_agent_in_swarm(self):
|
502
468
|
# Use list comprehension for faster iteration
|
503
|
-
|
504
|
-
|
505
|
-
agent
|
506
|
-
|
507
|
-
agent.system_prompt + MULTI_AGENT_COLLAB_PROMPT_TWO,
|
508
|
-
)
|
509
|
-
for agent in self.agents
|
510
|
-
]
|
469
|
+
for agent in self.agents:
|
470
|
+
if agent.system_prompt is None:
|
471
|
+
agent.system_prompt = ""
|
472
|
+
agent.system_prompt += MULTI_AGENT_COLLAB_PROMPT_TWO
|
511
473
|
|
512
|
-
def
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
task: str = "",
|
517
|
-
metadata: Dict[str, Any] = None,
|
518
|
-
):
|
519
|
-
"""
|
520
|
-
Create a log entry and add it to the logs list.
|
474
|
+
def agent_config(self):
|
475
|
+
agent_config = {}
|
476
|
+
for agent in self.agents:
|
477
|
+
agent_config[agent.agent_name] = agent.to_dict()
|
521
478
|
|
522
|
-
|
523
|
-
level (str): The log level (e.g., "info", "error").
|
524
|
-
message (str): The log message.
|
525
|
-
task (str, optional): The task being performed. Defaults to "".
|
526
|
-
metadata (Dict[str, Any], optional): Additional metadata. Defaults to None.
|
527
|
-
"""
|
528
|
-
log_entry = SwarmLog(
|
529
|
-
level=level,
|
530
|
-
message=message,
|
531
|
-
swarm_type=self.swarm_type,
|
532
|
-
task=task,
|
533
|
-
metadata=metadata or {},
|
534
|
-
)
|
535
|
-
self.logs.append(log_entry)
|
536
|
-
logger.log(level.upper(), message)
|
479
|
+
return agent_config
|
537
480
|
|
538
481
|
def _run(
|
539
482
|
self,
|
540
483
|
task: str,
|
541
484
|
img: Optional[str] = None,
|
542
485
|
model_response: Optional[str] = None,
|
486
|
+
imgs: Optional[List[str]] = None,
|
543
487
|
*args,
|
544
488
|
**kwargs,
|
545
489
|
) -> Any:
|
@@ -559,17 +503,34 @@ class SwarmRouter:
|
|
559
503
|
"""
|
560
504
|
self.swarm = self._create_swarm(task, *args, **kwargs)
|
561
505
|
|
506
|
+
self.conversation = self.swarm.conversation
|
507
|
+
|
508
|
+
if self.list_all_agents is True:
|
509
|
+
list_all_agents(
|
510
|
+
agents=self.agents,
|
511
|
+
conversation=self.swarm.conversation,
|
512
|
+
name=self.name,
|
513
|
+
description=self.description,
|
514
|
+
add_collaboration_prompt=True,
|
515
|
+
add_to_conversation=True,
|
516
|
+
)
|
517
|
+
|
562
518
|
if self.multi_agent_collab_prompt is True:
|
563
519
|
self.update_system_prompt_for_agent_in_swarm()
|
564
520
|
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
)
|
521
|
+
log_execution(
|
522
|
+
swarm_id=self.id,
|
523
|
+
status="start",
|
524
|
+
swarm_config=self.to_dict(),
|
525
|
+
swarm_architecture="swarm_router",
|
526
|
+
)
|
569
527
|
|
528
|
+
try:
|
570
529
|
if self.swarm_type == "CouncilAsAJudge":
|
571
530
|
result = self.swarm.run(
|
572
531
|
task=task,
|
532
|
+
img=img,
|
533
|
+
imgs=imgs,
|
573
534
|
model_response=model_response,
|
574
535
|
*args,
|
575
536
|
**kwargs,
|
@@ -577,21 +538,24 @@ class SwarmRouter:
|
|
577
538
|
else:
|
578
539
|
result = self.swarm.run(task=task, *args, **kwargs)
|
579
540
|
|
580
|
-
|
541
|
+
log_execution(
|
542
|
+
swarm_id=self.id,
|
543
|
+
status="completion",
|
544
|
+
swarm_config=self.to_dict(),
|
545
|
+
swarm_architecture="swarm_router",
|
546
|
+
)
|
547
|
+
|
581
548
|
return result
|
582
549
|
except Exception as e:
|
583
|
-
|
584
|
-
"
|
585
|
-
f"Error occurred while running task on {self.swarm_type} swarm: {str(e)}",
|
586
|
-
task=task,
|
587
|
-
metadata={"error": str(e)},
|
550
|
+
raise RuntimeError(
|
551
|
+
f"SwarmRouter: Error executing task on swarm: {str(e)} Traceback: {traceback.format_exc()}"
|
588
552
|
)
|
589
|
-
raise
|
590
553
|
|
591
554
|
def run(
|
592
555
|
self,
|
593
556
|
task: str,
|
594
557
|
img: Optional[str] = None,
|
558
|
+
imgs: Optional[List[str]] = None,
|
595
559
|
model_response: Optional[str] = None,
|
596
560
|
*args,
|
597
561
|
**kwargs,
|
@@ -617,15 +581,24 @@ class SwarmRouter:
|
|
617
581
|
return self._run(
|
618
582
|
task=task,
|
619
583
|
img=img,
|
584
|
+
imgs=imgs,
|
620
585
|
model_response=model_response,
|
621
586
|
*args,
|
622
587
|
**kwargs,
|
623
588
|
)
|
624
589
|
except Exception as e:
|
625
|
-
|
626
|
-
|
590
|
+
raise RuntimeError(
|
591
|
+
f"SwarmRouter: Error executing task on swarm: {str(e)} Traceback: {traceback.format_exc()}"
|
592
|
+
)
|
627
593
|
|
628
|
-
def __call__(
|
594
|
+
def __call__(
|
595
|
+
self,
|
596
|
+
task: str,
|
597
|
+
img: Optional[str] = None,
|
598
|
+
imgs: Optional[List[str]] = None,
|
599
|
+
*args,
|
600
|
+
**kwargs,
|
601
|
+
) -> Any:
|
629
602
|
"""
|
630
603
|
Make the SwarmRouter instance callable.
|
631
604
|
|
@@ -637,10 +610,17 @@ class SwarmRouter:
|
|
637
610
|
Returns:
|
638
611
|
Any: The result of the swarm's execution.
|
639
612
|
"""
|
640
|
-
return self.run(
|
613
|
+
return self.run(
|
614
|
+
task=task, img=img, imgs=imgs, *args, **kwargs
|
615
|
+
)
|
641
616
|
|
642
617
|
def batch_run(
|
643
|
-
self,
|
618
|
+
self,
|
619
|
+
tasks: List[str],
|
620
|
+
img: Optional[str] = None,
|
621
|
+
imgs: Optional[List[str]] = None,
|
622
|
+
*args,
|
623
|
+
**kwargs,
|
644
624
|
) -> List[Any]:
|
645
625
|
"""
|
646
626
|
Execute a batch of tasks on the selected or matched swarm type.
|
@@ -659,21 +639,26 @@ class SwarmRouter:
|
|
659
639
|
results = []
|
660
640
|
for task in tasks:
|
661
641
|
try:
|
662
|
-
result = self.run(
|
642
|
+
result = self.run(
|
643
|
+
task, img=img, imgs=imgs, *args, **kwargs
|
644
|
+
)
|
663
645
|
results.append(result)
|
664
646
|
except Exception as e:
|
665
|
-
|
666
|
-
"
|
667
|
-
f"Error occurred while running batch task on {self.swarm_type} swarm: {str(e)}",
|
668
|
-
task=task,
|
669
|
-
metadata={"error": str(e)},
|
647
|
+
raise RuntimeError(
|
648
|
+
f"SwarmRouter: Error executing batch task on swarm: {str(e)} Traceback: {traceback.format_exc()}"
|
670
649
|
)
|
671
|
-
raise
|
672
650
|
return results
|
673
651
|
|
674
|
-
def
|
652
|
+
def concurrent_run(
|
653
|
+
self,
|
654
|
+
task: str,
|
655
|
+
img: Optional[str] = None,
|
656
|
+
imgs: Optional[List[str]] = None,
|
657
|
+
*args,
|
658
|
+
**kwargs,
|
659
|
+
) -> Any:
|
675
660
|
"""
|
676
|
-
Execute a task on the selected or matched swarm type
|
661
|
+
Execute a task on the selected or matched swarm type concurrently.
|
677
662
|
|
678
663
|
Args:
|
679
664
|
task (str): The task to be executed by the swarm.
|
@@ -686,95 +671,70 @@ class SwarmRouter:
|
|
686
671
|
Raises:
|
687
672
|
Exception: If an error occurs during task execution.
|
688
673
|
"""
|
689
|
-
import asyncio
|
690
|
-
|
691
|
-
async def run_async():
|
692
|
-
try:
|
693
|
-
result = await asyncio.to_thread(
|
694
|
-
self.run, task, *args, **kwargs
|
695
|
-
)
|
696
|
-
return result
|
697
|
-
except Exception as e:
|
698
|
-
self._log(
|
699
|
-
"error",
|
700
|
-
f"Error occurred while running task asynchronously on {self.swarm_type} swarm: {str(e)}",
|
701
|
-
task=task,
|
702
|
-
metadata={"error": str(e)},
|
703
|
-
)
|
704
|
-
raise
|
705
674
|
|
706
|
-
|
675
|
+
with concurrent.futures.ThreadPoolExecutor(
|
676
|
+
max_workers=os.cpu_count()
|
677
|
+
) as executor:
|
678
|
+
future = executor.submit(
|
679
|
+
self.run, task, img=img, imgs=imgs, *args, **kwargs
|
680
|
+
)
|
681
|
+
result = future.result()
|
682
|
+
return result
|
707
683
|
|
708
|
-
def
|
684
|
+
def _serialize_callable(
|
685
|
+
self, attr_value: Callable
|
686
|
+
) -> Dict[str, Any]:
|
709
687
|
"""
|
710
|
-
|
688
|
+
Serializes callable attributes by extracting their name and docstring.
|
689
|
+
|
690
|
+
Args:
|
691
|
+
attr_value (Callable): The callable to serialize.
|
711
692
|
|
712
693
|
Returns:
|
713
|
-
|
694
|
+
Dict[str, Any]: Dictionary with name and docstring of the callable.
|
714
695
|
"""
|
715
|
-
return
|
716
|
-
|
717
|
-
|
696
|
+
return {
|
697
|
+
"name": getattr(
|
698
|
+
attr_value, "__name__", type(attr_value).__name__
|
699
|
+
),
|
700
|
+
"doc": getattr(attr_value, "__doc__", None),
|
701
|
+
}
|
702
|
+
|
703
|
+
def _serialize_attr(self, attr_name: str, attr_value: Any) -> Any:
|
718
704
|
"""
|
719
|
-
|
705
|
+
Serializes an individual attribute, handling non-serializable objects.
|
720
706
|
|
721
707
|
Args:
|
722
|
-
|
723
|
-
|
724
|
-
**kwargs: Arbitrary keyword arguments.
|
708
|
+
attr_name (str): The name of the attribute.
|
709
|
+
attr_value (Any): The value of the attribute.
|
725
710
|
|
726
711
|
Returns:
|
727
|
-
Any: The
|
728
|
-
|
729
|
-
Raises:
|
730
|
-
Exception: If an error occurs during task execution.
|
712
|
+
Any: The serialized value of the attribute.
|
731
713
|
"""
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
714
|
+
try:
|
715
|
+
if callable(attr_value):
|
716
|
+
return self._serialize_callable(attr_value)
|
717
|
+
elif hasattr(attr_value, "to_dict"):
|
718
|
+
return (
|
719
|
+
attr_value.to_dict()
|
720
|
+
) # Recursive serialization for nested objects
|
721
|
+
else:
|
722
|
+
json.dumps(
|
723
|
+
attr_value
|
724
|
+
) # Attempt to serialize to catch non-serializable objects
|
725
|
+
return attr_value
|
726
|
+
except (TypeError, ValueError):
|
727
|
+
return f"<Non-serializable: {type(attr_value).__name__}>"
|
728
|
+
|
729
|
+
def to_dict(self) -> Dict[str, Any]:
|
744
730
|
"""
|
745
|
-
|
746
|
-
|
747
|
-
Args:
|
748
|
-
tasks (List[str]): A list of tasks to be executed by the swarm.
|
749
|
-
*args: Variable length argument list.
|
750
|
-
**kwargs: Arbitrary keyword arguments.
|
731
|
+
Converts all attributes of the class, including callables, into a dictionary.
|
732
|
+
Handles non-serializable attributes by converting them or skipping them.
|
751
733
|
|
752
734
|
Returns:
|
753
|
-
|
754
|
-
|
755
|
-
Raises:
|
756
|
-
Exception: If an error occurs during task execution.
|
735
|
+
Dict[str, Any]: A dictionary representation of the class attributes.
|
757
736
|
"""
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
results = []
|
764
|
-
with ThreadPoolExecutor() as executor:
|
765
|
-
# Submit all tasks to executor
|
766
|
-
futures = [
|
767
|
-
executor.submit(self.run, task, *args, **kwargs)
|
768
|
-
for task in tasks
|
769
|
-
]
|
770
|
-
|
771
|
-
# Process results as they complete rather than waiting for all
|
772
|
-
for future in as_completed(futures):
|
773
|
-
try:
|
774
|
-
result = future.result()
|
775
|
-
results.append(result)
|
776
|
-
except Exception as e:
|
777
|
-
logger.error(f"Task execution failed: {str(e)}")
|
778
|
-
results.append(None)
|
779
|
-
|
780
|
-
return results
|
737
|
+
return {
|
738
|
+
attr_name: self._serialize_attr(attr_name, attr_value)
|
739
|
+
for attr_name, attr_value in self.__dict__.items()
|
740
|
+
}
|
swarms/telemetry/__init__.py
CHANGED
@@ -1,27 +1,13 @@
|
|
1
1
|
from swarms.telemetry.main import (
|
2
|
-
generate_unique_identifier,
|
3
2
|
generate_user_id,
|
4
|
-
get_cpu_info,
|
5
3
|
get_machine_id,
|
6
|
-
|
7
|
-
|
8
|
-
get_python_version,
|
9
|
-
get_ram_info,
|
10
|
-
get_system_info,
|
11
|
-
get_user_device_data,
|
12
|
-
system_info,
|
4
|
+
get_comprehensive_system_info,
|
5
|
+
log_agent_data,
|
13
6
|
)
|
14
7
|
|
15
8
|
__all__ = [
|
16
9
|
"generate_user_id",
|
17
10
|
"get_machine_id",
|
18
|
-
"
|
19
|
-
"
|
20
|
-
"get_python_version",
|
21
|
-
"get_pip_version",
|
22
|
-
"get_os_version",
|
23
|
-
"get_cpu_info",
|
24
|
-
"get_ram_info",
|
25
|
-
"system_info",
|
26
|
-
"get_user_device_data",
|
11
|
+
"get_comprehensive_system_info",
|
12
|
+
"log_agent_data",
|
27
13
|
]
|
@@ -0,0 +1,43 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
from swarms.telemetry.main import log_agent_data
|
3
|
+
|
4
|
+
|
5
|
+
def log_execution(
|
6
|
+
swarm_id: Optional[str] = None,
|
7
|
+
status: Optional[str] = None,
|
8
|
+
swarm_config: Optional[dict] = None,
|
9
|
+
swarm_architecture: Optional[str] = None,
|
10
|
+
):
|
11
|
+
"""
|
12
|
+
Log execution data for a swarm router instance.
|
13
|
+
|
14
|
+
This function logs telemetry data about swarm router executions, including
|
15
|
+
the swarm ID, execution status, and configuration details. It silently
|
16
|
+
handles any logging errors to prevent execution interruption.
|
17
|
+
|
18
|
+
Args:
|
19
|
+
swarm_id (str): Unique identifier for the swarm router instance
|
20
|
+
status (str): Current status of the execution (e.g., "start", "completion", "error")
|
21
|
+
swarm_config (dict): Configuration dictionary containing swarm router settings
|
22
|
+
swarm_architecture (str): Name of the swarm architecture used
|
23
|
+
Returns:
|
24
|
+
None
|
25
|
+
|
26
|
+
Example:
|
27
|
+
>>> log_execution(
|
28
|
+
... swarm_id="swarm-router-abc123",
|
29
|
+
... status="start",
|
30
|
+
... swarm_config={"name": "my-swarm", "swarm_type": "SequentialWorkflow"}
|
31
|
+
... )
|
32
|
+
"""
|
33
|
+
try:
|
34
|
+
log_agent_data(
|
35
|
+
data_dict={
|
36
|
+
"swarm_router_id": swarm_id,
|
37
|
+
"status": status,
|
38
|
+
"swarm_router_config": swarm_config,
|
39
|
+
"swarm_architecture": swarm_architecture,
|
40
|
+
}
|
41
|
+
)
|
42
|
+
except Exception:
|
43
|
+
pass
|