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.
@@ -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[tool] for tool in details.get('tools', []) if tool in 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("O.K. you can start talking!")
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 send_to_twilio: {e}")
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
- import praisonai.api.call as call_module
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.6 gunicorn markdown\n")
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.6
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=8d1WRbubvEkBrW1HZ7_xnGyqgJi0yxmXa3MgTIqef1c,19127
4
- praisonai/api/call.py,sha256=6yVJqczuCnVYk3EIKsPzLYjSLC79IwD5o57mpGz9dxo,7277
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=BlVEsQW45pbYoqAtm-EiNpoHt8BFKX5frsbJ9s-tko0,20667
8
- praisonai/deploy.py,sha256=tXQBqMtNxOYuTKBeUkhz6UTAfJMhYJ1CBtw5W8Jc-pM,6027
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.6.dist-info/LICENSE,sha256=kqvFysVlnFxYOu0HxCe2HlmZmJtdmNGOxWRRkT9TsWc,1035
50
- praisonai-0.1.6.dist-info/METADATA,sha256=8_nLIQ4kHTff3Kmb3RMWJdf3bkKDw7sOWifoC5jVF2I,13291
51
- praisonai-0.1.6.dist-info/WHEEL,sha256=Ie8mbC-etDUh6aDhzdvvvp_A-4mQQX7whlOFBnSJhcE,110
52
- praisonai-0.1.6.dist-info/entry_points.txt,sha256=LT8Ie95dy4JkUlpgS0YyvD4Tf9zTstjaXISJnijDxoM,172
53
- praisonai-0.1.6.dist-info/RECORD,,
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,,