PraisonAI 1.0.2__tar.gz → 1.0.3__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.
- {praisonai-1.0.2 → praisonai-1.0.3}/PKG-INFO +1 -1
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/deploy.py +1 -1
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/chat.py +261 -131
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/code.py +2 -5
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/sql_alchemy.py +28 -26
- {praisonai-1.0.2 → praisonai-1.0.3}/pyproject.toml +1 -1
- {praisonai-1.0.2 → praisonai-1.0.3}/LICENSE +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/README.md +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/__init__.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/__main__.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/agents_generator.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/api/call.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/auto.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/chainlit_ui.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/cli.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/inbuilt_tools/__init__.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/inbuilt_tools/autogen_tools.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/inc/__init__.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/inc/config.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/inc/models.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/public/android-chrome-192x192.png +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/public/android-chrome-512x512.png +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/public/apple-touch-icon.png +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/public/fantasy.svg +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/public/favicon-16x16.png +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/public/favicon-32x32.png +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/public/favicon.ico +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/public/game.svg +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/public/logo_dark.png +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/public/logo_light.png +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/public/movie.svg +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/public/thriller.svg +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/setup/__init__.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/setup/build.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/setup/config.yaml +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/setup/post_install.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/setup/setup_conda_env.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/setup/setup_conda_env.sh +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/setup.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/test.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/train.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/context.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/public/fantasy.svg +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/public/game.svg +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/public/logo_dark.png +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/public/logo_light.png +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/public/movie.svg +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/public/thriller.svg +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/realtime.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/realtimeclient/__init__.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/realtimeclient/realtimedocs.txt +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/ui/realtimeclient/tools.py +0 -0
- {praisonai-1.0.2 → praisonai-1.0.3}/praisonai/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PraisonAI
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
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
|
|
@@ -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==1.0.
|
|
59
|
+
file.write("RUN pip install flask praisonai==1.0.3 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
|
import chainlit as cl
|
|
2
2
|
from chainlit.input_widget import TextInput
|
|
3
|
-
from chainlit.types import ThreadDict
|
|
3
|
+
from chainlit.types import ThreadDict
|
|
4
4
|
from litellm import acompletion
|
|
5
5
|
import os
|
|
6
6
|
import sqlite3
|
|
@@ -9,7 +9,6 @@ from typing import Dict, List, Optional
|
|
|
9
9
|
from dotenv import load_dotenv
|
|
10
10
|
load_dotenv()
|
|
11
11
|
import chainlit.data as cl_data
|
|
12
|
-
from chainlit.step import StepDict
|
|
13
12
|
from literalai.helper import utc_now
|
|
14
13
|
import logging
|
|
15
14
|
import json
|
|
@@ -20,6 +19,8 @@ import asyncio
|
|
|
20
19
|
from PIL import Image
|
|
21
20
|
import io
|
|
22
21
|
import base64
|
|
22
|
+
from sqlalchemy import text
|
|
23
|
+
from sqlalchemy.exc import DatabaseError
|
|
23
24
|
|
|
24
25
|
# Set up logging
|
|
25
26
|
logger = logging.getLogger(__name__)
|
|
@@ -48,140 +49,226 @@ create_step_counter = 0
|
|
|
48
49
|
|
|
49
50
|
DB_PATH = os.path.expanduser("~/.praison/database.sqlite")
|
|
50
51
|
|
|
51
|
-
def
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
52
|
+
async def create_tables(engine):
|
|
53
|
+
"""Create all necessary tables if they don't exist."""
|
|
54
|
+
try:
|
|
55
|
+
async with engine.begin() as conn:
|
|
56
|
+
# Check if we're using PostgreSQL
|
|
57
|
+
dialect = engine.dialect.name
|
|
58
|
+
if dialect == 'postgresql':
|
|
59
|
+
# Create tables with PostgreSQL-specific types
|
|
60
|
+
await conn.execute(text("""
|
|
61
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
62
|
+
id UUID PRIMARY KEY,
|
|
63
|
+
identifier TEXT NOT NULL UNIQUE,
|
|
64
|
+
metadata JSONB NOT NULL,
|
|
65
|
+
createdAt TEXT
|
|
66
|
+
)
|
|
67
|
+
"""))
|
|
68
|
+
|
|
69
|
+
await conn.execute(text("""
|
|
70
|
+
CREATE TABLE IF NOT EXISTS threads (
|
|
71
|
+
id UUID PRIMARY KEY,
|
|
72
|
+
createdAt TEXT,
|
|
73
|
+
name TEXT,
|
|
74
|
+
userId UUID,
|
|
75
|
+
userIdentifier TEXT,
|
|
76
|
+
tags TEXT[],
|
|
77
|
+
metadata JSONB NOT NULL DEFAULT '{}',
|
|
78
|
+
FOREIGN KEY (userId) REFERENCES users(id) ON DELETE CASCADE
|
|
79
|
+
)
|
|
80
|
+
"""))
|
|
81
|
+
|
|
82
|
+
await conn.execute(text("""
|
|
83
|
+
CREATE TABLE IF NOT EXISTS steps (
|
|
84
|
+
id UUID PRIMARY KEY,
|
|
85
|
+
name TEXT NOT NULL,
|
|
86
|
+
type TEXT NOT NULL,
|
|
87
|
+
threadId UUID NOT NULL,
|
|
88
|
+
parentId UUID,
|
|
89
|
+
disableFeedback BOOLEAN NOT NULL DEFAULT 0,
|
|
90
|
+
streaming BOOLEAN NOT NULL DEFAULT 0,
|
|
91
|
+
waitForAnswer BOOLEAN DEFAULT 0,
|
|
92
|
+
isError BOOLEAN NOT NULL DEFAULT 0,
|
|
93
|
+
metadata JSONB DEFAULT '{}',
|
|
94
|
+
tags TEXT[],
|
|
95
|
+
input TEXT,
|
|
96
|
+
output TEXT,
|
|
97
|
+
createdAt TEXT,
|
|
98
|
+
start TEXT,
|
|
99
|
+
end TEXT,
|
|
100
|
+
generation JSONB,
|
|
101
|
+
showInput TEXT,
|
|
102
|
+
language TEXT,
|
|
103
|
+
indent INT,
|
|
104
|
+
FOREIGN KEY (threadId) REFERENCES threads (id) ON DELETE CASCADE
|
|
105
|
+
)
|
|
106
|
+
"""))
|
|
107
|
+
|
|
108
|
+
await conn.execute(text("""
|
|
109
|
+
CREATE TABLE IF NOT EXISTS elements (
|
|
110
|
+
id UUID PRIMARY KEY,
|
|
111
|
+
threadId UUID,
|
|
112
|
+
type TEXT,
|
|
113
|
+
url TEXT,
|
|
114
|
+
chainlitKey TEXT,
|
|
115
|
+
name TEXT NOT NULL,
|
|
116
|
+
display TEXT,
|
|
117
|
+
objectKey TEXT,
|
|
118
|
+
size TEXT,
|
|
119
|
+
page INT,
|
|
120
|
+
language TEXT,
|
|
121
|
+
forId UUID,
|
|
122
|
+
mime TEXT,
|
|
123
|
+
FOREIGN KEY (threadId) REFERENCES threads (id) ON DELETE CASCADE
|
|
124
|
+
)
|
|
125
|
+
"""))
|
|
126
|
+
|
|
127
|
+
await conn.execute(text("""
|
|
128
|
+
CREATE TABLE IF NOT EXISTS feedbacks (
|
|
129
|
+
id UUID PRIMARY KEY,
|
|
130
|
+
forId UUID NOT NULL,
|
|
131
|
+
value INT NOT NULL,
|
|
132
|
+
threadId UUID,
|
|
133
|
+
comment TEXT
|
|
134
|
+
)
|
|
135
|
+
"""))
|
|
136
|
+
|
|
137
|
+
await conn.execute(text("""
|
|
138
|
+
CREATE TABLE IF NOT EXISTS settings (
|
|
139
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
140
|
+
key TEXT UNIQUE,
|
|
141
|
+
value TEXT
|
|
142
|
+
)
|
|
143
|
+
"""))
|
|
144
|
+
|
|
145
|
+
# Create indexes
|
|
146
|
+
await conn.execute(text(
|
|
147
|
+
"CREATE INDEX IF NOT EXISTS idx_steps_threadId ON steps(threadId)"
|
|
148
|
+
))
|
|
149
|
+
await conn.execute(text(
|
|
150
|
+
"CREATE INDEX IF NOT EXISTS idx_threads_createdAt ON threads(createdAt DESC)"
|
|
151
|
+
))
|
|
152
|
+
else:
|
|
153
|
+
# SQLite tables (existing schema)
|
|
154
|
+
await conn.execute(text("""
|
|
155
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
156
|
+
id TEXT PRIMARY KEY,
|
|
157
|
+
identifier TEXT NOT NULL UNIQUE,
|
|
158
|
+
metadata TEXT NOT NULL,
|
|
159
|
+
createdAt TEXT
|
|
160
|
+
)
|
|
161
|
+
"""))
|
|
162
|
+
|
|
163
|
+
await conn.execute(text("""
|
|
164
|
+
CREATE TABLE IF NOT EXISTS threads (
|
|
165
|
+
id TEXT PRIMARY KEY,
|
|
166
|
+
createdAt TEXT,
|
|
167
|
+
name TEXT,
|
|
168
|
+
userId TEXT,
|
|
169
|
+
userIdentifier TEXT,
|
|
170
|
+
tags TEXT,
|
|
171
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
172
|
+
FOREIGN KEY (userId) REFERENCES users(id) ON DELETE CASCADE
|
|
173
|
+
)
|
|
174
|
+
"""))
|
|
175
|
+
|
|
176
|
+
await conn.execute(text("""
|
|
177
|
+
CREATE TABLE IF NOT EXISTS steps (
|
|
178
|
+
id TEXT PRIMARY KEY,
|
|
179
|
+
name TEXT NOT NULL,
|
|
180
|
+
type TEXT NOT NULL,
|
|
181
|
+
threadId TEXT NOT NULL,
|
|
182
|
+
parentId TEXT,
|
|
183
|
+
disableFeedback BOOLEAN NOT NULL DEFAULT 0,
|
|
184
|
+
streaming BOOLEAN NOT NULL DEFAULT 0,
|
|
185
|
+
waitForAnswer BOOLEAN DEFAULT 0,
|
|
186
|
+
isError BOOLEAN NOT NULL DEFAULT 0,
|
|
187
|
+
metadata TEXT DEFAULT '{}',
|
|
188
|
+
tags TEXT,
|
|
189
|
+
input TEXT,
|
|
190
|
+
output TEXT,
|
|
191
|
+
createdAt TEXT,
|
|
192
|
+
start TEXT,
|
|
193
|
+
end TEXT,
|
|
194
|
+
generation TEXT,
|
|
195
|
+
showInput TEXT,
|
|
196
|
+
language TEXT,
|
|
197
|
+
indent INT,
|
|
198
|
+
FOREIGN KEY (threadId) REFERENCES threads (id) ON DELETE CASCADE
|
|
199
|
+
)
|
|
200
|
+
"""))
|
|
201
|
+
|
|
202
|
+
await conn.execute(text("""
|
|
203
|
+
CREATE TABLE IF NOT EXISTS elements (
|
|
204
|
+
id TEXT PRIMARY KEY,
|
|
205
|
+
threadId TEXT,
|
|
206
|
+
type TEXT,
|
|
207
|
+
url TEXT,
|
|
208
|
+
chainlitKey TEXT,
|
|
209
|
+
name TEXT NOT NULL,
|
|
210
|
+
display TEXT,
|
|
211
|
+
objectKey TEXT,
|
|
212
|
+
size TEXT,
|
|
213
|
+
page INT,
|
|
214
|
+
language TEXT,
|
|
215
|
+
forId TEXT,
|
|
216
|
+
mime TEXT,
|
|
217
|
+
FOREIGN KEY (threadId) REFERENCES threads (id) ON DELETE CASCADE
|
|
218
|
+
)
|
|
219
|
+
"""))
|
|
220
|
+
|
|
221
|
+
await conn.execute(text("""
|
|
222
|
+
CREATE TABLE IF NOT EXISTS feedbacks (
|
|
223
|
+
id TEXT PRIMARY KEY,
|
|
224
|
+
forId TEXT NOT NULL,
|
|
225
|
+
value INT NOT NULL,
|
|
226
|
+
threadId TEXT,
|
|
227
|
+
comment TEXT
|
|
228
|
+
)
|
|
229
|
+
"""))
|
|
230
|
+
|
|
231
|
+
await conn.execute(text("""
|
|
232
|
+
CREATE TABLE IF NOT EXISTS settings (
|
|
233
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
234
|
+
key TEXT UNIQUE,
|
|
235
|
+
value TEXT
|
|
236
|
+
)
|
|
237
|
+
"""))
|
|
238
|
+
|
|
239
|
+
# Create indexes
|
|
240
|
+
await conn.execute(text(
|
|
241
|
+
"CREATE INDEX IF NOT EXISTS idx_steps_threadId ON steps(threadId)"
|
|
242
|
+
))
|
|
243
|
+
await conn.execute(text(
|
|
244
|
+
"CREATE INDEX IF NOT EXISTS idx_threads_createdAt ON threads(createdAt DESC)"
|
|
245
|
+
))
|
|
246
|
+
|
|
247
|
+
logger.info(f"Successfully created tables for {dialect} database")
|
|
248
|
+
except Exception as e:
|
|
249
|
+
logger.error(f"Error creating tables: {str(e)}")
|
|
250
|
+
raise DatabaseError(f"Failed to create database tables: {str(e)}")
|
|
172
251
|
|
|
173
252
|
# Initialize the database
|
|
174
|
-
initialize_db()
|
|
175
|
-
|
|
176
|
-
deleted_thread_ids = [] # type: List[str]
|
|
253
|
+
async def initialize_db():
|
|
254
|
+
await create_tables(cl_data._data_layer.engine)
|
|
177
255
|
|
|
178
256
|
# Get database connection string from environment variable or use SQLite as default
|
|
179
257
|
DB_URL = os.getenv("DATABASE_URL", f"sqlite+aiosqlite:///{DB_PATH}")
|
|
258
|
+
if DB_URL.startswith('postgresql'):
|
|
259
|
+
# Convert postgresql:// to postgresql+psycopg:// if needed
|
|
260
|
+
DB_URL = DB_URL.replace('postgresql://', 'postgresql+psycopg://')
|
|
261
|
+
|
|
262
|
+
# Initialize SQLAlchemy data layer
|
|
180
263
|
cl_data._data_layer = SQLAlchemyDataLayer(
|
|
181
264
|
conninfo=DB_URL,
|
|
182
265
|
ssl_require=bool(os.getenv("DATABASE_SSL", False))
|
|
183
266
|
)
|
|
184
267
|
|
|
268
|
+
# Create tables if using PostgreSQL
|
|
269
|
+
if DB_URL.startswith('postgresql'):
|
|
270
|
+
asyncio.run(initialize_db())
|
|
271
|
+
|
|
185
272
|
# Set Tavily API key
|
|
186
273
|
tavily_api_key = os.getenv("TAVILY_API_KEY")
|
|
187
274
|
tavily_client = TavilyClient(api_key=tavily_api_key) if tavily_api_key else None
|
|
@@ -241,10 +328,53 @@ tools = [{
|
|
|
241
328
|
}
|
|
242
329
|
}] if tavily_api_key else []
|
|
243
330
|
|
|
331
|
+
async def save_setting(key: str, value: str):
|
|
332
|
+
"""Saves a setting to the database.
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
key: The setting key.
|
|
336
|
+
value: The setting value.
|
|
337
|
+
"""
|
|
338
|
+
try:
|
|
339
|
+
async with cl_data._data_layer.engine.begin() as conn:
|
|
340
|
+
await conn.execute(
|
|
341
|
+
text("""
|
|
342
|
+
INSERT INTO settings (key, value)
|
|
343
|
+
VALUES (:key, :value)
|
|
344
|
+
ON CONFLICT (key) DO UPDATE SET value = :value
|
|
345
|
+
"""),
|
|
346
|
+
{"key": key, "value": value}
|
|
347
|
+
)
|
|
348
|
+
logger.debug(f"Saved setting {key}={value}")
|
|
349
|
+
except Exception as e:
|
|
350
|
+
logger.error(f"Error saving setting {key}: {str(e)}")
|
|
351
|
+
raise DatabaseError(f"Failed to save setting: {str(e)}")
|
|
352
|
+
|
|
353
|
+
async def load_setting(key: str) -> str:
|
|
354
|
+
"""Loads a setting from the database.
|
|
355
|
+
|
|
356
|
+
Args:
|
|
357
|
+
key: The setting key.
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
The setting value, or None if the key is not found.
|
|
361
|
+
"""
|
|
362
|
+
try:
|
|
363
|
+
async with cl_data._data_layer.engine.connect() as conn:
|
|
364
|
+
result = await conn.execute(
|
|
365
|
+
text("SELECT value FROM settings WHERE key = :key"),
|
|
366
|
+
{"key": key}
|
|
367
|
+
)
|
|
368
|
+
row = result.fetchone()
|
|
369
|
+
return row[0] if row else None
|
|
370
|
+
except Exception as e:
|
|
371
|
+
logger.error(f"Error loading setting {key}: {str(e)}")
|
|
372
|
+
return None
|
|
373
|
+
|
|
244
374
|
@cl.on_chat_start
|
|
245
375
|
async def start():
|
|
246
|
-
initialize_db()
|
|
247
|
-
model_name = load_setting("model_name")
|
|
376
|
+
await initialize_db()
|
|
377
|
+
model_name = await load_setting("model_name")
|
|
248
378
|
|
|
249
379
|
if model_name:
|
|
250
380
|
cl.user_session.set("model_name", model_name)
|
|
@@ -274,7 +404,7 @@ async def setup_agent(settings):
|
|
|
274
404
|
cl.user_session.set("model_name", model_name)
|
|
275
405
|
|
|
276
406
|
# Save in settings table
|
|
277
|
-
save_setting("model_name", model_name)
|
|
407
|
+
await save_setting("model_name", model_name)
|
|
278
408
|
|
|
279
409
|
# Save in thread metadata
|
|
280
410
|
thread_id = cl.user_session.get("thread_id")
|
|
@@ -292,7 +422,7 @@ async def setup_agent(settings):
|
|
|
292
422
|
|
|
293
423
|
@cl.on_message
|
|
294
424
|
async def main(message: cl.Message):
|
|
295
|
-
model_name = load_setting("model_name") or os.getenv("MODEL_NAME") or "gpt-4o-mini"
|
|
425
|
+
model_name = await load_setting("model_name") or os.getenv("MODEL_NAME") or "gpt-4o-mini"
|
|
296
426
|
message_history = cl.user_session.get("message_history", [])
|
|
297
427
|
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
298
428
|
|
|
@@ -474,7 +604,7 @@ async def send_count():
|
|
|
474
604
|
@cl.on_chat_resume
|
|
475
605
|
async def on_chat_resume(thread: ThreadDict):
|
|
476
606
|
logger.info(f"Resuming chat: {thread['id']}")
|
|
477
|
-
model_name = load_setting("model_name") or os.getenv("MODEL_NAME") or "gpt-4o-mini"
|
|
607
|
+
model_name = await load_setting("model_name") or os.getenv("MODEL_NAME") or "gpt-4o-mini"
|
|
478
608
|
logger.debug(f"Model name: {model_name}")
|
|
479
609
|
settings = cl.ChatSettings(
|
|
480
610
|
[
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import chainlit as cl
|
|
2
2
|
from chainlit.input_widget import TextInput
|
|
3
|
-
from chainlit.types import ThreadDict
|
|
4
|
-
from litellm import acompletion, completion
|
|
3
|
+
from chainlit.types import ThreadDict, StepDict
|
|
5
4
|
import os
|
|
6
5
|
import sqlite3
|
|
7
6
|
from datetime import datetime
|
|
@@ -9,8 +8,6 @@ from typing import Dict, List, Optional
|
|
|
9
8
|
from dotenv import load_dotenv
|
|
10
9
|
load_dotenv()
|
|
11
10
|
import chainlit.data as cl_data
|
|
12
|
-
from chainlit.step import StepDict
|
|
13
|
-
from literalai.helper import utc_now
|
|
14
11
|
import logging
|
|
15
12
|
import json
|
|
16
13
|
from sql_alchemy import SQLAlchemyDataLayer
|
|
@@ -43,7 +40,7 @@ if not CHAINLIT_AUTH_SECRET:
|
|
|
43
40
|
os.environ["CHAINLIT_AUTH_SECRET"] = "p8BPhQChpg@J>jBz$wGxqLX2V>yTVgP*7Ky9H$aV:axW~ANNX-7_T:o@lnyCBu^U"
|
|
44
41
|
CHAINLIT_AUTH_SECRET = os.getenv("CHAINLIT_AUTH_SECRET")
|
|
45
42
|
|
|
46
|
-
now =
|
|
43
|
+
now = datetime.now()
|
|
47
44
|
|
|
48
45
|
create_step_counter = 0
|
|
49
46
|
|
|
@@ -12,6 +12,7 @@ from chainlit.data.base import BaseDataLayer, BaseStorageClient
|
|
|
12
12
|
from chainlit.data.utils import queue_until_user_message
|
|
13
13
|
from chainlit.element import ElementDict
|
|
14
14
|
from chainlit.logger import logger
|
|
15
|
+
from chainlit.message import Message
|
|
15
16
|
from chainlit.step import StepDict
|
|
16
17
|
from chainlit.types import (
|
|
17
18
|
Feedback,
|
|
@@ -204,9 +205,10 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
204
205
|
async def get_thread(self, thread_id: str) -> Optional[ThreadDict]:
|
|
205
206
|
if self.show_logger:
|
|
206
207
|
logger.info(f"SQLAlchemy: get_thread, thread_id={thread_id}")
|
|
207
|
-
user_threads: Optional[List[ThreadDict]] =
|
|
208
|
-
thread_id=thread_id
|
|
208
|
+
user_threads: Optional[List[ThreadDict]] = (
|
|
209
|
+
await self.get_all_user_threads(thread_id=thread_id) or []
|
|
209
210
|
)
|
|
211
|
+
|
|
210
212
|
if user_threads:
|
|
211
213
|
return user_threads[0]
|
|
212
214
|
else:
|
|
@@ -335,7 +337,7 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
335
337
|
|
|
336
338
|
###### Steps ######
|
|
337
339
|
@queue_until_user_message()
|
|
338
|
-
async def create_step(self, step_dict:
|
|
340
|
+
async def create_step(self, step_dict: dict):
|
|
339
341
|
if self.show_logger:
|
|
340
342
|
logger.info(f"SQLAlchemy: create_step, step_id={step_dict.get('id')}")
|
|
341
343
|
|
|
@@ -365,7 +367,7 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
365
367
|
await self.execute_sql(query=query, parameters=parameters)
|
|
366
368
|
|
|
367
369
|
@queue_until_user_message()
|
|
368
|
-
async def update_step(self, step_dict:
|
|
370
|
+
async def update_step(self, step_dict: dict):
|
|
369
371
|
if self.show_logger:
|
|
370
372
|
logger.info(f"SQLAlchemy: update_step, step_id={step_dict.get('id')}")
|
|
371
373
|
await self.create_step(step_dict)
|
|
@@ -646,37 +648,37 @@ class SQLAlchemyDataLayer(BaseDataLayer):
|
|
|
646
648
|
value=step_feedback["feedback_value"],
|
|
647
649
|
comment=step_feedback.get("feedback_comment"),
|
|
648
650
|
)
|
|
649
|
-
step_dict =
|
|
650
|
-
id
|
|
651
|
-
name
|
|
652
|
-
type
|
|
653
|
-
threadId
|
|
654
|
-
parentId
|
|
655
|
-
streaming
|
|
656
|
-
waitForAnswer
|
|
657
|
-
isError
|
|
658
|
-
metadata
|
|
651
|
+
step_dict = {
|
|
652
|
+
"id": step_feedback["step_id"],
|
|
653
|
+
"name": step_feedback["step_name"],
|
|
654
|
+
"type": step_feedback["step_type"],
|
|
655
|
+
"threadId": thread_id,
|
|
656
|
+
"parentId": step_feedback.get("step_parentid"),
|
|
657
|
+
"streaming": step_feedback.get("step_streaming", False),
|
|
658
|
+
"waitForAnswer": step_feedback.get("step_waitforanswer"),
|
|
659
|
+
"isError": step_feedback.get("step_iserror"),
|
|
660
|
+
"metadata": (
|
|
659
661
|
step_feedback["step_metadata"]
|
|
660
662
|
if step_feedback.get("step_metadata") is not None
|
|
661
663
|
else {}
|
|
662
664
|
),
|
|
663
|
-
tags
|
|
664
|
-
input
|
|
665
|
+
"tags": step_feedback.get("step_tags"),
|
|
666
|
+
"input": (
|
|
665
667
|
step_feedback.get("step_input", "")
|
|
666
668
|
if step_feedback.get("step_showinput")
|
|
667
669
|
not in [None, "false"]
|
|
668
670
|
else ""
|
|
669
671
|
),
|
|
670
|
-
output
|
|
671
|
-
createdAt
|
|
672
|
-
start
|
|
673
|
-
end
|
|
674
|
-
generation
|
|
675
|
-
showInput
|
|
676
|
-
language
|
|
677
|
-
indent
|
|
678
|
-
feedback
|
|
679
|
-
|
|
672
|
+
"output": step_feedback.get("step_output", ""),
|
|
673
|
+
"createdAt": step_feedback.get("step_createdat"),
|
|
674
|
+
"start": step_feedback.get("step_start"),
|
|
675
|
+
"end": step_feedback.get("step_end"),
|
|
676
|
+
"generation": step_feedback.get("step_generation"),
|
|
677
|
+
"showInput": step_feedback.get("step_showinput"),
|
|
678
|
+
"language": step_feedback.get("step_language"),
|
|
679
|
+
"indent": step_feedback.get("step_indent"),
|
|
680
|
+
"feedback": feedback,
|
|
681
|
+
}
|
|
680
682
|
# Append the step to the steps list of the corresponding ThreadDict
|
|
681
683
|
thread_dicts[thread_id]["steps"].append(step_dict)
|
|
682
684
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "PraisonAI"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.3"
|
|
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 = ""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|