PraisonAI 0.1.6__cp312-cp312-manylinux_2_35_x86_64.whl → 0.1.8__cp312-cp312-manylinux_2_35_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.
- praisonai/agents_generator.py +1 -1
- praisonai/api/call.py +107 -5
- praisonai/cli.py +6 -1
- praisonai/deploy.py +1 -1
- {praisonai-0.1.6.dist-info → praisonai-0.1.8.dist-info}/METADATA +1 -1
- {praisonai-0.1.6.dist-info → praisonai-0.1.8.dist-info}/RECORD +9 -9
- {praisonai-0.1.6.dist-info → praisonai-0.1.8.dist-info}/LICENSE +0 -0
- {praisonai-0.1.6.dist-info → praisonai-0.1.8.dist-info}/WHEEL +0 -0
- {praisonai-0.1.6.dist-info → praisonai-0.1.8.dist-info}/entry_points.txt +0 -0
praisonai/agents_generator.py
CHANGED
|
@@ -288,7 +288,7 @@ class AgentsGenerator:
|
|
|
288
288
|
backstory_filled = details['backstory'].format(topic=topic)
|
|
289
289
|
|
|
290
290
|
# Adding tools to the agent if exists
|
|
291
|
-
agent_tools = [tools_dict
|
|
291
|
+
agent_tools = [tools_dict.get(tool) for tool in details.get('tools', [])]
|
|
292
292
|
|
|
293
293
|
llm_model = details.get('llm') # Get the llm configuration
|
|
294
294
|
if llm_model:
|
praisonai/api/call.py
CHANGED
|
@@ -12,6 +12,8 @@ import uvicorn
|
|
|
12
12
|
from pyngrok import ngrok, conf
|
|
13
13
|
from rich import print
|
|
14
14
|
import argparse
|
|
15
|
+
import logging
|
|
16
|
+
import importlib.util
|
|
15
17
|
|
|
16
18
|
load_dotenv()
|
|
17
19
|
|
|
@@ -23,8 +25,10 @@ PUBLIC = os.getenv('PUBLIC', 'false').lower() == 'true'
|
|
|
23
25
|
SYSTEM_MESSAGE = (
|
|
24
26
|
"You are a helpful and bubbly AI assistant who loves to chat about "
|
|
25
27
|
"anything the user is interested in and is prepared to offer them facts. "
|
|
28
|
+
"Keep your responses short and to the point. "
|
|
26
29
|
"You have a penchant for dad jokes, owl jokes, and rickrolling – subtly. "
|
|
27
30
|
"Always stay positive, but work in a joke when appropriate."
|
|
31
|
+
"Start your conversation by saying 'Hi! I'm Praison AI. How can I help you today?'"
|
|
28
32
|
)
|
|
29
33
|
VOICE = 'alloy'
|
|
30
34
|
LOG_EVENT_TYPES = [
|
|
@@ -38,6 +42,46 @@ app = FastAPI()
|
|
|
38
42
|
if not OPENAI_API_KEY:
|
|
39
43
|
raise ValueError('Missing the OpenAI API key. Please set it in the .env file.')
|
|
40
44
|
|
|
45
|
+
# Set up logging
|
|
46
|
+
logger = logging.getLogger(__name__)
|
|
47
|
+
log_level = os.getenv("LOGLEVEL", "INFO").upper()
|
|
48
|
+
logger.handlers = []
|
|
49
|
+
|
|
50
|
+
# Try to import tools from the root directory
|
|
51
|
+
tools = []
|
|
52
|
+
tools_path = os.path.join(os.getcwd(), 'tools.py')
|
|
53
|
+
logger.info(f"Tools path: {tools_path}")
|
|
54
|
+
|
|
55
|
+
def import_tools_from_file(file_path):
|
|
56
|
+
spec = importlib.util.spec_from_file_location("custom_tools", file_path)
|
|
57
|
+
custom_tools_module = importlib.util.module_from_spec(spec)
|
|
58
|
+
spec.loader.exec_module(custom_tools_module)
|
|
59
|
+
logger.debug(f"Imported tools from {file_path}")
|
|
60
|
+
return custom_tools_module
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
if os.path.exists(tools_path):
|
|
64
|
+
# tools.py exists in the root directory, import from file
|
|
65
|
+
custom_tools_module = import_tools_from_file(tools_path)
|
|
66
|
+
logger.info("Successfully imported custom tools from root tools.py")
|
|
67
|
+
else:
|
|
68
|
+
logger.info("No custom tools.py file found in the root directory")
|
|
69
|
+
custom_tools_module = None
|
|
70
|
+
|
|
71
|
+
if custom_tools_module:
|
|
72
|
+
# Update the tools list with custom tools
|
|
73
|
+
if hasattr(custom_tools_module, 'tools') and isinstance(custom_tools_module.tools, list):
|
|
74
|
+
tools.extend(custom_tools_module.tools)
|
|
75
|
+
else:
|
|
76
|
+
for name, obj in custom_tools_module.__dict__.items():
|
|
77
|
+
if callable(obj) and not name.startswith("__"):
|
|
78
|
+
tool_definition = getattr(obj, 'definition', None)
|
|
79
|
+
if tool_definition:
|
|
80
|
+
tools.append(tool_definition)
|
|
81
|
+
|
|
82
|
+
except Exception as e:
|
|
83
|
+
logger.warning(f"Error importing custom tools: {str(e)}. Continuing without custom tools.")
|
|
84
|
+
|
|
41
85
|
@app.get("/status", response_class=HTMLResponse)
|
|
42
86
|
async def index_page():
|
|
43
87
|
return """
|
|
@@ -57,7 +101,7 @@ async def handle_incoming_call(request: Request):
|
|
|
57
101
|
response = VoiceResponse()
|
|
58
102
|
response.say("")
|
|
59
103
|
response.pause(length=1)
|
|
60
|
-
response.say("
|
|
104
|
+
# response.say("")
|
|
61
105
|
host = request.url.hostname
|
|
62
106
|
connect = Connect()
|
|
63
107
|
connect.stream(url=f'wss://{host}/media-stream')
|
|
@@ -110,6 +154,10 @@ async def handle_media_stream(websocket: WebSocket):
|
|
|
110
154
|
print(f"Received event: {response['type']}", response)
|
|
111
155
|
if response['type'] == 'session.updated':
|
|
112
156
|
print("Session updated successfully:", response)
|
|
157
|
+
|
|
158
|
+
if response['type'] == 'response.done':
|
|
159
|
+
await handle_response_done(response, openai_ws)
|
|
160
|
+
|
|
113
161
|
if response['type'] == 'response.audio.delta' and response.get('delta'):
|
|
114
162
|
# Audio from OpenAI
|
|
115
163
|
try:
|
|
@@ -125,12 +173,68 @@ async def handle_media_stream(websocket: WebSocket):
|
|
|
125
173
|
except Exception as e:
|
|
126
174
|
print(f"Error processing audio data: {e}")
|
|
127
175
|
except Exception as e:
|
|
128
|
-
print(f"Error in
|
|
176
|
+
print(f"Error in Sending to Phone: {e}")
|
|
129
177
|
|
|
130
178
|
await asyncio.gather(receive_from_twilio(), send_to_twilio())
|
|
131
179
|
|
|
180
|
+
async def handle_response_done(response, openai_ws):
|
|
181
|
+
"""Handle the response.done event and process any function calls."""
|
|
182
|
+
print("Handling response.done:", response)
|
|
183
|
+
output_items = response.get('response', {}).get('output', [])
|
|
184
|
+
for item in output_items:
|
|
185
|
+
if item.get('type') == 'function_call':
|
|
186
|
+
await process_function_call(item, openai_ws)
|
|
187
|
+
|
|
188
|
+
async def process_function_call(item, openai_ws):
|
|
189
|
+
"""Process a function call item and send the result back to OpenAI."""
|
|
190
|
+
function_name = item.get('name')
|
|
191
|
+
arguments = json.loads(item.get('arguments', '{}'))
|
|
192
|
+
call_id = item.get('call_id')
|
|
193
|
+
|
|
194
|
+
print(f"Processing function call: {function_name}")
|
|
195
|
+
print(f"Arguments: {arguments}")
|
|
196
|
+
|
|
197
|
+
result = await call_tool(function_name, arguments)
|
|
198
|
+
|
|
199
|
+
# Send the function call result back to OpenAI
|
|
200
|
+
await openai_ws.send(json.dumps({
|
|
201
|
+
"type": "conversation.item.create",
|
|
202
|
+
"item": {
|
|
203
|
+
"type": "function_call_output",
|
|
204
|
+
"call_id": call_id,
|
|
205
|
+
"output": json.dumps(result)
|
|
206
|
+
}
|
|
207
|
+
}))
|
|
208
|
+
|
|
209
|
+
# Create a new response after sending the function call result
|
|
210
|
+
await openai_ws.send(json.dumps({
|
|
211
|
+
"type": "response.create"
|
|
212
|
+
}))
|
|
213
|
+
|
|
214
|
+
async def call_tool(function_name, arguments):
|
|
215
|
+
"""Call the appropriate tool function and return the result."""
|
|
216
|
+
tool = next((t for t in tools if t[0]['name'] == function_name), None)
|
|
217
|
+
if not tool:
|
|
218
|
+
return {"error": f"Function {function_name} not found"}
|
|
219
|
+
|
|
220
|
+
try:
|
|
221
|
+
# Assuming the tool function is the second element in the tuple
|
|
222
|
+
result = await tool[1](**arguments)
|
|
223
|
+
return result
|
|
224
|
+
except Exception as e:
|
|
225
|
+
return {"error": str(e)}
|
|
226
|
+
|
|
132
227
|
async def send_session_update(openai_ws):
|
|
133
228
|
"""Send session update to OpenAI WebSocket."""
|
|
229
|
+
global tools
|
|
230
|
+
print(f"Formatted tools: {tools}")
|
|
231
|
+
|
|
232
|
+
use_tools = [
|
|
233
|
+
{**tool[0], "type": "function"}
|
|
234
|
+
for tool in tools
|
|
235
|
+
if isinstance(tool, tuple) and len(tool) > 0 and isinstance(tool[0], dict)
|
|
236
|
+
]
|
|
237
|
+
|
|
134
238
|
session_update = {
|
|
135
239
|
"type": "session.update",
|
|
136
240
|
"session": {
|
|
@@ -142,10 +246,8 @@ async def send_session_update(openai_ws):
|
|
|
142
246
|
},
|
|
143
247
|
"input_audio_format": "g711_ulaw",
|
|
144
248
|
"output_audio_format": "g711_ulaw",
|
|
145
|
-
# "input_audio_transcription": { "model": 'whisper-1' },
|
|
146
|
-
# "transcription_models": [{"model": "whisper-1"}],
|
|
147
249
|
"voice": VOICE,
|
|
148
|
-
"tools":
|
|
250
|
+
"tools": use_tools,
|
|
149
251
|
"tool_choice": "auto",
|
|
150
252
|
"instructions": SYSTEM_MESSAGE,
|
|
151
253
|
"modalities": ["text", "audio"],
|
praisonai/cli.py
CHANGED
|
@@ -17,7 +17,12 @@ import shutil
|
|
|
17
17
|
import subprocess
|
|
18
18
|
import logging
|
|
19
19
|
import importlib
|
|
20
|
-
|
|
20
|
+
try:
|
|
21
|
+
import praisonai.api.call as call_module
|
|
22
|
+
CALL_MODULE_AVAILABLE = True
|
|
23
|
+
except ImportError:
|
|
24
|
+
CALL_MODULE_AVAILABLE = False
|
|
25
|
+
|
|
21
26
|
logging.basicConfig(level=os.environ.get('LOGLEVEL', 'INFO'), format='%(asctime)s - %(levelname)s - %(message)s')
|
|
22
27
|
|
|
23
28
|
try:
|
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==0.1.
|
|
59
|
+
file.write("RUN pip install flask praisonai==0.1.8 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
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PraisonAI
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.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
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
praisonai/__init__.py,sha256=JrgyPlzZfLlozoW7SHZ1nVJ63rLPR3ki2k5ZPywYrnI,175
|
|
2
2
|
praisonai/__main__.py,sha256=MVgsjMThjBexHt4nhd760JCqvP4x0IQcwo8kULOK4FQ,144
|
|
3
|
-
praisonai/agents_generator.py,sha256=
|
|
4
|
-
praisonai/api/call.py,sha256=
|
|
3
|
+
praisonai/agents_generator.py,sha256=SltYtjFrADEkYkbzNrWHT6tIxpyjAMBbwH2czZOGPhg,19109
|
|
4
|
+
praisonai/api/call.py,sha256=iHdAlgIH_oTsEbjaGGu1Jjo6DTfMR-SfFdtSxnOLCeY,11032
|
|
5
5
|
praisonai/auto.py,sha256=9spTXqj47Hmmqv5QHRYE_RzSVHH_KoPbaZjskUj2UcE,7895
|
|
6
6
|
praisonai/chainlit_ui.py,sha256=bNR7s509lp0I9JlJNvwCZRUZosC64qdvlFCt8NmFamQ,12216
|
|
7
|
-
praisonai/cli.py,sha256=
|
|
8
|
-
praisonai/deploy.py,sha256=
|
|
7
|
+
praisonai/cli.py,sha256=8q8nfvc9ztKW3AQ0NpFnby739MCcvaqF3Y14BrpuCXo,20768
|
|
8
|
+
praisonai/deploy.py,sha256=MY4PCgp8iSA-T1ovph00zZ8dTjIL7gZ7sjNENOOZ5sg,6027
|
|
9
9
|
praisonai/inbuilt_tools/__init__.py,sha256=mUKnbL6Gram9c9f2m8wJwEzURBLmPEOcHzwySBH89YA,74
|
|
10
10
|
praisonai/inbuilt_tools/autogen_tools.py,sha256=svYkM2N7DVFvbiwgoAS7U_MqTOD8rHf8VD3BaFUV5_Y,14907
|
|
11
11
|
praisonai/inc/__init__.py,sha256=sPDlYBBwdk0VlWzaaM_lG0_LD07lS2HRGvPdxXJFiYg,62
|
|
@@ -46,8 +46,8 @@ praisonai/ui/realtimeclient/realtimedocs.txt,sha256=hmgd8Uwy2SkjSndyyF_-ZOaNxiyH
|
|
|
46
46
|
praisonai/ui/realtimeclient/tools.py,sha256=IJOYwVOBW5Ocn5_iV9pFkmSKR3WU3YpX3kwF0I3jikQ,7855
|
|
47
47
|
praisonai/ui/sql_alchemy.py,sha256=kf025P_37C505YDDJZ-dPSmN_d62J2DCrkxbDAzXyrM,29884
|
|
48
48
|
praisonai/version.py,sha256=ugyuFliEqtAwQmH4sTlc16YXKYbFWDmfyk87fErB8-8,21
|
|
49
|
-
praisonai-0.1.
|
|
50
|
-
praisonai-0.1.
|
|
51
|
-
praisonai-0.1.
|
|
52
|
-
praisonai-0.1.
|
|
53
|
-
praisonai-0.1.
|
|
49
|
+
praisonai-0.1.8.dist-info/LICENSE,sha256=kqvFysVlnFxYOu0HxCe2HlmZmJtdmNGOxWRRkT9TsWc,1035
|
|
50
|
+
praisonai-0.1.8.dist-info/METADATA,sha256=C2u3l914yI9enMAZLYuaaAY72fRXXwZ8e--VkGn3KdQ,13291
|
|
51
|
+
praisonai-0.1.8.dist-info/WHEEL,sha256=Ie8mbC-etDUh6aDhzdvvvp_A-4mQQX7whlOFBnSJhcE,110
|
|
52
|
+
praisonai-0.1.8.dist-info/entry_points.txt,sha256=LT8Ie95dy4JkUlpgS0YyvD4Tf9zTstjaXISJnijDxoM,172
|
|
53
|
+
praisonai-0.1.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|