swarms 7.9.8__py3-none-any.whl → 8.0.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.
@@ -30,20 +30,12 @@ Example usage:
30
30
  >>> results = router.batched_run(["2+2?", "3+3?"])
31
31
  >>> print(results)
32
32
 
33
- See also:
34
- - docs/swarms/agents/reasoning_agent_router.md for detailed documentation and architecture diagrams.
35
- - consistency_example.py for a usage example with SelfConsistencyAgent.
36
-
37
33
  """
38
34
 
35
+ import traceback
39
36
  from typing import (
40
37
  List,
41
38
  Literal,
42
- Dict,
43
- Callable,
44
- Any,
45
- Tuple,
46
- Hashable,
47
39
  Optional,
48
40
  )
49
41
 
@@ -71,6 +63,22 @@ agent_types = Literal[
71
63
  ]
72
64
 
73
65
 
66
+ class ReasoningAgentExecutorError(Exception):
67
+ """
68
+ Exception raised when an error occurs during the execution of a reasoning agent.
69
+ """
70
+
71
+ pass
72
+
73
+
74
+ class ReasoningAgentInitializationError(Exception):
75
+ """
76
+ Exception raised when an error occurs during the initialization of a reasoning agent.
77
+ """
78
+
79
+ pass
80
+
81
+
74
82
  class ReasoningAgentRouter:
75
83
  """
76
84
  A router for advanced reasoning agent swarms.
@@ -99,9 +107,6 @@ class ReasoningAgentRouter:
99
107
  >>> print(result)
100
108
  """
101
109
 
102
- # Class variable to store cached agent instances
103
- _agent_cache: Dict[Tuple[Hashable, ...], Any] = {}
104
-
105
110
  def __init__(
106
111
  self,
107
112
  agent_name: str = "reasoning_agent",
@@ -117,6 +122,9 @@ class ReasoningAgentRouter:
117
122
  eval: bool = False,
118
123
  random_models_on: bool = False,
119
124
  majority_voting_prompt: Optional[str] = None,
125
+ reasoning_model_name: Optional[
126
+ str
127
+ ] = "claude-3-5-sonnet-20240620",
120
128
  ):
121
129
  """
122
130
  Initialize the ReasoningAgentRouter with the specified configuration.
@@ -136,9 +144,29 @@ class ReasoningAgentRouter:
136
144
  self.eval = eval
137
145
  self.random_models_on = random_models_on
138
146
  self.majority_voting_prompt = majority_voting_prompt
147
+ self.reasoning_model_name = reasoning_model_name
148
+
149
+ self.reliability_check()
150
+
151
+ def reliability_check(self):
152
+
153
+ if self.max_loops == 0:
154
+ raise ReasoningAgentInitializationError(
155
+ "ReasoningAgentRouter Error: Max loops must be greater than 0"
156
+ )
157
+
158
+ if self.model_name == "" or self.model_name is None:
159
+ raise ReasoningAgentInitializationError(
160
+ "ReasoningAgentRouter Error: Model name must be provided"
161
+ )
162
+
163
+ if self.swarm_type == "" or self.swarm_type is None:
164
+ raise ReasoningAgentInitializationError(
165
+ "ReasoningAgentRouter Error: Swarm type must be provided. This is the type of reasoning agent you want to use. For example, 'reasoning-duo' for a reasoning duo agent, 'self-consistency' for a self-consistency agent, 'ire' for an iterative reflective expansion agent, 'reasoning-agent' for a reasoning agent, 'consistency-agent' for a consistency agent, 'ire-agent' for an iterative reflective expansion agent, 'ReflexionAgent' for a reflexion agent, 'GKPAgent' for a generated knowledge prompting agent, 'AgentJudge' for an agent judge."
166
+ )
139
167
 
140
168
  # Initialize the factory mapping dictionary
141
- self._initialize_agent_factories()
169
+ self.agent_factories = self._initialize_agent_factories()
142
170
 
143
171
  def _initialize_agent_factories(self) -> None:
144
172
  """
@@ -146,46 +174,19 @@ class ReasoningAgentRouter:
146
174
 
147
175
  This method replaces the original if-elif chain, making the code more maintainable and extensible.
148
176
  """
149
- self.agent_factories: Dict[str, Callable[[], Any]] = {
150
- # ReasoningDuo factory method
177
+ agent_factories = {
151
178
  "reasoning-duo": self._create_reasoning_duo,
152
179
  "reasoning-agent": self._create_reasoning_duo,
153
- # SelfConsistencyAgent factory methods
154
180
  "self-consistency": self._create_consistency_agent,
155
181
  "consistency-agent": self._create_consistency_agent,
156
- # IREAgent factory methods
157
182
  "ire": self._create_ire_agent,
158
183
  "ire-agent": self._create_ire_agent,
159
- # Other agent type factory methods
160
184
  "AgentJudge": self._create_agent_judge,
161
185
  "ReflexionAgent": self._create_reflexion_agent,
162
186
  "GKPAgent": self._create_gkp_agent,
163
187
  }
164
188
 
165
- def _get_cache_key(self) -> Tuple[Hashable, ...]:
166
- """
167
- Generate a unique key for cache lookup.
168
-
169
- The key is based on all relevant configuration parameters of the agent.
170
-
171
- Returns:
172
- Tuple[Hashable, ...]: A hashable tuple to serve as the cache key.
173
- """
174
- return (
175
- self.swarm_type,
176
- self.agent_name,
177
- self.description,
178
- self.model_name,
179
- self.system_prompt,
180
- self.max_loops,
181
- self.num_samples,
182
- self.output_type,
183
- self.num_knowledge_items,
184
- self.memory_capacity,
185
- self.eval,
186
- self.random_models_on,
187
- self.majority_voting_prompt,
188
- )
189
+ return agent_factories
189
190
 
190
191
  def _create_reasoning_duo(self):
191
192
  """
@@ -200,6 +201,8 @@ class ReasoningAgentRouter:
200
201
  model_name=[self.model_name, self.model_name],
201
202
  system_prompt=self.system_prompt,
202
203
  output_type=self.output_type,
204
+ reasoning_model_name=self.reasoning_model_name,
205
+ max_loops=self.max_loops,
203
206
  )
204
207
 
205
208
  def _create_consistency_agent(self):
@@ -285,32 +288,23 @@ class ReasoningAgentRouter:
285
288
  """
286
289
  Select and initialize the appropriate reasoning swarm based on the specified swarm type.
287
290
 
288
- Uses a caching mechanism to return a cached instance if an agent with the same configuration already exists.
289
-
290
291
  Returns:
291
292
  The selected reasoning swarm instance.
292
293
 
293
294
  Raises:
294
295
  ValueError: If the specified swarm type is invalid.
295
296
  """
296
- # Generate cache key
297
- cache_key = self._get_cache_key()
298
-
299
- # Check if an instance with the same configuration already exists in the cache
300
- if cache_key in self.__class__._agent_cache:
301
- return self.__class__._agent_cache[cache_key]
302
-
303
297
  try:
304
- # Use the factory method to create a new instance
305
- agent = self.agent_factories[self.swarm_type]()
306
-
307
- # Add the newly created instance to the cache
308
- self.__class__._agent_cache[cache_key] = agent
309
-
310
- return agent
311
- except KeyError:
312
- # Keep the same error handling as the original code
313
- raise ValueError(f"Invalid swarm type: {self.swarm_type}")
298
+ if self.swarm_type in self.agent_factories:
299
+ return self.agent_factories[self.swarm_type]()
300
+ else:
301
+ raise ReasoningAgentInitializationError(
302
+ f"ReasoningAgentRouter Error: Invalid swarm type: {self.swarm_type}"
303
+ )
304
+ except Exception as e:
305
+ raise ReasoningAgentInitializationError(
306
+ f"ReasoningAgentRouter Error: {e} Traceback: {traceback.format_exc()} If the error persists, please check the agent's configuration and try again. If you would like support book a call with our team at https://cal.com/swarms"
307
+ )
314
308
 
315
309
  def run(self, task: str, *args, **kwargs):
316
310
  """
@@ -324,8 +318,13 @@ class ReasoningAgentRouter:
324
318
  Returns:
325
319
  The result of the reasoning process (format depends on agent and output_type).
326
320
  """
327
- swarm = self.select_swarm()
328
- return swarm.run(task=task, *args, **kwargs)
321
+ try:
322
+ swarm = self.select_swarm()
323
+ return swarm.run(task=task, *args, **kwargs)
324
+ except Exception as e:
325
+ raise ReasoningAgentExecutorError(
326
+ f"ReasoningAgentRouter Error: {e} Traceback: {traceback.format_exc()} If the error persists, please check the agent's configuration and try again. If you would like support book a call with our team at https://cal.com/swarms"
327
+ )
329
328
 
330
329
  def batched_run(self, tasks: List[str], *args, **kwargs):
331
330
  """
@@ -343,12 +342,3 @@ class ReasoningAgentRouter:
343
342
  for task in tasks:
344
343
  results.append(self.run(task, *args, **kwargs))
345
344
  return results
346
-
347
- @classmethod
348
- def clear_cache(cls):
349
- """
350
- Clear the agent instance cache.
351
-
352
- Use this when you need to free memory or force the creation of new instances.
353
- """
354
- cls._agent_cache.clear()
@@ -1,4 +1,4 @@
1
- from typing import List
1
+ from typing import List, Optional
2
2
 
3
3
  from loguru import logger
4
4
 
@@ -9,6 +9,7 @@ from swarms.structs.conversation import Conversation
9
9
  from swarms.utils.history_output_formatter import (
10
10
  history_output_formatter,
11
11
  )
12
+ import uuid
12
13
 
13
14
 
14
15
  class ReasoningDuo:
@@ -26,26 +27,44 @@ class ReasoningDuo:
26
27
 
27
28
  def __init__(
28
29
  self,
30
+ id: str = str(uuid.uuid4()),
29
31
  agent_name: str = "reasoning-agent-01",
30
32
  agent_description: str = "A highly intelligent and thoughtful AI designed to provide accurate and well-reasoned answers to the user's questions.",
31
33
  model_name: str = "gpt-4o-mini",
32
34
  description: str = "A highly intelligent and thoughtful AI designed to provide accurate and well-reasoned answers to the user's questions.",
33
35
  model_names: list[str] = ["gpt-4o-mini", "gpt-4o"],
34
36
  system_prompt: str = "You are a helpful assistant that can answer questions and help with tasks.",
35
- output_type: OutputType = "dict",
37
+ output_type: OutputType = "dict-all-except-first",
38
+ reasoning_model_name: Optional[
39
+ str
40
+ ] = "claude-3-5-sonnet-20240620",
41
+ max_loops: int = 1,
42
+ *args,
43
+ **kwargs,
36
44
  ):
45
+ self.id = id
37
46
  self.agent_name = agent_name
38
47
  self.agent_description = agent_description
39
48
  self.model_name = model_name
40
49
  self.description = description
41
50
  self.output_type = output_type
51
+ self.reasoning_model_name = reasoning_model_name
52
+ self.max_loops = max_loops
53
+
54
+ if self.reasoning_model_name is None:
55
+ self.reasoning_model_name = model_names[0]
56
+
57
+ self.conversation = Conversation()
58
+
42
59
  self.reasoning_agent = Agent(
43
- agent_name="Your",
44
- description="A highly intelligent and thoughtful AI designed to provide accurate and well-reasoned answers to the user's questions.",
60
+ agent_name=self.agent_name,
61
+ description=self.agent_description,
45
62
  system_prompt=REASONING_PROMPT,
46
63
  max_loops=1,
47
- model_name=model_names[0],
64
+ model_name=self.reasoning_model_name,
48
65
  dynamic_temperature_enabled=True,
66
+ *args,
67
+ **kwargs,
49
68
  )
50
69
 
51
70
  self.main_agent = Agent(
@@ -55,55 +74,89 @@ class ReasoningDuo:
55
74
  max_loops=1,
56
75
  model_name=model_names[1],
57
76
  dynamic_temperature_enabled=True,
77
+ *args,
78
+ **kwargs,
58
79
  )
59
80
 
60
- self.conversation = Conversation()
61
-
62
- def run(self, task: str):
81
+ def step(self, task: str, img: Optional[str] = None):
63
82
  """
64
- Executes the reasoning and main agents on the provided task.
83
+ Executes one step of reasoning and main agent processing.
65
84
 
66
85
  Args:
67
- task (str): The task to be processed by the agents.
68
-
69
- Returns:
70
- str: The output from the main agent after processing the task.
86
+ task (str): The task to be processed.
87
+ img (Optional[str]): Optional image input.
71
88
  """
72
- logger.info(f"Running task: {task}")
73
-
74
- self.conversation.add(role="user", content=task)
75
-
76
- output_reasoner = self.reasoning_agent.run(task)
89
+ # For reasoning agent, use the current task (which may include conversation context)
90
+ output_reasoner = self.reasoning_agent.run(task, img=img)
77
91
 
78
92
  self.conversation.add(
79
93
  role=self.reasoning_agent.agent_name,
80
94
  content=output_reasoner,
81
95
  )
82
96
 
83
- prompt = f"Task: {task} \n\n Your thoughts: {output_reasoner}"
84
-
85
- output_main = self.main_agent.run(prompt)
97
+ # For main agent, always use the full conversation context
98
+ output_main = self.main_agent.run(
99
+ task=self.conversation.get_str(), img=img
100
+ )
86
101
 
87
102
  self.conversation.add(
88
103
  role=self.main_agent.agent_name, content=output_main
89
104
  )
90
105
 
106
+ def run(self, task: str, img: Optional[str] = None):
107
+ """
108
+ Executes the reasoning and main agents on the provided task.
109
+
110
+ Args:
111
+ task (str): The task to be processed by the agents.
112
+ img (Optional[str]): Optional image input.
113
+
114
+ Returns:
115
+ str: The output from the main agent after processing the task.
116
+ """
117
+ logger.info(
118
+ f"Running task: {task} with max_loops: {self.max_loops}"
119
+ )
120
+ self.conversation.add(role="user", content=task)
121
+
122
+ for loop_iteration in range(self.max_loops):
123
+ logger.info(
124
+ f"Loop iteration {loop_iteration + 1}/{self.max_loops}"
125
+ )
126
+
127
+ if loop_iteration == 0:
128
+ # First iteration: use original task
129
+ current_task = task
130
+ else:
131
+ # Subsequent iterations: use task with context of previous reasoning
132
+ current_task = f"Continue reasoning and refining your analysis. Original task: {task}\n\nPrevious conversation context:\n{self.conversation.get_str()}"
133
+
134
+ self.step(task=current_task, img=img)
135
+
91
136
  return history_output_formatter(
92
137
  self.conversation, self.output_type
93
138
  )
94
139
 
95
- def batched_run(self, tasks: List[str]):
140
+ def batched_run(
141
+ self, tasks: List[str], imgs: Optional[List[str]] = None
142
+ ):
96
143
  """
97
144
  Executes the run method for a list of tasks.
98
145
 
99
146
  Args:
100
147
  tasks (list[str]): A list of tasks to be processed.
148
+ imgs (Optional[List[str]]): Optional list of images corresponding to tasks.
101
149
 
102
150
  Returns:
103
151
  list: A list of outputs from the main agent for each task.
104
152
  """
105
153
  outputs = []
106
- for task in tasks:
154
+
155
+ # Handle case where imgs is None
156
+ if imgs is None:
157
+ imgs = [None] * len(tasks)
158
+
159
+ for task, img in zip(tasks, imgs):
107
160
  logger.info(f"Processing task: {task}")
108
- outputs.append(self.run(task))
161
+ outputs.append(self.run(task, img=img))
109
162
  return outputs
@@ -92,6 +92,7 @@ from swarms.structs.interactive_groupchat import (
92
92
  )
93
93
 
94
94
  from swarms.structs.hiearchical_swarm import HierarchicalSwarm
95
+ from swarms.structs.heavy_swarm import HeavySwarm
95
96
 
96
97
  __all__ = [
97
98
  "Agent",
@@ -169,4 +170,5 @@ __all__ = [
169
170
  "priority_speaker",
170
171
  "random_dynamic_speaker",
171
172
  "HierarchicalSwarm",
173
+ "HeavySwarm",
172
174
  ]
swarms/structs/agent.py CHANGED
@@ -1110,6 +1110,8 @@ class Agent:
1110
1110
  f"Structured Output - Attempting Function Call Execution [{time.strftime('%H:%M:%S')}] \n\n Output: {format_data_structure(response)} ",
1111
1111
  loop_count,
1112
1112
  )
1113
+ elif self.streaming_on:
1114
+ pass
1113
1115
  else:
1114
1116
  self.pretty_print(
1115
1117
  response, loop_count
@@ -1239,12 +1241,13 @@ class Agent:
1239
1241
  traceback_info = traceback.format_exc()
1240
1242
 
1241
1243
  logger.error(
1242
- f"Error detected running your agent {self.agent_name}\n"
1244
+ f"An error occurred while running your agent {self.agent_name}.\n"
1243
1245
  f"Error Type: {error_type}\n"
1244
1246
  f"Error Message: {error_message}\n"
1245
1247
  f"Traceback:\n{traceback_info}\n"
1246
1248
  f"Agent State: {self.to_dict()}\n"
1247
- f"Optimize your input parameters and or add an issue on the swarms github and contact our team on discord for support ;)"
1249
+ f"Please optimize your input parameters, or create an issue on the Swarms GitHub and contact our team on Discord for support. "
1250
+ f"For technical support, refer to this document: https://docs.swarms.world/en/latest/swarms/support/"
1248
1251
  )
1249
1252
 
1250
1253
  raise error
@@ -1539,15 +1542,16 @@ class Agent:
1539
1542
 
1540
1543
  if self.tools_list_dictionary is not None:
1541
1544
  if not supports_function_calling(self.model_name):
1542
- raise AgentInitializationError(
1545
+ logger.warning(
1543
1546
  f"The model '{self.model_name}' does not support function calling. Please use a model that supports function calling."
1544
1547
  )
1545
1548
 
1546
1549
  try:
1547
1550
  if self.max_tokens > get_max_tokens(self.model_name):
1548
- raise AgentInitializationError(
1551
+ logger.warning(
1549
1552
  f"Max tokens is set to {self.max_tokens}, but the model '{self.model_name}' only supports {get_max_tokens(self.model_name)} tokens. Please set max tokens to {get_max_tokens(self.model_name)} or less."
1550
1553
  )
1554
+
1551
1555
  except Exception:
1552
1556
  pass
1553
1557
 
@@ -2683,9 +2687,18 @@ class Agent:
2683
2687
 
2684
2688
  return output
2685
2689
 
2686
- except ValueError as e:
2690
+ except AgentRunError as e:
2687
2691
  self._handle_run_error(e)
2688
2692
 
2693
+ except KeyboardInterrupt:
2694
+ logger.warning(
2695
+ f"Keyboard interrupt detected for agent '{self.agent_name}'. "
2696
+ "If autosave is enabled, the agent's state will be saved to the workspace directory. "
2697
+ "To enable autosave, please initialize the agent with Agent(autosave=True)."
2698
+ "For technical support, refer to this document: https://docs.swarms.world/en/latest/swarms/support/"
2699
+ )
2700
+ raise KeyboardInterrupt
2701
+
2689
2702
  def handle_artifacts(
2690
2703
  self, text: str, file_output_path: str, file_extension: str
2691
2704
  ) -> None:
@@ -2824,6 +2837,9 @@ class Agent:
2824
2837
  if response is None:
2825
2838
  response = "No response generated"
2826
2839
 
2840
+ if self.streaming_on:
2841
+ pass
2842
+
2827
2843
  if self.print_on:
2828
2844
  formatter.print_panel(
2829
2845
  response,
@@ -3231,13 +3247,3 @@ class Agent:
3231
3247
  f"Full traceback: {traceback.format_exc()}. "
3232
3248
  f"Attempting to retry tool execution with 3 attempts"
3233
3249
  )
3234
-
3235
- def add_tool_schema(self, tool_schema: dict):
3236
- self.tools_list_dictionary = [tool_schema]
3237
-
3238
- self.output_type = "dict-all-except-first"
3239
-
3240
- def add_multiple_tool_schemas(self, tool_schemas: list[dict]):
3241
- self.tools_list_dictionary = tool_schemas
3242
-
3243
- self.output_type = "dict-all-except-first"