swarms 7.5.6__py3-none-any.whl → 7.5.7__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/agents/__init__.py CHANGED
@@ -7,7 +7,7 @@ from swarms.agents.create_agents_from_yaml import (
7
7
  from swarms.agents.i_agent import IterativeReflectiveExpansion
8
8
  from swarms.agents.reasoning_agents import (
9
9
  ReasoningAgentRouter,
10
- agent_types as reasoning_agent_types,
10
+ agent_types,
11
11
  )
12
12
  from swarms.agents.reasoning_duo import ReasoningDuo
13
13
  from swarms.structs.stopping_conditions import (
@@ -40,5 +40,5 @@ __all__ = [
40
40
  "SelfConsistencyAgent",
41
41
  "ReasoningDuo",
42
42
  "ReasoningAgentRouter",
43
- "reasoning_agent_types",
43
+ "agent_types",
44
44
  ]
swarms/structs/agent.py CHANGED
@@ -83,7 +83,15 @@ def exists(val):
83
83
  # Agent output types
84
84
  # agent_output_type = Union[BaseModel, dict, str]
85
85
  agent_output_type = Literal[
86
- "string", "str", "list", "json", "dict", "yaml", "json_schema"
86
+ "string",
87
+ "str",
88
+ "list",
89
+ "json",
90
+ "dict",
91
+ "yaml",
92
+ "json_schema",
93
+ "memory-list",
94
+ "memory-dict",
87
95
  ]
88
96
  ToolUsageType = Union[BaseModel, Dict[str, Any]]
89
97
 
@@ -461,10 +469,11 @@ class Agent:
461
469
  self.role = role
462
470
  self.no_print = no_print
463
471
  self.tools_list_dictionary = tools_list_dictionary
472
+
464
473
  # Initialize the short term memory
465
474
  self.short_memory = Conversation(
466
475
  system_prompt=system_prompt,
467
- time_enabled=True,
476
+ time_enabled=False,
468
477
  user=user_name,
469
478
  rules=rules,
470
479
  *args,
@@ -586,13 +595,36 @@ class Agent:
586
595
  from swarms.utils.litellm_wrapper import LiteLLM
587
596
 
588
597
  if self.model_name is None:
589
- raise ValueError("Model name cannot be None")
598
+ # raise ValueError("Model name cannot be None")
599
+ logger.warning(
600
+ "Model name is not provided, using gpt-4o-mini. You can configure any model from litellm if desired."
601
+ )
602
+ self.model_name = "gpt-4o-mini"
590
603
 
591
604
  try:
592
605
  if self.llm_args is not None:
593
606
  llm = LiteLLM(
594
607
  model_name=self.model_name, **self.llm_args
595
608
  )
609
+ elif self.tools_list_dictionary is not None:
610
+
611
+ length_of_tools_list_dictionary = len(
612
+ self.tools_list_dictionary
613
+ )
614
+
615
+ if length_of_tools_list_dictionary > 0:
616
+
617
+ parallel_tool_calls = True
618
+
619
+ llm = LiteLLM(
620
+ model_name=self.model_name,
621
+ temperature=self.temperature,
622
+ max_tokens=self.max_tokens,
623
+ system_prompt=self.system_prompt,
624
+ tools_list_dictionary=self.tools_list_dictionary,
625
+ tool_choice="auto",
626
+ parallel_tool_calls=parallel_tool_calls,
627
+ )
596
628
  else:
597
629
  llm = LiteLLM(
598
630
  model_name=self.model_name,
@@ -1107,6 +1139,14 @@ class Agent:
1107
1139
  return yaml.safe_dump(
1108
1140
  self.agent_output.model_dump(), sort_keys=False
1109
1141
  )
1142
+
1143
+ elif self.output_type == "memory-list":
1144
+ return self.short_memory.return_messages_as_list()
1145
+
1146
+ elif self.output_type == "memory-dict":
1147
+ return (
1148
+ self.short_memory.return_messages_as_dictionary()
1149
+ )
1110
1150
  elif self.return_history is True:
1111
1151
  history = self.short_memory.get_str()
1112
1152
 
@@ -1639,7 +1679,7 @@ class Agent:
1639
1679
  ):
1640
1680
  self.short_memory = Conversation(
1641
1681
  system_prompt=self.system_prompt,
1642
- time_enabled=True,
1682
+ time_enabled=False,
1643
1683
  user=self.user_name,
1644
1684
  rules=self.rules,
1645
1685
  )
@@ -137,7 +137,7 @@ class BaseSwarm(ABC):
137
137
 
138
138
  # Initialize conversation
139
139
  self.conversation = Conversation(
140
- time_enabled=True, rules=self.rules, *args, **kwargs
140
+ time_enabled=False, rules=self.rules, *args, **kwargs
141
141
  )
142
142
 
143
143
  # Handle callbacks
@@ -8,6 +8,7 @@ from typing import TYPE_CHECKING
8
8
  from swarms.utils.any_to_str import any_to_str
9
9
  from swarms.utils.formatter import formatter
10
10
  from swarms.utils.litellm_tokenizer import count_tokens
11
+ import threading
11
12
 
12
13
  if TYPE_CHECKING:
13
14
  from swarms.structs.agent import (
@@ -17,53 +18,25 @@ if TYPE_CHECKING:
17
18
 
18
19
  class Conversation(BaseStructure):
19
20
  """
20
- A class structure to represent a conversation in a chatbot. This class is used to store the conversation history.
21
- And, it can be used to save the conversation history to a file, load the conversation history from a file, and
22
- display the conversation history. We can also use this class to add the conversation history to a database, query
23
- the conversation history from a database, delete the conversation history from a database, update the conversation
24
- history from a database, and get the conversation history from a database.
25
-
26
-
27
- Args:
28
- time_enabled (bool): Whether to enable timestamps for the conversation history. Default is False.
29
- database (AbstractDatabase): The database to use for storing the conversation history. Default is None.
30
- autosave (bool): Whether to autosave the conversation history to a file. Default is None.
31
- save_filepath (str): The filepath to save the conversation history to. Default is None.
32
-
33
-
34
- Methods:
35
- add(role: str, content: str): Add a message to the conversation history.
36
- delete(index: str): Delete a message from the conversation history.
37
- update(index: str, role, content): Update a message in the conversation history.
38
- query(index: str): Query a message in the conversation history.
39
- search(keyword: str): Search for a message in the conversation history.
40
- display_conversation(detailed: bool = False): Display the conversation history.
41
- export_conversation(filename: str): Export the conversation history to a file.
42
- import_conversation(filename: str): Import a conversation history from a file.
43
- count_messages_by_role(): Count the number of messages by role.
44
- return_history_as_string(): Return the conversation history as a string.
45
- save_as_json(filename: str): Save the conversation history as a JSON file.
46
- load_from_json(filename: str): Load the conversation history from a JSON file.
47
- search_keyword_in_conversation(keyword: str): Search for a keyword in the conversation history.
48
- pretty_print_conversation(messages): Pretty print the conversation history.
49
- add_to_database(): Add the conversation history to the database.
50
- query_from_database(query): Query the conversation history from the database.
51
- delete_from_database(): Delete the conversation history from the database.
52
- update_from_database(): Update the conversation history from the database.
53
- get_from_database(): Get the conversation history from the database.
54
- execute_query_from_database(query): Execute a query on the database.
55
- fetch_all_from_database(): Fetch all from the database.
56
- fetch_one_from_database(): Fetch one from the database.
57
-
58
- Examples:
59
- >>> from swarms import Conversation
60
- >>> conversation = Conversation()
61
- >>> conversation.add("user", "Hello, how are you?")
62
- >>> conversation.add("assistant", "I am doing well, thanks.")
63
- >>> conversation.display_conversation()
64
- user: Hello, how are you?
65
- assistant: I am doing well, thanks.
66
-
21
+ A class to manage a conversation history, allowing for the addition, deletion,
22
+ and retrieval of messages, as well as saving and loading the conversation
23
+ history in various formats.
24
+
25
+ Attributes:
26
+ system_prompt (Optional[str]): The system prompt for the conversation.
27
+ time_enabled (bool): Flag to enable time tracking for messages.
28
+ autosave (bool): Flag to enable automatic saving of conversation history.
29
+ save_filepath (str): File path for saving the conversation history.
30
+ tokenizer (Any): Tokenizer for counting tokens in messages.
31
+ context_length (int): Maximum number of tokens allowed in the conversation history.
32
+ rules (str): Rules for the conversation.
33
+ custom_rules_prompt (str): Custom prompt for rules.
34
+ user (str): The user identifier for messages.
35
+ auto_save (bool): Flag to enable auto-saving of conversation history.
36
+ save_as_yaml (bool): Flag to save conversation history as YAML.
37
+ save_as_json_bool (bool): Flag to save conversation history as JSON.
38
+ token_count (bool): Flag to enable token counting for messages.
39
+ conversation_history (list): List to store the history of messages.
67
40
  """
68
41
 
69
42
  def __init__(
@@ -84,6 +57,24 @@ class Conversation(BaseStructure):
84
57
  *args,
85
58
  **kwargs,
86
59
  ):
60
+ """
61
+ Initializes the Conversation object with the provided parameters.
62
+
63
+ Args:
64
+ system_prompt (Optional[str]): The system prompt for the conversation.
65
+ time_enabled (bool): Flag to enable time tracking for messages.
66
+ autosave (bool): Flag to enable automatic saving of conversation history.
67
+ save_filepath (str): File path for saving the conversation history.
68
+ tokenizer (Any): Tokenizer for counting tokens in messages.
69
+ context_length (int): Maximum number of tokens allowed in the conversation history.
70
+ rules (str): Rules for the conversation.
71
+ custom_rules_prompt (str): Custom prompt for rules.
72
+ user (str): The user identifier for messages.
73
+ auto_save (bool): Flag to enable auto-saving of conversation history.
74
+ save_as_yaml (bool): Flag to save conversation history as YAML.
75
+ save_as_json_bool (bool): Flag to save conversation history as JSON.
76
+ token_count (bool): Flag to enable token counting for messages.
77
+ """
87
78
  super().__init__()
88
79
  self.system_prompt = system_prompt
89
80
  self.time_enabled = time_enabled
@@ -121,53 +112,68 @@ class Conversation(BaseStructure):
121
112
  *args,
122
113
  **kwargs,
123
114
  ):
124
- """Add a message to the conversation history
115
+ """Add a message to the conversation history.
125
116
 
126
117
  Args:
127
- role (str): The role of the speaker
128
- content (str): The content of the message
129
-
118
+ role (str): The role of the speaker (e.g., 'User', 'System').
119
+ content (Union[str, dict, list]): The content of the message to be added.
130
120
  """
131
121
  now = datetime.datetime.now()
132
122
  timestamp = now.strftime("%Y-%m-%d %H:%M:%S")
133
123
 
134
- tokens = count_tokens(any_to_str(content))
124
+ # Base message with role
125
+ message = {
126
+ "role": role,
127
+ }
135
128
 
129
+ # Handle different content types
136
130
  if isinstance(content, dict) or isinstance(content, list):
137
-
138
- message = {
139
- "role": role,
140
- "content": content,
141
- "token_count": int(tokens),
142
- }
143
-
131
+ message["content"] = content
144
132
  else:
145
- message = {
146
- "role": role,
147
- "content": f"Time: {timestamp} \n {content}",
148
- "token_count": int(tokens),
149
- }
133
+ message["content"] = f"Time: {timestamp} \n {content}"
150
134
 
135
+ # Add the message to history immediately without waiting for token count
151
136
  self.conversation_history.append(message)
152
137
 
153
- if self.autosave:
138
+ # If token counting is enabled, do it in a separate thread
139
+ if self.token_count is True:
140
+ # Define a function to count tokens and update the message
141
+ def count_tokens_thread():
142
+ tokens = count_tokens(any_to_str(content))
143
+ # Update the message that's already in the conversation history
144
+ message["token_count"] = int(tokens)
145
+
146
+ # If autosave is enabled, save after token count is updated
147
+ if self.autosave:
148
+ self.save_as_json(self.save_filepath)
149
+
150
+ # Start a new thread for token counting
151
+ token_thread = threading.Thread(
152
+ target=count_tokens_thread
153
+ )
154
+ token_thread.daemon = (
155
+ True # Make thread terminate when main program exits
156
+ )
157
+ token_thread.start()
158
+ elif self.autosave:
159
+ # If token counting is disabled but autosave is enabled, save immediately
154
160
  self.save_as_json(self.save_filepath)
155
161
 
156
162
  def delete(self, index: str):
157
- """Delete a message from the conversation history
163
+ """Delete a message from the conversation history.
158
164
 
159
165
  Args:
160
- index (str): index of the message to delete
166
+ index (str): Index of the message to delete.
161
167
  """
162
168
  self.conversation_history.pop(index)
163
169
 
164
170
  def update(self, index: str, role, content):
165
- """Update a message in the conversation history
171
+ """Update a message in the conversation history.
166
172
 
167
173
  Args:
168
- index (str): index of the message to update
169
- role (_type_): role of the speaker
170
- content (_type_): content of the message
174
+ index (str): Index of the message to update.
175
+ role (str): Role of the speaker.
176
+ content (Union[str, dict]): New content of the message.
171
177
  """
172
178
  self.conversation_history[index] = {
173
179
  "role": role,
@@ -175,24 +181,24 @@ class Conversation(BaseStructure):
175
181
  }
176
182
 
177
183
  def query(self, index: str):
178
- """Query a message in the conversation history
184
+ """Query a message in the conversation history.
179
185
 
180
186
  Args:
181
- index (str): index of the message to query
187
+ index (str): Index of the message to query.
182
188
 
183
189
  Returns:
184
- str: the message
190
+ dict: The message with its role and content.
185
191
  """
186
192
  return self.conversation_history[index]
187
193
 
188
194
  def search(self, keyword: str):
189
- """Search for a message in the conversation history
195
+ """Search for a message in the conversation history.
190
196
 
191
197
  Args:
192
- keyword (str): Keyword to search for
198
+ keyword (str): Keyword to search for.
193
199
 
194
200
  Returns:
195
- str: description
201
+ list: List of messages containing the keyword.
196
202
  """
197
203
  return [
198
204
  msg
@@ -201,10 +207,10 @@ class Conversation(BaseStructure):
201
207
  ]
202
208
 
203
209
  def display_conversation(self, detailed: bool = False):
204
- """Display the conversation history
210
+ """Display the conversation history.
205
211
 
206
212
  Args:
207
- detailed (bool, optional): detailed. Defaults to False.
213
+ detailed (bool, optional): Flag to display detailed information. Defaults to False.
208
214
  """
209
215
  for message in self.conversation_history:
210
216
  formatter.print_panel(
@@ -212,20 +218,20 @@ class Conversation(BaseStructure):
212
218
  )
213
219
 
214
220
  def export_conversation(self, filename: str, *args, **kwargs):
215
- """Export the conversation history to a file
221
+ """Export the conversation history to a file.
216
222
 
217
223
  Args:
218
- filename (str): filename to export to
224
+ filename (str): Filename to export to.
219
225
  """
220
226
  with open(filename, "w") as f:
221
227
  for message in self.conversation_history:
222
228
  f.write(f"{message['role']}: {message['content']}\n")
223
229
 
224
230
  def import_conversation(self, filename: str):
225
- """Import a conversation history from a file
231
+ """Import a conversation history from a file.
226
232
 
227
233
  Args:
228
- filename (str): filename to import from
234
+ filename (str): Filename to import from.
229
235
  """
230
236
  with open(filename) as f:
231
237
  for line in f:
@@ -233,7 +239,11 @@ class Conversation(BaseStructure):
233
239
  self.add(role, content.strip())
234
240
 
235
241
  def count_messages_by_role(self):
236
- """Count the number of messages by role"""
242
+ """Count the number of messages by role.
243
+
244
+ Returns:
245
+ dict: A dictionary with counts of messages by role.
246
+ """
237
247
  counts = {
238
248
  "system": 0,
239
249
  "user": 0,
@@ -245,10 +255,10 @@ class Conversation(BaseStructure):
245
255
  return counts
246
256
 
247
257
  def return_history_as_string(self):
248
- """Return the conversation history as a string
258
+ """Return the conversation history as a string.
249
259
 
250
260
  Returns:
251
- str: the conversation history
261
+ str: The conversation history formatted as a string.
252
262
  """
253
263
  return "\n".join(
254
264
  [
@@ -258,39 +268,41 @@ class Conversation(BaseStructure):
258
268
  )
259
269
 
260
270
  def get_str(self):
271
+ """Get the conversation history as a string.
272
+
273
+ Returns:
274
+ str: The conversation history.
275
+ """
261
276
  return self.return_history_as_string()
262
277
 
263
278
  def save_as_json(self, filename: str = None):
264
- """Save the conversation history as a JSON file
279
+ """Save the conversation history as a JSON file.
265
280
 
266
281
  Args:
267
- filename (str): Save the conversation history as a JSON file
282
+ filename (str): Filename to save the conversation history.
268
283
  """
269
- # Create the directory if it does not exist
270
- # os.makedirs(os.path.dirname(filename), exist_ok=True)
271
284
  if filename is not None:
272
285
  with open(filename, "w") as f:
273
286
  json.dump(self.conversation_history, f)
274
287
 
275
288
  def load_from_json(self, filename: str):
276
- """Load the conversation history from a JSON file
289
+ """Load the conversation history from a JSON file.
277
290
 
278
291
  Args:
279
- filename (str): filename to load from
292
+ filename (str): Filename to load from.
280
293
  """
281
- # Load the conversation history from a JSON file
282
294
  if filename is not None:
283
295
  with open(filename) as f:
284
296
  self.conversation_history = json.load(f)
285
297
 
286
298
  def search_keyword_in_conversation(self, keyword: str):
287
- """Search for a keyword in the conversation history
299
+ """Search for a keyword in the conversation history.
288
300
 
289
301
  Args:
290
- keyword (str): keyword to search for
302
+ keyword (str): Keyword to search for.
291
303
 
292
304
  Returns:
293
- str: description
305
+ list: List of messages containing the keyword.
294
306
  """
295
307
  return [
296
308
  msg
@@ -299,10 +311,10 @@ class Conversation(BaseStructure):
299
311
  ]
300
312
 
301
313
  def pretty_print_conversation(self, messages):
302
- """Pretty print the conversation history
314
+ """Pretty print the conversation history.
303
315
 
304
316
  Args:
305
- messages (str): messages to print
317
+ messages (list): List of messages to print.
306
318
  """
307
319
  role_to_color = {
308
320
  "system": "red",
@@ -383,15 +395,31 @@ class Conversation(BaseStructure):
383
395
  self.conversation_history = truncated_history
384
396
 
385
397
  def clear(self):
398
+ """Clear the conversation history."""
386
399
  self.conversation_history = []
387
400
 
388
401
  def to_json(self):
402
+ """Convert the conversation history to a JSON string.
403
+
404
+ Returns:
405
+ str: The conversation history as a JSON string.
406
+ """
389
407
  return json.dumps(self.conversation_history)
390
408
 
391
409
  def to_dict(self):
410
+ """Convert the conversation history to a dictionary.
411
+
412
+ Returns:
413
+ list: The conversation history as a list of dictionaries.
414
+ """
392
415
  return self.conversation_history
393
416
 
394
417
  def to_yaml(self):
418
+ """Convert the conversation history to a YAML string.
419
+
420
+ Returns:
421
+ str: The conversation history as a YAML string.
422
+ """
395
423
  return yaml.dump(self.conversation_history)
396
424
 
397
425
  def get_visible_messages(self, agent: "Agent", turn: int):
@@ -422,17 +450,30 @@ class Conversation(BaseStructure):
422
450
  return visible_messages
423
451
 
424
452
  def get_last_message_as_string(self):
425
- # fetch the last message from the conversation history with the agent name and the message of the agent
453
+ """Fetch the last message from the conversation history.
454
+
455
+ Returns:
456
+ str: The last message formatted as 'role: content'.
457
+ """
426
458
  return f"{self.conversation_history[-1]['role']}: {self.conversation_history[-1]['content']}"
427
459
 
428
460
  def return_messages_as_list(self):
429
- # we must concat the role and the content of the message
461
+ """Return the conversation messages as a list of formatted strings.
462
+
463
+ Returns:
464
+ list: List of messages formatted as 'role: content'.
465
+ """
430
466
  return [
431
467
  f"{message['role']}: {message['content']}"
432
468
  for message in self.conversation_history
433
469
  ]
434
470
 
435
471
  def return_messages_as_dictionary(self):
472
+ """Return the conversation messages as a list of dictionaries.
473
+
474
+ Returns:
475
+ list: List of dictionaries containing role and content of each message.
476
+ """
436
477
  return [
437
478
  {
438
479
  "role": message["role"],
@@ -443,15 +484,32 @@ class Conversation(BaseStructure):
443
484
 
444
485
  def add_tool_output_to_agent(self, role: str, tool_output: dict):
445
486
  """
446
- Add a tool output to the conversation history
487
+ Add a tool output to the conversation history.
488
+
489
+ Args:
490
+ role (str): The role of the tool.
491
+ tool_output (dict): The output from the tool to be added.
447
492
  """
448
493
  self.add(role, tool_output)
449
494
 
450
495
  def return_json(self):
496
+ """Return the conversation messages as a JSON string.
497
+
498
+ Returns:
499
+ str: The conversation messages formatted as a JSON string.
500
+ """
451
501
  return json.dumps(
452
502
  self.return_messages_as_dictionary(), indent=4
453
503
  )
454
504
 
505
+ def get_final_message(self):
506
+ """Return the final message from the conversation history.
507
+
508
+ Returns:
509
+ str: The final message formatted as 'role: content'.
510
+ """
511
+ return f"{self.conversation_history[-1]['role']}: {self.conversation_history[-1]['content']}"
512
+
455
513
 
456
514
  # # Example usage
457
515
  # # conversation = Conversation()
@@ -236,7 +236,7 @@ class GroupChat:
236
236
  self.agents = agents
237
237
  self.speaker_fn = speaker_fn
238
238
  self.max_loops = max_loops
239
- self.conversation = Conversation(time_enabled=True)
239
+ self.conversation = Conversation(time_enabled=False)
240
240
  self.rules = rules
241
241
 
242
242
  self.reliability_check()
@@ -257,7 +257,7 @@ class HierarchicalSwarm(BaseSwarm):
257
257
  self.return_all_history = return_all_history
258
258
  self.output_type = output_type
259
259
  self.director_model_name = director_model_name
260
- self.conversation = Conversation(time_enabled=True)
260
+ self.conversation = Conversation(time_enabled=False)
261
261
  self.current_loop = 0
262
262
  self.agent_outputs = {} # Store agent outputs for each loop
263
263
 
@@ -163,7 +163,7 @@ class MajorityVoting:
163
163
  self.output_type = output_type
164
164
 
165
165
  self.conversation = Conversation(
166
- time_enabled=True, *args, **kwargs
166
+ time_enabled=False, *args, **kwargs
167
167
  )
168
168
 
169
169
  self.initialize_majority_voting()
@@ -153,7 +153,7 @@ class MultiAgentCollaboration(BaseSwarm):
153
153
 
154
154
  # Conversation
155
155
  self.conversation = Conversation(
156
- time_enabled=True, *args, **kwargs
156
+ time_enabled=False, *args, **kwargs
157
157
  )
158
158
 
159
159
  def default_select_next_speaker(
@@ -11,4 +11,6 @@ OutputType = Literal[
11
11
  ".txt",
12
12
  ".yaml",
13
13
  ".toml",
14
+ "string",
15
+ "str",
14
16
  ]
@@ -282,7 +282,7 @@ class ForestSwarm:
282
282
  self.shared_memory = shared_memory
283
283
  self.save_file_path = f"forest_swarm_{uuid.uuid4().hex}.json"
284
284
  self.conversation = Conversation(
285
- time_enabled=True,
285
+ time_enabled=False,
286
286
  auto_save=True,
287
287
  save_filepath=self.save_file_path,
288
288
  rules=rules,
@@ -10,5 +10,9 @@ def history_output_formatter(
10
10
  return conversation.to_dict()
11
11
  elif type == "string" or type == "str":
12
12
  return conversation.get_str()
13
+ elif type == "final":
14
+ return conversation.get_final_message()
15
+ elif type == "json":
16
+ return conversation.to_json()
13
17
  else:
14
18
  raise ValueError(f"Invalid type: {type}")
@@ -1,5 +1,11 @@
1
+ import asyncio
2
+ from typing import List
3
+
4
+ from loguru import logger
5
+
6
+
1
7
  try:
2
- from litellm import completion
8
+ from litellm import completion, acompletion
3
9
  except ImportError:
4
10
  import subprocess
5
11
  import sys
@@ -33,6 +39,9 @@ class LiteLLM:
33
39
  max_tokens: int = 4000,
34
40
  ssl_verify: bool = False,
35
41
  max_completion_tokens: int = 4000,
42
+ tools_list_dictionary: List[dict] = None,
43
+ tool_choice: str = "auto",
44
+ parallel_tool_calls: bool = False,
36
45
  *args,
37
46
  **kwargs,
38
47
  ):
@@ -53,8 +62,9 @@ class LiteLLM:
53
62
  self.max_tokens = max_tokens
54
63
  self.ssl_verify = ssl_verify
55
64
  self.max_completion_tokens = max_completion_tokens
56
-
57
- self.max_completion_tokens = max_tokens
65
+ self.tools_list_dictionary = tools_list_dictionary
66
+ self.tool_choice = tool_choice
67
+ self.parallel_tool_calls = parallel_tool_calls
58
68
 
59
69
  def _prepare_messages(self, task: str) -> list:
60
70
  """
@@ -77,7 +87,7 @@ class LiteLLM:
77
87
 
78
88
  return messages
79
89
 
80
- def run(self, task: str, tools: list = [], *args, **kwargs):
90
+ def run(self, task: str, *args, **kwargs):
81
91
  """
82
92
  Run the LLM model for the given task.
83
93
 
@@ -93,23 +103,45 @@ class LiteLLM:
93
103
 
94
104
  messages = self._prepare_messages(task)
95
105
 
96
- response = completion(
97
- model=self.model_name,
98
- messages=messages,
99
- stream=self.stream,
100
- temperature=self.temperature,
101
- max_tokens=self.max_tokens,
102
- *args,
103
- **kwargs,
104
- )
105
-
106
- content = response.choices[
107
- 0
108
- ].message.content # Accessing the content
109
-
110
- return content
106
+ if self.tools_list_dictionary is not None:
107
+ response = completion(
108
+ model=self.model_name,
109
+ messages=messages,
110
+ stream=self.stream,
111
+ temperature=self.temperature,
112
+ max_tokens=self.max_tokens,
113
+ tools=self.tools_list_dictionary,
114
+ tool_choice=self.tool_choice,
115
+ parallel_tool_calls=self.parallel_tool_calls,
116
+ *args,
117
+ **kwargs,
118
+ )
119
+
120
+ return (
121
+ response.choices[0]
122
+ .message.tool_calls[0]
123
+ .function.arguments
124
+ )
125
+
126
+ else:
127
+ response = completion(
128
+ model=self.model_name,
129
+ messages=messages,
130
+ stream=self.stream,
131
+ temperature=self.temperature,
132
+ max_tokens=self.max_tokens,
133
+ *args,
134
+ **kwargs,
135
+ )
136
+
137
+ content = response.choices[
138
+ 0
139
+ ].message.content # Accessing the content
140
+
141
+ return content
111
142
  except Exception as error:
112
- print(error)
143
+ logger.error(f"Error in LiteLLM: {error}")
144
+ raise error
113
145
 
114
146
  def __call__(self, task: str, *args, **kwargs):
115
147
  """
@@ -124,3 +156,88 @@ class LiteLLM:
124
156
  str: The content of the response from the model.
125
157
  """
126
158
  return self.run(task, *args, **kwargs)
159
+
160
+ async def arun(self, task: str, *args, **kwargs):
161
+ """
162
+ Run the LLM model for the given task.
163
+
164
+ Args:
165
+ task (str): The task to run the model for.
166
+ *args: Additional positional arguments to pass to the model.
167
+ **kwargs: Additional keyword arguments to pass to the model.
168
+
169
+ Returns:
170
+ str: The content of the response from the model.
171
+ """
172
+ try:
173
+ messages = self._prepare_messages(task)
174
+
175
+ if self.tools_list_dictionary is not None:
176
+ response = await acompletion(
177
+ model=self.model_name,
178
+ messages=messages,
179
+ stream=self.stream,
180
+ temperature=self.temperature,
181
+ max_tokens=self.max_tokens,
182
+ tools=self.tools_list_dictionary,
183
+ tool_choice=self.tool_choice,
184
+ parallel_tool_calls=self.parallel_tool_calls,
185
+ *args,
186
+ **kwargs,
187
+ )
188
+
189
+ content = (
190
+ response.choices[0]
191
+ .message.tool_calls[0]
192
+ .function.arguments
193
+ )
194
+
195
+ # return response
196
+
197
+ else:
198
+ response = await acompletion(
199
+ model=self.model_name,
200
+ messages=messages,
201
+ stream=self.stream,
202
+ temperature=self.temperature,
203
+ max_tokens=self.max_tokens,
204
+ *args,
205
+ **kwargs,
206
+ )
207
+
208
+ content = response.choices[
209
+ 0
210
+ ].message.content # Accessing the content
211
+
212
+ return content
213
+ except Exception as error:
214
+ logger.error(f"Error in LiteLLM: {error}")
215
+ raise error
216
+
217
+ def batched_run(self, tasks: List[str], batch_size: int = 10):
218
+ """
219
+ Run the LLM model for the given tasks in batches.
220
+ """
221
+ logger.info(
222
+ f"Running tasks in batches of size {batch_size}. Total tasks: {len(tasks)}"
223
+ )
224
+ results = []
225
+ for task in tasks:
226
+ logger.info(f"Running task: {task}")
227
+ results.append(self.run(task))
228
+ logger.info("Completed all tasks.")
229
+ return results
230
+
231
+ def batched_arun(self, tasks: List[str], batch_size: int = 10):
232
+ """
233
+ Run the LLM model for the given tasks in batches.
234
+ """
235
+ logger.info(
236
+ f"Running asynchronous tasks in batches of size {batch_size}. Total tasks: {len(tasks)}"
237
+ )
238
+ results = []
239
+ for task in tasks:
240
+ logger.info(f"Running asynchronous task: {task}")
241
+ results.append(asyncio.run(self.arun(task)))
242
+ logger.info("Completed all asynchronous tasks.")
243
+ return results
@@ -0,0 +1,51 @@
1
+ import json
2
+ from typing import Dict
3
+ import asyncio
4
+
5
+
6
+ async def async_str_to_dict(s: str, retries: int = 3) -> Dict:
7
+ """
8
+ Asynchronously converts a JSON-formatted string to a dictionary.
9
+
10
+ Args:
11
+ s (str): The JSON string to be converted.
12
+ retries (int): The number of times to retry parsing the string in case of a JSONDecodeError. Default is 3.
13
+
14
+ Returns:
15
+ Dict: The parsed dictionary from the JSON string.
16
+
17
+ Raises:
18
+ json.JSONDecodeError: If the string cannot be parsed into a dictionary after the specified number of retries.
19
+ """
20
+ for attempt in range(retries):
21
+ try:
22
+ # Run json.loads directly since it's fast enough
23
+ return json.loads(s)
24
+ except json.JSONDecodeError as e:
25
+ if attempt < retries - 1:
26
+ continue # Retry on failure
27
+ else:
28
+ raise e # Raise the error if all retries fail
29
+
30
+
31
+ def str_to_dict(s: str, retries: int = 3) -> Dict:
32
+ """
33
+ Converts a JSON string to dictionary, handling both sync and async contexts.
34
+
35
+ Args:
36
+ s (str): The JSON string to be converted.
37
+ retries (int): The number of times to retry parsing the string in case of a JSONDecodeError. Default is 3.
38
+
39
+ Returns:
40
+ Dict: The parsed dictionary from the JSON string.
41
+ """
42
+ # For simplicity and reliability, just try to parse the JSON directly first
43
+ try:
44
+ return json.loads(s)
45
+ except json.JSONDecodeError:
46
+ # If direct parsing fails, try the async path
47
+ try:
48
+ return async_str_to_dict(s, retries).__await__()
49
+ except (AttributeError, RuntimeError):
50
+ # If we can't await (not in async context), use run
51
+ return asyncio.run(async_str_to_dict(s, retries))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: swarms
3
- Version: 7.5.6
3
+ Version: 7.5.7
4
4
  Summary: Swarms - TGSC
5
5
  Home-page: https://github.com/kyegomez/swarms
6
6
  License: MIT
@@ -1,5 +1,5 @@
1
1
  swarms/__init__.py,sha256=DDfir3E4H8z1PlQqpc2HzovJQtNvIAzye4Fs165J0o8,512
2
- swarms/agents/__init__.py,sha256=HVR2hOuRVM_XcHtnbLwrrmhlrfBkhdDnZR-GHrVEqMI,1070
2
+ swarms/agents/__init__.py,sha256=7MJORblMZSbJMNhcKfmVeYC_9EfK6OBW9wdZkFqUwzc,1035
3
3
  swarms/agents/agent_print.py,sha256=SXqWA2ZzXwRFdv8hkuYwOPMTasvaGTG6U29413qRCAA,918
4
4
  swarms/agents/ape_agent.py,sha256=1kz_65LJgjLlY1yv2WLBeVMs7sP9BgEVWk0w1f67YLc,1563
5
5
  swarms/agents/auto_generate_swarm_config.py,sha256=7eJ873xS7PJmyreMaa5Uub8qFu-qIinuyMuogB2Ehjc,8474
@@ -75,7 +75,7 @@ swarms/schemas/agent_input_schema.py,sha256=qhPyThMx2on91yG9mzNdP_08GpMh1IRDHDwF
75
75
  swarms/schemas/agent_step_schemas.py,sha256=a14gb58vR0xOwB_fwSJQbN6yb9HddEaT30E6hUrzEQA,2573
76
76
  swarms/schemas/base_schemas.py,sha256=UvBLVWg2qRen4tK5GJz50v42SiX95EQ5qK7hfyAHTEU,3267
77
77
  swarms/structs/__init__.py,sha256=iPQmbvhyBMobHP1SXIxncVdpsMDnPWwcAEZz_TEORt0,4354
78
- swarms/structs/agent.py,sha256=1AObxdhxtY_UwnQklDS9rXi0tNlJwgywQUczAc0BnyU,94970
78
+ swarms/structs/agent.py,sha256=tcGFYvQGdv-2VD9kaQvIKcdBxhv4H9WhWmEMzNcFeYc,96232
79
79
  swarms/structs/agent_builder.py,sha256=c-SVjfntqO7B3_VSANxw7Swu53PNVoJCmbqK9F8Nns0,11597
80
80
  swarms/structs/agent_registry.py,sha256=il507cO1NF-d4ChyANVLuWrN8bXsEAi8_7bLJ_sTU6A,12112
81
81
  swarms/structs/agent_roles.py,sha256=8XEw6RjOOZelaZaWt4gXaYQm5WMLEhSO7W6Z8sQjmFg,582
@@ -87,30 +87,30 @@ swarms/structs/async_workflow.py,sha256=7YWsLPyGY-1-mMxoIXWQ0FnYH6F227nxsS9PFAJo
87
87
  swarms/structs/auto_swarm.py,sha256=AHWswlEWDL_i3V8IP362tx6pi_B2arlZhALykrkI5OA,8215
88
88
  swarms/structs/auto_swarm_builder.py,sha256=vPM5Kq59D_FvuWJB8hxgHuEvTXsxDxovlBnHGVQsM4o,10938
89
89
  swarms/structs/base_structure.py,sha256=GDu4QJQQmhU7IyuFJHIh9UVThACCva-L7uoMbVD9l4s,15901
90
- swarms/structs/base_swarm.py,sha256=oJe6_C6Kr9yd4Qye7JAsmriTdeFnLfgEkJbxbZU6Ik0,24032
90
+ swarms/structs/base_swarm.py,sha256=_pggyl32BoEq-W2Cg-03h0z9xpPT_wXFjss4Yvysoxc,24033
91
91
  swarms/structs/base_workflow.py,sha256=DTfFwX3AdFYxACDYwUDqhsbcDZnITlg5TeEYyxmJBCc,11414
92
92
  swarms/structs/concat.py,sha256=utezSxNyh1mIwXgdf8-dJ803NDPyEy79WE8zJHuooGk,732
93
93
  swarms/structs/concurrent_workflow.py,sha256=8myerrLcOfEDGPlfp4xYbf79qBBAzxh80zrw1Dv7OXY,15525
94
- swarms/structs/conversation.py,sha256=yX1BoKPW3q7m0-LIiP2Osc_k7bE2bSjdq4rlYFD_OuU,16120
94
+ swarms/structs/conversation.py,sha256=7oh3x5XFyscnG1TAIMyL1BKJ4jC-unDEv-RFRVmxJO8,17966
95
95
  swarms/structs/csv_to_agent.py,sha256=ug9JqQFPguXeU9JQpSUXuVtOpHYdJhlpKJUJBovo694,9443
96
96
  swarms/structs/de_hallucination_swarm.py,sha256=Aa1kIJLmyXXrFl6qpmAq6mfkSaItQYD0MPgQ_e-nPvc,10305
97
97
  swarms/structs/graph_swarm.py,sha256=HPHlLWwdSPSe4o-I06ZOIgtBg72a06llEnv8-aglf3Q,20962
98
98
  swarms/structs/graph_workflow.py,sha256=TAaUG_J3898hhghPOp0WEAV3Zf0in6s48ZSVbSTX-vQ,8629
99
- swarms/structs/groupchat.py,sha256=GscqlpGrtlZ31AD1r5fZXY6nTgAtRGbbt8kc1KY6G3g,15905
100
- swarms/structs/hiearchical_swarm.py,sha256=TIjoppfLrdUTDMnEuTuBqttvFzbQZlEfgsTcPs_h9zo,35272
101
- swarms/structs/majority_voting.py,sha256=bDP5VOrG89bbkAodtwQErB4MASJ3ZGJUA6LiBevb2w0,10120
99
+ swarms/structs/groupchat.py,sha256=oLaWLuZ0ObHVXN9k3K8CpLSDSZwnCHBgJHsdGmHqAS8,15906
100
+ swarms/structs/hiearchical_swarm.py,sha256=-qepZLY7RLxHlT4dU-dMEWSKnfBHEVrFr6HRn8lGh1Q,35273
101
+ swarms/structs/majority_voting.py,sha256=1-FQGMxDwg5mYeoP5rXTgiXEXF8Yc4vTc93ByGoInK4,10121
102
102
  swarms/structs/malt.py,sha256=0ZOuLfOzaJ4vAVOM6J1aZ3yWAiKxfMkNIBNp8pjsEqE,19392
103
103
  swarms/structs/matrix_swarm.py,sha256=qHuhOYrTyOv6ujHMe8PrQT-h-WmaCPCfX4ghv5L8UFI,9765
104
104
  swarms/structs/meme_agent_persona_generator.py,sha256=b3kKlumhsV4KV88-GS3CUnGO1UfKTU3fT8SAMj0ZlwQ,10645
105
105
  swarms/structs/mixture_of_agents.py,sha256=OGCTvyRQjHk9os4ZDYixdbDIIMeLMxfseeznS9rzdko,10574
106
106
  swarms/structs/model_router.py,sha256=V5pZHYlxSmCvAA2Gsns7LaCz8dXtRi7pCvb-oLGHYIY,12739
107
- swarms/structs/multi_agent_collab.py,sha256=2pvMBQvdkKrMIdS9tlvKQNvWSiebEdD4ozqOKpIT-rw,7730
107
+ swarms/structs/multi_agent_collab.py,sha256=odh2NQRR23LidsphCxUfAke369lDdgL__w3Xovu9jkA,7731
108
108
  swarms/structs/multi_agent_exec.py,sha256=NbR-CnxxBuCa0Ll3Os9wfKdkIsQiCpqsTgFX9hWRefw,17421
109
109
  swarms/structs/multi_agent_orchestrator.py,sha256=MsCqBGrirhbdx4aZqY_1MRa9hRqt_ZF3HLmt7JCsINI,13399
110
110
  swarms/structs/octotools.py,sha256=GZo0qtFM69W7vvewk6_k09vicgw0c0_v7MiPvEZCagE,31406
111
111
  swarms/structs/omni_agent_types.py,sha256=RdKLfZ-lXDJrEa0aJT_Rfx9TypJQo8SISqKz4fnLkAk,230
112
112
  swarms/structs/output_type.py,sha256=56bALerdISngZ86Q-7LLlmHZw6edAFkea2bPlKdM_oE,279
113
- swarms/structs/output_types.py,sha256=SVPi9UNMBaVZFS5E9eq_87CiHrkOoSFLij2TQ8kvXaU,188
113
+ swarms/structs/output_types.py,sha256=i56WfkzUR6YgP1qINJ8t-By8OVS_sdbO64IvCmV-pbM,213
114
114
  swarms/structs/pulsar_swarm.py,sha256=4_L0GqPBgnA3AJajpNLgO4IAG6U36nIntFK9WNJScv8,15968
115
115
  swarms/structs/queue_swarm.py,sha256=8vcA-rh280midcdgfA5IwJzBmMgdn71nRH6KndWu-DA,6770
116
116
  swarms/structs/rearrange.py,sha256=KVBZVvoTd5vA7-kzpFHHpoQWzss0NZurCI1K-QR-MJc,28638
@@ -131,7 +131,7 @@ swarms/structs/swarm_router.py,sha256=V8qEojE0XkqZQKcrm_9w7NCou0uiesSAIgeuPbahRl
131
131
  swarms/structs/swarming_architectures.py,sha256=VvkSA9nQnF91V2C5-ALwSY1peZckeM1G4pPeQS7IVsE,13109
132
132
  swarms/structs/swarms_api.py,sha256=Pv-X-GkQ05gGPvTy8c_LES_IC8CBO9d2RPIssIjuqB8,13759
133
133
  swarms/structs/talk_hier.py,sha256=npyEuL52SCgQmMynIvGjfatNqOz4toq0EyhEtSNmQhQ,25649
134
- swarms/structs/tree_swarm.py,sha256=UAzRJ6J91XC8W3ND9_cmoSmUhYoD4epl-rbn2ocQlOs,12499
134
+ swarms/structs/tree_swarm.py,sha256=AnIxrt0KhWxAQN8uGjfCcOq-XCmsuTJiH8Ex4mXy8V8,12500
135
135
  swarms/structs/utils.py,sha256=Mo6wHQYOB8baWZUKnAJN5Dsgubpo81umNwJIEDitb2A,1873
136
136
  swarms/structs/various_alt_swarms.py,sha256=qdBuOF31UjatlKRu-9bxwyRQzIjohRhTv_63YoUeYEY,27866
137
137
  swarms/structs/workspace_manager.py,sha256=t0OgUP9dDU7xS6N3mAT2PbXvjHTsUK3nf2mxppcfZ70,5473
@@ -164,20 +164,21 @@ swarms/utils/disable_logging.py,sha256=-YXBrTMTLlXWCW-MhuY4XI6Q8KeEfBUJ_gmRWs1X8
164
164
  swarms/utils/file_processing.py,sha256=QjQCIPTcwicQlfy656BXBYpIzMR0s2343E7ftnok5Uo,4865
165
165
  swarms/utils/formatter.py,sha256=YykmcuWXkxvQ7a2Vq6OzWuqUDiIwro6VrtSt4ITbXcU,4194
166
166
  swarms/utils/function_caller_model.py,sha256=ZfgCMzOizNnuZipYLclTziECNHszH9p8RQcUq7VNr4Q,4156
167
- swarms/utils/history_output_formatter.py,sha256=iKmhiYjdVeZcLHfiU7I1BymZm3A5_miIgcdcekeEhuk,421
167
+ swarms/utils/history_output_formatter.py,sha256=TmYMMVsWmn8vtmXacuw8iujZnwdxaRnT8fGM8d9uJo8,558
168
168
  swarms/utils/litellm_tokenizer.py,sha256=0AAj4NffBe2eHii_3_5SpQAhSiBbunJR8MzaBTIm7hg,484
169
- swarms/utils/litellm_wrapper.py,sha256=5JzxF5rfm92MIDHXelcYYkhAG6Vg0V-WRRHwY1o1Fxc,3741
169
+ swarms/utils/litellm_wrapper.py,sha256=YmSwDPK97szRNrE81_9nTyh4q_VaVAJxH11VIwKUQb4,7778
170
170
  swarms/utils/loguru_logger.py,sha256=hIoSK3NHLpe7eAmjHRURrEYzNXYC2gbR7_Vv63Yaydk,685
171
171
  swarms/utils/markdown_message.py,sha256=RThHNnMf6ZLTlYK4vKn3yuewChaxWAYAWb0Xm_pTyIU,652
172
172
  swarms/utils/pandas_utils.py,sha256=AA0wNWM05CrNovW7x9aY63Zhw7CIGMERmxvjH2Q-Jjc,2567
173
173
  swarms/utils/parse_code.py,sha256=XFOLymbdP3HzMZuqsj7pwUyisvUmTm0ev9iThR_ambI,1987
174
174
  swarms/utils/pdf_to_text.py,sha256=nkySOS_sJ4Jf4RP5SoDpMB5WfjJ_GGc5z8gJfn2cxOM,1311
175
+ swarms/utils/str_to_dict.py,sha256=DXIokhuWN8OiX-7r6FtskrfnMcJXiCIFpZbLzD-N_tU,1778
175
176
  swarms/utils/swarm_reliability_checks.py,sha256=MsgUULt3HYg72D0HifZNmtCyJYpLA2UDA2wQixI-NbA,2562
176
177
  swarms/utils/try_except_wrapper.py,sha256=appEGu9Afy3TmdkNNXUgQ9yU9lj2j0uNkIoW0JhVzzY,3917
177
178
  swarms/utils/visualizer.py,sha256=0ylohEk62MAS6iPRaDOV03m9qo2k5J56tWlKJk_46p4,16927
178
179
  swarms/utils/wrapper_clusterop.py,sha256=PMSCVM7ZT1vgj1D_MYAe835RR3SMLYxA-si2JS02yNQ,4220
179
- swarms-7.5.6.dist-info/LICENSE,sha256=jwRtEmTWjLrEsvFB6QFdYs2cEeZPRMdj-UMOFkPF8_0,11363
180
- swarms-7.5.6.dist-info/METADATA,sha256=0qmkVA4FDlnoR1bzuwy9fo5z5xhtwMLZjTwJ557CaIU,103019
181
- swarms-7.5.6.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
182
- swarms-7.5.6.dist-info/entry_points.txt,sha256=2K0rTtfO1X1WaO-waJlXIKw5Voa_EpAL_yU0HXE2Jgc,47
183
- swarms-7.5.6.dist-info/RECORD,,
180
+ swarms-7.5.7.dist-info/LICENSE,sha256=jwRtEmTWjLrEsvFB6QFdYs2cEeZPRMdj-UMOFkPF8_0,11363
181
+ swarms-7.5.7.dist-info/METADATA,sha256=GDdLsEvLpTArX7_bjP6y75c3GEV_bV5e3M45c9ZnYlk,103019
182
+ swarms-7.5.7.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
183
+ swarms-7.5.7.dist-info/entry_points.txt,sha256=2K0rTtfO1X1WaO-waJlXIKw5Voa_EpAL_yU0HXE2Jgc,47
184
+ swarms-7.5.7.dist-info/RECORD,,
File without changes