PraisonAI 0.0.59__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.

Files changed (48) hide show
  1. praisonai/__init__.py +6 -0
  2. praisonai/__main__.py +10 -0
  3. praisonai/agents_generator.py +381 -0
  4. praisonai/auto.py +190 -0
  5. praisonai/chainlit_ui.py +304 -0
  6. praisonai/cli.py +416 -0
  7. praisonai/deploy.py +138 -0
  8. praisonai/inbuilt_tools/__init__.py +2 -0
  9. praisonai/inbuilt_tools/autogen_tools.py +209 -0
  10. praisonai/inc/__init__.py +2 -0
  11. praisonai/inc/config.py +96 -0
  12. praisonai/inc/models.py +128 -0
  13. praisonai/public/android-chrome-192x192.png +0 -0
  14. praisonai/public/android-chrome-512x512.png +0 -0
  15. praisonai/public/apple-touch-icon.png +0 -0
  16. praisonai/public/fantasy.svg +3 -0
  17. praisonai/public/favicon-16x16.png +0 -0
  18. praisonai/public/favicon-32x32.png +0 -0
  19. praisonai/public/favicon.ico +0 -0
  20. praisonai/public/game.svg +3 -0
  21. praisonai/public/logo_dark.png +0 -0
  22. praisonai/public/logo_light.png +0 -0
  23. praisonai/public/movie.svg +3 -0
  24. praisonai/public/thriller.svg +3 -0
  25. praisonai/setup/__init__.py +0 -0
  26. praisonai/setup/build.py +21 -0
  27. praisonai/setup/config.yaml +60 -0
  28. praisonai/setup/post_install.py +20 -0
  29. praisonai/setup/setup_conda_env.py +25 -0
  30. praisonai/setup/setup_conda_env.sh +72 -0
  31. praisonai/test.py +105 -0
  32. praisonai/train.py +276 -0
  33. praisonai/ui/chat.py +304 -0
  34. praisonai/ui/code.py +318 -0
  35. praisonai/ui/context.py +283 -0
  36. praisonai/ui/public/fantasy.svg +3 -0
  37. praisonai/ui/public/game.svg +3 -0
  38. praisonai/ui/public/logo_dark.png +0 -0
  39. praisonai/ui/public/logo_light.png +0 -0
  40. praisonai/ui/public/movie.svg +3 -0
  41. praisonai/ui/public/thriller.svg +3 -0
  42. praisonai/ui/sql_alchemy.py +638 -0
  43. praisonai/version.py +1 -0
  44. praisonai-0.0.59.dist-info/LICENSE +20 -0
  45. praisonai-0.0.59.dist-info/METADATA +344 -0
  46. praisonai-0.0.59.dist-info/RECORD +48 -0
  47. praisonai-0.0.59.dist-info/WHEEL +4 -0
  48. praisonai-0.0.59.dist-info/entry_points.txt +5 -0
praisonai/ui/chat.py ADDED
@@ -0,0 +1,304 @@
1
+ import chainlit as cl
2
+ from chainlit.input_widget import TextInput
3
+ from chainlit.types import ThreadDict
4
+ from litellm import acompletion
5
+ import os
6
+ import sqlite3
7
+ from datetime import datetime
8
+ from typing import Dict, List, Optional
9
+ from dotenv import load_dotenv
10
+ load_dotenv()
11
+ import chainlit.data as cl_data
12
+ from chainlit.step import StepDict
13
+ from literalai.helper import utc_now
14
+ import logging
15
+ import json
16
+ from sql_alchemy import SQLAlchemyDataLayer
17
+
18
+ # Set up logging
19
+ logger = logging.getLogger(__name__)
20
+ log_level = os.getenv("LOGLEVEL", "INFO").upper()
21
+ logger.handlers = []
22
+
23
+ # Set up logging to console
24
+ console_handler = logging.StreamHandler()
25
+ console_handler.setLevel(log_level)
26
+ console_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
27
+ console_handler.setFormatter(console_formatter)
28
+ logger.addHandler(console_handler)
29
+
30
+ # Set the logging level for the logger
31
+ logger.setLevel(log_level)
32
+
33
+ CHAINLIT_AUTH_SECRET = os.getenv("CHAINLIT_AUTH_SECRET")
34
+
35
+ if not CHAINLIT_AUTH_SECRET:
36
+ os.environ["CHAINLIT_AUTH_SECRET"] = "p8BPhQChpg@J>jBz$wGxqLX2V>yTVgP*7Ky9H$aV:axW~ANNX-7_T:o@lnyCBu^U"
37
+ CHAINLIT_AUTH_SECRET = os.getenv("CHAINLIT_AUTH_SECRET")
38
+
39
+ now = utc_now()
40
+
41
+ create_step_counter = 0
42
+
43
+ DB_PATH = os.path.expanduser("~/.praison/database.sqlite")
44
+
45
+ def initialize_db():
46
+ os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
47
+ conn = sqlite3.connect(DB_PATH)
48
+ cursor = conn.cursor()
49
+ cursor.execute('''
50
+ CREATE TABLE IF NOT EXISTS users (
51
+ id UUID PRIMARY KEY,
52
+ identifier TEXT NOT NULL UNIQUE,
53
+ metadata JSONB NOT NULL,
54
+ createdAt TEXT
55
+ )
56
+ ''')
57
+ cursor.execute('''
58
+ CREATE TABLE IF NOT EXISTS threads (
59
+ id UUID PRIMARY KEY,
60
+ createdAt TEXT,
61
+ name TEXT,
62
+ userId UUID,
63
+ userIdentifier TEXT,
64
+ tags TEXT[],
65
+ metadata JSONB NOT NULL DEFAULT '{}',
66
+ FOREIGN KEY (userId) REFERENCES users(id) ON DELETE CASCADE
67
+ )
68
+ ''')
69
+ cursor.execute('''
70
+ CREATE TABLE IF NOT EXISTS steps (
71
+ id UUID PRIMARY KEY,
72
+ name TEXT NOT NULL,
73
+ type TEXT NOT NULL,
74
+ threadId UUID NOT NULL,
75
+ parentId UUID,
76
+ disableFeedback BOOLEAN NOT NULL,
77
+ streaming BOOLEAN NOT NULL,
78
+ waitForAnswer BOOLEAN,
79
+ isError BOOLEAN,
80
+ metadata JSONB,
81
+ tags TEXT[],
82
+ input TEXT,
83
+ output TEXT,
84
+ createdAt TEXT,
85
+ start TEXT,
86
+ end TEXT,
87
+ generation JSONB,
88
+ showInput TEXT,
89
+ language TEXT,
90
+ indent INT,
91
+ FOREIGN KEY (threadId) REFERENCES threads (id) ON DELETE CASCADE
92
+ )
93
+ ''')
94
+ cursor.execute('''
95
+ CREATE TABLE IF NOT EXISTS elements (
96
+ id UUID PRIMARY KEY,
97
+ threadId UUID,
98
+ type TEXT,
99
+ url TEXT,
100
+ chainlitKey TEXT,
101
+ name TEXT NOT NULL,
102
+ display TEXT,
103
+ objectKey TEXT,
104
+ size TEXT,
105
+ page INT,
106
+ language TEXT,
107
+ forId UUID,
108
+ mime TEXT,
109
+ FOREIGN KEY (threadId) REFERENCES threads (id) ON DELETE CASCADE
110
+ )
111
+ ''')
112
+ cursor.execute('''
113
+ CREATE TABLE IF NOT EXISTS feedbacks (
114
+ id UUID PRIMARY KEY,
115
+ forId UUID NOT NULL,
116
+ value INT NOT NULL,
117
+ threadId UUID,
118
+ comment TEXT
119
+ )
120
+ ''')
121
+ cursor.execute('''
122
+ CREATE TABLE IF NOT EXISTS settings (
123
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
124
+ key TEXT UNIQUE,
125
+ value TEXT
126
+ )
127
+ ''')
128
+ conn.commit()
129
+ conn.close()
130
+
131
+ def save_setting(key: str, value: str):
132
+ """Saves a setting to the database.
133
+
134
+ Args:
135
+ key: The setting key.
136
+ value: The setting value.
137
+ """
138
+ conn = sqlite3.connect(DB_PATH)
139
+ cursor = conn.cursor()
140
+ cursor.execute(
141
+ """
142
+ INSERT OR REPLACE INTO settings (id, key, value)
143
+ VALUES ((SELECT id FROM settings WHERE key = ?), ?, ?)
144
+ """,
145
+ (key, key, value),
146
+ )
147
+ conn.commit()
148
+ conn.close()
149
+
150
+ def load_setting(key: str) -> str:
151
+ """Loads a setting from the database.
152
+
153
+ Args:
154
+ key: The setting key.
155
+
156
+ Returns:
157
+ The setting value, or None if the key is not found.
158
+ """
159
+ conn = sqlite3.connect(DB_PATH)
160
+ cursor = conn.cursor()
161
+ cursor.execute('SELECT value FROM settings WHERE key = ?', (key,))
162
+ result = cursor.fetchone()
163
+ conn.close()
164
+ return result[0] if result else None
165
+
166
+
167
+ # Initialize the database
168
+ initialize_db()
169
+
170
+ deleted_thread_ids = [] # type: List[str]
171
+
172
+ cl_data._data_layer = SQLAlchemyDataLayer(conninfo=f"sqlite+aiosqlite:///{DB_PATH}")
173
+
174
+ @cl.on_chat_start
175
+ async def start():
176
+ initialize_db()
177
+ model_name = load_setting("model_name")
178
+
179
+ if model_name:
180
+ cl.user_session.set("model_name", model_name)
181
+ else:
182
+ # If no setting found, use default or environment variable
183
+ model_name = os.getenv("MODEL_NAME", "gpt-4o-mini")
184
+ cl.user_session.set("model_name", model_name)
185
+ logger.debug(f"Model name: {model_name}")
186
+ settings = cl.ChatSettings(
187
+ [
188
+ TextInput(
189
+ id="model_name",
190
+ label="Enter the Model Name",
191
+ placeholder="e.g., gpt-4o-mini",
192
+ initial=model_name
193
+ )
194
+ ]
195
+ )
196
+ cl.user_session.set("settings", settings)
197
+ await settings.send()
198
+
199
+ @cl.on_settings_update
200
+ async def setup_agent(settings):
201
+ logger.debug(settings)
202
+ cl.user_session.set("settings", settings)
203
+ model_name = settings["model_name"]
204
+ cl.user_session.set("model_name", model_name)
205
+
206
+ # Save in settings table
207
+ save_setting("model_name", model_name)
208
+
209
+ # Save in thread metadata
210
+ thread_id = cl.user_session.get("thread_id")
211
+ if thread_id:
212
+ thread = await cl_data.get_thread(thread_id)
213
+ if thread:
214
+ metadata = thread.get("metadata", {})
215
+ metadata["model_name"] = model_name
216
+
217
+ # Always store metadata as a JSON string
218
+ await cl_data.update_thread(thread_id, metadata=json.dumps(metadata))
219
+
220
+ # Update the user session with the new metadata
221
+ cl.user_session.set("metadata", metadata)
222
+
223
+ @cl.on_message
224
+ async def main(message: cl.Message):
225
+ model_name = load_setting("model_name") or os.getenv("MODEL_NAME") or "gpt-4o-mini"
226
+ message_history = cl.user_session.get("message_history", [])
227
+ message_history.append({"role": "user", "content": message.content})
228
+
229
+ msg = cl.Message(content="")
230
+ await msg.send()
231
+
232
+ response = await acompletion(
233
+ model=model_name,
234
+ messages=message_history,
235
+ stream=True,
236
+ # temperature=0.7,
237
+ # max_tokens=500,
238
+ # top_p=1
239
+ )
240
+
241
+ full_response = ""
242
+ async for part in response:
243
+ if token := part['choices'][0]['delta']['content']:
244
+ await msg.stream_token(token)
245
+ full_response += token
246
+ logger.debug(f"Full response: {full_response}")
247
+ message_history.append({"role": "assistant", "content": full_response})
248
+ logger.debug(f"Message history: {message_history}")
249
+ cl.user_session.set("message_history", message_history)
250
+ await msg.update()
251
+
252
+ username = os.getenv("CHAINLIT_USERNAME", "admin") # Default to "admin" if not found
253
+ password = os.getenv("CHAINLIT_PASSWORD", "admin") # Default to "admin" if not found
254
+
255
+ @cl.password_auth_callback
256
+ def auth_callback(username: str, password: str):
257
+ if (username, password) == (username, password):
258
+ return cl.User(
259
+ identifier=username, metadata={"role": "ADMIN", "provider": "credentials"}
260
+ )
261
+ else:
262
+ return None
263
+
264
+ async def send_count():
265
+ await cl.Message(
266
+ f"Create step counter: {create_step_counter}", disable_feedback=True
267
+ ).send()
268
+
269
+ @cl.on_chat_resume
270
+ async def on_chat_resume(thread: cl_data.ThreadDict):
271
+ logger.info(f"Resuming chat: {thread['id']}")
272
+ model_name = load_setting("model_name") or os.getenv("MODEL_NAME") or "gpt-4o-mini"
273
+ logger.debug(f"Model name: {model_name}")
274
+ settings = cl.ChatSettings(
275
+ [
276
+ TextInput(
277
+ id="model_name",
278
+ label="Enter the Model Name",
279
+ placeholder="e.g., gpt-4o-mini",
280
+ initial=model_name
281
+ )
282
+ ]
283
+ )
284
+ await settings.send()
285
+ thread_id = thread["id"]
286
+ cl.user_session.set("thread_id", thread["id"])
287
+
288
+ # The metadata should now already be a dictionary
289
+ metadata = thread.get("metadata", {})
290
+ cl.user_session.set("metadata", metadata)
291
+
292
+ message_history = cl.user_session.get("message_history", [])
293
+ steps = thread["steps"]
294
+
295
+ for message in steps:
296
+ msg_type = message.get("type")
297
+ if msg_type == "user_message":
298
+ message_history.append({"role": "user", "content": message.get("output", "")})
299
+ elif msg_type == "assistant_message":
300
+ message_history.append({"role": "assistant", "content": message.get("output", "")})
301
+ else:
302
+ logger.warning(f"Message without type: {message}")
303
+
304
+ cl.user_session.set("message_history", message_history)
praisonai/ui/code.py ADDED
@@ -0,0 +1,318 @@
1
+ import chainlit as cl
2
+ from chainlit.input_widget import TextInput
3
+ from chainlit.types import ThreadDict
4
+ from litellm import acompletion
5
+ import os
6
+ import sqlite3
7
+ from datetime import datetime
8
+ from typing import Dict, List, Optional
9
+ from dotenv import load_dotenv
10
+ load_dotenv()
11
+ import chainlit.data as cl_data
12
+ from chainlit.step import StepDict
13
+ from literalai.helper import utc_now
14
+ import logging
15
+ import json
16
+ from sql_alchemy import SQLAlchemyDataLayer
17
+ from context import ContextGatherer
18
+
19
+ # Set up logging
20
+ logger = logging.getLogger(__name__)
21
+ log_level = os.getenv("LOGLEVEL", "INFO").upper()
22
+ logger.handlers = []
23
+
24
+ # Set up logging to console
25
+ console_handler = logging.StreamHandler()
26
+ console_handler.setLevel(log_level)
27
+ console_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
28
+ console_handler.setFormatter(console_formatter)
29
+ logger.addHandler(console_handler)
30
+
31
+ # Set the logging level for the logger
32
+ logger.setLevel(log_level)
33
+
34
+ CHAINLIT_AUTH_SECRET = os.getenv("CHAINLIT_AUTH_SECRET")
35
+
36
+ if not CHAINLIT_AUTH_SECRET:
37
+ os.environ["CHAINLIT_AUTH_SECRET"] = "p8BPhQChpg@J>jBz$wGxqLX2V>yTVgP*7Ky9H$aV:axW~ANNX-7_T:o@lnyCBu^U"
38
+ CHAINLIT_AUTH_SECRET = os.getenv("CHAINLIT_AUTH_SECRET")
39
+
40
+ now = utc_now()
41
+
42
+ create_step_counter = 0
43
+
44
+ DB_PATH = os.path.expanduser("~/.praison/database.sqlite")
45
+
46
+ def initialize_db():
47
+ os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
48
+ conn = sqlite3.connect(DB_PATH)
49
+ cursor = conn.cursor()
50
+ cursor.execute('''
51
+ CREATE TABLE IF NOT EXISTS users (
52
+ id UUID PRIMARY KEY,
53
+ identifier TEXT NOT NULL UNIQUE,
54
+ metadata JSONB NOT NULL,
55
+ createdAt TEXT
56
+ )
57
+ ''')
58
+ cursor.execute('''
59
+ CREATE TABLE IF NOT EXISTS threads (
60
+ id UUID PRIMARY KEY,
61
+ createdAt TEXT,
62
+ name TEXT,
63
+ userId UUID,
64
+ userIdentifier TEXT,
65
+ tags TEXT[],
66
+ metadata JSONB NOT NULL DEFAULT '{}',
67
+ FOREIGN KEY (userId) REFERENCES users(id) ON DELETE CASCADE
68
+ )
69
+ ''')
70
+ cursor.execute('''
71
+ CREATE TABLE IF NOT EXISTS steps (
72
+ id UUID PRIMARY KEY,
73
+ name TEXT NOT NULL,
74
+ type TEXT NOT NULL,
75
+ threadId UUID NOT NULL,
76
+ parentId UUID,
77
+ disableFeedback BOOLEAN NOT NULL,
78
+ streaming BOOLEAN NOT NULL,
79
+ waitForAnswer BOOLEAN,
80
+ isError BOOLEAN,
81
+ metadata JSONB,
82
+ tags TEXT[],
83
+ input TEXT,
84
+ output TEXT,
85
+ createdAt TEXT,
86
+ start TEXT,
87
+ end TEXT,
88
+ generation JSONB,
89
+ showInput TEXT,
90
+ language TEXT,
91
+ indent INT,
92
+ FOREIGN KEY (threadId) REFERENCES threads (id) ON DELETE CASCADE
93
+ )
94
+ ''')
95
+ cursor.execute('''
96
+ CREATE TABLE IF NOT EXISTS elements (
97
+ id UUID PRIMARY KEY,
98
+ threadId UUID,
99
+ type TEXT,
100
+ url TEXT,
101
+ chainlitKey TEXT,
102
+ name TEXT NOT NULL,
103
+ display TEXT,
104
+ objectKey TEXT,
105
+ size TEXT,
106
+ page INT,
107
+ language TEXT,
108
+ forId UUID,
109
+ mime TEXT,
110
+ FOREIGN KEY (threadId) REFERENCES threads (id) ON DELETE CASCADE
111
+ )
112
+ ''')
113
+ cursor.execute('''
114
+ CREATE TABLE IF NOT EXISTS feedbacks (
115
+ id UUID PRIMARY KEY,
116
+ forId UUID NOT NULL,
117
+ value INT NOT NULL,
118
+ threadId UUID,
119
+ comment TEXT
120
+ )
121
+ ''')
122
+ cursor.execute('''
123
+ CREATE TABLE IF NOT EXISTS settings (
124
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
125
+ key TEXT UNIQUE,
126
+ value TEXT
127
+ )
128
+ ''')
129
+ conn.commit()
130
+ conn.close()
131
+
132
+ def save_setting(key: str, value: str):
133
+ """Saves a setting to the database.
134
+
135
+ Args:
136
+ key: The setting key.
137
+ value: The setting value.
138
+ """
139
+ conn = sqlite3.connect(DB_PATH)
140
+ cursor = conn.cursor()
141
+ cursor.execute(
142
+ """
143
+ INSERT OR REPLACE INTO settings (id, key, value)
144
+ VALUES ((SELECT id FROM settings WHERE key = ?), ?, ?)
145
+ """,
146
+ (key, key, value),
147
+ )
148
+ conn.commit()
149
+ conn.close()
150
+
151
+ def load_setting(key: str) -> str:
152
+ """Loads a setting from the database.
153
+
154
+ Args:
155
+ key: The setting key.
156
+
157
+ Returns:
158
+ The setting value, or None if the key is not found.
159
+ """
160
+ conn = sqlite3.connect(DB_PATH)
161
+ cursor = conn.cursor()
162
+ cursor.execute('SELECT value FROM settings WHERE key = ?', (key,))
163
+ result = cursor.fetchone()
164
+ conn.close()
165
+ return result[0] if result else None
166
+
167
+
168
+ # Initialize the database
169
+ initialize_db()
170
+
171
+ deleted_thread_ids = [] # type: List[str]
172
+
173
+ cl_data._data_layer = SQLAlchemyDataLayer(conninfo=f"sqlite+aiosqlite:///{DB_PATH}")
174
+
175
+ @cl.on_chat_start
176
+ async def start():
177
+ initialize_db()
178
+ model_name = load_setting("model_name")
179
+
180
+ if model_name:
181
+ cl.user_session.set("model_name", model_name)
182
+ else:
183
+ # If no setting found, use default or environment variable
184
+ model_name = os.getenv("MODEL_NAME", "gpt-4o-mini")
185
+ cl.user_session.set("model_name", model_name)
186
+ logger.debug(f"Model name: {model_name}")
187
+ settings = cl.ChatSettings(
188
+ [
189
+ TextInput(
190
+ id="model_name",
191
+ label="Enter the Model Name",
192
+ placeholder="e.g., gpt-4o-mini",
193
+ initial=model_name
194
+ )
195
+ ]
196
+ )
197
+ cl.user_session.set("settings", settings)
198
+ await settings.send()
199
+ gatherer = ContextGatherer()
200
+ context, token_count, context_tree = gatherer.run()
201
+ msg = cl.Message(content="""Token Count: {token_count},
202
+ Files include: \n```bash\n{context_tree}\n"""
203
+ .format(token_count=token_count, context_tree=context_tree))
204
+ await msg.send()
205
+
206
+ @cl.on_settings_update
207
+ async def setup_agent(settings):
208
+ logger.debug(settings)
209
+ cl.user_session.set("settings", settings)
210
+ model_name = settings["model_name"]
211
+ cl.user_session.set("model_name", model_name)
212
+
213
+ # Save in settings table
214
+ save_setting("model_name", model_name)
215
+
216
+ # Save in thread metadata
217
+ thread_id = cl.user_session.get("thread_id")
218
+ if thread_id:
219
+ thread = await cl_data.get_thread(thread_id)
220
+ if thread:
221
+ metadata = thread.get("metadata", {})
222
+ metadata["model_name"] = model_name
223
+
224
+ # Always store metadata as a JSON string
225
+ await cl_data.update_thread(thread_id, metadata=json.dumps(metadata))
226
+
227
+ # Update the user session with the new metadata
228
+ cl.user_session.set("metadata", metadata)
229
+
230
+ @cl.on_message
231
+ async def main(message: cl.Message):
232
+ model_name = load_setting("model_name") or os.getenv("MODEL_NAME") or "gpt-4o-mini"
233
+ message_history = cl.user_session.get("message_history", [])
234
+ message_history.append({"role": "user", "content": message.content})
235
+ gatherer = ContextGatherer()
236
+ context, token_count, context_tree = gatherer.run()
237
+ prompt_history = message_history
238
+ prompt_history.append({"role": "user", "content": """
239
+ Answer the question:\n{question}.\n\n
240
+ Below is the Context:\n{context}\n\n"""
241
+ .format(context=context, question=message.content)})
242
+
243
+ msg = cl.Message(content="")
244
+ await msg.send()
245
+
246
+ response = await acompletion(
247
+ model=model_name,
248
+ messages=prompt_history,
249
+ stream=True,
250
+ # temperature=0.7,
251
+ # max_tokens=500,
252
+ # top_p=1
253
+ )
254
+
255
+ full_response = ""
256
+ async for part in response:
257
+ if token := part['choices'][0]['delta']['content']:
258
+ await msg.stream_token(token)
259
+ full_response += token
260
+ logger.debug(f"Full response: {full_response}")
261
+ message_history.append({"role": "assistant", "content": full_response})
262
+ logger.debug(f"Message history: {message_history}")
263
+ cl.user_session.set("message_history", message_history)
264
+ await msg.update()
265
+
266
+ username = os.getenv("CHAINLIT_USERNAME", "admin") # Default to "admin" if not found
267
+ password = os.getenv("CHAINLIT_PASSWORD", "admin") # Default to "admin" if not found
268
+
269
+ @cl.password_auth_callback
270
+ def auth_callback(username: str, password: str):
271
+ if (username, password) == (username, password):
272
+ return cl.User(
273
+ identifier=username, metadata={"role": "ADMIN", "provider": "credentials"}
274
+ )
275
+ else:
276
+ return None
277
+
278
+ async def send_count():
279
+ await cl.Message(
280
+ f"Create step counter: {create_step_counter}", disable_feedback=True
281
+ ).send()
282
+
283
+ @cl.on_chat_resume
284
+ async def on_chat_resume(thread: cl_data.ThreadDict):
285
+ logger.info(f"Resuming chat: {thread['id']}")
286
+ model_name = load_setting("model_name") or os.getenv("MODEL_NAME") or "gpt-4o-mini"
287
+ logger.debug(f"Model name: {model_name}")
288
+ settings = cl.ChatSettings(
289
+ [
290
+ TextInput(
291
+ id="model_name",
292
+ label="Enter the Model Name",
293
+ placeholder="e.g., gpt-4o-mini",
294
+ initial=model_name
295
+ )
296
+ ]
297
+ )
298
+ await settings.send()
299
+ thread_id = thread["id"]
300
+ cl.user_session.set("thread_id", thread["id"])
301
+
302
+ # The metadata should now already be a dictionary
303
+ metadata = thread.get("metadata", {})
304
+ cl.user_session.set("metadata", metadata)
305
+
306
+ message_history = cl.user_session.get("message_history", [])
307
+ steps = thread["steps"]
308
+
309
+ for message in steps:
310
+ msg_type = message.get("type")
311
+ if msg_type == "user_message":
312
+ message_history.append({"role": "user", "content": message.get("output", "")})
313
+ elif msg_type == "assistant_message":
314
+ message_history.append({"role": "assistant", "content": message.get("output", "")})
315
+ else:
316
+ logger.warning(f"Message without type: {message}")
317
+
318
+ cl.user_session.set("message_history", message_history)