PraisonAI 0.0.6__tar.gz → 0.0.8__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.
- {praisonai-0.0.6 → praisonai-0.0.8}/PKG-INFO +8 -1
- {praisonai-0.0.6 → praisonai-0.0.8}/README.md +6 -0
- praisonai-0.0.8/praisonai/__init__.py +2 -0
- praisonai-0.0.8/praisonai/__main__.py +10 -0
- praisonai-0.0.8/praisonai/auto-old.py +151 -0
- praisonai-0.0.8/praisonai/auto.py +135 -0
- praisonai-0.0.6/praisonai/cli.py → praisonai-0.0.8/praisonai/cli-old.py +45 -18
- praisonai-0.0.8/praisonai/cli.py +168 -0
- {praisonai-0.0.6 → praisonai-0.0.8}/pyproject.toml +2 -1
- praisonai-0.0.6/praisonai/__init__.py +0 -1
- praisonai-0.0.6/praisonai/__main__.py +0 -6
- {praisonai-0.0.6 → praisonai-0.0.8}/praisonai/test.py +0 -0
- {praisonai-0.0.6 → praisonai-0.0.8}/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.8
|
|
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
|
|
@@ -10,6 +10,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.12
|
|
11
11
|
Provides-Extra: tools
|
|
12
12
|
Requires-Dist: crewai (>=0.22.5)
|
|
13
|
+
Requires-Dist: gradio (>=4.20.0)
|
|
13
14
|
Requires-Dist: pyautogen (>=0.2.19)
|
|
14
15
|
Requires-Dist: rich (>=13.7)
|
|
15
16
|
Project-URL: Homepage, https://github.com/mervinpraison/praisonAI
|
|
@@ -31,3 +32,9 @@ pip install praisonai
|
|
|
31
32
|
```bash
|
|
32
33
|
praisonai
|
|
33
34
|
```
|
|
35
|
+
|
|
36
|
+
## Test
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
python -m unittest tests.test
|
|
40
|
+
```
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
from openai import OpenAI
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
|
+
from typing import Dict
|
|
4
|
+
import instructor
|
|
5
|
+
import os
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
config_list = [
|
|
9
|
+
{
|
|
10
|
+
'model': os.environ.get("OPENAI_MODEL_NAME", "gpt-4-turbo-preview"),
|
|
11
|
+
'base_url': os.environ.get("OPENAI_API_BASE", "https://api.openai.com/v1"),
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
task = "Movie Story writing"
|
|
16
|
+
|
|
17
|
+
# Define new Pydantic models to represent the script writing team structure
|
|
18
|
+
class TaskDetails(BaseModel):
|
|
19
|
+
description: str
|
|
20
|
+
expected_output: str
|
|
21
|
+
|
|
22
|
+
class RoleDetails(BaseModel):
|
|
23
|
+
role: str
|
|
24
|
+
goal: str
|
|
25
|
+
backstory: str
|
|
26
|
+
tasks: Dict[str, TaskDetails]
|
|
27
|
+
|
|
28
|
+
class TeamStructure(BaseModel):
|
|
29
|
+
roles: Dict[str, RoleDetails]
|
|
30
|
+
|
|
31
|
+
# Enables `response_model` in create call with the new model
|
|
32
|
+
client = instructor.patch(
|
|
33
|
+
OpenAI(
|
|
34
|
+
base_url=config_list[0]['base_url'],
|
|
35
|
+
api_key=os.getenv("OPENAI_API_KEY"),
|
|
36
|
+
),
|
|
37
|
+
mode=instructor.Mode.JSON,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
response = client.chat.completions.create(
|
|
41
|
+
model=config_list[0]['model'],
|
|
42
|
+
response_model=TeamStructure,
|
|
43
|
+
max_retries=10,
|
|
44
|
+
messages=[
|
|
45
|
+
{"role": "system", "content": "You are a helpful assistant designed to output complex team structures."},
|
|
46
|
+
{"role": "user", "content":
|
|
47
|
+
"""Generate a team structure for """ + task + """ task.
|
|
48
|
+
No Input data will be provided to the team.
|
|
49
|
+
The team will work in sequence. First role will pass the output to the next role, and so on.
|
|
50
|
+
The last role will generate the final output.
|
|
51
|
+
Think step by step.
|
|
52
|
+
With maximum 3 roles, each with 1 task. Include role goals, backstories, task descriptions, and expected outputs.
|
|
53
|
+
Output Structure:
|
|
54
|
+
{
|
|
55
|
+
"roles": {
|
|
56
|
+
"<role_id>": {
|
|
57
|
+
"role": "<role_name>",
|
|
58
|
+
"goal": "<role_goal>",
|
|
59
|
+
"backstory": "<role_backstory>",
|
|
60
|
+
"tasks": {
|
|
61
|
+
"<task_id>": {
|
|
62
|
+
"description": "<task_description>",
|
|
63
|
+
"expected_output": "<task_expected_output>"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"<role_id>": {
|
|
68
|
+
"role": "<role_name>",
|
|
69
|
+
"goal": "<role_goal>",
|
|
70
|
+
"backstory": "<role_backstory>",
|
|
71
|
+
"tasks": {
|
|
72
|
+
"<task_id>": {
|
|
73
|
+
"description": "<task_description>",
|
|
74
|
+
"expected_output": "<task_expected_output>"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
Example Below:
|
|
81
|
+
{
|
|
82
|
+
"roles": {
|
|
83
|
+
"narrative_designer": {
|
|
84
|
+
"role": "Narrative Designer",
|
|
85
|
+
"goal": "Create AI storylines",
|
|
86
|
+
"backstory": "Skilled in narrative development for AI, with a focus on story resonance.",
|
|
87
|
+
"tasks": {
|
|
88
|
+
"story_concept_development": {
|
|
89
|
+
"description": "Craft a unique AI story concept with depth and engagement.",
|
|
90
|
+
"expected_output": "Document with narrative arcs, character bios, and settings."
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"scriptwriter": {
|
|
95
|
+
"role": "Scriptwriter",
|
|
96
|
+
"goal": "Write scripts from AI concepts",
|
|
97
|
+
"backstory": "Expert in dialogue and script structure, translating concepts into scripts.",
|
|
98
|
+
"tasks": {
|
|
99
|
+
"scriptwriting_task": {
|
|
100
|
+
"description": "Turn narrative concepts into scripts, including dialogue and scenes.",
|
|
101
|
+
"expected_output": "Production-ready script with dialogue and scene details."
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
"""}
|
|
108
|
+
]
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
print(response.model_dump_json(indent=2))
|
|
112
|
+
|
|
113
|
+
import yaml
|
|
114
|
+
|
|
115
|
+
def convert_and_save(json_data, topic="Artificial Intelligence", filename="test.yaml"):
|
|
116
|
+
"""Converts the provided JSON data into the desired YAML format and saves it to a file.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
json_data (dict): The JSON data representing the team structure.
|
|
120
|
+
topic (str, optional): The topic to be inserted into the YAML. Defaults to "Artificial Intelligence".
|
|
121
|
+
filename (str, optional): The name of the YAML file to save. Defaults to "test.yaml".
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
yaml_data = {
|
|
125
|
+
"framework": "crewai",
|
|
126
|
+
"topic": topic,
|
|
127
|
+
"roles": {},
|
|
128
|
+
"dependencies": []
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
# Process roles in the order they appear in JSON
|
|
132
|
+
for role_id, role_details in json_data['roles'].items():
|
|
133
|
+
yaml_data['roles'][role_id] = {
|
|
134
|
+
"backstory": "" + role_details['backstory'],
|
|
135
|
+
"goal": role_details['goal'],
|
|
136
|
+
"role": role_details['role'],
|
|
137
|
+
"tasks": {}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
for task_id, task_details in role_details['tasks'].items():
|
|
141
|
+
yaml_data['roles'][role_id]['tasks'][task_id] = {
|
|
142
|
+
"description": "" + task_details['description'],
|
|
143
|
+
"expected_output": "" + task_details['expected_output']
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
# Save to YAML file, maintaining the order
|
|
147
|
+
with open(filename, 'w') as f:
|
|
148
|
+
yaml.dump(yaml_data, f, allow_unicode=True, sort_keys=False)
|
|
149
|
+
|
|
150
|
+
json_data = json.loads(response.model_dump_json())
|
|
151
|
+
convert_and_save(json_data)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
from openai import OpenAI
|
|
2
|
+
from pydantic import BaseModel
|
|
3
|
+
from typing import Dict
|
|
4
|
+
import instructor
|
|
5
|
+
import os
|
|
6
|
+
import json
|
|
7
|
+
import yaml
|
|
8
|
+
from rich import print
|
|
9
|
+
|
|
10
|
+
# Define Pydantic models outside of the generate method
|
|
11
|
+
class TaskDetails(BaseModel):
|
|
12
|
+
description: str
|
|
13
|
+
expected_output: str
|
|
14
|
+
|
|
15
|
+
class RoleDetails(BaseModel):
|
|
16
|
+
role: str
|
|
17
|
+
goal: str
|
|
18
|
+
backstory: str
|
|
19
|
+
tasks: Dict[str, TaskDetails]
|
|
20
|
+
|
|
21
|
+
class TeamStructure(BaseModel):
|
|
22
|
+
roles: Dict[str, RoleDetails]
|
|
23
|
+
|
|
24
|
+
class AutoGenerator:
|
|
25
|
+
def __init__(self, topic="Movie Story writing about AI", filename="test.yaml", framework="crewai"):
|
|
26
|
+
self.config_list = [
|
|
27
|
+
{
|
|
28
|
+
'model': os.environ.get("OPENAI_MODEL_NAME", "gpt-4-turbo-preview"),
|
|
29
|
+
'base_url': os.environ.get("OPENAI_API_BASE", "https://api.openai.com/v1"),
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
self.topic = topic
|
|
33
|
+
self.filename = filename
|
|
34
|
+
self.framework = framework
|
|
35
|
+
self.client = instructor.patch(
|
|
36
|
+
OpenAI(
|
|
37
|
+
base_url=self.config_list[0]['base_url'],
|
|
38
|
+
api_key=os.getenv("OPENAI_API_KEY"),
|
|
39
|
+
),
|
|
40
|
+
mode=instructor.Mode.JSON,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def generate(self):
|
|
44
|
+
response = self.client.chat.completions.create(
|
|
45
|
+
model=self.config_list[0]['model'],
|
|
46
|
+
response_model=TeamStructure,
|
|
47
|
+
max_retries=10,
|
|
48
|
+
messages=[
|
|
49
|
+
{"role": "system", "content": "You are a helpful assistant designed to output complex team structures."},
|
|
50
|
+
{"role": "user", "content": self.get_user_content()}
|
|
51
|
+
]
|
|
52
|
+
)
|
|
53
|
+
json_data = json.loads(response.model_dump_json())
|
|
54
|
+
self.convert_and_save(json_data)
|
|
55
|
+
full_path = os.path.abspath(self.filename)
|
|
56
|
+
return full_path
|
|
57
|
+
|
|
58
|
+
def convert_and_save(self, json_data):
|
|
59
|
+
"""Converts the provided JSON data into the desired YAML format and saves it to a file.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
json_data (dict): The JSON data representing the team structure.
|
|
63
|
+
topic (str, optional): The topic to be inserted into the YAML. Defaults to "Artificial Intelligence".
|
|
64
|
+
filename (str, optional): The name of the YAML file to save. Defaults to "test.yaml".
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
yaml_data = {
|
|
68
|
+
"framework": "crewai",
|
|
69
|
+
"topic": self.topic,
|
|
70
|
+
"roles": {},
|
|
71
|
+
"dependencies": []
|
|
72
|
+
}
|
|
73
|
+
print(self.topic)
|
|
74
|
+
print(self.framework)
|
|
75
|
+
|
|
76
|
+
for role_id, role_details in json_data['roles'].items():
|
|
77
|
+
yaml_data['roles'][role_id] = {
|
|
78
|
+
"backstory": "" + role_details['backstory'],
|
|
79
|
+
"goal": role_details['goal'],
|
|
80
|
+
"role": role_details['role'],
|
|
81
|
+
"tasks": {}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
for task_id, task_details in role_details['tasks'].items():
|
|
85
|
+
yaml_data['roles'][role_id]['tasks'][task_id] = {
|
|
86
|
+
"description": "" + task_details['description'],
|
|
87
|
+
"expected_output": "" + task_details['expected_output']
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Save to YAML file, maintaining the order
|
|
91
|
+
with open(self.filename, 'w') as f:
|
|
92
|
+
yaml.dump(yaml_data, f, allow_unicode=True, sort_keys=False)
|
|
93
|
+
|
|
94
|
+
def get_user_content(self):
|
|
95
|
+
user_content = """Generate a team structure for \"""" + self.topic + """\" task.
|
|
96
|
+
No Input data will be provided to the team.
|
|
97
|
+
The team will work in sequence. First role will pass the output to the next role, and so on.
|
|
98
|
+
The last role will generate the final output.
|
|
99
|
+
Think step by step.
|
|
100
|
+
With maximum 3 roles, each with 1 task. Include role goals, backstories, task descriptions, and expected outputs.
|
|
101
|
+
Example Below:
|
|
102
|
+
Use below example to understand the structure of the output.
|
|
103
|
+
The final role you create should satisfy the provided task: """ + self.topic + """.
|
|
104
|
+
{
|
|
105
|
+
"roles": {
|
|
106
|
+
"narrative_designer": {
|
|
107
|
+
"role": "Narrative Designer",
|
|
108
|
+
"goal": "Create AI storylines",
|
|
109
|
+
"backstory": "Skilled in narrative development for AI, with a focus on story resonance.",
|
|
110
|
+
"tasks": {
|
|
111
|
+
"story_concept_development": {
|
|
112
|
+
"description": "Craft a unique AI story concept with depth and engagement.",
|
|
113
|
+
"expected_output": "Document with narrative arcs, character bios, and settings."
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"scriptwriter": {
|
|
118
|
+
"role": "Scriptwriter",
|
|
119
|
+
"goal": "Write scripts from AI concepts",
|
|
120
|
+
"backstory": "Expert in dialogue and script structure, translating concepts into scripts.",
|
|
121
|
+
"tasks": {
|
|
122
|
+
"scriptwriting_task": {
|
|
123
|
+
"description": "Turn narrative concepts into scripts, including dialogue and scenes.",
|
|
124
|
+
"expected_output": "Production-ready script with dialogue and scene details."
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
"""
|
|
131
|
+
return user_content
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
generator = AutoGenerator(framework="crewai", topic="Create a snake game in python")
|
|
135
|
+
print(generator.generate())
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
# cli.py
|
|
1
|
+
# praisonai/cli.py
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
|
-
from
|
|
4
|
+
from version import __version__
|
|
5
5
|
import yaml, os
|
|
6
6
|
from rich import print
|
|
7
7
|
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
|
+
import argparse
|
|
13
|
+
|
|
11
14
|
config_list = [
|
|
12
15
|
{
|
|
13
16
|
'model': os.environ.get("OPENAI_MODEL_NAME", "gpt-3.5-turbo"),
|
|
@@ -47,7 +50,7 @@ def generate_crew_and_kickoff(agent_file, framework=None):
|
|
|
47
50
|
chat_task = {
|
|
48
51
|
"recipient": agents[role],
|
|
49
52
|
"message": description_filled,
|
|
50
|
-
"summary_method": "last_msg",
|
|
53
|
+
"summary_method": "last_msg",
|
|
51
54
|
# Additional fields like carryover can be added based on dependencies
|
|
52
55
|
}
|
|
53
56
|
tasks.append(chat_task)
|
|
@@ -56,7 +59,7 @@ def generate_crew_and_kickoff(agent_file, framework=None):
|
|
|
56
59
|
user = autogen.UserProxyAgent(
|
|
57
60
|
name="User",
|
|
58
61
|
human_input_mode="NEVER",
|
|
59
|
-
is_termination_msg=lambda x: (x.get("content") or "").rstrip().endswith("TERMINATE"),
|
|
62
|
+
is_termination_msg=lambda x: (x.get("content") or "").rstrip().rstrip(".").lower().endswith("terminate") or "TERMINATE" in (x.get("content") or ""),
|
|
60
63
|
code_execution_config={
|
|
61
64
|
"work_dir": "coding",
|
|
62
65
|
"use_docker": False,
|
|
@@ -72,7 +75,7 @@ def generate_crew_and_kickoff(agent_file, framework=None):
|
|
|
72
75
|
backstory_filled = details['backstory'].format(topic=topic)
|
|
73
76
|
|
|
74
77
|
# Assume tools are loaded and handled here as per your requirements
|
|
75
|
-
agent = Agent(role=role_filled, goal=goal_filled, backstory=backstory_filled)
|
|
78
|
+
agent = Agent(role=role_filled, goal=goal_filled, backstory=backstory_filled, allow_delegation=False)
|
|
76
79
|
agents[role] = agent
|
|
77
80
|
|
|
78
81
|
for task_name, task_details in details.get('tasks', {}).items():
|
|
@@ -88,29 +91,53 @@ def generate_crew_and_kickoff(agent_file, framework=None):
|
|
|
88
91
|
verbose=2
|
|
89
92
|
)
|
|
90
93
|
|
|
91
|
-
|
|
94
|
+
response = crew.kickoff()
|
|
95
|
+
result = f"### Output ###\n{response}"
|
|
92
96
|
return result
|
|
93
97
|
|
|
94
98
|
def main(args=None):
|
|
95
99
|
if args is None:
|
|
96
|
-
args =
|
|
100
|
+
args = parse_args()
|
|
97
101
|
|
|
98
102
|
invocation_cmd = "praisonai"
|
|
99
103
|
version_string = f"praisonAI version {__version__}"
|
|
100
|
-
framework =
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
framework_index = args.index("--framework")
|
|
104
|
-
framework = args[framework_index + 1]
|
|
105
|
-
args = args[:framework_index] + args[framework_index + 2:]
|
|
104
|
+
framework = args.framework # Default framework
|
|
105
|
+
ui = args.ui # Default UI flag
|
|
106
|
+
print(args)
|
|
106
107
|
|
|
107
|
-
if args:
|
|
108
|
-
agent_file = args
|
|
108
|
+
if args.agent_file:
|
|
109
|
+
agent_file = args.agent_file
|
|
109
110
|
else:
|
|
110
111
|
agent_file = "agents.yaml"
|
|
111
112
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
if ui:
|
|
114
|
+
create_gradio_interface()
|
|
115
|
+
else:
|
|
116
|
+
result = generate_crew_and_kickoff(agent_file, framework)
|
|
117
|
+
print(result)
|
|
118
|
+
|
|
119
|
+
def parse_args():
|
|
120
|
+
parser = argparse.ArgumentParser(prog="praisonai", description="praisonAI command-line interface")
|
|
121
|
+
parser.add_argument("--framework", choices=["crewai", "autogen"], default="crewai", help="Specify the framework")
|
|
122
|
+
parser.add_argument("--ui", action="store_true", help="Enable UI mode")
|
|
123
|
+
parser.add_argument("--auto", action="store_true", help="Enable auto mode")
|
|
124
|
+
parser.add_argument("agent_file", nargs="?", help="Specify the agent file")
|
|
125
|
+
|
|
126
|
+
return parser.parse_args()
|
|
127
|
+
|
|
128
|
+
def create_gradio_interface():
|
|
129
|
+
def generate_crew_and_kickoff_interface(agent_file, framework):
|
|
130
|
+
result = generate_crew_and_kickoff(agent_file, framework)
|
|
131
|
+
return result
|
|
132
|
+
|
|
133
|
+
gr.Interface(
|
|
134
|
+
fn=generate_crew_and_kickoff_interface,
|
|
135
|
+
inputs=["textbox", "radio"],
|
|
136
|
+
outputs="textbox",
|
|
137
|
+
title="Generate Crew and Kickoff",
|
|
138
|
+
description="Generate a crew and kickoff the tasks",
|
|
139
|
+
theme="default"
|
|
140
|
+
).launch()
|
|
141
|
+
|
|
115
142
|
if __name__ == "__main__":
|
|
116
143
|
main()
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# praisonai/cli.py
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from .version import __version__
|
|
5
|
+
import yaml, os
|
|
6
|
+
from rich import print
|
|
7
|
+
from dotenv import load_dotenv
|
|
8
|
+
from crewai import Agent, Task, Crew
|
|
9
|
+
load_dotenv()
|
|
10
|
+
import autogen
|
|
11
|
+
import gradio as gr
|
|
12
|
+
import argparse
|
|
13
|
+
from .auto import AutoGenerator
|
|
14
|
+
|
|
15
|
+
class PraisonAI:
|
|
16
|
+
def __init__(self, agent_file="agents.yaml", framework="crewai", auto=False):
|
|
17
|
+
self.config_list = [
|
|
18
|
+
{
|
|
19
|
+
'model': os.environ.get("OPENAI_MODEL_NAME", "gpt-4-turbo-preview"),
|
|
20
|
+
'base_url': os.environ.get("OPENAI_API_BASE", "https://api.openai.com/v1"),
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
self.agent_file = agent_file
|
|
24
|
+
self.framework = framework
|
|
25
|
+
self.auto = auto
|
|
26
|
+
|
|
27
|
+
def generate_crew_and_kickoff(self):
|
|
28
|
+
with open(self.agent_file, 'r') as f:
|
|
29
|
+
config = yaml.safe_load(f)
|
|
30
|
+
|
|
31
|
+
topic = config['topic']
|
|
32
|
+
framework = self.framework or config.get('framework')
|
|
33
|
+
|
|
34
|
+
agents = {}
|
|
35
|
+
tasks = []
|
|
36
|
+
if framework == "autogen":
|
|
37
|
+
# Load the LLM configuration dynamically
|
|
38
|
+
# print(self.config_list)
|
|
39
|
+
llm_config = {"config_list": self.config_list}
|
|
40
|
+
|
|
41
|
+
for role, details in config['roles'].items():
|
|
42
|
+
agent_name = details['role'].format(topic=topic).replace("{topic}", topic)
|
|
43
|
+
agent_goal = details['goal'].format(topic=topic)
|
|
44
|
+
# Creating an AssistantAgent for each role dynamically
|
|
45
|
+
agents[role] = autogen.AssistantAgent(
|
|
46
|
+
name=agent_name,
|
|
47
|
+
llm_config=llm_config,
|
|
48
|
+
system_message=details['backstory'].format(topic=topic)+". Must Reply \"TERMINATE\" in the end when everything is done.",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Preparing tasks for initiate_chats
|
|
52
|
+
for task_name, task_details in details.get('tasks', {}).items():
|
|
53
|
+
description_filled = task_details['description'].format(topic=topic)
|
|
54
|
+
expected_output_filled = task_details['expected_output'].format(topic=topic)
|
|
55
|
+
|
|
56
|
+
chat_task = {
|
|
57
|
+
"recipient": agents[role],
|
|
58
|
+
"message": description_filled,
|
|
59
|
+
"summary_method": "last_msg",
|
|
60
|
+
# Additional fields like carryover can be added based on dependencies
|
|
61
|
+
}
|
|
62
|
+
tasks.append(chat_task)
|
|
63
|
+
|
|
64
|
+
# Assuming the user proxy agent is set up as per your requirements
|
|
65
|
+
user = autogen.UserProxyAgent(
|
|
66
|
+
name="User",
|
|
67
|
+
human_input_mode="NEVER",
|
|
68
|
+
is_termination_msg=lambda x: (x.get("content") or "").rstrip().rstrip(".").lower().endswith("terminate") or "TERMINATE" in (x.get("content") or ""),
|
|
69
|
+
code_execution_config={
|
|
70
|
+
"work_dir": "coding",
|
|
71
|
+
"use_docker": False,
|
|
72
|
+
},
|
|
73
|
+
# additional setup for the user proxy agent
|
|
74
|
+
)
|
|
75
|
+
response = user.initiate_chats(tasks)
|
|
76
|
+
result = "### Output ###\n"+response[-1].summary if hasattr(response[-1], 'summary') else ""
|
|
77
|
+
else:
|
|
78
|
+
for role, details in config['roles'].items():
|
|
79
|
+
role_filled = details['role'].format(topic=topic)
|
|
80
|
+
goal_filled = details['goal'].format(topic=topic)
|
|
81
|
+
backstory_filled = details['backstory'].format(topic=topic)
|
|
82
|
+
|
|
83
|
+
# Assume tools are loaded and handled here as per your requirements
|
|
84
|
+
agent = Agent(role=role_filled, goal=goal_filled, backstory=backstory_filled, allow_delegation=False)
|
|
85
|
+
agents[role] = agent
|
|
86
|
+
|
|
87
|
+
for task_name, task_details in details.get('tasks', {}).items():
|
|
88
|
+
description_filled = task_details['description'].format(topic=topic)
|
|
89
|
+
expected_output_filled = task_details['expected_output'].format(topic=topic)
|
|
90
|
+
|
|
91
|
+
task = Task(description=description_filled, expected_output=expected_output_filled, agent=agent)
|
|
92
|
+
tasks.append(task)
|
|
93
|
+
|
|
94
|
+
crew = Crew(
|
|
95
|
+
agents=list(agents.values()),
|
|
96
|
+
tasks=tasks,
|
|
97
|
+
verbose=2
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
response = crew.kickoff()
|
|
101
|
+
result = f"### Output ###\n{response}"
|
|
102
|
+
return result
|
|
103
|
+
|
|
104
|
+
def main(self):
|
|
105
|
+
args = self.parse_args()
|
|
106
|
+
if args is None:
|
|
107
|
+
result = self.generate_crew_and_kickoff()
|
|
108
|
+
return result
|
|
109
|
+
invocation_cmd = "praisonai"
|
|
110
|
+
version_string = f"praisonAI version {__version__}"
|
|
111
|
+
|
|
112
|
+
# if args.framework:
|
|
113
|
+
# self.framework = args.framework
|
|
114
|
+
ui = args.ui # Default UI flag
|
|
115
|
+
|
|
116
|
+
if args.agent_file:
|
|
117
|
+
if args.agent_file == "tests.test": # Argument used for testing purposes
|
|
118
|
+
full_path = os.path.abspath("agents.yaml")
|
|
119
|
+
else:
|
|
120
|
+
full_path = os.path.abspath(args.agent_file)
|
|
121
|
+
self.agent_file = full_path
|
|
122
|
+
else:
|
|
123
|
+
full_path = os.path.abspath(self.agent_file)
|
|
124
|
+
self.filename = full_path
|
|
125
|
+
|
|
126
|
+
if args.auto:
|
|
127
|
+
self.topic = ' '.join(args.auto)
|
|
128
|
+
elif self.auto: # Use the auto attribute if args.auto is not provided
|
|
129
|
+
self.topic = self.auto
|
|
130
|
+
|
|
131
|
+
if args.auto or self.auto:
|
|
132
|
+
generator = AutoGenerator(topic=self.topic , framework=self.framework)
|
|
133
|
+
self.agent_file = generator.generate()
|
|
134
|
+
result = self.generate_crew_and_kickoff()
|
|
135
|
+
return result
|
|
136
|
+
|
|
137
|
+
if ui:
|
|
138
|
+
self.create_gradio_interface()
|
|
139
|
+
else:
|
|
140
|
+
result = self.generate_crew_and_kickoff()
|
|
141
|
+
return result
|
|
142
|
+
|
|
143
|
+
def parse_args(self):
|
|
144
|
+
parser = argparse.ArgumentParser(prog="praisonai", description="praisonAI command-line interface")
|
|
145
|
+
parser.add_argument("--framework", choices=["crewai", "autogen"], default="crewai", help="Specify the framework")
|
|
146
|
+
parser.add_argument("--ui", action="store_true", help="Enable UI mode")
|
|
147
|
+
parser.add_argument("--auto", nargs=argparse.REMAINDER, help="Enable auto mode and pass arguments for it")
|
|
148
|
+
parser.add_argument("agent_file", nargs="?", help="Specify the agent file")
|
|
149
|
+
|
|
150
|
+
return parser.parse_args()
|
|
151
|
+
|
|
152
|
+
def create_gradio_interface(self):
|
|
153
|
+
def generate_crew_and_kickoff_interface(agent_file, framework):
|
|
154
|
+
result = self.generate_crew_and_kickoff()
|
|
155
|
+
return result
|
|
156
|
+
|
|
157
|
+
gr.Interface(
|
|
158
|
+
fn=generate_crew_and_kickoff_interface,
|
|
159
|
+
inputs=["textbox"],
|
|
160
|
+
outputs="textbox",
|
|
161
|
+
title="Praison AI Studio",
|
|
162
|
+
description="Create Agents and perform tasks",
|
|
163
|
+
theme="default"
|
|
164
|
+
).launch()
|
|
165
|
+
|
|
166
|
+
if __name__ == "__main__":
|
|
167
|
+
praison_ai = PraisonAI()
|
|
168
|
+
praison_ai.main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "praisonAI"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.8"
|
|
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,6 +18,7 @@ python = ">=3.10,<3.13"
|
|
|
18
18
|
rich = ">=13.7"
|
|
19
19
|
pyautogen = ">=0.2.19"
|
|
20
20
|
crewai = ">=0.22.5"
|
|
21
|
+
gradio = ">=4.20.0"
|
|
21
22
|
|
|
22
23
|
[tool.poetry.dev-dependencies]
|
|
23
24
|
pytest = "^5.2"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .version import __version__
|
|
File without changes
|
|
File without changes
|