chainlit 0.2.111__py3-none-any.whl → 0.3.0__py3-none-any.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 chainlit might be problematic. Click here for more details.
- chainlit/__init__.py +48 -32
- chainlit/action.py +12 -12
- chainlit/cache.py +20 -0
- chainlit/cli/__init__.py +43 -62
- chainlit/cli/mock.py +48 -0
- chainlit/client.py +111 -89
- chainlit/config.py +22 -3
- chainlit/element.py +95 -124
- chainlit/{sdk.py → emitter.py} +55 -64
- chainlit/frontend/dist/assets/index-0b7e367e.js +717 -0
- chainlit/frontend/dist/assets/index-0cc9e355.css +1 -0
- chainlit/frontend/dist/index.html +3 -3
- chainlit/hello.py +3 -3
- chainlit/lc/__init__.py +11 -0
- chainlit/lc/agent.py +32 -0
- chainlit/lc/callbacks.py +411 -0
- chainlit/message.py +72 -96
- chainlit/server.py +280 -195
- chainlit/session.py +4 -2
- chainlit/sync.py +37 -0
- chainlit/types.py +18 -1
- chainlit/user_session.py +16 -16
- {chainlit-0.2.111.dist-info → chainlit-0.3.0.dist-info}/METADATA +15 -14
- chainlit-0.3.0.dist-info/RECORD +37 -0
- chainlit/frontend/dist/assets/index-4d8f8873.js +0 -713
- chainlit/frontend/dist/assets/index-bdffdaa0.css +0 -1
- chainlit/lc/chainlit_handler.py +0 -271
- chainlit/lc/monkey.py +0 -28
- chainlit/lc/new_monkey.py +0 -167
- chainlit/lc/old_monkey.py +0 -119
- chainlit/lc/utils.py +0 -38
- chainlit/watch.py +0 -54
- chainlit-0.2.111.dist-info/RECORD +0 -38
- {chainlit-0.2.111.dist-info → chainlit-0.3.0.dist-info}/WHEEL +0 -0
- {chainlit-0.2.111.dist-info → chainlit-0.3.0.dist-info}/entry_points.txt +0 -0
chainlit/message.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
from typing import List, Dict, Union
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
2
3
|
import uuid
|
|
3
4
|
import time
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
from chainlit.logger import logger
|
|
7
|
-
from chainlit.sdk import get_sdk, Chainlit
|
|
5
|
+
import asyncio
|
|
6
|
+
|
|
8
7
|
from chainlit.telemetry import trace_event
|
|
8
|
+
from chainlit.emitter import get_emitter
|
|
9
9
|
from chainlit.config import config
|
|
10
10
|
from chainlit.types import (
|
|
11
11
|
LLMSettings,
|
|
@@ -27,27 +27,30 @@ class MessageBase(ABC):
|
|
|
27
27
|
id: int = None
|
|
28
28
|
temp_id: str = None
|
|
29
29
|
streaming = False
|
|
30
|
+
created_at: int = None
|
|
31
|
+
|
|
32
|
+
def __post_init__(self) -> None:
|
|
33
|
+
trace_event(f"init {self.__class__.__name__}")
|
|
34
|
+
self.temp_id = uuid.uuid4().hex
|
|
35
|
+
self.created_at = current_milli_time()
|
|
36
|
+
self.emitter = get_emitter()
|
|
37
|
+
if not self.emitter:
|
|
38
|
+
raise RuntimeError("Message should be instantiated in a Chainlit context")
|
|
30
39
|
|
|
31
40
|
@abstractmethod
|
|
32
41
|
def to_dict(self):
|
|
33
42
|
pass
|
|
34
43
|
|
|
35
|
-
def _create(self
|
|
44
|
+
async def _create(self):
|
|
36
45
|
msg_dict = self.to_dict()
|
|
37
|
-
if
|
|
38
|
-
self.id =
|
|
46
|
+
if self.emitter.client and not self.id:
|
|
47
|
+
self.id = await self.emitter.client.create_message(msg_dict)
|
|
39
48
|
if self.id:
|
|
40
49
|
msg_dict["id"] = self.id
|
|
41
50
|
|
|
42
|
-
if not "id" in msg_dict:
|
|
43
|
-
self.temp_id = uuid.uuid4().hex
|
|
44
|
-
msg_dict["tempId"] = self.temp_id
|
|
45
|
-
|
|
46
|
-
msg_dict["createdAt"] = current_milli_time()
|
|
47
|
-
|
|
48
51
|
return msg_dict
|
|
49
52
|
|
|
50
|
-
def update(
|
|
53
|
+
async def update(
|
|
51
54
|
self,
|
|
52
55
|
author: str = None,
|
|
53
56
|
content: str = None,
|
|
@@ -60,12 +63,6 @@ class MessageBase(ABC):
|
|
|
60
63
|
"""
|
|
61
64
|
trace_event("update_message")
|
|
62
65
|
|
|
63
|
-
sdk = get_sdk()
|
|
64
|
-
|
|
65
|
-
if not sdk:
|
|
66
|
-
logger.warning("No SDK found, cannot update message")
|
|
67
|
-
return False
|
|
68
|
-
|
|
69
66
|
if author:
|
|
70
67
|
self.author = author
|
|
71
68
|
if content:
|
|
@@ -79,77 +76,54 @@ class MessageBase(ABC):
|
|
|
79
76
|
|
|
80
77
|
msg_dict = self.to_dict()
|
|
81
78
|
|
|
82
|
-
if
|
|
83
|
-
|
|
79
|
+
if self.emitter.client and self.id:
|
|
80
|
+
self.emitter.client.update_message(self.id, msg_dict)
|
|
84
81
|
msg_dict["id"] = self.id
|
|
85
|
-
elif self.temp_id:
|
|
86
|
-
msg_dict["tempId"] = self.temp_id
|
|
87
|
-
else:
|
|
88
|
-
logger.error("Cannot update a message that has no ID")
|
|
89
|
-
return False
|
|
90
82
|
|
|
91
|
-
|
|
83
|
+
await self.emitter.update_message(msg_dict)
|
|
92
84
|
|
|
93
85
|
return True
|
|
94
86
|
|
|
95
|
-
def remove(self):
|
|
87
|
+
async def remove(self):
|
|
96
88
|
"""
|
|
97
89
|
Remove a message already sent to the UI.
|
|
98
90
|
This will not automatically remove potential nested messages and could lead to undesirable side effects in the UI.
|
|
99
91
|
"""
|
|
100
92
|
trace_event("remove_message")
|
|
101
93
|
|
|
102
|
-
|
|
94
|
+
if self.emitter.client and self.id:
|
|
95
|
+
await self.emitter.client.delete_message(self.id)
|
|
103
96
|
|
|
104
|
-
|
|
105
|
-
logger.warning("No SDK found, cannot delete message")
|
|
106
|
-
return False
|
|
107
|
-
if sdk.client and self.id:
|
|
108
|
-
sdk.client.delete_message(self.id)
|
|
109
|
-
sdk.delete_message(self.id)
|
|
110
|
-
elif self.temp_id:
|
|
111
|
-
sdk.delete_message(self.temp_id)
|
|
112
|
-
else:
|
|
113
|
-
logger.error("Cannot delete a message that has no ID")
|
|
114
|
-
return False
|
|
97
|
+
await self.emitter.delete_message(self.to_dict())
|
|
115
98
|
|
|
116
99
|
return True
|
|
117
100
|
|
|
118
|
-
def send(self) -> Union[str, int]:
|
|
119
|
-
|
|
101
|
+
async def send(self) -> Union[str, int]:
|
|
102
|
+
if self.content is None:
|
|
103
|
+
self.content = ""
|
|
120
104
|
|
|
121
|
-
|
|
122
|
-
logger.warning("No SDK found, cannot send message")
|
|
123
|
-
return
|
|
124
|
-
|
|
125
|
-
msg_dict = self._create(sdk)
|
|
105
|
+
msg_dict = await self._create()
|
|
126
106
|
|
|
127
107
|
if self.streaming:
|
|
128
108
|
self.streaming = False
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
sdk.send_message(msg_dict)
|
|
109
|
+
|
|
110
|
+
await self.emitter.send_message(msg_dict)
|
|
132
111
|
|
|
133
112
|
return self.id or self.temp_id
|
|
134
113
|
|
|
135
|
-
def stream_token(self, token: str):
|
|
114
|
+
async def stream_token(self, token: str):
|
|
136
115
|
"""
|
|
137
116
|
Sends a token to the UI. This is useful for streaming messages.
|
|
138
117
|
Once all tokens have been streamed, call .send() to persist the message.
|
|
139
118
|
"""
|
|
140
|
-
sdk = get_sdk()
|
|
141
|
-
|
|
142
|
-
if not sdk:
|
|
143
|
-
logger.warning("No SDK found, cannot send message")
|
|
144
|
-
return
|
|
145
119
|
|
|
146
120
|
if not self.streaming:
|
|
147
121
|
self.streaming = True
|
|
148
122
|
msg_dict = self.to_dict()
|
|
149
|
-
|
|
123
|
+
await self.emitter.stream_start(msg_dict)
|
|
150
124
|
|
|
151
125
|
self.content += token
|
|
152
|
-
|
|
126
|
+
await self.emitter.send_token(id=self.id or self.temp_id, token=token)
|
|
153
127
|
|
|
154
128
|
|
|
155
129
|
class Message(MessageBase):
|
|
@@ -194,8 +168,12 @@ class Message(MessageBase):
|
|
|
194
168
|
if llm_settings:
|
|
195
169
|
self.llmSettings = llm_settings.to_dict()
|
|
196
170
|
|
|
171
|
+
super().__post_init__()
|
|
172
|
+
|
|
197
173
|
def to_dict(self):
|
|
198
174
|
return {
|
|
175
|
+
"tempId": self.temp_id,
|
|
176
|
+
"createdAt": self.created_at,
|
|
199
177
|
"content": self.content,
|
|
200
178
|
"author": self.author,
|
|
201
179
|
"prompt": self.prompt,
|
|
@@ -204,19 +182,18 @@ class Message(MessageBase):
|
|
|
204
182
|
"indent": self.indent,
|
|
205
183
|
}
|
|
206
184
|
|
|
207
|
-
def send(self):
|
|
185
|
+
async def send(self):
|
|
208
186
|
"""
|
|
209
187
|
Send the message to the UI and persist it in the cloud if a project ID is configured.
|
|
210
188
|
Return the ID of the message.
|
|
211
189
|
"""
|
|
212
190
|
trace_event("send_message")
|
|
213
|
-
id = super().send()
|
|
191
|
+
id = await super().send()
|
|
214
192
|
|
|
215
|
-
for action in self.actions
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
element.send(for_id=str(id))
|
|
193
|
+
action_coros = [action.send(for_id=str(id)) for action in self.actions]
|
|
194
|
+
element_coros = [element.send(for_id=str(id)) for element in self.elements]
|
|
195
|
+
all_coros = action_coros + element_coros
|
|
196
|
+
await asyncio.gather(*all_coros)
|
|
220
197
|
|
|
221
198
|
return id
|
|
222
199
|
|
|
@@ -242,35 +219,32 @@ class ErrorMessage(MessageBase):
|
|
|
242
219
|
self.author = author
|
|
243
220
|
self.indent = indent
|
|
244
221
|
|
|
222
|
+
super().__post_init__()
|
|
223
|
+
|
|
245
224
|
def to_dict(self):
|
|
246
225
|
return {
|
|
226
|
+
"tempId": self.temp_id,
|
|
227
|
+
"createdAt": self.created_at,
|
|
247
228
|
"content": self.content,
|
|
248
229
|
"author": self.author,
|
|
249
230
|
"indent": self.indent,
|
|
250
231
|
"isError": True,
|
|
251
232
|
}
|
|
252
233
|
|
|
253
|
-
def send(self):
|
|
234
|
+
async def send(self):
|
|
254
235
|
"""
|
|
255
236
|
Send the error message to the UI and persist it in the cloud if a project ID is configured.
|
|
256
237
|
Return the ID of the message.
|
|
257
238
|
"""
|
|
258
239
|
trace_event("send_error_message")
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return id
|
|
240
|
+
return await super().send()
|
|
262
241
|
|
|
263
242
|
|
|
264
243
|
class AskMessageBase(MessageBase):
|
|
265
244
|
def remove(self):
|
|
266
245
|
removed = super().remove()
|
|
267
246
|
if removed:
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
if not sdk:
|
|
271
|
-
return
|
|
272
|
-
|
|
273
|
-
sdk.clear_ask()
|
|
247
|
+
self.emitter.clear_ask()
|
|
274
248
|
|
|
275
249
|
|
|
276
250
|
class AskUserMessage(AskMessageBase):
|
|
@@ -298,33 +272,33 @@ class AskUserMessage(AskMessageBase):
|
|
|
298
272
|
self.timeout = timeout
|
|
299
273
|
self.raise_on_timeout = raise_on_timeout
|
|
300
274
|
|
|
275
|
+
super().__post_init__()
|
|
276
|
+
|
|
301
277
|
def to_dict(self):
|
|
302
278
|
return {
|
|
279
|
+
"tempId": self.temp_id,
|
|
280
|
+
"createdAt": self.created_at,
|
|
303
281
|
"content": self.content,
|
|
304
282
|
"author": self.author,
|
|
305
283
|
"waitForAnswer": True,
|
|
306
284
|
}
|
|
307
285
|
|
|
308
|
-
def send(self) -> Union[AskResponse, None]:
|
|
286
|
+
async def send(self) -> Union[AskResponse, None]:
|
|
309
287
|
"""
|
|
310
288
|
Sends the question to ask to the UI and waits for the reply.
|
|
311
289
|
"""
|
|
312
290
|
trace_event("send_ask_user")
|
|
313
291
|
|
|
314
|
-
sdk = get_sdk()
|
|
315
|
-
|
|
316
|
-
if not sdk:
|
|
317
|
-
logger.warning("No SDK found, cannot send message")
|
|
318
|
-
return
|
|
319
|
-
|
|
320
292
|
if self.streaming:
|
|
321
293
|
self.streaming = False
|
|
322
294
|
|
|
323
|
-
msg_dict = self._create(
|
|
295
|
+
msg_dict = await self._create()
|
|
324
296
|
|
|
325
297
|
spec = AskSpec(type="text", timeout=self.timeout)
|
|
326
298
|
|
|
327
|
-
|
|
299
|
+
res = await self.emitter.send_ask_user(msg_dict, spec, self.raise_on_timeout)
|
|
300
|
+
|
|
301
|
+
return res
|
|
328
302
|
|
|
329
303
|
|
|
330
304
|
class AskFileMessage(AskMessageBase):
|
|
@@ -336,7 +310,8 @@ class AskFileMessage(AskMessageBase):
|
|
|
336
310
|
Args:
|
|
337
311
|
content (str): Text displayed above the upload button.
|
|
338
312
|
accept (Union[List[str], Dict[str, List[str]]]): List of mime type to accept like ["text/csv", "application/pdf"] or a dict like {"text/plain": [".txt", ".py"]}.
|
|
339
|
-
max_size_mb (int, optional): Maximum file
|
|
313
|
+
max_size_mb (int, optional): Maximum size per file in MB. Maximum value is 100.
|
|
314
|
+
max_files (int, optional): Maximum number of files to upload. Maximum value is 10.
|
|
340
315
|
author (str, optional): The author of the message, this will be used in the UI. Defaults to the chatbot name (see config).
|
|
341
316
|
timeout (int, optional): The number of seconds to wait for an answer before raising a TimeoutError.
|
|
342
317
|
raise_on_timeout (bool, optional): Whether to raise a socketio TimeoutError if the user does not answer in time.
|
|
@@ -347,51 +322,52 @@ class AskFileMessage(AskMessageBase):
|
|
|
347
322
|
content: str,
|
|
348
323
|
accept: Union[List[str], Dict[str, List[str]]],
|
|
349
324
|
max_size_mb=2,
|
|
325
|
+
max_files=1,
|
|
350
326
|
author=config.chatbot_name,
|
|
351
327
|
timeout=90,
|
|
352
328
|
raise_on_timeout=False,
|
|
353
329
|
):
|
|
354
330
|
self.content = content
|
|
355
331
|
self.max_size_mb = max_size_mb
|
|
332
|
+
self.max_files = max_files
|
|
356
333
|
self.accept = accept
|
|
357
334
|
self.author = author
|
|
358
335
|
self.timeout = timeout
|
|
359
336
|
self.raise_on_timeout = raise_on_timeout
|
|
360
337
|
|
|
338
|
+
super().__post_init__()
|
|
339
|
+
|
|
361
340
|
def to_dict(self):
|
|
362
341
|
return {
|
|
342
|
+
"tempId": self.temp_id,
|
|
343
|
+
"createdAt": self.created_at,
|
|
363
344
|
"content": self.content,
|
|
364
345
|
"author": self.author,
|
|
365
346
|
"waitForAnswer": True,
|
|
366
347
|
}
|
|
367
348
|
|
|
368
|
-
def send(self) -> Union[AskFileResponse, None]:
|
|
349
|
+
async def send(self) -> Union[List[AskFileResponse], None]:
|
|
369
350
|
"""
|
|
370
351
|
Sends the message to request a file from the user to the UI and waits for the reply.
|
|
371
352
|
"""
|
|
372
353
|
trace_event("send_ask_file")
|
|
373
354
|
|
|
374
|
-
sdk = get_sdk()
|
|
375
|
-
|
|
376
|
-
if not sdk:
|
|
377
|
-
logger.warning("No SDK found, cannot send message")
|
|
378
|
-
return
|
|
379
|
-
|
|
380
355
|
if self.streaming:
|
|
381
356
|
self.streaming = False
|
|
382
357
|
|
|
383
|
-
msg_dict = self._create(
|
|
358
|
+
msg_dict = await self._create()
|
|
384
359
|
|
|
385
360
|
spec = AskFileSpec(
|
|
386
361
|
type="file",
|
|
387
362
|
accept=self.accept,
|
|
388
363
|
max_size_mb=self.max_size_mb,
|
|
364
|
+
max_files=self.max_files,
|
|
389
365
|
timeout=self.timeout,
|
|
390
366
|
)
|
|
391
367
|
|
|
392
|
-
res =
|
|
368
|
+
res = await self.emitter.send_ask_user(msg_dict, spec, self.raise_on_timeout)
|
|
393
369
|
|
|
394
370
|
if res:
|
|
395
|
-
return AskFileResponse(**res
|
|
371
|
+
return [AskFileResponse(**r) for r in res]
|
|
396
372
|
else:
|
|
397
373
|
return None
|