PraisonAI 0.0.65__cp312-cp312-manylinux_2_35_x86_64.whl → 0.0.67__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.
Potentially problematic release.
This version of PraisonAI might be problematic. Click here for more details.
- praisonai/cli.py +1 -0
- praisonai/deploy.py +1 -1
- praisonai/setup/__init__.py +1 -0
- praisonai/ui/sql_alchemy.py +101 -43
- {praisonai-0.0.65.dist-info → praisonai-0.0.67.dist-info}/METADATA +1 -1
- {praisonai-0.0.65.dist-info → praisonai-0.0.67.dist-info}/RECORD +9 -9
- praisonai/setup/__init__.py +0 -0
- {praisonai-0.0.65.dist-info → praisonai-0.0.67.dist-info}/LICENSE +0 -0
- {praisonai-0.0.65.dist-info → praisonai-0.0.67.dist-info}/WHEEL +0 -0
- {praisonai-0.0.65.dist-info → praisonai-0.0.67.dist-info}/entry_points.txt +0 -0
praisonai/cli.py
CHANGED
|
@@ -19,6 +19,7 @@ import logging
|
|
|
19
19
|
logging.basicConfig(level=os.environ.get('LOGLEVEL', 'INFO'), format='%(asctime)s - %(levelname)s - %(message)s')
|
|
20
20
|
|
|
21
21
|
try:
|
|
22
|
+
os.environ["CHAINLIT_APP_ROOT"] = os.path.join(os.path.expanduser("~"), ".praison")
|
|
22
23
|
from chainlit.cli import chainlit_run
|
|
23
24
|
CHAINLIT_AVAILABLE = True
|
|
24
25
|
except ImportError:
|
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.0.
|
|
59
|
+
file.write("RUN pip install flask praisonai==0.0.67 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
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
praisonai/ui/sql_alchemy.py
CHANGED
|
@@ -7,8 +7,9 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
|
|
|
7
7
|
|
|
8
8
|
import aiofiles
|
|
9
9
|
import aiohttp
|
|
10
|
-
|
|
11
|
-
from chainlit.data import BaseDataLayer, BaseStorageClient
|
|
10
|
+
|
|
11
|
+
from chainlit.data.base import BaseDataLayer, BaseStorageClient
|
|
12
|
+
from chainlit.data.utils import queue_until_user_message
|
|
12
13
|
from chainlit.element import ElementDict
|
|
13
14
|
from chainlit.logger import logger
|
|
14
15
|
from chainlit.step import StepDict
|
|
@@ -26,9 +27,6 @@ from sqlalchemy import text
|
|
|
26
27
|
from sqlalchemy.exc import SQLAlchemyError
|
|
27
28
|
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, create_async_engine
|
|
28
29
|
from sqlalchemy.orm import sessionmaker
|
|
29
|
-
import chainlit as cl
|
|
30
|
-
from literalai.helper import utc_now
|
|
31
|
-
now = utc_now()
|
|
32
30
|
|
|
33
31
|
if TYPE_CHECKING:
|
|
34
32
|
from chainlit.element import Element, ElementDict
|
|
@@ -57,7 +55,9 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
57
55
|
self.engine: AsyncEngine = create_async_engine(
|
|
58
56
|
self._conninfo, connect_args=ssl_args
|
|
59
57
|
)
|
|
60
|
-
self.async_session = sessionmaker(
|
|
58
|
+
self.async_session = sessionmaker(
|
|
59
|
+
bind=self.engine, expire_on_commit=False, class_=AsyncSession
|
|
60
|
+
) # type: ignore
|
|
61
61
|
if storage_provider:
|
|
62
62
|
self.storage_provider: Optional[BaseStorageClient] = storage_provider
|
|
63
63
|
if self.show_logger:
|
|
@@ -84,6 +84,9 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
84
84
|
if result.returns_rows:
|
|
85
85
|
json_result = [dict(row._mapping) for row in result.fetchall()]
|
|
86
86
|
clean_json_result = self.clean_result(json_result)
|
|
87
|
+
assert isinstance(clean_json_result, list) or isinstance(
|
|
88
|
+
clean_json_result, int
|
|
89
|
+
)
|
|
87
90
|
return clean_json_result
|
|
88
91
|
else:
|
|
89
92
|
return result.rowcount
|
|
@@ -111,8 +114,6 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
111
114
|
|
|
112
115
|
###### User ######
|
|
113
116
|
async def get_user(self, identifier: str) -> Optional[PersistedUser]:
|
|
114
|
-
logger.debug(f"Getting user: {identifier}")
|
|
115
|
-
return cl.PersistedUser(id="test", createdAt=now, identifier=identifier)
|
|
116
117
|
if self.show_logger:
|
|
117
118
|
logger.info(f"SQLAlchemy: get_user, identifier={identifier}")
|
|
118
119
|
query = "SELECT * FROM users WHERE identifier = :identifier"
|
|
@@ -120,12 +121,50 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
120
121
|
result = await self.execute_sql(query=query, parameters=parameters)
|
|
121
122
|
if result and isinstance(result, list):
|
|
122
123
|
user_data = result[0]
|
|
123
|
-
|
|
124
|
+
|
|
125
|
+
# SQLite returns JSON as string, we most convert it. (#1137)
|
|
126
|
+
metadata = user_data.get("metadata", {})
|
|
127
|
+
if isinstance(metadata, str):
|
|
128
|
+
metadata = json.loads(metadata)
|
|
129
|
+
|
|
130
|
+
assert isinstance(metadata, dict)
|
|
131
|
+
assert isinstance(user_data["id"], str)
|
|
132
|
+
assert isinstance(user_data["identifier"], str)
|
|
133
|
+
assert isinstance(user_data["createdAt"], str)
|
|
134
|
+
|
|
135
|
+
return PersistedUser(
|
|
136
|
+
id=user_data["id"],
|
|
137
|
+
identifier=user_data["identifier"],
|
|
138
|
+
createdAt=user_data["createdAt"],
|
|
139
|
+
metadata=metadata,
|
|
140
|
+
)
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
async def _get_user_identifer_by_id(self, user_id: str) -> str:
|
|
144
|
+
if self.show_logger:
|
|
145
|
+
logger.info(f"SQLAlchemy: _get_user_identifer_by_id, user_id={user_id}")
|
|
146
|
+
query = "SELECT identifier FROM users WHERE id = :user_id"
|
|
147
|
+
parameters = {"user_id": user_id}
|
|
148
|
+
result = await self.execute_sql(query=query, parameters=parameters)
|
|
149
|
+
|
|
150
|
+
assert result
|
|
151
|
+
assert isinstance(result, list)
|
|
152
|
+
|
|
153
|
+
return result[0]["identifier"]
|
|
154
|
+
|
|
155
|
+
async def _get_user_id_by_thread(self, thread_id: str) -> Optional[str]:
|
|
156
|
+
if self.show_logger:
|
|
157
|
+
logger.info(f"SQLAlchemy: _get_user_id_by_thread, thread_id={thread_id}")
|
|
158
|
+
query = "SELECT userId FROM threads WHERE id = :thread_id"
|
|
159
|
+
parameters = {"thread_id": thread_id}
|
|
160
|
+
result = await self.execute_sql(query=query, parameters=parameters)
|
|
161
|
+
if result:
|
|
162
|
+
assert isinstance(result, list)
|
|
163
|
+
return result[0]["userId"]
|
|
164
|
+
|
|
124
165
|
return None
|
|
125
166
|
|
|
126
167
|
async def create_user(self, user: User) -> Optional[PersistedUser]:
|
|
127
|
-
logger.debug(f"Creating user: {user.identifier}")
|
|
128
|
-
return cl.PersistedUser(id="test", createdAt=now, identifier=user.identifier)
|
|
129
168
|
if self.show_logger:
|
|
130
169
|
logger.info(f"SQLAlchemy: create_user, user_identifier={user.identifier}")
|
|
131
170
|
existing_user: Optional["PersistedUser"] = await self.get_user(user.identifier)
|
|
@@ -151,8 +190,6 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
151
190
|
|
|
152
191
|
###### Threads ######
|
|
153
192
|
async def get_thread_author(self, thread_id: str) -> str:
|
|
154
|
-
logger.debug(f"Getting thread author: {thread_id}")
|
|
155
|
-
return "admin"
|
|
156
193
|
if self.show_logger:
|
|
157
194
|
logger.info(f"SQLAlchemy: get_thread_author, thread_id={thread_id}")
|
|
158
195
|
query = """SELECT "userIdentifier" FROM threads WHERE "id" = :id"""
|
|
@@ -171,16 +208,7 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
171
208
|
thread_id=thread_id
|
|
172
209
|
)
|
|
173
210
|
if user_threads:
|
|
174
|
-
|
|
175
|
-
# Parse the metadata here
|
|
176
|
-
if isinstance(thread['metadata'], str):
|
|
177
|
-
try:
|
|
178
|
-
thread['metadata'] = json.loads(thread['metadata'])
|
|
179
|
-
except json.JSONDecodeError:
|
|
180
|
-
thread['metadata'] = {}
|
|
181
|
-
elif thread['metadata'] is None:
|
|
182
|
-
thread['metadata'] = {}
|
|
183
|
-
return thread
|
|
211
|
+
return user_threads[0]
|
|
184
212
|
else:
|
|
185
213
|
return None
|
|
186
214
|
|
|
@@ -194,10 +222,11 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
194
222
|
):
|
|
195
223
|
if self.show_logger:
|
|
196
224
|
logger.info(f"SQLAlchemy: update_thread, thread_id={thread_id}")
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
225
|
+
|
|
226
|
+
user_identifier = None
|
|
227
|
+
if user_id:
|
|
228
|
+
user_identifier = await self._get_user_identifer_by_id(user_id)
|
|
229
|
+
|
|
201
230
|
data = {
|
|
202
231
|
"id": thread_id,
|
|
203
232
|
"createdAt": (
|
|
@@ -309,8 +338,7 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
309
338
|
async def create_step(self, step_dict: "StepDict"):
|
|
310
339
|
if self.show_logger:
|
|
311
340
|
logger.info(f"SQLAlchemy: create_step, step_id={step_dict.get('id')}")
|
|
312
|
-
|
|
313
|
-
raise ValueError("No authenticated user in context")
|
|
341
|
+
|
|
314
342
|
step_dict["showInput"] = (
|
|
315
343
|
str(step_dict.get("showInput", "")).lower()
|
|
316
344
|
if "showInput" in step_dict
|
|
@@ -388,15 +416,48 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
388
416
|
return True
|
|
389
417
|
|
|
390
418
|
###### Elements ######
|
|
419
|
+
async def get_element(
|
|
420
|
+
self, thread_id: str, element_id: str
|
|
421
|
+
) -> Optional["ElementDict"]:
|
|
422
|
+
if self.show_logger:
|
|
423
|
+
logger.info(
|
|
424
|
+
f"SQLAlchemy: get_element, thread_id={thread_id}, element_id={element_id}"
|
|
425
|
+
)
|
|
426
|
+
query = """SELECT * FROM elements WHERE "threadId" = :thread_id AND "id" = :element_id"""
|
|
427
|
+
parameters = {"thread_id": thread_id, "element_id": element_id}
|
|
428
|
+
element: Union[List[Dict[str, Any]], int, None] = await self.execute_sql(
|
|
429
|
+
query=query, parameters=parameters
|
|
430
|
+
)
|
|
431
|
+
if isinstance(element, list) and element:
|
|
432
|
+
element_dict: Dict[str, Any] = element[0]
|
|
433
|
+
return ElementDict(
|
|
434
|
+
id=element_dict["id"],
|
|
435
|
+
threadId=element_dict.get("threadId"),
|
|
436
|
+
type=element_dict["type"],
|
|
437
|
+
chainlitKey=element_dict.get("chainlitKey"),
|
|
438
|
+
url=element_dict.get("url"),
|
|
439
|
+
objectKey=element_dict.get("objectKey"),
|
|
440
|
+
name=element_dict["name"],
|
|
441
|
+
display=element_dict["display"],
|
|
442
|
+
size=element_dict.get("size"),
|
|
443
|
+
language=element_dict.get("language"),
|
|
444
|
+
page=element_dict.get("page"),
|
|
445
|
+
autoPlay=element_dict.get("autoPlay"),
|
|
446
|
+
playerConfig=element_dict.get("playerConfig"),
|
|
447
|
+
forId=element_dict.get("forId"),
|
|
448
|
+
mime=element_dict.get("mime"),
|
|
449
|
+
)
|
|
450
|
+
else:
|
|
451
|
+
return None
|
|
452
|
+
|
|
391
453
|
@queue_until_user_message()
|
|
392
454
|
async def create_element(self, element: "Element"):
|
|
393
455
|
if self.show_logger:
|
|
394
456
|
logger.info(f"SQLAlchemy: create_element, element_id = {element.id}")
|
|
395
|
-
|
|
396
|
-
raise ValueError("No authenticated user in context")
|
|
457
|
+
|
|
397
458
|
if not self.storage_provider:
|
|
398
459
|
logger.warn(
|
|
399
|
-
|
|
460
|
+
"SQLAlchemy: create_element error. No blob_storage_client is configured!"
|
|
400
461
|
)
|
|
401
462
|
return
|
|
402
463
|
if not element.for_id:
|
|
@@ -421,10 +482,8 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
421
482
|
if content is None:
|
|
422
483
|
raise ValueError("Content is None, cannot upload file")
|
|
423
484
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
user_folder = getattr(context_user, "id", "unknown")
|
|
427
|
-
file_object_key = f"{user_folder}/{element.id}" + (
|
|
485
|
+
user_id: str = await self._get_user_id_by_thread(element.thread_id) or "unknown"
|
|
486
|
+
file_object_key = f"{user_id}/{element.id}" + (
|
|
428
487
|
f"/{element.name}" if element.name else ""
|
|
429
488
|
)
|
|
430
489
|
|
|
@@ -458,15 +517,12 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
458
517
|
parameters = {"id": element_id}
|
|
459
518
|
await self.execute_sql(query=query, parameters=parameters)
|
|
460
519
|
|
|
461
|
-
async def delete_user_session(self, id: str) -> bool:
|
|
462
|
-
return False # Not sure why documentation wants this
|
|
463
|
-
|
|
464
520
|
async def get_all_user_threads(
|
|
465
521
|
self, user_id: Optional[str] = None, thread_id: Optional[str] = None
|
|
466
522
|
) -> Optional[List[ThreadDict]]:
|
|
467
523
|
"""Fetch all user threads up to self.user_thread_limit, or one thread by id if thread_id is provided."""
|
|
468
524
|
if self.show_logger:
|
|
469
|
-
logger.info(
|
|
525
|
+
logger.info("SQLAlchemy: get_all_user_threads")
|
|
470
526
|
user_threads_query = """
|
|
471
527
|
SELECT
|
|
472
528
|
"id" AS thread_id,
|
|
@@ -522,7 +578,8 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
522
578
|
s."language" AS step_language,
|
|
523
579
|
s."indent" AS step_indent,
|
|
524
580
|
f."value" AS feedback_value,
|
|
525
|
-
f."comment" AS feedback_comment
|
|
581
|
+
f."comment" AS feedback_comment,
|
|
582
|
+
f."id" AS feedback_id
|
|
526
583
|
FROM steps s LEFT JOIN feedbacks f ON s."id" = f."forId"
|
|
527
584
|
WHERE s."threadId" IN {thread_ids}
|
|
528
585
|
ORDER BY s."createdAt" ASC
|
|
@@ -596,8 +653,9 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
596
653
|
tags=step_feedback.get("step_tags"),
|
|
597
654
|
input=(
|
|
598
655
|
step_feedback.get("step_input", "")
|
|
599
|
-
if step_feedback
|
|
600
|
-
|
|
656
|
+
if step_feedback.get("step_showinput")
|
|
657
|
+
not in [None, "false"]
|
|
658
|
+
else ""
|
|
601
659
|
),
|
|
602
660
|
output=step_feedback.get("step_output", ""),
|
|
603
661
|
createdAt=step_feedback.get("step_createdat"),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PraisonAI
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.67
|
|
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
|
|
@@ -3,8 +3,8 @@ praisonai/__main__.py,sha256=MVgsjMThjBexHt4nhd760JCqvP4x0IQcwo8kULOK4FQ,144
|
|
|
3
3
|
praisonai/agents_generator.py,sha256=8d1WRbubvEkBrW1HZ7_xnGyqgJi0yxmXa3MgTIqef1c,19127
|
|
4
4
|
praisonai/auto.py,sha256=9spTXqj47Hmmqv5QHRYE_RzSVHH_KoPbaZjskUj2UcE,7895
|
|
5
5
|
praisonai/chainlit_ui.py,sha256=bNR7s509lp0I9JlJNvwCZRUZosC64qdvlFCt8NmFamQ,12216
|
|
6
|
-
praisonai/cli.py,sha256=
|
|
7
|
-
praisonai/deploy.py,sha256=
|
|
6
|
+
praisonai/cli.py,sha256=M23MbUUzNS7z9ZHz3cGawUrGWzXM-FzhMyiRWQPZSEk,18485
|
|
7
|
+
praisonai/deploy.py,sha256=Beog_GZSCcqXcx9FiWDGu6B1fQj4BrwikG8VtBzlDVg,6028
|
|
8
8
|
praisonai/inbuilt_tools/__init__.py,sha256=mUKnbL6Gram9c9f2m8wJwEzURBLmPEOcHzwySBH89YA,74
|
|
9
9
|
praisonai/inbuilt_tools/autogen_tools.py,sha256=svYkM2N7DVFvbiwgoAS7U_MqTOD8rHf8VD3BaFUV5_Y,14907
|
|
10
10
|
praisonai/inc/__init__.py,sha256=sPDlYBBwdk0VlWzaaM_lG0_LD07lS2HRGvPdxXJFiYg,62
|
|
@@ -22,7 +22,7 @@ praisonai/public/logo_dark.png,sha256=frHz1zkrnivGssJgk9iy1cabojkVgm8B4MllFwL_Cn
|
|
|
22
22
|
praisonai/public/logo_light.png,sha256=8cQRti_Ysa30O3_7C3ku2w40LnVUUlUok47H-3ZZHSU,19656
|
|
23
23
|
praisonai/public/movie.svg,sha256=aJ2EQ8vXZusVsF2SeuAVxP4RFJzQ14T26ejrGYdBgzk,1289
|
|
24
24
|
praisonai/public/thriller.svg,sha256=2dYY72EcgbEyTxS4QzjAm37Y4srtPWEW4vCMFki98ZI,3163
|
|
25
|
-
praisonai/setup/__init__.py
|
|
25
|
+
praisonai/setup/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
26
26
|
praisonai/setup/build.py,sha256=NyTAXQ_UZ8vKo_KwCINp8ctmauZyCMDkw1rys3ay0ec,646
|
|
27
27
|
praisonai/setup/config.yaml,sha256=sr_D1RIvv3LQ_eueOMZV0rAUiWTR-n2xuE1RhKK6b34,1211
|
|
28
28
|
praisonai/setup/post_install.py,sha256=hXukn_7bL64vE582SZcS-9MiZGeJj6hN7upoR1oJ-Bo,576
|
|
@@ -39,10 +39,10 @@ praisonai/ui/public/logo_dark.png,sha256=frHz1zkrnivGssJgk9iy1cabojkVgm8B4MllFwL
|
|
|
39
39
|
praisonai/ui/public/logo_light.png,sha256=8cQRti_Ysa30O3_7C3ku2w40LnVUUlUok47H-3ZZHSU,19656
|
|
40
40
|
praisonai/ui/public/movie.svg,sha256=aJ2EQ8vXZusVsF2SeuAVxP4RFJzQ14T26ejrGYdBgzk,1289
|
|
41
41
|
praisonai/ui/public/thriller.svg,sha256=2dYY72EcgbEyTxS4QzjAm37Y4srtPWEW4vCMFki98ZI,3163
|
|
42
|
-
praisonai/ui/sql_alchemy.py,sha256=
|
|
42
|
+
praisonai/ui/sql_alchemy.py,sha256=CABakQ2WVZbZcUnfRv_9THAcMz4Mp9BIukw8ZN4kMXk,29510
|
|
43
43
|
praisonai/version.py,sha256=ugyuFliEqtAwQmH4sTlc16YXKYbFWDmfyk87fErB8-8,21
|
|
44
|
-
praisonai-0.0.
|
|
45
|
-
praisonai-0.0.
|
|
46
|
-
praisonai-0.0.
|
|
47
|
-
praisonai-0.0.
|
|
48
|
-
praisonai-0.0.
|
|
44
|
+
praisonai-0.0.67.dist-info/LICENSE,sha256=kqvFysVlnFxYOu0HxCe2HlmZmJtdmNGOxWRRkT9TsWc,1035
|
|
45
|
+
praisonai-0.0.67.dist-info/METADATA,sha256=PG74-RzN4xLiLVnxRQJT8qp37HXPCk66_cvtXTB4Cp8,11406
|
|
46
|
+
praisonai-0.0.67.dist-info/WHEEL,sha256=HBsDV7Hj4OTiS1GX6ua7iQXUQTB9UHftbBxr7Q8Xm9c,110
|
|
47
|
+
praisonai-0.0.67.dist-info/entry_points.txt,sha256=jB078LEGLY3Ky_indhclomRIVVpXrPSksHjJ-tcBZ-o,133
|
|
48
|
+
praisonai-0.0.67.dist-info/RECORD,,
|
praisonai/setup/__init__.py
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|