PraisonAI 0.0.24__tar.gz → 0.0.31__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.24
3
+ Version: 0.0.31
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,12 +8,14 @@ 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: chainlit
11
+ Provides-Extra: api
12
12
  Provides-Extra: gradio
13
13
  Provides-Extra: ui
14
- Requires-Dist: Flask (>=3.0.0)
14
+ Requires-Dist: chainlit (>=1.1.301,<2.0.0) ; extra == "ui"
15
15
  Requires-Dist: crewai (>=0.30.4)
16
16
  Requires-Dist: crewai-tools (>=0.2.6,<0.3.0)
17
+ Requires-Dist: flask (>=3.0.0) ; extra == "api"
18
+ Requires-Dist: gradio (>=4.26.0) ; extra == "gradio"
17
19
  Requires-Dist: markdown (>=3.5)
18
20
  Requires-Dist: praisonai-tools (>=0.0.4)
19
21
  Requires-Dist: pyautogen (>=0.2.19)
@@ -9,7 +9,6 @@ from crewai import Agent, Task, Crew
9
9
  from crewai.telemetry import Telemetry
10
10
  load_dotenv()
11
11
  import autogen
12
- import gradio as gr
13
12
  import argparse
14
13
  from .auto import AutoGenerator
15
14
  from crewai_tools import (
@@ -1,6 +1,6 @@
1
1
  from openai import OpenAI
2
2
  from pydantic import BaseModel
3
- from typing import Dict, List
3
+ from typing import Dict, List, Optional
4
4
  import instructor
5
5
  import os
6
6
  import json
@@ -23,16 +23,17 @@ class TeamStructure(BaseModel):
23
23
  roles: Dict[str, RoleDetails]
24
24
 
25
25
  class AutoGenerator:
26
- def __init__(self, topic="Movie Story writing about AI", agent_file="test.yaml", framework="crewai"):
26
+ def __init__(self, topic="Movie Story writing about AI", agent_file="test.yaml", framework="crewai", config_list: Optional[List[Dict]] = None):
27
27
  """
28
28
  Initialize the AutoGenerator class with the specified topic, agent file, and framework.
29
- note: autogen framework is different from this AutoGenerator class.
29
+ Note: autogen framework is different from this AutoGenerator class.
30
30
 
31
31
  Args:
32
32
  topic (str, optional): The topic for the generated team structure. Defaults to "Movie Story writing about AI".
33
33
  agent_file (str, optional): The name of the YAML file to save the generated team structure. Defaults to "test.yaml".
34
34
  framework (str, optional): The framework for the generated team structure. Defaults to "crewai".
35
-
35
+ config_list (Optional[List[Dict]], optional): A list containing the configuration details for the OpenAI API.
36
+ If None, it defaults to using environment variables or hardcoded values.
36
37
  Attributes:
37
38
  config_list (list): A list containing the configuration details for the OpenAI API.
38
39
  topic (str): The specified topic for the generated team structure.
@@ -40,10 +41,11 @@ class AutoGenerator:
40
41
  framework (str): The specified framework for the generated team structure.
41
42
  client (instructor.Client): An instance of the instructor.Client class initialized with the specified OpenAI API configuration.
42
43
  """
43
- self.config_list = [
44
+ self.config_list = config_list or [
44
45
  {
45
46
  'model': os.environ.get("OPENAI_MODEL_NAME", "gpt-4o"),
46
47
  'base_url': os.environ.get("OPENAI_API_BASE", "https://api.openai.com/v1"),
48
+ 'api_key': os.environ.get("OPENAI_API_KEY")
47
49
  }
48
50
  ]
49
51
  self.topic = topic
@@ -0,0 +1,240 @@
1
+ # praisonai/chainlit_ui.py
2
+ from praisonai.agents_generator import AgentsGenerator
3
+ from praisonai.auto import AutoGenerator
4
+ import chainlit as cl
5
+ import os
6
+ from chainlit.types import ThreadDict
7
+ from chainlit.input_widget import Select, TextInput
8
+ from typing import Optional
9
+ from dotenv import load_dotenv
10
+ load_dotenv()
11
+
12
+ framework = "crewai"
13
+ config_list = [
14
+ {
15
+ 'model': os.environ.get("OPENAI_MODEL_NAME", "gpt-4o"),
16
+ 'base_url': os.environ.get("OPENAI_API_BASE", "https://api.openai.com/v1"),
17
+ 'api_key': os.environ.get("OPENAI_API_KEY")
18
+ }
19
+ ]
20
+ agent_file = "test.yaml"
21
+
22
+ actions=[
23
+ cl.Action(name="run", value="run", label="✅ Run"),
24
+ cl.Action(name="modify", value="modify", label="🔧 Modify"),
25
+ ]
26
+
27
+ @cl.action_callback("run")
28
+ async def on_run(action):
29
+ await main(cl.Message(content=""))
30
+
31
+ @cl.action_callback("modify")
32
+ async def on_modify(action):
33
+ await cl.Message(content="Modify the agents and tools from below settings").send()
34
+
35
+
36
+ @cl.set_chat_profiles
37
+ async def set_profiles(current_user: cl.User):
38
+ return [
39
+ cl.ChatProfile(
40
+ name="Auto",
41
+ markdown_description="Automatically generate agents and tasks based on your input.",
42
+ starters=[
43
+ cl.Starter(
44
+ label="Create a movie script",
45
+ message="Create a movie script about a futuristic society where AI and humans coexist, focusing on the conflict and resolution between them. Start with an intriguing opening scene.",
46
+ icon="/public/movie.svg",
47
+ ),
48
+ cl.Starter(
49
+ label="Design a fantasy world",
50
+ message="Design a detailed fantasy world with unique geography, cultures, and magical systems. Start by describing the main continent and its inhabitants.",
51
+ icon="/public/fantasy.svg",
52
+ ),
53
+ cl.Starter(
54
+ label="Write a futuristic political thriller",
55
+ message="Write a futuristic political thriller involving a conspiracy within a global government. Start with a high-stakes meeting that sets the plot in motion.",
56
+ icon="/public/thriller.svg",
57
+ ),
58
+ cl.Starter(
59
+ label="Develop a new board game",
60
+ message="Develop a new, innovative board game. Describe the game's objective, rules, and unique mechanics. Create a scenario to illustrate gameplay.",
61
+ icon="/public/game.svg",
62
+ ),
63
+ ]
64
+ ),
65
+ cl.ChatProfile(
66
+ name="Manual",
67
+ markdown_description="Manually define your agents and tasks using a YAML file.",
68
+ ),
69
+ ]
70
+
71
+
72
+ @cl.on_chat_start
73
+ async def start_chat():
74
+ cl.user_session.set(
75
+ "message_history",
76
+ [{"role": "system", "content": "You are a helpful assistant."}],
77
+ )
78
+
79
+ # Create tools.py if it doesn't exist
80
+ if not os.path.exists("tools.py"):
81
+ with open("tools.py", "w") as f:
82
+ f.write("# Add your custom tools here\n")
83
+
84
+ settings = await cl.ChatSettings(
85
+ [
86
+ TextInput(id="Model", label="OpenAI - Model", initial=config_list[0]['model']),
87
+ TextInput(id="BaseUrl", label="OpenAI - Base URL", initial=config_list[0]['base_url']),
88
+ TextInput(id="ApiKey", label="OpenAI - API Key", initial=config_list[0]['api_key']),
89
+ Select(
90
+ id="Framework",
91
+ label="Framework",
92
+ values=["crewai", "autogen"],
93
+ initial_index=0,
94
+ ),
95
+ ]
96
+ ).send()
97
+ cl.user_session.set("settings", settings)
98
+ chat_profile = cl.user_session.get("chat_profile")
99
+ if chat_profile=="Manual":
100
+
101
+ agent_file = "agents.yaml"
102
+ full_agent_file_path = os.path.abspath(agent_file) # Get full path
103
+ if os.path.exists(full_agent_file_path):
104
+ with open(full_agent_file_path, 'r') as f:
105
+ yaml_content = f.read()
106
+ msg = cl.Message(content=yaml_content, language="yaml")
107
+ await msg.send()
108
+
109
+
110
+ full_tools_file_path = os.path.abspath("tools.py") # Get full path
111
+ if os.path.exists(full_tools_file_path):
112
+ with open(full_tools_file_path, 'r') as f:
113
+ tools_content = f.read()
114
+ msg = cl.Message(content=tools_content, language="python")
115
+ await msg.send()
116
+
117
+ settings = await cl.ChatSettings(
118
+ [
119
+ TextInput(id="Model", label="OpenAI - Model", initial=config_list[0]['model']),
120
+ TextInput(id="BaseUrl", label="OpenAI - Base URL", initial=config_list[0]['base_url']),
121
+ TextInput(id="ApiKey", label="OpenAI - API Key", initial=config_list[0]['api_key']),
122
+ Select(
123
+ id="Framework",
124
+ label="Framework",
125
+ values=["crewai", "autogen"],
126
+ initial_index=0,
127
+ ),
128
+ TextInput(id="agents", label="agents.yaml", initial=yaml_content, multiline=True),
129
+ TextInput(id="tools", label="tools.py", initial=tools_content, multiline=True),
130
+ ]
131
+ ).send()
132
+ cl.user_session.set("settings", settings)
133
+
134
+ res = await cl.AskActionMessage(
135
+ content="Pick an action!",
136
+ actions=actions,
137
+ ).send()
138
+ if res and res.get("value") == "modify":
139
+ await cl.Message(content="Modify the agents and tools from below settings", actions=actions).send()
140
+ elif res and res.get("value") == "run":
141
+ await main(cl.Message(content="", actions=actions))
142
+
143
+ await on_settings_update(settings)
144
+
145
+ @cl.on_settings_update
146
+ async def on_settings_update(settings):
147
+ """Handle updates to the ChatSettings form."""
148
+ global config_list, framework
149
+ config_list[0]['model'] = settings["Model"]
150
+ config_list[0]['base_url'] = settings["BaseUrl"]
151
+ config_list[0]['api_key'] = settings["ApiKey"]
152
+ os.environ["OPENAI_API_KEY"] = config_list[0]['api_key']
153
+ os.environ["OPENAI_MODEL_NAME"] = config_list[0]['model']
154
+ os.environ["OPENAI_API_BASE"] = config_list[0]['base_url']
155
+ framework = settings["Framework"]
156
+
157
+ if "agents" in settings:
158
+ with open("agents.yaml", "w") as f:
159
+ f.write(settings["agents"])
160
+ if "tools" in settings:
161
+ with open("tools.py", "w") as f:
162
+ f.write(settings["tools"])
163
+
164
+ print("Settings updated")
165
+
166
+ @cl.on_chat_resume
167
+ async def on_chat_resume(thread: ThreadDict):
168
+ message_history = cl.user_session.get("message_history", [])
169
+ root_messages = [m for m in thread["steps"] if m["parentId"] is None]
170
+ for message in root_messages:
171
+ if message["type"] == "user_message":
172
+ message_history.append({"role": "user", "content": message["output"]})
173
+ elif message["type"] == "ai_message":
174
+ message_history.append({"role": "assistant", "content": message["content"]})
175
+ cl.user_session.set("message_history", message_history)
176
+
177
+ # @cl.step(type="tool")
178
+ # async def tool(data: Optional[str] = None, language: Optional[str] = None):
179
+ # return cl.Message(content=data, language=language)
180
+
181
+ @cl.on_message
182
+ async def main(message: cl.Message):
183
+ """Run PraisonAI with the provided message as the topic."""
184
+ message_history = cl.user_session.get("message_history")
185
+ message_history.append({"role": "user", "content": message.content})
186
+ topic = message.content
187
+ chat_profile = cl.user_session.get("chat_profile")
188
+
189
+ if chat_profile == "Auto":
190
+ agent_file = "agents.yaml"
191
+ generator = AutoGenerator(topic=topic, agent_file=agent_file, framework=framework, config_list=config_list)
192
+ agent_file = generator.generate()
193
+ agents_generator = AgentsGenerator(agent_file, framework, config_list)
194
+ result = agents_generator.generate_crew_and_kickoff()
195
+ msg = cl.Message(content=result)
196
+ await msg.send()
197
+ message_history.append({"role": "assistant", "content": message.content})
198
+ else: # chat_profile == "Manual"
199
+ agent_file = "agents.yaml"
200
+ full_agent_file_path = os.path.abspath(agent_file) # Get full path
201
+ full_tools_file_path = os.path.abspath("tools.py")
202
+ if os.path.exists(full_agent_file_path):
203
+ with open(full_agent_file_path, 'r') as f:
204
+ yaml_content = f.read()
205
+ # tool_res = await tool()
206
+ msg_agents = cl.Message(content=yaml_content, language="yaml")
207
+ await msg_agents.send()
208
+ if os.path.exists(full_tools_file_path):
209
+ with open(full_tools_file_path, 'r') as f:
210
+ tools_content = f.read()
211
+ msg_tools = cl.Message(content=tools_content, language="python")
212
+ await msg_tools.send()
213
+ else:
214
+ # If the file doesn't exist, follow the same process as "Auto"
215
+ generator = AutoGenerator(topic=topic, agent_file=agent_file, framework=framework, config_list=config_list)
216
+ agent_file = generator.generate()
217
+
218
+ agents_generator = AgentsGenerator(agent_file, framework, config_list)
219
+ result = agents_generator.generate_crew_and_kickoff()
220
+ msg = cl.Message(content=result, actions=actions)
221
+ await msg.send()
222
+ message_history.append({"role": "assistant", "content": message.content})
223
+
224
+ # Load environment variables from .env file
225
+ load_dotenv()
226
+
227
+ # Get username and password from environment variables
228
+ username = os.getenv("CHAINLIT_USERNAME", "admin") # Default to "admin" if not found
229
+ password = os.getenv("CHAINLIT_PASSWORD", "admin") # Default to "admin" if not found
230
+
231
+ @cl.password_auth_callback
232
+ def auth_callback(username: str, password: str):
233
+ # Fetch the user matching username from your database
234
+ # and compare the hashed password with the value stored in the database
235
+ if (username, password) == (username, password):
236
+ return cl.User(
237
+ identifier=username, metadata={"role": "ADMIN", "provider": "credentials"}
238
+ )
239
+ else:
240
+ return None
@@ -8,7 +8,6 @@ from dotenv import load_dotenv
8
8
  from crewai import Agent, Task, Crew
9
9
  load_dotenv()
10
10
  import autogen
11
- import gradio as gr
12
11
  import argparse
13
12
  from .auto import AutoGenerator
14
13
  from .agents_generator import AgentsGenerator
@@ -48,6 +47,7 @@ class PraisonAI:
48
47
  {
49
48
  'model': os.environ.get("OPENAI_MODEL_NAME", "gpt-4o"),
50
49
  'base_url': os.environ.get("OPENAI_API_BASE", "https://api.openai.com/v1"),
50
+ 'api_key': os.environ.get("OPENAI_API_KEY")
51
51
  }
52
52
  ]
53
53
  self.agent_file = agent_file
@@ -156,6 +156,8 @@ class PraisonAI:
156
156
  args.agent_file = 'agents.yaml'
157
157
  if args.agent_file == 'api:app' or args.agent_file == '/app/api:app':
158
158
  args.agent_file = 'agents.yaml'
159
+ if args.agent_file == 'ui':
160
+ args.ui = 'chainlit'
159
161
 
160
162
  return args
161
163
 
@@ -211,7 +213,7 @@ class PraisonAI:
211
213
  theme="default"
212
214
  ).launch()
213
215
  else:
214
- print("ERROR: Gradio is not installed. Please install it with 'pip install \"praisonai[gradio]\"' to use this feature.")
216
+ print("ERROR: Gradio is not installed. Please install it with 'pip install gradio' to use this feature.")
215
217
 
216
218
  def create_chainlit_interface(self):
217
219
  """
@@ -226,9 +228,11 @@ class PraisonAI:
226
228
  """
227
229
  if CHAINLIT_AVAILABLE:
228
230
  os.environ["CHAINLIT_PORT"] = "8082"
229
- chainlit_run(["praisonai/chainlit_ui.py"])
231
+ import praisonai
232
+ chainlit_ui_path = os.path.join(os.path.dirname(praisonai.__file__), 'chainlit_ui.py')
233
+ chainlit_run([chainlit_ui_path])
230
234
  else:
231
- print("ERROR: Chainlit is not installed. Please install it with 'pip install \"praisonai\[ui]\"' to use the UI.")
235
+ print("ERROR: Chainlit is not installed. Please install it with 'pip install chainlit' to use the UI.")
232
236
 
233
237
  if __name__ == "__main__":
234
238
  praison_ai = PraisonAI()
@@ -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.24 gunicorn markdown\n")
59
+ file.write("RUN pip install flask praisonai==0.0.31 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
 
@@ -166,7 +166,11 @@ def autogen_ScrapeWebsiteTool(assistant, user_proxy):
166
166
  def register_scrape_website_tool(tool_class, tool_name, tool_description, assistant, user_proxy):
167
167
  def tool_func(website_url: str) -> Any:
168
168
  tool_instance = tool_class(website_url=website_url)
169
- return tool_instance.run()
169
+ content = tool_instance.run()
170
+ # Ensure content is properly decoded as UTF-8 if it's a bytes object
171
+ if isinstance(content, bytes):
172
+ content = content.decode('utf-8')
173
+ return content
170
174
  register_function(tool_func, caller=assistant, executor=user_proxy, name=tool_name, description=tool_description)
171
175
  register_scrape_website_tool(ScrapeWebsiteTool, "scrape_website_tool", "Read website content(website_url: 'string') - A tool that can be used to read content from a specified website.", assistant, user_proxy)
172
176
 
@@ -9,6 +9,7 @@ config_list = [
9
9
  {
10
10
  'model': os.environ.get("OPENAI_MODEL_NAME", "gpt-3.5-turbo"),
11
11
  'base_url': os.environ.get("OPENAI_API_BASE", "https://api.openai.com/v1"),
12
+ 'api_key': os.environ.get("OPENAI_API_KEY")
12
13
  }
13
14
  ]
14
15
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "PraisonAI"
3
- version = "0.0.24"
3
+ version = "0.0.31"
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 = ""
@@ -18,10 +18,12 @@ python = ">=3.10,<3.13"
18
18
  rich = ">=13.7"
19
19
  pyautogen = ">=0.2.19"
20
20
  crewai = ">=0.30.4"
21
- Flask = ">=3.0.0"
22
21
  markdown = ">=3.5"
23
22
  crewai-tools = "^0.2.6"
24
23
  praisonai-tools = ">=0.0.4"
24
+ chainlit = {version = "^1.1.301", optional = true}
25
+ gradio = {version = ">=4.26.0", optional = true}
26
+ flask = {version = ">=3.0.0", optional = true}
25
27
 
26
28
  [tool.poetry.dev-dependencies]
27
29
  pytest = "^8.0.0"
@@ -36,5 +38,5 @@ praisonai = "praisonai.__main__:main"
36
38
 
37
39
  [tool.poetry.extras]
38
40
  ui = ["chainlit"]
39
- chainlit = ["chainlit"]
40
- gradio = ["gradio"]
41
+ gradio = ["gradio"]
42
+ api = ["flask"]
@@ -1,67 +0,0 @@
1
- from praisonai.agents_generator import AgentsGenerator
2
- from praisonai.auto import AutoGenerator
3
- import chainlit as cl
4
- import os
5
- from chainlit.types import ThreadDict
6
- from typing import Optional
7
- from dotenv import load_dotenv
8
-
9
- framework = "crewai"
10
- config_list = [
11
- {
12
- 'model': os.environ.get("OPENAI_MODEL_NAME", "gpt-4o"),
13
- 'base_url': os.environ.get("OPENAI_API_BASE", "https://api.openai.com/v1"),
14
- }
15
- ]
16
- agent_file = "test.yaml"
17
-
18
- @cl.on_chat_start
19
- async def start_chat():
20
- cl.user_session.set(
21
- "message_history",
22
- [{"role": "system", "content": "You are a helpful assistant."}],
23
- )
24
-
25
- @cl.on_chat_resume
26
- async def on_chat_resume(thread: ThreadDict):
27
- message_history = cl.user_session.get("message_history", [])
28
- root_messages = [m for m in thread["steps"] if m["parentId"] is None]
29
- for message in root_messages:
30
- if message["type"] == "user_message":
31
- message_history.append({"role": "user", "content": message["output"]})
32
- elif message["type"] == "ai_message":
33
- message_history.append({"role": "assistant", "content": message["content"]})
34
- cl.user_session.set("message_history", message_history)
35
-
36
- @cl.on_message
37
- async def main(message: cl.Message):
38
- """Run PraisonAI with the provided message as the topic."""
39
- message_history = cl.user_session.get("message_history")
40
- message_history.append({"role": "user", "content": message.content})
41
- topic = message.content
42
- agent_file = "test.yaml"
43
- generator = AutoGenerator(topic=topic, framework=framework)
44
- agent_file = generator.generate()
45
- agents_generator = AgentsGenerator(agent_file, framework, config_list)
46
- result = agents_generator.generate_crew_and_kickoff()
47
- msg = cl.Message(content=result)
48
- await msg.send()
49
- message_history.append({"role": "assistant", "content": message.content})
50
-
51
- # Load environment variables from .env file
52
- load_dotenv()
53
-
54
- # Get username and password from environment variables
55
- username = os.getenv("CHAINLIT_USERNAME", "admin") # Default to "admin" if not found
56
- password = os.getenv("CHAINLIT_PASSWORD", "admin") # Default to "admin" if not found
57
-
58
- @cl.password_auth_callback
59
- def auth_callback(username: str, password: str):
60
- # Fetch the user matching username from your database
61
- # and compare the hashed password with the value stored in the database
62
- if (username, password) == ("admin", "admin"):
63
- return cl.User(
64
- identifier="admin", metadata={"role": "admin", "provider": "credentials"}
65
- )
66
- else:
67
- return None
File without changes
File without changes