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 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.33 gunicorn markdown\n")
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 AsyncAsyncWebCrawler() as crawler:
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
- "type": "function",
102
- "function": {
103
- "name": "tavily_web_search",
104
- "description": "Search the web using Tavily API and crawl the resulting URLs",
105
- "parameters": {
106
- "type": "object",
107
- "properties": {
108
- "query": {"type": "string", "description": "Search query"}
109
- },
110
- "required": ["query"]
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
- }] if tavily_api_key else []
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 tavily_api_key:
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 tavily_api_key and 'tool_calls' in delta and delta['tool_calls'] is not None:
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 tavily_api_key and tool_calls:
288
- available_functions = {
289
- "tavily_web_search": tavily_web_search,
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
- function_response = await function_to_call(
305
- query=function_args.get("query"),
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.33
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.106)
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=GJYcyXkp7CuOb2Hy6U_6bYmd6vrxZGVOetptn9n_PNY,6028
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=-QfO3wK5-_bzPkwAslfGBNQuiXAtrHBqT5Ty_E5vnr0,32831
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=mfNU-fmJt4-x3sKe10DuiieOTZYsP5046yGlZq3yVI0,13570
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.33.dist-info/METADATA,sha256=jz3maSJ-2WTTVul2ej5DcjCeP3aSX6EDomDmnKmsvSc,4762
78
- praisonai-2.2.33.dist-info/WHEEL,sha256=dCzwOzx-VmbmLA5u8QpkARaxx3rsePBxa1nmZphhNQk,110
79
- praisonai-2.2.33.dist-info/entry_points.txt,sha256=QSSfuXjZMhf16FZ201I_oSoX_s1nWYbi_4_UXPE3S-o,145
80
- praisonai-2.2.33.dist-info/RECORD,,
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,,