PraisonAI 2.2.33__cp313-cp313-manylinux_2_39_x86_64.whl → 2.2.35__cp313-cp313-manylinux_2_39_x86_64.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.
Potentially problematic release.
This version of PraisonAI might be problematic. Click here for more details.
- praisonai/deploy.py +1 -1
- praisonai/ui/agents.py +4 -2
- praisonai/ui/chat.py +136 -23
- {praisonai-2.2.33.dist-info → praisonai-2.2.35.dist-info}/METADATA +2 -2
- {praisonai-2.2.33.dist-info → praisonai-2.2.35.dist-info}/RECORD +7 -7
- {praisonai-2.2.33.dist-info → praisonai-2.2.35.dist-info}/WHEEL +0 -0
- {praisonai-2.2.33.dist-info → praisonai-2.2.35.dist-info}/entry_points.txt +0 -0
praisonai/deploy.py
CHANGED
|
@@ -56,7 +56,7 @@ class CloudDeployer:
|
|
|
56
56
|
file.write("FROM python:3.11-slim\n")
|
|
57
57
|
file.write("WORKDIR /app\n")
|
|
58
58
|
file.write("COPY . .\n")
|
|
59
|
-
file.write("RUN pip install flask praisonai==2.2.
|
|
59
|
+
file.write("RUN pip install flask praisonai==2.2.35 gunicorn markdown\n")
|
|
60
60
|
file.write("EXPOSE 8080\n")
|
|
61
61
|
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
|
62
62
|
|
praisonai/ui/agents.py
CHANGED
|
@@ -467,10 +467,12 @@ async def ui_run_praisonai(config, topic, tools_dict):
|
|
|
467
467
|
role_tools.append(callable_func)
|
|
468
468
|
# Add API tool definition to task's tools
|
|
469
469
|
task_tools.append(tool_def)
|
|
470
|
-
# Also set the agent's tools to include both
|
|
471
|
-
agent.tools = role_tools
|
|
472
470
|
else:
|
|
473
471
|
logger.warning(f"Tool '{tool_name}' not found. Skipping.")
|
|
472
|
+
|
|
473
|
+
# Set the agent's tools after collecting all tools
|
|
474
|
+
if role_tools:
|
|
475
|
+
agent.tools = role_tools
|
|
474
476
|
|
|
475
477
|
for tname, tdetails in details.get('tasks', {}).items():
|
|
476
478
|
description_filled = tdetails['description'].format(topic=topic)
|
praisonai/ui/chat.py
CHANGED
|
@@ -7,6 +7,8 @@ import json
|
|
|
7
7
|
import asyncio
|
|
8
8
|
import io
|
|
9
9
|
import base64
|
|
10
|
+
import importlib.util
|
|
11
|
+
import inspect
|
|
10
12
|
|
|
11
13
|
# Third-party imports
|
|
12
14
|
from dotenv import load_dotenv
|
|
@@ -59,6 +61,76 @@ def load_setting(key: str) -> str:
|
|
|
59
61
|
|
|
60
62
|
cl_data._data_layer = db_manager
|
|
61
63
|
|
|
64
|
+
def load_custom_tools():
|
|
65
|
+
"""Load custom tools from tools.py if it exists"""
|
|
66
|
+
custom_tools = {}
|
|
67
|
+
try:
|
|
68
|
+
spec = importlib.util.spec_from_file_location("tools", "tools.py")
|
|
69
|
+
if spec is None:
|
|
70
|
+
logger.debug("tools.py not found in current directory")
|
|
71
|
+
return custom_tools
|
|
72
|
+
|
|
73
|
+
module = importlib.util.module_from_spec(spec)
|
|
74
|
+
spec.loader.exec_module(module)
|
|
75
|
+
|
|
76
|
+
# Load all functions from tools.py
|
|
77
|
+
for name, obj in inspect.getmembers(module):
|
|
78
|
+
if not name.startswith('_') and callable(obj) and not inspect.isclass(obj):
|
|
79
|
+
# Store function in globals for access
|
|
80
|
+
globals()[name] = obj
|
|
81
|
+
|
|
82
|
+
# Get function signature to build parameters
|
|
83
|
+
sig = inspect.signature(obj)
|
|
84
|
+
params_properties = {}
|
|
85
|
+
required_params = []
|
|
86
|
+
|
|
87
|
+
for param_name, param in sig.parameters.items():
|
|
88
|
+
if param_name != 'self': # Skip self parameter
|
|
89
|
+
# Get type annotation if available
|
|
90
|
+
param_type = "string" # Default type
|
|
91
|
+
if param.annotation != inspect.Parameter.empty:
|
|
92
|
+
if param.annotation == int:
|
|
93
|
+
param_type = "integer"
|
|
94
|
+
elif param.annotation == float:
|
|
95
|
+
param_type = "number"
|
|
96
|
+
elif param.annotation == bool:
|
|
97
|
+
param_type = "boolean"
|
|
98
|
+
|
|
99
|
+
params_properties[param_name] = {
|
|
100
|
+
"type": param_type,
|
|
101
|
+
"description": f"Parameter {param_name}"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
# Add to required if no default value
|
|
105
|
+
if param.default == inspect.Parameter.empty:
|
|
106
|
+
required_params.append(param_name)
|
|
107
|
+
|
|
108
|
+
# Build tool definition
|
|
109
|
+
tool_def = {
|
|
110
|
+
"type": "function",
|
|
111
|
+
"function": {
|
|
112
|
+
"name": name,
|
|
113
|
+
"description": obj.__doc__ or f"Function {name.replace('_', ' ')}",
|
|
114
|
+
"parameters": {
|
|
115
|
+
"type": "object",
|
|
116
|
+
"properties": params_properties,
|
|
117
|
+
"required": required_params
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
custom_tools[name] = tool_def
|
|
123
|
+
logger.info(f"Loaded custom tool: {name}")
|
|
124
|
+
|
|
125
|
+
logger.info(f"Loaded {len(custom_tools)} custom tools from tools.py")
|
|
126
|
+
except Exception as e:
|
|
127
|
+
logger.warning(f"Error loading custom tools: {e}")
|
|
128
|
+
|
|
129
|
+
return custom_tools
|
|
130
|
+
|
|
131
|
+
# Load custom tools
|
|
132
|
+
custom_tools_dict = load_custom_tools()
|
|
133
|
+
|
|
62
134
|
tavily_api_key = os.getenv("TAVILY_API_KEY")
|
|
63
135
|
tavily_client = TavilyClient(api_key=tavily_api_key) if tavily_api_key else None
|
|
64
136
|
|
|
@@ -72,7 +144,7 @@ async def tavily_web_search(query):
|
|
|
72
144
|
response = tavily_client.search(query)
|
|
73
145
|
logger.debug(f"Tavily search response: {response}")
|
|
74
146
|
|
|
75
|
-
async with
|
|
147
|
+
async with AsyncWebCrawler() as crawler:
|
|
76
148
|
results = []
|
|
77
149
|
for result in response.get('results', []):
|
|
78
150
|
url = result.get('url')
|
|
@@ -97,20 +169,28 @@ async def tavily_web_search(query):
|
|
|
97
169
|
"results": results
|
|
98
170
|
})
|
|
99
171
|
|
|
100
|
-
tools
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
"
|
|
172
|
+
# Build tools list with Tavily and custom tools
|
|
173
|
+
tools = []
|
|
174
|
+
|
|
175
|
+
# Add Tavily tool if API key is available
|
|
176
|
+
if tavily_api_key:
|
|
177
|
+
tools.append({
|
|
178
|
+
"type": "function",
|
|
179
|
+
"function": {
|
|
180
|
+
"name": "tavily_web_search",
|
|
181
|
+
"description": "Search the web using Tavily API and crawl the resulting URLs",
|
|
182
|
+
"parameters": {
|
|
183
|
+
"type": "object",
|
|
184
|
+
"properties": {
|
|
185
|
+
"query": {"type": "string", "description": "Search query"}
|
|
186
|
+
},
|
|
187
|
+
"required": ["query"]
|
|
188
|
+
}
|
|
111
189
|
}
|
|
112
|
-
}
|
|
113
|
-
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
# Add custom tools from tools.py
|
|
193
|
+
tools.extend(list(custom_tools_dict.values()))
|
|
114
194
|
|
|
115
195
|
# Authentication configuration
|
|
116
196
|
AUTH_PASSWORD_ENABLED = os.getenv("AUTH_PASSWORD_ENABLED", "true").lower() == "true" # Password authentication enabled by default
|
|
@@ -235,7 +315,8 @@ User Question: {message.content}
|
|
|
235
315
|
]
|
|
236
316
|
}
|
|
237
317
|
|
|
238
|
-
if
|
|
318
|
+
# Pass tools if we have any (Tavily or custom)
|
|
319
|
+
if tools:
|
|
239
320
|
completion_params["tools"] = tools
|
|
240
321
|
completion_params["tool_choice"] = "auto"
|
|
241
322
|
|
|
@@ -254,7 +335,7 @@ User Question: {message.content}
|
|
|
254
335
|
await msg.stream_token(token)
|
|
255
336
|
full_response += token
|
|
256
337
|
|
|
257
|
-
if
|
|
338
|
+
if tools and 'tool_calls' in delta and delta['tool_calls'] is not None:
|
|
258
339
|
for tool_call in delta['tool_calls']:
|
|
259
340
|
if current_tool_call is None or tool_call.index != current_tool_call['index']:
|
|
260
341
|
if current_tool_call:
|
|
@@ -284,10 +365,17 @@ User Question: {message.content}
|
|
|
284
365
|
cl.user_session.set("message_history", message_history)
|
|
285
366
|
await msg.update()
|
|
286
367
|
|
|
287
|
-
if
|
|
288
|
-
available_functions = {
|
|
289
|
-
|
|
290
|
-
|
|
368
|
+
if tool_calls and tools: # Check if we have any tools and tool calls
|
|
369
|
+
available_functions = {}
|
|
370
|
+
|
|
371
|
+
# Add Tavily function if available
|
|
372
|
+
if tavily_api_key:
|
|
373
|
+
available_functions["tavily_web_search"] = tavily_web_search
|
|
374
|
+
|
|
375
|
+
# Add all custom tool functions from globals
|
|
376
|
+
for tool_name in custom_tools_dict:
|
|
377
|
+
if tool_name in globals():
|
|
378
|
+
available_functions[tool_name] = globals()[tool_name]
|
|
291
379
|
messages = message_history + [{"role": "assistant", "content": None, "function_call": {
|
|
292
380
|
"name": tool_calls[0]['function']['name'],
|
|
293
381
|
"arguments": tool_calls[0]['function']['arguments']
|
|
@@ -301,9 +389,25 @@ User Question: {message.content}
|
|
|
301
389
|
if function_args:
|
|
302
390
|
try:
|
|
303
391
|
function_args = json.loads(function_args)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
)
|
|
392
|
+
|
|
393
|
+
# Call function based on whether it's async or sync
|
|
394
|
+
if asyncio.iscoroutinefunction(function_to_call):
|
|
395
|
+
# For async functions like tavily_web_search
|
|
396
|
+
if function_name == "tavily_web_search":
|
|
397
|
+
function_response = await function_to_call(
|
|
398
|
+
query=function_args.get("query"),
|
|
399
|
+
)
|
|
400
|
+
else:
|
|
401
|
+
# For custom async functions, pass all arguments
|
|
402
|
+
function_response = await function_to_call(**function_args)
|
|
403
|
+
else:
|
|
404
|
+
# For sync functions (most custom tools)
|
|
405
|
+
function_response = function_to_call(**function_args)
|
|
406
|
+
|
|
407
|
+
# Convert response to string if needed
|
|
408
|
+
if not isinstance(function_response, str):
|
|
409
|
+
function_response = json.dumps(function_response)
|
|
410
|
+
|
|
307
411
|
messages.append(
|
|
308
412
|
{
|
|
309
413
|
"role": "function",
|
|
@@ -313,6 +417,15 @@ User Question: {message.content}
|
|
|
313
417
|
)
|
|
314
418
|
except json.JSONDecodeError:
|
|
315
419
|
logger.error(f"Failed to parse function arguments: {function_args}")
|
|
420
|
+
except Exception as e:
|
|
421
|
+
logger.error(f"Error calling function {function_name}: {str(e)}")
|
|
422
|
+
messages.append(
|
|
423
|
+
{
|
|
424
|
+
"role": "function",
|
|
425
|
+
"name": function_name,
|
|
426
|
+
"content": f"Error: {str(e)}",
|
|
427
|
+
}
|
|
428
|
+
)
|
|
316
429
|
|
|
317
430
|
second_response = await acompletion(
|
|
318
431
|
model=model_name,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: PraisonAI
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.35
|
|
4
4
|
Summary: PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration.
|
|
5
5
|
Author: Mervin Praison
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -64,7 +64,7 @@ Requires-Dist: playwright (>=1.47.0) ; extra == "code"
|
|
|
64
64
|
Requires-Dist: plotly (>=5.24.0) ; extra == "realtime"
|
|
65
65
|
Requires-Dist: praisonai-tools (>=0.0.15) ; extra == "autogen"
|
|
66
66
|
Requires-Dist: praisonai-tools (>=0.0.15) ; extra == "crewai"
|
|
67
|
-
Requires-Dist: praisonaiagents (>=0.0.
|
|
67
|
+
Requires-Dist: praisonaiagents (>=0.0.108)
|
|
68
68
|
Requires-Dist: pyautogen (>=0.2.19) ; extra == "autogen"
|
|
69
69
|
Requires-Dist: pydantic (<=2.10.1) ; extra == "chat"
|
|
70
70
|
Requires-Dist: pydantic (<=2.10.1) ; extra == "code"
|
|
@@ -6,7 +6,7 @@ praisonai/api/call.py,sha256=-dV9DKNDi4w9vN6K63TUh15_PC0M5KzYOmBqHbuJqq0,11079
|
|
|
6
6
|
praisonai/auto.py,sha256=0omuyIIuu-zBAXpsGo3JwuhX6zpjQg3ZtqbPtF5LZbg,12331
|
|
7
7
|
praisonai/chainlit_ui.py,sha256=1lmqZ7_W9Pp1ueFYLvOq1YoH5NnKy3blssDrVvn95pc,12236
|
|
8
8
|
praisonai/cli.py,sha256=4mG3TVE4DJxOC2KFfJcOiOhd814q9WEK2W2XNp7fIY8,36627
|
|
9
|
-
praisonai/deploy.py,sha256=
|
|
9
|
+
praisonai/deploy.py,sha256=MUguy-5jcKyxRolVXdOyHf2hRpqWRavodNKOGElYjPw,6028
|
|
10
10
|
praisonai/inbuilt_tools/__init__.py,sha256=mZOEximj3zCyJHq9Lz0bGXhQpBsa_QR-R-yA9UKC3zI,565
|
|
11
11
|
praisonai/inbuilt_tools/autogen_tools.py,sha256=kJdEv61BTYvdHOaURNEpBcWq8Rs-oC03loNFTIjT-ak,4687
|
|
12
12
|
praisonai/inc/__init__.py,sha256=sPDlYBBwdk0VlWzaaM_lG0_LD07lS2HRGvPdxXJFiYg,62
|
|
@@ -38,9 +38,9 @@ praisonai/test.py,sha256=OL-wesjA5JTohr8rtr6kWoaS4ImkJg2l0GXJ-dUUfRU,4090
|
|
|
38
38
|
praisonai/train.py,sha256=Cjb0TKU3esNrCk2OX24Qm1S1crRC00FdiGUYJLw3iPQ,24094
|
|
39
39
|
praisonai/train_vision.py,sha256=OLDtr5u9rszWQ80LC5iFy37yPuYguES6AQybm_2RtM4,12514
|
|
40
40
|
praisonai/ui/README.md,sha256=QG9yucvBieVjCjWFzu6hL9xNtYllkoqyJ_q1b0YYAco,1124
|
|
41
|
-
praisonai/ui/agents.py,sha256
|
|
41
|
+
praisonai/ui/agents.py,sha256=bnyHozpfhnX-LAipjG_X618yqXL_6BveW8ZsuAUQ7Zk,32865
|
|
42
42
|
praisonai/ui/callbacks.py,sha256=V4_-GjxmjDFmugUZGfQHKtNSysx7rT6i1UblbM_8lIM,1968
|
|
43
|
-
praisonai/ui/chat.py,sha256=
|
|
43
|
+
praisonai/ui/chat.py,sha256=c2nZfWBiprjs_X_B86M4ObhyVM1RZB0ZdZudDeHTN3g,18602
|
|
44
44
|
praisonai/ui/code.py,sha256=pBD7v35qCRSq2Q5YXKmGWUf3J7gAnBJDQoJSe90r9qQ,26449
|
|
45
45
|
praisonai/ui/colab.py,sha256=A2NceDVazMy53mIpp-NIn5w3y8aQKwQu5LmHTepVwlo,19584
|
|
46
46
|
praisonai/ui/colab_chainlit.py,sha256=wrB1O0ttRlmOH8aMxU8QdGpse-X54U87ZcEEA3R1aFg,2432
|
|
@@ -74,7 +74,7 @@ praisonai/ui/sql_alchemy.py,sha256=ilWAWicUGja7ADbXW9_OgIYeyKNuAQ1ZI_RMqjmMI9k,2
|
|
|
74
74
|
praisonai/ui/tools.md,sha256=Ad3YH_ZCLMWlz3mDXllQnQ_S5l55LWqLdcZSh-EXrHI,3956
|
|
75
75
|
praisonai/upload_vision.py,sha256=lMpFn993UiYVJxRNZQTmcbPbEajQ5TFKCNGK1Icn_hg,5253
|
|
76
76
|
praisonai/version.py,sha256=ugyuFliEqtAwQmH4sTlc16YXKYbFWDmfyk87fErB8-8,21
|
|
77
|
-
praisonai-2.2.
|
|
78
|
-
praisonai-2.2.
|
|
79
|
-
praisonai-2.2.
|
|
80
|
-
praisonai-2.2.
|
|
77
|
+
praisonai-2.2.35.dist-info/METADATA,sha256=PAQy4iS7n5QgOsAZzkhA6p9-VXGeZMs6PuIkxDFPrtA,4762
|
|
78
|
+
praisonai-2.2.35.dist-info/WHEEL,sha256=dCzwOzx-VmbmLA5u8QpkARaxx3rsePBxa1nmZphhNQk,110
|
|
79
|
+
praisonai-2.2.35.dist-info/entry_points.txt,sha256=QSSfuXjZMhf16FZ201I_oSoX_s1nWYbi_4_UXPE3S-o,145
|
|
80
|
+
praisonai-2.2.35.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|