chainlit 1.0.401__py3-none-any.whl → 2.0.3__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 +98 -279
- chainlit/_utils.py +8 -0
- chainlit/action.py +12 -10
- chainlit/{auth.py → auth/__init__.py} +28 -36
- chainlit/auth/cookie.py +122 -0
- chainlit/auth/jwt.py +39 -0
- chainlit/cache.py +4 -6
- chainlit/callbacks.py +362 -0
- chainlit/chat_context.py +64 -0
- chainlit/chat_settings.py +3 -1
- chainlit/cli/__init__.py +77 -8
- chainlit/config.py +181 -101
- chainlit/context.py +42 -13
- chainlit/copilot/dist/index.js +8750 -903
- chainlit/data/__init__.py +101 -416
- chainlit/data/acl.py +6 -2
- chainlit/data/base.py +107 -0
- chainlit/data/chainlit_data_layer.py +608 -0
- chainlit/data/dynamodb.py +590 -0
- chainlit/data/literalai.py +500 -0
- chainlit/data/sql_alchemy.py +721 -0
- chainlit/data/storage_clients/__init__.py +0 -0
- chainlit/data/storage_clients/azure.py +81 -0
- chainlit/data/storage_clients/azure_blob.py +89 -0
- chainlit/data/storage_clients/base.py +26 -0
- chainlit/data/storage_clients/gcs.py +88 -0
- chainlit/data/storage_clients/s3.py +75 -0
- chainlit/data/utils.py +29 -0
- chainlit/discord/__init__.py +6 -0
- chainlit/discord/app.py +354 -0
- chainlit/element.py +91 -33
- chainlit/emitter.py +80 -29
- chainlit/frontend/dist/assets/DailyMotion-C_XC7xJI.js +1 -0
- chainlit/frontend/dist/assets/Dataframe-Cs4l4hA1.js +22 -0
- chainlit/frontend/dist/assets/Facebook-CUeCH7hk.js +1 -0
- chainlit/frontend/dist/assets/FilePlayer-CB-fYkx8.js +1 -0
- chainlit/frontend/dist/assets/Kaltura-YX6qaq72.js +1 -0
- chainlit/frontend/dist/assets/Mixcloud-DGV0ldjP.js +1 -0
- chainlit/frontend/dist/assets/Mux-CmRss5oc.js +1 -0
- chainlit/frontend/dist/assets/Preview-DBVJn7-H.js +1 -0
- chainlit/frontend/dist/assets/SoundCloud-qLUb18oY.js +1 -0
- chainlit/frontend/dist/assets/Streamable-BvYP7bFp.js +1 -0
- chainlit/frontend/dist/assets/Twitch-CTHt-sGZ.js +1 -0
- chainlit/frontend/dist/assets/Vidyard-B-0mCJbm.js +1 -0
- chainlit/frontend/dist/assets/Vimeo-Dnp7ri8q.js +1 -0
- chainlit/frontend/dist/assets/Wistia-DW0x_UBn.js +1 -0
- chainlit/frontend/dist/assets/YouTube--98FipvA.js +1 -0
- chainlit/frontend/dist/assets/index-D71nZ46o.js +8665 -0
- chainlit/frontend/dist/assets/index-g8LTJwwr.css +1 -0
- chainlit/frontend/dist/assets/react-plotly-Cn_BQTQw.js +3484 -0
- chainlit/frontend/dist/index.html +2 -4
- chainlit/haystack/callbacks.py +4 -7
- chainlit/input_widget.py +8 -4
- chainlit/langchain/callbacks.py +103 -68
- chainlit/langflow/__init__.py +1 -0
- chainlit/llama_index/callbacks.py +65 -40
- chainlit/markdown.py +22 -6
- chainlit/message.py +54 -56
- chainlit/mistralai/__init__.py +50 -0
- chainlit/oauth_providers.py +266 -8
- chainlit/openai/__init__.py +10 -18
- chainlit/secret.py +1 -1
- chainlit/server.py +789 -228
- chainlit/session.py +108 -90
- chainlit/slack/__init__.py +6 -0
- chainlit/slack/app.py +397 -0
- chainlit/socket.py +199 -116
- chainlit/step.py +141 -89
- chainlit/sync.py +2 -1
- chainlit/teams/__init__.py +6 -0
- chainlit/teams/app.py +338 -0
- chainlit/translations/bn.json +235 -0
- chainlit/translations/en-US.json +83 -4
- chainlit/translations/gu.json +235 -0
- chainlit/translations/he-IL.json +235 -0
- chainlit/translations/hi.json +235 -0
- chainlit/translations/kn.json +235 -0
- chainlit/translations/ml.json +235 -0
- chainlit/translations/mr.json +235 -0
- chainlit/translations/nl-NL.json +233 -0
- chainlit/translations/ta.json +235 -0
- chainlit/translations/te.json +235 -0
- chainlit/translations/zh-CN.json +233 -0
- chainlit/translations.py +60 -0
- chainlit/types.py +133 -28
- chainlit/user.py +14 -3
- chainlit/user_session.py +6 -3
- chainlit/utils.py +52 -5
- chainlit/version.py +3 -2
- {chainlit-1.0.401.dist-info → chainlit-2.0.3.dist-info}/METADATA +48 -50
- chainlit-2.0.3.dist-info/RECORD +106 -0
- chainlit/cli/utils.py +0 -24
- chainlit/frontend/dist/assets/index-9711593e.js +0 -723
- chainlit/frontend/dist/assets/index-d088547c.css +0 -1
- chainlit/frontend/dist/assets/react-plotly-d8762cc2.js +0 -3602
- chainlit/playground/__init__.py +0 -2
- chainlit/playground/config.py +0 -40
- chainlit/playground/provider.py +0 -108
- chainlit/playground/providers/__init__.py +0 -13
- chainlit/playground/providers/anthropic.py +0 -118
- chainlit/playground/providers/huggingface.py +0 -75
- chainlit/playground/providers/langchain.py +0 -89
- chainlit/playground/providers/openai.py +0 -408
- chainlit/playground/providers/vertexai.py +0 -171
- chainlit/translations/pt-BR.json +0 -155
- chainlit-1.0.401.dist-info/RECORD +0 -66
- /chainlit/copilot/dist/assets/{logo_dark-2a3cf740.svg → logo_dark-IkGJ_IwC.svg} +0 -0
- /chainlit/copilot/dist/assets/{logo_light-b078e7bc.svg → logo_light-Bb_IPh6r.svg} +0 -0
- /chainlit/frontend/dist/assets/{logo_dark-2a3cf740.svg → logo_dark-IkGJ_IwC.svg} +0 -0
- /chainlit/frontend/dist/assets/{logo_light-b078e7bc.svg → logo_light-Bb_IPh6r.svg} +0 -0
- {chainlit-1.0.401.dist-info → chainlit-2.0.3.dist-info}/WHEEL +0 -0
- {chainlit-1.0.401.dist-info → chainlit-2.0.3.dist-info}/entry_points.txt +0 -0
chainlit/session.py
CHANGED
|
@@ -1,50 +1,51 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import json
|
|
2
3
|
import mimetypes
|
|
3
4
|
import shutil
|
|
4
5
|
import uuid
|
|
5
|
-
from typing import
|
|
6
|
-
TYPE_CHECKING,
|
|
7
|
-
Any,
|
|
8
|
-
Callable,
|
|
9
|
-
Deque,
|
|
10
|
-
Dict,
|
|
11
|
-
List,
|
|
12
|
-
Literal,
|
|
13
|
-
Optional,
|
|
14
|
-
Union,
|
|
15
|
-
)
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Callable, Deque, Dict, Literal, Optional, Union
|
|
16
7
|
|
|
17
8
|
import aiofiles
|
|
9
|
+
|
|
18
10
|
from chainlit.logger import logger
|
|
11
|
+
from chainlit.types import FileReference
|
|
19
12
|
|
|
20
13
|
if TYPE_CHECKING:
|
|
21
|
-
from chainlit.
|
|
22
|
-
from chainlit.step import Step
|
|
23
|
-
from chainlit.types import FileDict, FileReference
|
|
14
|
+
from chainlit.types import FileDict
|
|
24
15
|
from chainlit.user import PersistedUser, User
|
|
25
16
|
|
|
26
|
-
ClientType = Literal["
|
|
17
|
+
ClientType = Literal["webapp", "copilot", "teams", "slack", "discord"]
|
|
27
18
|
|
|
28
19
|
|
|
29
20
|
class JSONEncoderIgnoreNonSerializable(json.JSONEncoder):
|
|
30
|
-
def default(self,
|
|
21
|
+
def default(self, o):
|
|
31
22
|
try:
|
|
32
|
-
return super(
|
|
23
|
+
return super().default(o)
|
|
33
24
|
except TypeError:
|
|
34
25
|
return None
|
|
35
26
|
|
|
36
27
|
|
|
37
|
-
def clean_metadata(metadata: Dict):
|
|
38
|
-
|
|
28
|
+
def clean_metadata(metadata: Dict, max_size: int = 1048576):
|
|
29
|
+
cleaned_metadata = json.loads(
|
|
39
30
|
json.dumps(metadata, cls=JSONEncoderIgnoreNonSerializable, ensure_ascii=False)
|
|
40
31
|
)
|
|
41
32
|
|
|
33
|
+
metadata_size = len(json.dumps(cleaned_metadata).encode("utf-8"))
|
|
34
|
+
if metadata_size > max_size:
|
|
35
|
+
# Redact the metadata if it exceeds the maximum size
|
|
36
|
+
cleaned_metadata = {
|
|
37
|
+
"message": f"Metadata size exceeds the limit of {max_size} bytes. Redacted."
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return cleaned_metadata
|
|
41
|
+
|
|
42
42
|
|
|
43
43
|
class BaseSession:
|
|
44
44
|
"""Base object."""
|
|
45
45
|
|
|
46
46
|
thread_id_to_resume: Optional[str] = None
|
|
47
47
|
client_type: ClientType
|
|
48
|
+
current_task: Optional[asyncio.Task] = None
|
|
48
49
|
|
|
49
50
|
def __init__(
|
|
50
51
|
self,
|
|
@@ -53,16 +54,18 @@ class BaseSession:
|
|
|
53
54
|
client_type: ClientType,
|
|
54
55
|
# Thread id
|
|
55
56
|
thread_id: Optional[str],
|
|
56
|
-
# Logged-in user
|
|
57
|
+
# Logged-in user information
|
|
57
58
|
user: Optional[Union["User", "PersistedUser"]],
|
|
58
59
|
# Logged-in user token
|
|
59
60
|
token: Optional[str],
|
|
60
61
|
# User specific environment variables. Empty if no user environment variables are required.
|
|
61
62
|
user_env: Optional[Dict[str, str]],
|
|
62
|
-
# Last message at the root of the chat
|
|
63
|
-
root_message: Optional["Message"] = None,
|
|
64
63
|
# Chat profile selected before the session was created
|
|
65
64
|
chat_profile: Optional[str] = None,
|
|
65
|
+
# Origin of the request
|
|
66
|
+
http_referer: Optional[str] = None,
|
|
67
|
+
# Cookie
|
|
68
|
+
http_cookie: Optional[str] = None,
|
|
66
69
|
):
|
|
67
70
|
if thread_id:
|
|
68
71
|
self.thread_id_to_resume = thread_id
|
|
@@ -70,23 +73,73 @@ class BaseSession:
|
|
|
70
73
|
self.user = user
|
|
71
74
|
self.client_type = client_type
|
|
72
75
|
self.token = token
|
|
73
|
-
self.root_message = root_message
|
|
74
76
|
self.has_first_interaction = False
|
|
75
77
|
self.user_env = user_env or {}
|
|
76
78
|
self.chat_profile = chat_profile
|
|
79
|
+
self.http_referer = http_referer
|
|
80
|
+
self.http_cookie = http_cookie
|
|
81
|
+
|
|
82
|
+
self.files: Dict[str, FileDict] = {}
|
|
77
83
|
|
|
78
84
|
self.id = id
|
|
79
85
|
|
|
80
86
|
self.chat_settings: Dict[str, Any] = {}
|
|
81
87
|
|
|
88
|
+
@property
|
|
89
|
+
def files_dir(self):
|
|
90
|
+
from chainlit.config import FILES_DIRECTORY
|
|
91
|
+
|
|
92
|
+
return FILES_DIRECTORY / self.id
|
|
93
|
+
|
|
82
94
|
async def persist_file(
|
|
83
95
|
self,
|
|
84
96
|
name: str,
|
|
85
97
|
mime: str,
|
|
86
98
|
path: Optional[str] = None,
|
|
87
99
|
content: Optional[Union[bytes, str]] = None,
|
|
88
|
-
):
|
|
89
|
-
|
|
100
|
+
) -> FileReference:
|
|
101
|
+
if not path and not content:
|
|
102
|
+
raise ValueError(
|
|
103
|
+
"Either path or content must be provided to persist a file"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
self.files_dir.mkdir(exist_ok=True)
|
|
107
|
+
|
|
108
|
+
file_id = str(uuid.uuid4())
|
|
109
|
+
|
|
110
|
+
file_path = self.files_dir / file_id
|
|
111
|
+
|
|
112
|
+
file_extension = mimetypes.guess_extension(mime)
|
|
113
|
+
|
|
114
|
+
if file_extension:
|
|
115
|
+
file_path = file_path.with_suffix(file_extension)
|
|
116
|
+
|
|
117
|
+
if path:
|
|
118
|
+
# Copy the file from the given path
|
|
119
|
+
async with (
|
|
120
|
+
aiofiles.open(path, "rb") as src,
|
|
121
|
+
aiofiles.open(file_path, "wb") as dst,
|
|
122
|
+
):
|
|
123
|
+
await dst.write(await src.read())
|
|
124
|
+
elif content:
|
|
125
|
+
# Write the provided content to the file
|
|
126
|
+
async with aiofiles.open(file_path, "wb") as buffer:
|
|
127
|
+
if isinstance(content, str):
|
|
128
|
+
content = content.encode("utf-8")
|
|
129
|
+
await buffer.write(content)
|
|
130
|
+
|
|
131
|
+
# Get the file size
|
|
132
|
+
file_size = file_path.stat().st_size
|
|
133
|
+
# Store the file content in memory
|
|
134
|
+
self.files[file_id] = {
|
|
135
|
+
"id": file_id,
|
|
136
|
+
"path": file_path,
|
|
137
|
+
"name": name,
|
|
138
|
+
"type": mime,
|
|
139
|
+
"size": file_size,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return {"id": file_id}
|
|
90
143
|
|
|
91
144
|
def to_persistable(self) -> Dict:
|
|
92
145
|
from chainlit.user_session import user_sessions
|
|
@@ -94,6 +147,8 @@ class BaseSession:
|
|
|
94
147
|
user_session = user_sessions.get(self.id) or {} # type: Dict
|
|
95
148
|
user_session["chat_settings"] = self.chat_settings
|
|
96
149
|
user_session["chat_profile"] = self.chat_profile
|
|
150
|
+
user_session["http_referer"] = self.http_referer
|
|
151
|
+
user_session["client_type"] = self.client_type
|
|
97
152
|
metadata = clean_metadata(user_session)
|
|
98
153
|
return metadata
|
|
99
154
|
|
|
@@ -108,14 +163,15 @@ class HTTPSession(BaseSession):
|
|
|
108
163
|
client_type: ClientType,
|
|
109
164
|
# Thread id
|
|
110
165
|
thread_id: Optional[str] = None,
|
|
111
|
-
# Logged-in user
|
|
166
|
+
# Logged-in user information
|
|
112
167
|
user: Optional[Union["User", "PersistedUser"]] = None,
|
|
113
168
|
# Logged-in user token
|
|
114
169
|
token: Optional[str] = None,
|
|
115
170
|
user_env: Optional[Dict[str, str]] = None,
|
|
116
|
-
#
|
|
117
|
-
|
|
118
|
-
#
|
|
171
|
+
# Origin of the request
|
|
172
|
+
http_referer: Optional[str] = None,
|
|
173
|
+
# Cookie
|
|
174
|
+
http_cookie: Optional[str] = None,
|
|
119
175
|
):
|
|
120
176
|
super().__init__(
|
|
121
177
|
id=id,
|
|
@@ -124,9 +180,18 @@ class HTTPSession(BaseSession):
|
|
|
124
180
|
token=token,
|
|
125
181
|
client_type=client_type,
|
|
126
182
|
user_env=user_env,
|
|
127
|
-
|
|
183
|
+
http_referer=http_referer,
|
|
184
|
+
http_cookie=http_cookie,
|
|
128
185
|
)
|
|
129
186
|
|
|
187
|
+
def delete(self):
|
|
188
|
+
"""Delete the session."""
|
|
189
|
+
if self.files_dir.is_dir():
|
|
190
|
+
shutil.rmtree(self.files_dir)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
ThreadQueue = Deque[tuple[Callable, object, tuple, Dict]]
|
|
194
|
+
|
|
130
195
|
|
|
131
196
|
class WebsocketSession(BaseSession):
|
|
132
197
|
"""Internal web socket session object.
|
|
@@ -140,6 +205,8 @@ class WebsocketSession(BaseSession):
|
|
|
140
205
|
socket id for convenience.
|
|
141
206
|
"""
|
|
142
207
|
|
|
208
|
+
to_clear: bool = False
|
|
209
|
+
|
|
143
210
|
def __init__(
|
|
144
211
|
self,
|
|
145
212
|
# Id from the session cookie
|
|
@@ -155,14 +222,18 @@ class WebsocketSession(BaseSession):
|
|
|
155
222
|
client_type: ClientType,
|
|
156
223
|
# Thread id
|
|
157
224
|
thread_id: Optional[str] = None,
|
|
158
|
-
# Logged-in user
|
|
225
|
+
# Logged-in user information
|
|
159
226
|
user: Optional[Union["User", "PersistedUser"]] = None,
|
|
160
227
|
# Logged-in user token
|
|
161
228
|
token: Optional[str] = None,
|
|
162
|
-
# Last message at the root of the chat
|
|
163
|
-
root_message: Optional["Message"] = None,
|
|
164
229
|
# Chat profile selected before the session was created
|
|
165
230
|
chat_profile: Optional[str] = None,
|
|
231
|
+
# Languages of the user's browser
|
|
232
|
+
languages: Optional[str] = None,
|
|
233
|
+
# Origin of the request
|
|
234
|
+
http_referer: Optional[str] = None,
|
|
235
|
+
# Cookie
|
|
236
|
+
http_cookie: Optional[str] = None,
|
|
166
237
|
):
|
|
167
238
|
super().__init__(
|
|
168
239
|
id=id,
|
|
@@ -171,76 +242,23 @@ class WebsocketSession(BaseSession):
|
|
|
171
242
|
token=token,
|
|
172
243
|
user_env=user_env,
|
|
173
244
|
client_type=client_type,
|
|
174
|
-
root_message=root_message,
|
|
175
245
|
chat_profile=chat_profile,
|
|
246
|
+
http_referer=http_referer,
|
|
247
|
+
http_cookie=http_cookie,
|
|
176
248
|
)
|
|
177
249
|
|
|
178
250
|
self.socket_id = socket_id
|
|
179
251
|
self.emit_call = emit_call
|
|
180
252
|
self.emit = emit
|
|
181
253
|
|
|
182
|
-
self.should_stop = False
|
|
183
254
|
self.restored = False
|
|
184
255
|
|
|
185
|
-
self.thread_queues
|
|
186
|
-
self.files = {} # type: Dict[str, "FileDict"]
|
|
256
|
+
self.thread_queues: Dict[str, ThreadQueue] = {}
|
|
187
257
|
|
|
188
258
|
ws_sessions_id[self.id] = self
|
|
189
259
|
ws_sessions_sid[socket_id] = self
|
|
190
260
|
|
|
191
|
-
|
|
192
|
-
def files_dir(self):
|
|
193
|
-
from chainlit.config import FILES_DIRECTORY
|
|
194
|
-
|
|
195
|
-
return FILES_DIRECTORY / self.id
|
|
196
|
-
|
|
197
|
-
async def persist_file(
|
|
198
|
-
self,
|
|
199
|
-
name: str,
|
|
200
|
-
mime: str,
|
|
201
|
-
path: Optional[str] = None,
|
|
202
|
-
content: Optional[Union[bytes, str]] = None,
|
|
203
|
-
) -> "FileReference":
|
|
204
|
-
if not path and not content:
|
|
205
|
-
raise ValueError(
|
|
206
|
-
"Either path or content must be provided to persist a file"
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
self.files_dir.mkdir(exist_ok=True)
|
|
210
|
-
|
|
211
|
-
file_id = str(uuid.uuid4())
|
|
212
|
-
|
|
213
|
-
file_path = self.files_dir / file_id
|
|
214
|
-
|
|
215
|
-
file_extension = mimetypes.guess_extension(mime)
|
|
216
|
-
if file_extension:
|
|
217
|
-
file_path = file_path.with_suffix(file_extension)
|
|
218
|
-
|
|
219
|
-
if path:
|
|
220
|
-
# Copy the file from the given path
|
|
221
|
-
async with aiofiles.open(path, "rb") as src, aiofiles.open(
|
|
222
|
-
file_path, "wb"
|
|
223
|
-
) as dst:
|
|
224
|
-
await dst.write(await src.read())
|
|
225
|
-
elif content:
|
|
226
|
-
# Write the provided content to the file
|
|
227
|
-
async with aiofiles.open(file_path, "wb") as buffer:
|
|
228
|
-
if isinstance(content, str):
|
|
229
|
-
content = content.encode("utf-8")
|
|
230
|
-
await buffer.write(content)
|
|
231
|
-
|
|
232
|
-
# Get the file size
|
|
233
|
-
file_size = file_path.stat().st_size
|
|
234
|
-
# Store the file content in memory
|
|
235
|
-
self.files[file_id] = {
|
|
236
|
-
"id": file_id,
|
|
237
|
-
"path": file_path,
|
|
238
|
-
"name": name,
|
|
239
|
-
"type": mime,
|
|
240
|
-
"size": file_size,
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
return {"id": file_id}
|
|
261
|
+
self.languages = languages
|
|
244
262
|
|
|
245
263
|
def restore(self, new_socket_id: str):
|
|
246
264
|
"""Associate a new socket id to the session."""
|