PraisonAI 0.0.34__tar.gz → 0.0.36__tar.gz

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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PraisonAI
3
- Version: 0.0.34
3
+ Version: 0.0.36
4
4
  Summary: PraisonAI application combines AutoGen and CrewAI or similar frameworks into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customization, and efficient human-agent collaboration.
5
5
  Author: Mervin Praison
6
6
  Requires-Python: >=3.10,<3.13
@@ -8,9 +8,11 @@ Classifier: Programming Language :: Python :: 3
8
8
  Classifier: Programming Language :: Python :: 3.10
9
9
  Classifier: Programming Language :: Python :: 3.11
10
10
  Classifier: Programming Language :: Python :: 3.12
11
+ Provides-Extra: agentops
11
12
  Provides-Extra: api
12
13
  Provides-Extra: gradio
13
14
  Provides-Extra: ui
15
+ Requires-Dist: agentops (==0.2.3) ; extra == "agentops"
14
16
  Requires-Dist: chainlit (>=1.1.301,<2.0.0) ; extra == "ui"
15
17
  Requires-Dist: crewai (>=0.32.0)
16
18
  Requires-Dist: flask (>=3.0.0) ; extra == "api"
@@ -300,22 +302,22 @@ gcloud run deploy praisonai-service \
300
302
  ## Other Models
301
303
 
302
304
  ```bash
303
- Ollama
305
+ # Ollama
304
306
  OPENAI_API_BASE='http://localhost:11434/v1'
305
307
  OPENAI_MODEL_NAME='mistral'
306
308
  OPENAI_API_KEY='NA'
307
309
 
308
- FastChat
310
+ # FastChat
309
311
  OPENAI_API_BASE="http://localhost:8001/v1"
310
312
  OPENAI_MODEL_NAME='oh-2.5m7b-q51'
311
313
  OPENAI_API_KEY=NA
312
314
 
313
- LM Studio
314
- OPENAI_API_BASE="http://localhost:8000/v1"
315
+ # LM Studio
316
+ OPENAI_API_BASE="http://localhost:1234/v1"
315
317
  OPENAI_MODEL_NAME=NA
316
318
  OPENAI_API_KEY=NA
317
319
 
318
- Mistral API
320
+ # Mistral API
319
321
  OPENAI_API_BASE=https://api.mistral.ai/v1
320
322
  OPENAI_MODEL_NAME="mistral-small"
321
323
  OPENAI_API_KEY=your-mistral-api-key
@@ -274,22 +274,22 @@ gcloud run deploy praisonai-service \
274
274
  ## Other Models
275
275
 
276
276
  ```bash
277
- Ollama
277
+ # Ollama
278
278
  OPENAI_API_BASE='http://localhost:11434/v1'
279
279
  OPENAI_MODEL_NAME='mistral'
280
280
  OPENAI_API_KEY='NA'
281
281
 
282
- FastChat
282
+ # FastChat
283
283
  OPENAI_API_BASE="http://localhost:8001/v1"
284
284
  OPENAI_MODEL_NAME='oh-2.5m7b-q51'
285
285
  OPENAI_API_KEY=NA
286
286
 
287
- LM Studio
288
- OPENAI_API_BASE="http://localhost:8000/v1"
287
+ # LM Studio
288
+ OPENAI_API_BASE="http://localhost:1234/v1"
289
289
  OPENAI_MODEL_NAME=NA
290
290
  OPENAI_API_KEY=NA
291
291
 
292
- Mistral API
292
+ # Mistral API
293
293
  OPENAI_API_BASE=https://api.mistral.ai/v1
294
294
  OPENAI_MODEL_NAME="mistral-small"
295
295
  OPENAI_API_KEY=your-mistral-api-key
@@ -11,7 +11,7 @@ load_dotenv()
11
11
  import autogen
12
12
  import argparse
13
13
  from .auto import AutoGenerator
14
- from crewai_tools import (
14
+ from praisonai_tools import (
15
15
  CodeDocsSearchTool, CSVSearchTool, DirectorySearchTool, DOCXSearchTool, DirectoryReadTool,
16
16
  FileReadTool, TXTSearchTool, JSONSearchTool, MDXSearchTool, PDFSearchTool, RagTool,
17
17
  ScrapeElementFromWebsiteTool, ScrapeWebsiteTool, WebsiteSearchTool, XMLSearchTool, YoutubeChannelSearchTool,
@@ -24,6 +24,14 @@ import importlib
24
24
  import importlib.util
25
25
  from praisonai_tools import BaseTool
26
26
  import os
27
+ import logging
28
+
29
+ agentops = False
30
+ try:
31
+ import agentops
32
+ agentops = True
33
+ except ImportError:
34
+ agentops = False
27
35
 
28
36
  os.environ["OTEL_SDK_DISABLED"] = "true"
29
37
 
@@ -38,7 +46,7 @@ def disable_crewai_telemetry():
38
46
  disable_crewai_telemetry()
39
47
 
40
48
  class AgentsGenerator:
41
- def __init__(self, agent_file, framework, config_list):
49
+ def __init__(self, agent_file, framework, config_list, log_level=None, agent_callback=None, task_callback=None):
42
50
  """
43
51
  Initialize the AgentsGenerator object.
44
52
 
@@ -46,15 +54,31 @@ class AgentsGenerator:
46
54
  agent_file (str): The path to the agent file.
47
55
  framework (str): The framework to be used for the agents.
48
56
  config_list (list): A list of configurations for the agents.
57
+ log_level (int, optional): The logging level to use. Defaults to logging.INFO.
58
+ agent_callback (callable, optional): A callback function to be executed after each agent step.
59
+ task_callback (callable, optional): A callback function to be executed after each tool run.
49
60
 
50
61
  Attributes:
51
62
  agent_file (str): The path to the agent file.
52
63
  framework (str): The framework to be used for the agents.
53
64
  config_list (list): A list of configurations for the agents.
65
+ log_level (int): The logging level to use.
66
+ agent_callback (callable, optional): A callback function to be executed after each agent step.
67
+ task_callback (callable, optional): A callback function to be executed after each tool run.
54
68
  """
55
69
  self.agent_file = agent_file
56
70
  self.framework = framework
57
71
  self.config_list = config_list
72
+ self.log_level = log_level
73
+ self.agent_callback = agent_callback
74
+ self.task_callback = task_callback
75
+ self.log_level = log_level or logging.getLogger().getEffectiveLevel()
76
+ if self.log_level == logging.NOTSET:
77
+ self.log_level = os.environ.get('LOGLEVEL', 'INFO').upper()
78
+
79
+ logging.basicConfig(level=self.log_level, format='%(asctime)s - %(levelname)s - %(message)s')
80
+ self.logger = logging.getLogger(__name__)
81
+ self.logger.setLevel(self.log_level)
58
82
 
59
83
  def is_function_or_decorated(self, obj):
60
84
  """
@@ -183,10 +207,10 @@ class AgentsGenerator:
183
207
 
184
208
  if os.path.isfile(tools_py_path):
185
209
  tools_dict.update(self.load_tools_from_module_class(tools_py_path))
186
- # print("tools.py exists in the root directory. Loading tools.py and skipping tools folder.")
210
+ self.logger.debug("tools.py exists in the root directory. Loading tools.py and skipping tools folder.")
187
211
  elif tools_dir_path.is_dir():
188
212
  tools_dict.update(self.load_tools_from_module_class(tools_dir_path))
189
- # print("tools folder exists in the root directory")
213
+ self.logger.debug("tools folder exists in the root directory")
190
214
 
191
215
  framework = self.framework or config.get('framework')
192
216
 
@@ -252,6 +276,11 @@ class AgentsGenerator:
252
276
  # Adding tools to the agent if exists
253
277
  agent_tools = [tools_dict[tool] for tool in details.get('tools', []) if tool in tools_dict]
254
278
  agent = Agent(role=role_filled, goal=goal_filled, backstory=backstory_filled, tools=agent_tools, allow_delegation=False)
279
+
280
+ # Set agent callback if provided
281
+ if self.agent_callback:
282
+ agent.step_callback = self.agent_callback
283
+
255
284
  agents[role] = agent
256
285
 
257
286
  for task_name, task_details in details.get('tasks', {}).items():
@@ -259,13 +288,27 @@ class AgentsGenerator:
259
288
  expected_output_filled = task_details['expected_output'].format(topic=topic)
260
289
 
261
290
  task = Task(description=description_filled, expected_output=expected_output_filled, agent=agent)
291
+
292
+ # Set tool callback if provided
293
+ if self.task_callback:
294
+ task.callback = self.task_callback
295
+
262
296
  tasks.append(task)
297
+ if agentops:
298
+ agentops.init()
263
299
  crew = Crew(
264
300
  agents=list(agents.values()),
265
301
  tasks=tasks,
266
302
  verbose=2
267
303
  )
304
+ if agentops:
305
+ agentops.end_session("Success")
306
+
307
+ self.logger.debug("Final Crew Configuration:")
308
+ self.logger.debug(f"Agents: {crew.agents}")
309
+ self.logger.debug(f"Tasks: {crew.tasks}")
268
310
 
269
311
  response = crew.kickoff()
270
312
  result = f"### Task Output ###\n{response}"
271
313
  return result
314
+
@@ -8,6 +8,8 @@ from chainlit.input_widget import Select, TextInput
8
8
  from typing import Optional
9
9
  from dotenv import load_dotenv
10
10
  load_dotenv()
11
+ from contextlib import redirect_stdout
12
+ from io import StringIO
11
13
 
12
14
  framework = "crewai"
13
15
  config_list = [
@@ -178,10 +180,57 @@ async def on_chat_resume(thread: ThreadDict):
178
180
  # async def tool(data: Optional[str] = None, language: Optional[str] = None):
179
181
  # return cl.Message(content=data, language=language)
180
182
 
183
+ @cl.step(type="tool", show_input=False)
184
+ async def run_agents(agent_file: str, framework: str):
185
+ """Runs the agents and returns the result."""
186
+ agents_generator = AgentsGenerator(agent_file, framework, config_list)
187
+ current_step = cl.context.current_step
188
+ print("Current Step:", current_step)
189
+
190
+ stdout_buffer = StringIO()
191
+ with redirect_stdout(stdout_buffer):
192
+ result = agents_generator.generate_crew_and_kickoff()
193
+
194
+ complete_output = stdout_buffer.getvalue()
195
+
196
+ async with cl.Step(name="gpt4", type="llm", show_input=True) as step:
197
+ step.input = ""
198
+
199
+ for line in stdout_buffer.getvalue().splitlines():
200
+ print(line)
201
+ await step.stream_token(line)
202
+
203
+ tool_res = await output(complete_output)
204
+
205
+ yield result
206
+
207
+ @cl.step(type="tool", show_input=False, language="yaml")
208
+ async def output(output):
209
+ return output
210
+
211
+ @cl.step(type="tool", show_input=False, language="yaml")
212
+ def agent(output):
213
+ return(f"""
214
+ Agent Step Completed!
215
+ Output: {output}
216
+ """)
217
+
218
+ @cl.step(type="tool", show_input=False, language="yaml")
219
+ def task(output):
220
+ return(f"""
221
+ Task Completed!
222
+ Task: {output.description}
223
+ Output: {output.raw_output}
224
+ {output}
225
+ """)
226
+
181
227
  @cl.on_message
182
228
  async def main(message: cl.Message):
183
229
  """Run PraisonAI with the provided message as the topic."""
184
230
  message_history = cl.user_session.get("message_history")
231
+ if message_history is None:
232
+ message_history = []
233
+ cl.user_session.set("message_history", message_history)
185
234
  message_history.append({"role": "user", "content": message.content})
186
235
  topic = message.content
187
236
  chat_profile = cl.user_session.get("chat_profile")
@@ -189,9 +238,22 @@ async def main(message: cl.Message):
189
238
  if chat_profile == "Auto":
190
239
  agent_file = "agents.yaml"
191
240
  generator = AutoGenerator(topic=topic, agent_file=agent_file, framework=framework, config_list=config_list)
241
+ await cl.sleep(2)
192
242
  agent_file = generator.generate()
193
- agents_generator = AgentsGenerator(agent_file, framework, config_list)
194
- result = agents_generator.generate_crew_and_kickoff()
243
+ agents_generator = AgentsGenerator(
244
+ agent_file,
245
+ framework,
246
+ config_list,
247
+ # agent_callback=agent,
248
+ # task_callback=task
249
+ )
250
+ # Capture stdout
251
+ stdout_buffer = StringIO()
252
+ with redirect_stdout(stdout_buffer):
253
+ result = agents_generator.generate_crew_and_kickoff()
254
+
255
+ complete_output = stdout_buffer.getvalue()
256
+ tool_res = await output(complete_output)
195
257
  msg = cl.Message(content=result)
196
258
  await msg.send()
197
259
  message_history.append({"role": "assistant", "content": message.content})
@@ -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==0.0.34 gunicorn markdown\n")
59
+ file.write("RUN pip install flask praisonai==0.0.36 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
 
@@ -14,6 +14,8 @@ from pathlib import Path
14
14
  import os
15
15
  import inspect
16
16
  import sys
17
+ import logging
18
+ logging.basicConfig(level=os.environ.get('LOGLEVEL', 'INFO'), format='%(asctime)s - %(levelname)s - %(message)s')
17
19
 
18
20
  def create_autogen_tool_function(tool_name):
19
21
  def autogen_tool(assistant, user_proxy):
@@ -51,10 +53,10 @@ tools_dir_path = Path(root_directory) / 'tools'
51
53
  tools_module = None
52
54
 
53
55
  if os.path.isfile(tools_py_path):
54
- print(f"{tools_py_path} exists in the root directory. Loading {tools_py_path} and skipping tools folder.")
56
+ logging.info(f"{tools_py_path} exists in the root directory. Loading {tools_py_path} and skipping tools folder.")
55
57
  tools_module = importlib.import_module("tools")
56
58
  elif tools_dir_path.is_dir():
57
- print(f"tools folder exists in the root directory. Loading {tool_name} from tools/{tool_name}.py.")
59
+ logging.info(f"tools folder exists in the root directory. Loading {tool_name} from tools/{tool_name}.py.")
58
60
  tools_module = importlib.import_module(f"tools.{tool_name}")
59
61
 
60
62
  # Create autogen_TOOL_NAME_HERE function for each tool
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "PraisonAI"
3
- version = "0.0.34"
3
+ version = "0.0.36"
4
4
  description = "PraisonAI application combines AutoGen and CrewAI or similar frameworks into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customization, and efficient human-agent collaboration."
5
5
  authors = ["Mervin Praison"]
6
6
  license = ""
@@ -24,10 +24,12 @@ pyparsing = ">=3.0.0"
24
24
  chainlit = {version = "^1.1.301", optional = true}
25
25
  gradio = {version = ">=4.26.0", optional = true}
26
26
  flask = {version = ">=3.0.0", optional = true}
27
+ agentops = {version = "==0.2.3", optional = true}
27
28
 
28
29
  [tool.poetry.dev-dependencies]
29
- pytest = "^8.0.0"
30
- pre-commit = "^3.7"
30
+ pytest = "8.2.2"
31
+ pre-commit = "3.7.1"
32
+ unittest-xml-reporting = "3.2.0"
31
33
 
32
34
  [build-system]
33
35
  requires = ["poetry-core"]
@@ -39,4 +41,5 @@ praisonai = "praisonai.__main__:main"
39
41
  [tool.poetry.extras]
40
42
  ui = ["chainlit"]
41
43
  gradio = ["gradio"]
42
- api = ["flask"]
44
+ api = ["flask"]
45
+ agentops = ["agentops"]
File without changes
File without changes
File without changes
File without changes