swarms 7.8.9__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 +349 -87
- swarms/structs/concurrent_workflow.py +70 -196
- 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 -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 +5 -1
- swarms-7.9.0.dist-info/METADATA +626 -0
- {swarms-7.8.9.dist-info → swarms-7.9.0.dist-info}/RECORD +19 -17
- swarms-7.8.9.dist-info/METADATA +0 -2119
- {swarms-7.8.9.dist-info → swarms-7.9.0.dist-info}/LICENSE +0 -0
- {swarms-7.8.9.dist-info → swarms-7.9.0.dist-info}/WHEEL +0 -0
- {swarms-7.8.9.dist-info → swarms-7.9.0.dist-info}/entry_points.txt +0 -0
@@ -1,17 +1,18 @@
|
|
1
|
-
import asyncio
|
2
1
|
import os
|
3
2
|
from typing import List, Optional
|
4
3
|
|
5
4
|
|
6
5
|
from swarms.structs.agent import Agent
|
7
6
|
from swarms.prompts.ag_prompt import aggregator_system_prompt_main
|
7
|
+
from swarms.structs.ma_utils import list_all_agents
|
8
|
+
from swarms.utils.history_output_formatter import (
|
9
|
+
history_output_formatter,
|
10
|
+
)
|
8
11
|
from swarms.utils.loguru_logger import initialize_logger
|
9
12
|
import concurrent.futures
|
10
13
|
from swarms.utils.output_types import OutputType
|
11
14
|
from swarms.structs.conversation import Conversation
|
12
|
-
|
13
|
-
history_output_formatter,
|
14
|
-
)
|
15
|
+
|
15
16
|
|
16
17
|
logger = initialize_logger(log_folder="mixture_of_agents")
|
17
18
|
|
@@ -25,13 +26,13 @@ class MixtureOfAgents:
|
|
25
26
|
self,
|
26
27
|
name: str = "MixtureOfAgents",
|
27
28
|
description: str = "A class to run a mixture of agents and aggregate their responses.",
|
28
|
-
agents: List[Agent] =
|
29
|
+
agents: List[Agent] = None,
|
29
30
|
aggregator_agent: Agent = None,
|
30
31
|
aggregator_system_prompt: str = aggregator_system_prompt_main,
|
31
32
|
layers: int = 3,
|
32
33
|
max_loops: int = 1,
|
33
|
-
|
34
|
-
|
34
|
+
output_type: OutputType = "final",
|
35
|
+
aggregator_model_name: str = "claude-3-5-sonnet-20240620",
|
35
36
|
) -> None:
|
36
37
|
"""
|
37
38
|
Initialize the Mixture of Agents class with agents and configuration.
|
@@ -48,16 +49,36 @@ class MixtureOfAgents:
|
|
48
49
|
self.description = description
|
49
50
|
self.agents = agents
|
50
51
|
self.aggregator_agent = aggregator_agent
|
51
|
-
self.aggregator_system_prompt =
|
52
|
+
self.aggregator_system_prompt = aggregator_system_prompt
|
52
53
|
self.layers = layers
|
53
54
|
self.max_loops = max_loops
|
54
|
-
self.return_str_on = return_str_on
|
55
55
|
self.output_type = output_type
|
56
|
+
self.aggregator_model_name = aggregator_model_name
|
57
|
+
self.aggregator_agent = self.aggregator_agent_setup()
|
56
58
|
|
57
59
|
self.reliability_check()
|
58
60
|
|
59
61
|
self.conversation = Conversation()
|
60
62
|
|
63
|
+
list_all_agents(
|
64
|
+
agents=self.agents,
|
65
|
+
conversation=self.conversation,
|
66
|
+
description=self.description,
|
67
|
+
name=self.name,
|
68
|
+
add_to_conversation=True,
|
69
|
+
)
|
70
|
+
|
71
|
+
def aggregator_agent_setup(self):
|
72
|
+
return Agent(
|
73
|
+
agent_name="Aggregator Agent",
|
74
|
+
description="An agent that aggregates the responses of the other agents.",
|
75
|
+
system_prompt=aggregator_system_prompt_main,
|
76
|
+
model_name=self.aggregator_model_name,
|
77
|
+
temperature=0.5,
|
78
|
+
max_loops=1,
|
79
|
+
output_type="str-all-except-first",
|
80
|
+
)
|
81
|
+
|
61
82
|
def reliability_check(self) -> None:
|
62
83
|
"""
|
63
84
|
Performs a reliability check on the Mixture of Agents class.
|
@@ -66,8 +87,8 @@ class MixtureOfAgents:
|
|
66
87
|
"Checking the reliability of the Mixture of Agents class."
|
67
88
|
)
|
68
89
|
|
69
|
-
if
|
70
|
-
raise ValueError("No
|
90
|
+
if len(self.agents) == 0:
|
91
|
+
raise ValueError("No agents provided.")
|
71
92
|
|
72
93
|
if not self.aggregator_agent:
|
73
94
|
raise ValueError("No aggregator agent provided.")
|
@@ -78,129 +99,83 @@ class MixtureOfAgents:
|
|
78
99
|
if not self.layers:
|
79
100
|
raise ValueError("No layers provided.")
|
80
101
|
|
81
|
-
if self.layers < 1:
|
82
|
-
raise ValueError("Layers must be greater than 0.")
|
83
|
-
|
84
102
|
logger.info("Reliability check passed.")
|
85
103
|
logger.info("Mixture of Agents class is ready for use.")
|
86
104
|
|
87
|
-
def
|
88
|
-
|
89
|
-
|
90
|
-
"""
|
91
|
-
Constructs a system prompt for subsequent layers that includes previous responses.
|
105
|
+
def save_to_markdown_file(self, file_path: str = "moa.md"):
|
106
|
+
with open(file_path, "w") as f:
|
107
|
+
f.write(self.conversation.get_str())
|
92
108
|
|
93
|
-
|
94
|
-
system_prompt (str): The initial system prompt.
|
95
|
-
results (List[str]): A list of previous responses.
|
96
|
-
|
97
|
-
Returns:
|
98
|
-
str: The final system prompt including previous responses.
|
99
|
-
"""
|
100
|
-
return (
|
101
|
-
system_prompt
|
102
|
-
+ "\n"
|
103
|
-
+ "\n".join(
|
104
|
-
[
|
105
|
-
f"{i+1}. {str(element)}"
|
106
|
-
for i, element in enumerate(results)
|
107
|
-
]
|
108
|
-
)
|
109
|
-
)
|
110
|
-
|
111
|
-
async def _run_agent_async(
|
109
|
+
def step(
|
112
110
|
self,
|
113
|
-
agent: Agent,
|
114
111
|
task: str,
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
112
|
+
img: Optional[str] = None,
|
113
|
+
imgs: Optional[List[str]] = None,
|
114
|
+
):
|
115
|
+
# self.conversation.add(role="User", content=task)
|
119
116
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
117
|
+
# Run agents concurrently
|
118
|
+
with concurrent.futures.ThreadPoolExecutor(
|
119
|
+
max_workers=os.cpu_count()
|
120
|
+
) as executor:
|
121
|
+
# Submit all agent tasks and store with their index
|
122
|
+
future_to_agent = {
|
123
|
+
executor.submit(
|
124
|
+
agent.run, task=task, img=img, imgs=imgs
|
125
|
+
): agent
|
126
|
+
for agent in self.agents
|
127
|
+
}
|
124
128
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
self.
|
132
|
-
self.aggregator_system_prompt, prev_responses
|
133
|
-
)
|
134
|
-
)
|
135
|
-
agent.system_prompt = system_prompt_with_responses
|
129
|
+
# Collect results and add to conversation in completion order
|
130
|
+
for future in concurrent.futures.as_completed(
|
131
|
+
future_to_agent
|
132
|
+
):
|
133
|
+
agent = future_to_agent[future]
|
134
|
+
output = future.result()
|
135
|
+
self.conversation.add(role=agent.name, content=output)
|
136
136
|
|
137
|
-
|
138
|
-
response = await asyncio.to_thread(agent.run, task)
|
137
|
+
return self.conversation.get_str()
|
139
138
|
|
140
|
-
|
139
|
+
def _run(
|
140
|
+
self,
|
141
|
+
task: str,
|
142
|
+
img: Optional[str] = None,
|
143
|
+
imgs: Optional[List[str]] = None,
|
144
|
+
):
|
141
145
|
|
142
|
-
|
143
|
-
print(f"Agent {agent.agent_name} response: {response}")
|
144
|
-
return response
|
146
|
+
self.conversation.add(role="User", content=task)
|
145
147
|
|
146
|
-
|
147
|
-
|
148
|
-
|
148
|
+
for i in range(self.layers):
|
149
|
+
out = self.step(
|
150
|
+
task=self.conversation.get_str(), img=img, imgs=imgs
|
151
|
+
)
|
152
|
+
task = out
|
149
153
|
|
150
|
-
|
151
|
-
task
|
152
|
-
"""
|
153
|
-
# Gather initial responses from reference agents
|
154
|
-
results: List[str] = await asyncio.gather(
|
155
|
-
*[
|
156
|
-
self._run_agent_async(agent, task)
|
157
|
-
for agent in self.agents
|
158
|
-
]
|
154
|
+
out = self.aggregator_agent.run(
|
155
|
+
task=self.conversation.get_str()
|
159
156
|
)
|
160
157
|
|
161
|
-
|
162
|
-
|
163
|
-
results = await asyncio.gather(
|
164
|
-
*[
|
165
|
-
self._run_agent_async(
|
166
|
-
agent, task, prev_responses=results
|
167
|
-
)
|
168
|
-
for agent in self.agents
|
169
|
-
]
|
170
|
-
)
|
171
|
-
|
172
|
-
# Perform final aggregation using the aggregator agent
|
173
|
-
final_result = await self._run_agent_async(
|
174
|
-
self.aggregator_agent, task, prev_responses=results
|
158
|
+
self.conversation.add(
|
159
|
+
role=self.aggregator_agent.agent_name, content=out
|
175
160
|
)
|
176
161
|
|
177
|
-
|
162
|
+
out = history_output_formatter(
|
163
|
+
conversation=self.conversation, type=self.output_type
|
164
|
+
)
|
178
165
|
|
179
|
-
|
180
|
-
"""
|
181
|
-
Synchronous wrapper to run the async process.
|
166
|
+
return out
|
182
167
|
|
183
|
-
|
184
|
-
|
185
|
-
|
168
|
+
def run(
|
169
|
+
self,
|
170
|
+
task: str,
|
171
|
+
img: Optional[str] = None,
|
172
|
+
imgs: Optional[List[str]] = None,
|
173
|
+
):
|
186
174
|
try:
|
187
|
-
self.
|
188
|
-
|
189
|
-
for _ in range(self.max_loops):
|
190
|
-
# Add previous context to task if available
|
191
|
-
prompt = f"History: {self.conversation.get_str()}\n\nTask: {task}"
|
192
|
-
|
193
|
-
# Run async process
|
194
|
-
asyncio.run(self._run_async(prompt))
|
195
|
-
|
196
|
-
return history_output_formatter(
|
197
|
-
conversation=self.conversation,
|
198
|
-
type=self.output_type,
|
199
|
-
)
|
200
|
-
|
175
|
+
return self._run(task=task, img=img, imgs=imgs)
|
201
176
|
except Exception as e:
|
202
|
-
logger.error(f"Error running
|
203
|
-
|
177
|
+
logger.error(f"Error running Mixture of Agents: {e}")
|
178
|
+
return f"Error: {e}"
|
204
179
|
|
205
180
|
def run_batched(self, tasks: List[str]) -> List[str]:
|
206
181
|
"""
|