PraisonAI 0.0.35__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.
- {praisonai-0.0.35 → praisonai-0.0.36}/PKG-INFO +3 -1
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/agents_generator.py +46 -3
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/chainlit_ui.py +64 -2
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/deploy.py +1 -1
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/inbuilt_tools/autogen_tools.py +4 -2
- {praisonai-0.0.35 → praisonai-0.0.36}/pyproject.toml +7 -4
- {praisonai-0.0.35 → praisonai-0.0.36}/LICENSE +0 -0
- {praisonai-0.0.35 → praisonai-0.0.36}/README.md +0 -0
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/__init__.py +0 -0
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/__main__.py +0 -0
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/auto.py +0 -0
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/cli.py +0 -0
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/inbuilt_tools/__init__.py +0 -0
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/public/fantasy.svg +0 -0
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/public/game.svg +0 -0
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/public/movie.svg +0 -0
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/public/thriller.svg +0 -0
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/test.py +0 -0
- {praisonai-0.0.35 → praisonai-0.0.36}/praisonai/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PraisonAI
|
|
3
|
-
Version: 0.0.
|
|
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"
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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(
|
|
194
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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 = "
|
|
30
|
-
pre-commit = "
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|