swarms 7.7.8__py3-none-any.whl → 7.8.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/__init__.py +0 -1
- swarms/agents/cort_agent.py +206 -0
- swarms/agents/react_agent.py +173 -0
- swarms/agents/self_agent_builder.py +40 -0
- swarms/communication/base_communication.py +290 -0
- swarms/communication/duckdb_wrap.py +369 -72
- swarms/communication/pulsar_struct.py +691 -0
- swarms/communication/redis_wrap.py +1362 -0
- swarms/communication/sqlite_wrap.py +547 -44
- swarms/prompts/agent_self_builder_prompt.py +103 -0
- swarms/prompts/safety_prompt.py +50 -0
- swarms/schemas/__init__.py +6 -1
- swarms/schemas/agent_class_schema.py +91 -0
- swarms/schemas/agent_mcp_errors.py +18 -0
- swarms/schemas/agent_tool_schema.py +13 -0
- swarms/schemas/llm_agent_schema.py +92 -0
- swarms/schemas/mcp_schemas.py +43 -0
- swarms/structs/__init__.py +4 -0
- swarms/structs/agent.py +315 -267
- swarms/structs/aop.py +3 -1
- swarms/structs/batch_agent_execution.py +64 -0
- swarms/structs/conversation.py +261 -57
- swarms/structs/council_judge.py +542 -0
- swarms/structs/deep_research_swarm.py +19 -22
- swarms/structs/long_agent.py +424 -0
- swarms/structs/ma_utils.py +11 -8
- swarms/structs/malt.py +30 -28
- swarms/structs/multi_model_gpu_manager.py +1 -1
- swarms/structs/output_types.py +1 -1
- swarms/structs/swarm_router.py +70 -15
- swarms/tools/__init__.py +12 -0
- swarms/tools/base_tool.py +2840 -264
- swarms/tools/create_agent_tool.py +104 -0
- swarms/tools/mcp_client_call.py +504 -0
- swarms/tools/py_func_to_openai_func_str.py +45 -7
- swarms/tools/pydantic_to_json.py +10 -27
- swarms/utils/audio_processing.py +343 -0
- swarms/utils/history_output_formatter.py +5 -5
- swarms/utils/index.py +226 -0
- swarms/utils/litellm_wrapper.py +65 -67
- swarms/utils/try_except_wrapper.py +2 -2
- swarms/utils/xml_utils.py +42 -0
- {swarms-7.7.8.dist-info → swarms-7.8.0.dist-info}/METADATA +5 -4
- {swarms-7.7.8.dist-info → swarms-7.8.0.dist-info}/RECORD +47 -30
- {swarms-7.7.8.dist-info → swarms-7.8.0.dist-info}/WHEEL +1 -1
- swarms/client/__init__.py +0 -15
- swarms/client/main.py +0 -407
- swarms/tools/mcp_client.py +0 -246
- swarms/tools/mcp_integration.py +0 -340
- {swarms-7.7.8.dist-info → swarms-7.8.0.dist-info}/LICENSE +0 -0
- {swarms-7.7.8.dist-info → swarms-7.8.0.dist-info}/entry_points.txt +0 -0
swarms/utils/index.py
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
def exists(val):
|
2
|
+
return val is not None
|
3
|
+
|
4
|
+
|
5
|
+
def format_dict_to_string(data: dict, indent_level=0, use_colon=True):
|
6
|
+
"""
|
7
|
+
Recursively formats a dictionary into a multi-line string.
|
8
|
+
|
9
|
+
Args:
|
10
|
+
data (dict): The dictionary to format
|
11
|
+
indent_level (int): Current indentation level for nested structures
|
12
|
+
use_colon (bool): Whether to use "key: value" or "key value" format
|
13
|
+
|
14
|
+
Returns:
|
15
|
+
str: Formatted string representation of the dictionary
|
16
|
+
"""
|
17
|
+
if not isinstance(data, dict):
|
18
|
+
return str(data)
|
19
|
+
|
20
|
+
lines = []
|
21
|
+
indent = " " * indent_level # 2 spaces per indentation level
|
22
|
+
separator = ": " if use_colon else " "
|
23
|
+
|
24
|
+
for key, value in data.items():
|
25
|
+
if isinstance(value, dict):
|
26
|
+
# Recursive case: nested dictionary
|
27
|
+
lines.append(f"{indent}{key}:")
|
28
|
+
nested_string = format_dict_to_string(
|
29
|
+
value, indent_level + 1, use_colon
|
30
|
+
)
|
31
|
+
lines.append(nested_string)
|
32
|
+
else:
|
33
|
+
# Base case: simple key-value pair
|
34
|
+
lines.append(f"{indent}{key}{separator}{value}")
|
35
|
+
|
36
|
+
return "\n".join(lines)
|
37
|
+
|
38
|
+
|
39
|
+
def format_data_structure(
|
40
|
+
data: any, indent_level: int = 0, max_depth: int = 10
|
41
|
+
) -> str:
|
42
|
+
"""
|
43
|
+
Fast formatter for any Python data structure into readable new-line format.
|
44
|
+
|
45
|
+
Args:
|
46
|
+
data: Any Python data structure to format
|
47
|
+
indent_level (int): Current indentation level for nested structures
|
48
|
+
max_depth (int): Maximum depth to prevent infinite recursion
|
49
|
+
|
50
|
+
Returns:
|
51
|
+
str: Formatted string representation with new lines
|
52
|
+
"""
|
53
|
+
if indent_level >= max_depth:
|
54
|
+
return f"{' ' * indent_level}... (max depth reached)"
|
55
|
+
|
56
|
+
indent = " " * indent_level
|
57
|
+
data_type = type(data)
|
58
|
+
|
59
|
+
# Fast type checking using type() instead of isinstance() for speed
|
60
|
+
if data_type is dict:
|
61
|
+
if not data:
|
62
|
+
return f"{indent}{{}} (empty dict)"
|
63
|
+
|
64
|
+
lines = []
|
65
|
+
for key, value in data.items():
|
66
|
+
if type(value) in (dict, list, tuple, set):
|
67
|
+
lines.append(f"{indent}{key}:")
|
68
|
+
lines.append(
|
69
|
+
format_data_structure(
|
70
|
+
value, indent_level + 1, max_depth
|
71
|
+
)
|
72
|
+
)
|
73
|
+
else:
|
74
|
+
lines.append(f"{indent}{key}: {value}")
|
75
|
+
return "\n".join(lines)
|
76
|
+
|
77
|
+
elif data_type is list:
|
78
|
+
if not data:
|
79
|
+
return f"{indent}[] (empty list)"
|
80
|
+
|
81
|
+
lines = []
|
82
|
+
for i, item in enumerate(data):
|
83
|
+
if type(item) in (dict, list, tuple, set):
|
84
|
+
lines.append(f"{indent}[{i}]:")
|
85
|
+
lines.append(
|
86
|
+
format_data_structure(
|
87
|
+
item, indent_level + 1, max_depth
|
88
|
+
)
|
89
|
+
)
|
90
|
+
else:
|
91
|
+
lines.append(f"{indent}{item}")
|
92
|
+
return "\n".join(lines)
|
93
|
+
|
94
|
+
elif data_type is tuple:
|
95
|
+
if not data:
|
96
|
+
return f"{indent}() (empty tuple)"
|
97
|
+
|
98
|
+
lines = []
|
99
|
+
for i, item in enumerate(data):
|
100
|
+
if type(item) in (dict, list, tuple, set):
|
101
|
+
lines.append(f"{indent}({i}):")
|
102
|
+
lines.append(
|
103
|
+
format_data_structure(
|
104
|
+
item, indent_level + 1, max_depth
|
105
|
+
)
|
106
|
+
)
|
107
|
+
else:
|
108
|
+
lines.append(f"{indent}{item}")
|
109
|
+
return "\n".join(lines)
|
110
|
+
|
111
|
+
elif data_type is set:
|
112
|
+
if not data:
|
113
|
+
return f"{indent}set() (empty set)"
|
114
|
+
|
115
|
+
lines = []
|
116
|
+
for item in sorted(
|
117
|
+
data, key=str
|
118
|
+
): # Sort for consistent output
|
119
|
+
if type(item) in (dict, list, tuple, set):
|
120
|
+
lines.append(f"{indent}set item:")
|
121
|
+
lines.append(
|
122
|
+
format_data_structure(
|
123
|
+
item, indent_level + 1, max_depth
|
124
|
+
)
|
125
|
+
)
|
126
|
+
else:
|
127
|
+
lines.append(f"{indent}{item}")
|
128
|
+
return "\n".join(lines)
|
129
|
+
|
130
|
+
elif data_type is str:
|
131
|
+
# Handle multi-line strings
|
132
|
+
if "\n" in data:
|
133
|
+
lines = data.split("\n")
|
134
|
+
return "\n".join(f"{indent}{line}" for line in lines)
|
135
|
+
return f"{indent}{data}"
|
136
|
+
|
137
|
+
elif data_type in (int, float, bool, type(None)):
|
138
|
+
return f"{indent}{data}"
|
139
|
+
|
140
|
+
else:
|
141
|
+
# Handle other types (custom objects, etc.)
|
142
|
+
if hasattr(data, "__dict__"):
|
143
|
+
# Object with attributes
|
144
|
+
lines = [f"{indent}{data_type.__name__} object:"]
|
145
|
+
for attr, value in data.__dict__.items():
|
146
|
+
if not attr.startswith(
|
147
|
+
"_"
|
148
|
+
): # Skip private attributes
|
149
|
+
if type(value) in (dict, list, tuple, set):
|
150
|
+
lines.append(f"{indent} {attr}:")
|
151
|
+
lines.append(
|
152
|
+
format_data_structure(
|
153
|
+
value, indent_level + 2, max_depth
|
154
|
+
)
|
155
|
+
)
|
156
|
+
else:
|
157
|
+
lines.append(f"{indent} {attr}: {value}")
|
158
|
+
return "\n".join(lines)
|
159
|
+
else:
|
160
|
+
# Fallback for other types
|
161
|
+
return f"{indent}{data} ({data_type.__name__})"
|
162
|
+
|
163
|
+
|
164
|
+
# test_dict = {
|
165
|
+
# "name": "John",
|
166
|
+
# "age": 30,
|
167
|
+
# "address": {
|
168
|
+
# "street": "123 Main St",
|
169
|
+
# "city": "Anytown",
|
170
|
+
# "state": "CA",
|
171
|
+
# "zip": "12345"
|
172
|
+
# }
|
173
|
+
# }
|
174
|
+
|
175
|
+
# print(format_dict_to_string(test_dict))
|
176
|
+
|
177
|
+
|
178
|
+
# # Example usage of format_data_structure:
|
179
|
+
# if __name__ == "__main__":
|
180
|
+
# # Test different data structures
|
181
|
+
|
182
|
+
# # Dictionary
|
183
|
+
# test_dict = {
|
184
|
+
# "name": "John",
|
185
|
+
# "age": 30,
|
186
|
+
# "address": {
|
187
|
+
# "street": "123 Main St",
|
188
|
+
# "city": "Anytown"
|
189
|
+
# }
|
190
|
+
# }
|
191
|
+
# print("=== Dictionary ===")
|
192
|
+
# print(format_data_structure(test_dict))
|
193
|
+
# print()
|
194
|
+
|
195
|
+
# # List
|
196
|
+
# test_list = ["apple", "banana", {"nested": "dict"}, [1, 2, 3]]
|
197
|
+
# print("=== List ===")
|
198
|
+
# print(format_data_structure(test_list))
|
199
|
+
# print()
|
200
|
+
|
201
|
+
# # Tuple
|
202
|
+
# test_tuple = ("first", "second", {"key": "value"}, (1, 2))
|
203
|
+
# print("=== Tuple ===")
|
204
|
+
# print(format_data_structure(test_tuple))
|
205
|
+
# print()
|
206
|
+
|
207
|
+
# # Set
|
208
|
+
# test_set = {"apple", "banana", "cherry"}
|
209
|
+
# print("=== Set ===")
|
210
|
+
# print(format_data_structure(test_set))
|
211
|
+
# print()
|
212
|
+
|
213
|
+
# # Mixed complex structure
|
214
|
+
# complex_data = {
|
215
|
+
# "users": [
|
216
|
+
# {"name": "Alice", "scores": [95, 87, 92]},
|
217
|
+
# {"name": "Bob", "scores": [88, 91, 85]}
|
218
|
+
# ],
|
219
|
+
# "metadata": {
|
220
|
+
# "total_users": 2,
|
221
|
+
# "categories": ("students", "teachers"),
|
222
|
+
# "settings": {"debug": True, "version": "1.0"}
|
223
|
+
# }
|
224
|
+
# }
|
225
|
+
# print("=== Complex Structure ===")
|
226
|
+
# print(format_data_structure(complex_data))
|
swarms/utils/litellm_wrapper.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
from typing import Optional
|
1
2
|
import base64
|
2
3
|
import requests
|
3
4
|
|
@@ -6,25 +7,13 @@ from typing import List
|
|
6
7
|
|
7
8
|
from loguru import logger
|
8
9
|
import litellm
|
10
|
+
from pydantic import BaseModel
|
9
11
|
|
10
|
-
|
11
|
-
from litellm import completion, acompletion
|
12
|
-
except ImportError:
|
13
|
-
import subprocess
|
14
|
-
import sys
|
15
|
-
import litellm
|
12
|
+
from litellm import completion, acompletion
|
16
13
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
[sys.executable, "-m", "pip", "install", "-U", "litellm"]
|
21
|
-
)
|
22
|
-
print("litellm installed")
|
23
|
-
|
24
|
-
from litellm import completion
|
25
|
-
|
26
|
-
litellm.set_verbose = True
|
27
|
-
litellm.ssl_verify = False
|
14
|
+
litellm.set_verbose = True
|
15
|
+
litellm.ssl_verify = False
|
16
|
+
# litellm._turn_on_debug()
|
28
17
|
|
29
18
|
|
30
19
|
class LiteLLMException(Exception):
|
@@ -86,6 +75,9 @@ class LiteLLM:
|
|
86
75
|
retries: int = 3,
|
87
76
|
verbose: bool = False,
|
88
77
|
caching: bool = False,
|
78
|
+
mcp_call: bool = False,
|
79
|
+
top_p: float = 1.0,
|
80
|
+
functions: List[dict] = None,
|
89
81
|
*args,
|
90
82
|
**kwargs,
|
91
83
|
):
|
@@ -110,6 +102,9 @@ class LiteLLM:
|
|
110
102
|
self.tool_choice = tool_choice
|
111
103
|
self.parallel_tool_calls = parallel_tool_calls
|
112
104
|
self.caching = caching
|
105
|
+
self.mcp_call = mcp_call
|
106
|
+
self.top_p = top_p
|
107
|
+
self.functions = functions
|
113
108
|
self.modalities = []
|
114
109
|
self._cached_messages = {} # Cache for prepared messages
|
115
110
|
self.messages = [] # Initialize messages list
|
@@ -123,6 +118,23 @@ class LiteLLM:
|
|
123
118
|
retries # Add retries for better reliability
|
124
119
|
)
|
125
120
|
|
121
|
+
def output_for_tools(self, response: any):
|
122
|
+
if self.mcp_call is True:
|
123
|
+
out = response.choices[0].message.tool_calls[0].function
|
124
|
+
output = {
|
125
|
+
"function": {
|
126
|
+
"name": out.name,
|
127
|
+
"arguments": out.arguments,
|
128
|
+
}
|
129
|
+
}
|
130
|
+
return output
|
131
|
+
else:
|
132
|
+
out = response.choices[0].message.tool_calls
|
133
|
+
|
134
|
+
if isinstance(out, BaseModel):
|
135
|
+
out = out.model_dump()
|
136
|
+
return out
|
137
|
+
|
126
138
|
def _prepare_messages(self, task: str) -> list:
|
127
139
|
"""
|
128
140
|
Prepare the messages for the given task.
|
@@ -222,8 +234,8 @@ class LiteLLM:
|
|
222
234
|
def run(
|
223
235
|
self,
|
224
236
|
task: str,
|
225
|
-
audio: str = None,
|
226
|
-
img: str = None,
|
237
|
+
audio: Optional[str] = None,
|
238
|
+
img: Optional[str] = None,
|
227
239
|
*args,
|
228
240
|
**kwargs,
|
229
241
|
):
|
@@ -250,38 +262,28 @@ class LiteLLM:
|
|
250
262
|
self.handle_modalities(
|
251
263
|
task=task, audio=audio, img=img
|
252
264
|
)
|
253
|
-
messages =
|
254
|
-
self.messages
|
255
|
-
) # Use modality-processed messages
|
256
|
-
|
257
|
-
if (
|
258
|
-
self.model_name == "openai/o4-mini"
|
259
|
-
or self.model_name == "openai/o3-2025-04-16"
|
260
|
-
):
|
261
|
-
# Prepare common completion parameters
|
262
|
-
completion_params = {
|
263
|
-
"model": self.model_name,
|
264
|
-
"messages": messages,
|
265
|
-
"stream": self.stream,
|
266
|
-
# "temperature": self.temperature,
|
267
|
-
"max_completion_tokens": self.max_tokens,
|
268
|
-
"caching": self.caching,
|
269
|
-
**kwargs,
|
270
|
-
}
|
265
|
+
messages = self.messages
|
271
266
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
267
|
+
# Base completion parameters
|
268
|
+
completion_params = {
|
269
|
+
"model": self.model_name,
|
270
|
+
"messages": messages,
|
271
|
+
"stream": self.stream,
|
272
|
+
"max_tokens": self.max_tokens,
|
273
|
+
"caching": self.caching,
|
274
|
+
"temperature": self.temperature,
|
275
|
+
"top_p": self.top_p,
|
276
|
+
**kwargs,
|
277
|
+
}
|
283
278
|
|
284
|
-
#
|
279
|
+
# Add temperature for non-o4/o3 models
|
280
|
+
if self.model_name not in [
|
281
|
+
"openai/o4-mini",
|
282
|
+
"openai/o3-2025-04-16",
|
283
|
+
]:
|
284
|
+
completion_params["temperature"] = self.temperature
|
285
|
+
|
286
|
+
# Add tools if specified
|
285
287
|
if self.tools_list_dictionary is not None:
|
286
288
|
completion_params.update(
|
287
289
|
{
|
@@ -290,28 +292,24 @@ class LiteLLM:
|
|
290
292
|
"parallel_tool_calls": self.parallel_tool_calls,
|
291
293
|
}
|
292
294
|
)
|
293
|
-
response = completion(**completion_params)
|
294
|
-
return (
|
295
|
-
response.choices[0]
|
296
|
-
.message.tool_calls[0]
|
297
|
-
.function.arguments
|
298
|
-
)
|
299
295
|
|
300
|
-
|
301
|
-
if (
|
302
|
-
self.modalities and len(self.modalities) > 1
|
303
|
-
): # More than just text
|
296
|
+
if self.functions is not None:
|
304
297
|
completion_params.update(
|
305
|
-
{"
|
298
|
+
{"functions": self.functions}
|
306
299
|
)
|
307
|
-
response = completion(**completion_params)
|
308
|
-
return response.choices[0].message.content
|
309
300
|
|
310
|
-
#
|
311
|
-
if self.
|
312
|
-
|
301
|
+
# Add modalities if needed
|
302
|
+
if self.modalities and len(self.modalities) >= 2:
|
303
|
+
completion_params["modalities"] = self.modalities
|
304
|
+
|
305
|
+
# Make the completion call
|
306
|
+
response = completion(**completion_params)
|
307
|
+
|
308
|
+
# Handle tool-based response
|
309
|
+
if self.tools_list_dictionary is not None:
|
310
|
+
return self.output_for_tools(response)
|
313
311
|
else:
|
314
|
-
response
|
312
|
+
# Return standard response content
|
315
313
|
return response.choices[0].message.content
|
316
314
|
|
317
315
|
except LiteLLMException as error:
|
@@ -322,7 +320,7 @@ class LiteLLM:
|
|
322
320
|
)
|
323
321
|
import time
|
324
322
|
|
325
|
-
time.sleep(2)
|
323
|
+
time.sleep(2)
|
326
324
|
return self.run(task, audio, img, *args, **kwargs)
|
327
325
|
raise error
|
328
326
|
|
@@ -21,7 +21,7 @@ def retry(
|
|
21
21
|
"""
|
22
22
|
|
23
23
|
def decorator_retry(
|
24
|
-
func: Callable[..., Any]
|
24
|
+
func: Callable[..., Any],
|
25
25
|
) -> Callable[..., Any]:
|
26
26
|
@wraps(func)
|
27
27
|
def wrapper_retry(*args, **kwargs) -> Any:
|
@@ -48,7 +48,7 @@ def retry(
|
|
48
48
|
|
49
49
|
|
50
50
|
def log_execution_time(
|
51
|
-
func: Callable[..., Any]
|
51
|
+
func: Callable[..., Any],
|
52
52
|
) -> Callable[..., Any]:
|
53
53
|
"""
|
54
54
|
A decorator that logs the execution time of a function.
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import xml.etree.ElementTree as ET
|
2
|
+
from typing import Any
|
3
|
+
|
4
|
+
|
5
|
+
def dict_to_xml(tag: str, d: dict) -> ET.Element:
|
6
|
+
"""Convert a dictionary to an XML Element."""
|
7
|
+
elem = ET.Element(tag)
|
8
|
+
for key, val in d.items():
|
9
|
+
child = ET.Element(str(key))
|
10
|
+
if isinstance(val, dict):
|
11
|
+
child.append(dict_to_xml(str(key), val))
|
12
|
+
elif isinstance(val, list):
|
13
|
+
for item in val:
|
14
|
+
if isinstance(item, dict):
|
15
|
+
child.append(dict_to_xml(str(key), item))
|
16
|
+
else:
|
17
|
+
item_elem = ET.Element("item")
|
18
|
+
item_elem.text = str(item)
|
19
|
+
child.append(item_elem)
|
20
|
+
else:
|
21
|
+
child.text = str(val)
|
22
|
+
elem.append(child)
|
23
|
+
return elem
|
24
|
+
|
25
|
+
|
26
|
+
def to_xml_string(data: Any, root_tag: str = "root") -> str:
|
27
|
+
"""Convert a dict or list to an XML string."""
|
28
|
+
if isinstance(data, dict):
|
29
|
+
elem = dict_to_xml(root_tag, data)
|
30
|
+
elif isinstance(data, list):
|
31
|
+
elem = ET.Element(root_tag)
|
32
|
+
for item in data:
|
33
|
+
if isinstance(item, dict):
|
34
|
+
elem.append(dict_to_xml("item", item))
|
35
|
+
else:
|
36
|
+
item_elem = ET.Element("item")
|
37
|
+
item_elem.text = str(item)
|
38
|
+
elem.append(item_elem)
|
39
|
+
else:
|
40
|
+
elem = ET.Element(root_tag)
|
41
|
+
elem.text = str(data)
|
42
|
+
return ET.tostring(elem, encoding="unicode")
|
@@ -1,8 +1,7 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: swarms
|
3
|
-
Version: 7.
|
3
|
+
Version: 7.8.0
|
4
4
|
Summary: Swarms - TGSC
|
5
|
-
Home-page: https://github.com/kyegomez/swarms
|
6
5
|
License: MIT
|
7
6
|
Keywords: artificial intelligence,deep learning,optimizers,Prompt Engineering,swarms,agents,llms,transformers,multi-agent,swarms of agents,Enterprise-Grade Agents,Production-Grade Agents,Agents,Multi-Grade-Agents,Swarms,Transformers,LLMs,Prompt Engineering,Agents,Generative Agents,Generative AI,Agent Marketplace,Agent Store,quant,finance,algorithmic trading,portfolio optimization,risk management,financial modeling,machine learning for finance,natural language processing for finance
|
8
7
|
Author: Kye Gomez
|
@@ -15,19 +14,20 @@ Classifier: Programming Language :: Python :: 3
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.10
|
16
15
|
Classifier: Programming Language :: Python :: 3.11
|
17
16
|
Classifier: Programming Language :: Python :: 3.12
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
18
18
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
19
19
|
Requires-Dist: PyYAML
|
20
20
|
Requires-Dist: aiofiles
|
21
21
|
Requires-Dist: aiohttp
|
22
22
|
Requires-Dist: asyncio (>=3.4.3,<4.0)
|
23
23
|
Requires-Dist: docstring_parser (==0.16)
|
24
|
-
Requires-Dist: fastmcp
|
25
24
|
Requires-Dist: httpx
|
26
25
|
Requires-Dist: litellm
|
27
26
|
Requires-Dist: loguru
|
28
27
|
Requires-Dist: mcp
|
29
28
|
Requires-Dist: networkx
|
30
29
|
Requires-Dist: numpy
|
30
|
+
Requires-Dist: numpydoc
|
31
31
|
Requires-Dist: psutil
|
32
32
|
Requires-Dist: pydantic
|
33
33
|
Requires-Dist: pypdf (==5.1.0)
|
@@ -38,6 +38,7 @@ Requires-Dist: tenacity
|
|
38
38
|
Requires-Dist: toml
|
39
39
|
Requires-Dist: torch
|
40
40
|
Project-URL: Documentation, https://docs.swarms.world
|
41
|
+
Project-URL: Homepage, https://github.com/kyegomez/swarms
|
41
42
|
Project-URL: Repository, https://github.com/kyegomez/swarms
|
42
43
|
Description-Content-Type: text/markdown
|
43
44
|
|