chainlit 1.2.0rc0__py3-none-any.whl → 1.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 +0 -10
- chainlit/auth.py +9 -7
- chainlit/callbacks.py +0 -32
- chainlit/cli/__init__.py +2 -0
- chainlit/config.py +7 -11
- chainlit/context.py +4 -6
- chainlit/copilot/dist/index.js +298 -307
- chainlit/data/__init__.py +11 -6
- chainlit/data/dynamodb.py +7 -3
- chainlit/data/literalai.py +168 -59
- chainlit/data/sql_alchemy.py +89 -15
- chainlit/element.py +2 -1
- chainlit/emitter.py +0 -7
- chainlit/frontend/dist/assets/DailyMotion-CwoOhIL8.js +1 -0
- chainlit/frontend/dist/assets/Facebook-BhnGXlzq.js +1 -0
- chainlit/frontend/dist/assets/FilePlayer-CPSVT6fz.js +1 -0
- chainlit/frontend/dist/assets/Kaltura-COYaLzsL.js +1 -0
- chainlit/frontend/dist/assets/Mixcloud-JdadNiQ5.js +1 -0
- chainlit/frontend/dist/assets/Mux-CBN7RO2u.js +1 -0
- chainlit/frontend/dist/assets/Preview-CxAFvvjV.js +1 -0
- chainlit/frontend/dist/assets/SoundCloud-JlgmASWm.js +1 -0
- chainlit/frontend/dist/assets/Streamable-CUWgr6Zw.js +1 -0
- chainlit/frontend/dist/assets/Twitch-BiN1HEDM.js +1 -0
- chainlit/frontend/dist/assets/Vidyard-qhPmrhDm.js +1 -0
- chainlit/frontend/dist/assets/Vimeo-CrZVSCaT.js +1 -0
- chainlit/frontend/dist/assets/Wistia-C891KrBP.js +1 -0
- chainlit/frontend/dist/assets/YouTube-DKjw5Hbn.js +1 -0
- chainlit/frontend/dist/assets/index-DLRdQOIx.js +723 -0
- chainlit/frontend/dist/assets/{react-plotly-55648373.js → react-plotly-Dpmqg5Sy.js} +94 -94
- chainlit/frontend/dist/index.html +2 -3
- chainlit/haystack/callbacks.py +1 -3
- chainlit/input_widget.py +0 -22
- chainlit/langchain/callbacks.py +1 -2
- chainlit/message.py +1 -1
- chainlit/mistralai/__init__.py +0 -1
- chainlit/oauth_providers.py +46 -3
- chainlit/openai/__init__.py +3 -5
- chainlit/server.py +20 -32
- chainlit/session.py +5 -36
- chainlit/socket.py +2 -51
- chainlit/step.py +13 -20
- chainlit/translations/en-US.json +0 -6
- chainlit/types.py +1 -1
- chainlit/user_session.py +0 -4
- {chainlit-1.2.0rc0.dist-info → chainlit-1.3.0.dist-info}/METADATA +17 -9
- chainlit-1.3.0.dist-info/RECORD +96 -0
- chainlit/assistant.py +0 -16
- chainlit/assistant_settings.py +0 -35
- chainlit/frontend/dist/assets/DailyMotion-aa368b7e.js +0 -1
- chainlit/frontend/dist/assets/Facebook-0335db46.js +0 -1
- chainlit/frontend/dist/assets/FilePlayer-8d04256c.js +0 -1
- chainlit/frontend/dist/assets/Kaltura-67c9dd31.js +0 -1
- chainlit/frontend/dist/assets/Mixcloud-6bbaccf5.js +0 -1
- chainlit/frontend/dist/assets/Mux-c2bcb757.js +0 -1
- chainlit/frontend/dist/assets/Preview-210f3955.js +0 -1
- chainlit/frontend/dist/assets/SoundCloud-a0276b84.js +0 -1
- chainlit/frontend/dist/assets/Streamable-a007323d.js +0 -1
- chainlit/frontend/dist/assets/Twitch-e6a88aa3.js +0 -1
- chainlit/frontend/dist/assets/Vidyard-dfb88a35.js +0 -1
- chainlit/frontend/dist/assets/Vimeo-3baa13d9.js +0 -1
- chainlit/frontend/dist/assets/Wistia-e52f7bef.js +0 -1
- chainlit/frontend/dist/assets/YouTube-1715f22b.js +0 -1
- chainlit/frontend/dist/assets/index-bfdd8585.js +0 -729
- chainlit/translations/fr-FR.json +0 -236
- chainlit-1.2.0rc0.dist-info/RECORD +0 -99
- /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/{index-aaf974a9.css → index-CwmincdQ.css} +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.2.0rc0.dist-info → chainlit-1.3.0.dist-info}/WHEEL +0 -0
- {chainlit-1.2.0rc0.dist-info → chainlit-1.3.0.dist-info}/entry_points.txt +0 -0
|
@@ -21,11 +21,10 @@
|
|
|
21
21
|
<script>
|
|
22
22
|
const global = globalThis;
|
|
23
23
|
</script>
|
|
24
|
-
<script type="module" crossorigin src="/assets/index-
|
|
25
|
-
<link rel="stylesheet" href="/assets/index-
|
|
24
|
+
<script type="module" crossorigin src="/assets/index-DLRdQOIx.js"></script>
|
|
25
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CwmincdQ.css">
|
|
26
26
|
</head>
|
|
27
27
|
<body>
|
|
28
28
|
<div id="root"></div>
|
|
29
|
-
|
|
30
29
|
</body>
|
|
31
30
|
</html>
|
chainlit/haystack/callbacks.py
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import re
|
|
2
2
|
from typing import Any, Generic, List, Optional, TypeVar
|
|
3
3
|
|
|
4
|
-
from chainlit
|
|
4
|
+
from chainlit import Message
|
|
5
5
|
from chainlit.step import Step
|
|
6
6
|
from chainlit.sync import run_sync
|
|
7
7
|
from haystack.agents import Agent, Tool
|
|
8
8
|
from haystack.agents.agent_step import AgentStep
|
|
9
9
|
from literalai.helper import utc_now
|
|
10
10
|
|
|
11
|
-
from chainlit import Message
|
|
12
|
-
|
|
13
11
|
T = TypeVar("T")
|
|
14
12
|
|
|
15
13
|
|
chainlit/input_widget.py
CHANGED
|
@@ -161,28 +161,6 @@ class NumberInput(InputWidget):
|
|
|
161
161
|
"description": self.description,
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
@dataclass
|
|
165
|
-
class FileUploadInput(InputWidget):
|
|
166
|
-
"""Useful to create a file upload input."""
|
|
167
|
-
|
|
168
|
-
type: InputWidgetType = "fileupload"
|
|
169
|
-
initial: Optional[str] = None
|
|
170
|
-
placeholder: Optional[str] = None
|
|
171
|
-
accept: List[str] = Field(default_factory=lambda: [])
|
|
172
|
-
max_size_mb: Optional[int] = None
|
|
173
|
-
max_files: Optional[int] = None
|
|
174
|
-
|
|
175
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
176
|
-
return {
|
|
177
|
-
"type": self.type,
|
|
178
|
-
"id": self.id,
|
|
179
|
-
"label": self.label,
|
|
180
|
-
"initial": self.initial,
|
|
181
|
-
"placeholder": self.placeholder,
|
|
182
|
-
"tooltip": self.tooltip,
|
|
183
|
-
"description": self.description,
|
|
184
|
-
}
|
|
185
|
-
|
|
186
164
|
|
|
187
165
|
@dataclass
|
|
188
166
|
class Tags(InputWidget):
|
chainlit/langchain/callbacks.py
CHANGED
|
@@ -9,11 +9,10 @@ from chainlit.step import Step
|
|
|
9
9
|
from langchain.callbacks.tracers.base import BaseTracer
|
|
10
10
|
from langchain.callbacks.tracers.schemas import Run
|
|
11
11
|
from langchain.schema import BaseMessage
|
|
12
|
-
from langchain.schema.output import ChatGenerationChunk, GenerationChunk
|
|
13
12
|
from langchain_core.outputs import ChatGenerationChunk, GenerationChunk
|
|
14
13
|
from literalai import ChatGeneration, CompletionGeneration, GenerationMessage
|
|
15
14
|
from literalai.helper import utc_now
|
|
16
|
-
from literalai.step import TrueStepType
|
|
15
|
+
from literalai.observability.step import TrueStepType
|
|
17
16
|
|
|
18
17
|
DEFAULT_ANSWER_PREFIX_TOKENS = ["Final", "Answer", ":"]
|
|
19
18
|
|
chainlit/message.py
CHANGED
chainlit/mistralai/__init__.py
CHANGED
chainlit/oauth_providers.py
CHANGED
|
@@ -16,6 +16,7 @@ class OAuthProvider:
|
|
|
16
16
|
client_secret: str
|
|
17
17
|
authorize_url: str
|
|
18
18
|
authorize_params: Dict[str, str]
|
|
19
|
+
default_prompt: Optional[str] = None
|
|
19
20
|
|
|
20
21
|
def is_configured(self):
|
|
21
22
|
return all([os.environ.get(env) for env in self.env])
|
|
@@ -26,6 +27,21 @@ class OAuthProvider:
|
|
|
26
27
|
async def get_user_info(self, token: str) -> Tuple[Dict[str, str], User]:
|
|
27
28
|
raise NotImplementedError()
|
|
28
29
|
|
|
30
|
+
def get_env_prefix(self) -> str:
|
|
31
|
+
"""Return environment prefix, like AZURE_AD."""
|
|
32
|
+
|
|
33
|
+
return self.id.replace("-", "_").upper()
|
|
34
|
+
|
|
35
|
+
def get_prompt(self) -> Optional[str]:
|
|
36
|
+
"""Return OAuth prompt param."""
|
|
37
|
+
if prompt := os.environ.get(f"OAUTH_{self.get_env_prefix()}_PROMPT"):
|
|
38
|
+
return prompt
|
|
39
|
+
|
|
40
|
+
if prompt := os.environ.get("OAUTH_PROMPT"):
|
|
41
|
+
return prompt
|
|
42
|
+
|
|
43
|
+
return self.default_prompt
|
|
44
|
+
|
|
29
45
|
|
|
30
46
|
class GithubOAuthProvider(OAuthProvider):
|
|
31
47
|
id = "github"
|
|
@@ -39,6 +55,9 @@ class GithubOAuthProvider(OAuthProvider):
|
|
|
39
55
|
"scope": "user:email",
|
|
40
56
|
}
|
|
41
57
|
|
|
58
|
+
if prompt := self.get_prompt():
|
|
59
|
+
self.authorize_params["prompt"] = prompt
|
|
60
|
+
|
|
42
61
|
async def get_token(self, code: str, url: str):
|
|
43
62
|
payload = {
|
|
44
63
|
"client_id": self.client_id,
|
|
@@ -97,6 +116,9 @@ class GoogleOAuthProvider(OAuthProvider):
|
|
|
97
116
|
"access_type": "offline",
|
|
98
117
|
}
|
|
99
118
|
|
|
119
|
+
if prompt := self.get_prompt():
|
|
120
|
+
self.authorize_params["prompt"] = prompt
|
|
121
|
+
|
|
100
122
|
async def get_token(self, code: str, url: str):
|
|
101
123
|
payload = {
|
|
102
124
|
"client_id": self.client_id,
|
|
@@ -164,6 +186,9 @@ class AzureADOAuthProvider(OAuthProvider):
|
|
|
164
186
|
"response_mode": "query",
|
|
165
187
|
}
|
|
166
188
|
|
|
189
|
+
if prompt := self.get_prompt():
|
|
190
|
+
self.authorize_params["prompt"] = prompt
|
|
191
|
+
|
|
167
192
|
async def get_token(self, code: str, url: str):
|
|
168
193
|
payload = {
|
|
169
194
|
"client_id": self.client_id,
|
|
@@ -207,7 +232,7 @@ class AzureADOAuthProvider(OAuthProvider):
|
|
|
207
232
|
azure_user["image"] = (
|
|
208
233
|
f"data:{photo_response.headers['Content-Type']};base64,{base64_image.decode('utf-8')}"
|
|
209
234
|
)
|
|
210
|
-
except Exception
|
|
235
|
+
except Exception:
|
|
211
236
|
# Ignore errors getting the photo
|
|
212
237
|
pass
|
|
213
238
|
|
|
@@ -248,6 +273,9 @@ class AzureADHybridOAuthProvider(OAuthProvider):
|
|
|
248
273
|
"nonce": nonce,
|
|
249
274
|
}
|
|
250
275
|
|
|
276
|
+
if prompt := self.get_prompt():
|
|
277
|
+
self.authorize_params["prompt"] = prompt
|
|
278
|
+
|
|
251
279
|
async def get_token(self, code: str, url: str):
|
|
252
280
|
payload = {
|
|
253
281
|
"client_id": self.client_id,
|
|
@@ -291,7 +319,7 @@ class AzureADHybridOAuthProvider(OAuthProvider):
|
|
|
291
319
|
azure_user["image"] = (
|
|
292
320
|
f"data:{photo_response.headers['Content-Type']};base64,{base64_image.decode('utf-8')}"
|
|
293
321
|
)
|
|
294
|
-
except Exception
|
|
322
|
+
except Exception:
|
|
295
323
|
# Ignore errors getting the photo
|
|
296
324
|
pass
|
|
297
325
|
|
|
@@ -327,6 +355,9 @@ class OktaOAuthProvider(OAuthProvider):
|
|
|
327
355
|
"response_mode": "query",
|
|
328
356
|
}
|
|
329
357
|
|
|
358
|
+
if prompt := self.get_prompt():
|
|
359
|
+
self.authorize_params["prompt"] = prompt
|
|
360
|
+
|
|
330
361
|
def get_authorization_server_path(self):
|
|
331
362
|
if not self.authorization_server_id:
|
|
332
363
|
return "/default"
|
|
@@ -398,6 +429,9 @@ class Auth0OAuthProvider(OAuthProvider):
|
|
|
398
429
|
"audience": f"{self.original_domain}/userinfo",
|
|
399
430
|
}
|
|
400
431
|
|
|
432
|
+
if prompt := self.get_prompt():
|
|
433
|
+
self.authorize_params["prompt"] = prompt
|
|
434
|
+
|
|
401
435
|
async def get_token(self, code: str, url: str):
|
|
402
436
|
payload = {
|
|
403
437
|
"client_id": self.client_id,
|
|
@@ -442,7 +476,7 @@ class DescopeOAuthProvider(OAuthProvider):
|
|
|
442
476
|
id = "descope"
|
|
443
477
|
env = ["OAUTH_DESCOPE_CLIENT_ID", "OAUTH_DESCOPE_CLIENT_SECRET"]
|
|
444
478
|
# Ensure that the domain does not have a trailing slash
|
|
445
|
-
domain =
|
|
479
|
+
domain = "https://api.descope.com/oauth2/v1"
|
|
446
480
|
|
|
447
481
|
authorize_url = f"{domain}/authorize"
|
|
448
482
|
|
|
@@ -455,6 +489,9 @@ class DescopeOAuthProvider(OAuthProvider):
|
|
|
455
489
|
"audience": f"{self.domain}/userinfo",
|
|
456
490
|
}
|
|
457
491
|
|
|
492
|
+
if prompt := self.get_prompt():
|
|
493
|
+
self.authorize_params["prompt"] = prompt
|
|
494
|
+
|
|
458
495
|
async def get_token(self, code: str, url: str):
|
|
459
496
|
payload = {
|
|
460
497
|
"client_id": self.client_id,
|
|
@@ -513,6 +550,9 @@ class AWSCognitoOAuthProvider(OAuthProvider):
|
|
|
513
550
|
"scope": "openid profile email",
|
|
514
551
|
}
|
|
515
552
|
|
|
553
|
+
if prompt := self.get_prompt():
|
|
554
|
+
self.authorize_params["prompt"] = prompt
|
|
555
|
+
|
|
516
556
|
async def get_token(self, code: str, url: str):
|
|
517
557
|
payload = {
|
|
518
558
|
"client_id": self.client_id,
|
|
@@ -581,6 +621,9 @@ class GitlabOAuthProvider(OAuthProvider):
|
|
|
581
621
|
"response_type": "code",
|
|
582
622
|
}
|
|
583
623
|
|
|
624
|
+
if prompt := self.get_prompt():
|
|
625
|
+
self.authorize_params["prompt"] = prompt
|
|
626
|
+
|
|
584
627
|
async def get_token(self, code: str, url: str):
|
|
585
628
|
payload = {
|
|
586
629
|
"client_id": self.client_id,
|
chainlit/openai/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from typing import Union
|
|
3
3
|
|
|
4
|
-
from chainlit.context import
|
|
4
|
+
from chainlit.context import local_steps
|
|
5
5
|
from chainlit.step import Step
|
|
6
6
|
from chainlit.utils import check_module_version
|
|
7
7
|
from literalai import ChatGeneration, CompletionGeneration
|
|
@@ -19,11 +19,9 @@ def instrument_openai():
|
|
|
19
19
|
def on_new_generation(
|
|
20
20
|
generation: Union["ChatGeneration", "CompletionGeneration"], timing
|
|
21
21
|
):
|
|
22
|
-
|
|
22
|
+
previous_steps = local_steps.get()
|
|
23
23
|
|
|
24
|
-
parent_id = None
|
|
25
|
-
if context.current_step:
|
|
26
|
-
parent_id = context.current_step.id
|
|
24
|
+
parent_id = previous_steps[-1].id if previous_steps else None
|
|
27
25
|
|
|
28
26
|
step = Step(
|
|
29
27
|
name=generation.model if generation.model else generation.provider,
|
chainlit/server.py
CHANGED
|
@@ -41,6 +41,7 @@ from fastapi import (
|
|
|
41
41
|
APIRouter,
|
|
42
42
|
Depends,
|
|
43
43
|
FastAPI,
|
|
44
|
+
File,
|
|
44
45
|
Form,
|
|
45
46
|
HTTPException,
|
|
46
47
|
Query,
|
|
@@ -228,6 +229,7 @@ app.mount(
|
|
|
228
229
|
name="copilot",
|
|
229
230
|
)
|
|
230
231
|
|
|
232
|
+
|
|
231
233
|
# -------------------------------------------------------------------------------
|
|
232
234
|
# SLACK HANDLER
|
|
233
235
|
# -------------------------------------------------------------------------------
|
|
@@ -644,7 +646,7 @@ async def oauth_azure_hf_callback(
|
|
|
644
646
|
|
|
645
647
|
|
|
646
648
|
_language_pattern = (
|
|
647
|
-
"^[a-zA-Z]{2,3}(-[a-zA-
|
|
649
|
+
"^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,3})?(-[a-zA-Z0-9]{2,8})?(-x-[a-zA-Z0-9]{1,8})?$"
|
|
648
650
|
)
|
|
649
651
|
|
|
650
652
|
|
|
@@ -838,11 +840,9 @@ async def delete_thread(
|
|
|
838
840
|
|
|
839
841
|
@router.post("/project/file")
|
|
840
842
|
async def upload_file(
|
|
843
|
+
current_user: Annotated[Union[User, PersistedUser], Depends(get_current_user)],
|
|
841
844
|
session_id: str,
|
|
842
845
|
file: UploadFile,
|
|
843
|
-
current_user: Annotated[
|
|
844
|
-
Union[None, User, PersistedUser], Depends(get_current_user)
|
|
845
|
-
],
|
|
846
846
|
):
|
|
847
847
|
"""Upload a file to the session files directory."""
|
|
848
848
|
|
|
@@ -867,17 +867,21 @@ async def upload_file(
|
|
|
867
867
|
|
|
868
868
|
content = await file.read()
|
|
869
869
|
|
|
870
|
+
assert file.filename, "No filename for uploaded file"
|
|
871
|
+
assert file.content_type, "No content type for uploaded file"
|
|
872
|
+
|
|
870
873
|
file_response = await session.persist_file(
|
|
871
874
|
name=file.filename, content=content, mime=file.content_type
|
|
872
875
|
)
|
|
873
876
|
|
|
874
|
-
return JSONResponse(file_response)
|
|
877
|
+
return JSONResponse(content=file_response)
|
|
875
878
|
|
|
876
879
|
|
|
877
880
|
@router.get("/project/file/{file_id}")
|
|
878
881
|
async def get_file(
|
|
879
882
|
file_id: str,
|
|
880
|
-
session_id:
|
|
883
|
+
session_id: str,
|
|
884
|
+
current_user: Annotated[Union[User, PersistedUser], Depends(get_current_user)],
|
|
881
885
|
):
|
|
882
886
|
"""Get a file from the session files directory."""
|
|
883
887
|
|
|
@@ -887,10 +891,17 @@ async def get_file(
|
|
|
887
891
|
|
|
888
892
|
if not session:
|
|
889
893
|
raise HTTPException(
|
|
890
|
-
status_code=
|
|
891
|
-
detail="
|
|
894
|
+
status_code=401,
|
|
895
|
+
detail="Unauthorized",
|
|
892
896
|
)
|
|
893
897
|
|
|
898
|
+
if current_user:
|
|
899
|
+
if not session.user or session.user.identifier != current_user.identifier:
|
|
900
|
+
raise HTTPException(
|
|
901
|
+
status_code=401,
|
|
902
|
+
detail="You are not authorized to download files from this session",
|
|
903
|
+
)
|
|
904
|
+
|
|
894
905
|
if file_id in session.files:
|
|
895
906
|
file = session.files[file_id]
|
|
896
907
|
return FileResponse(file["path"], media_type=file["type"])
|
|
@@ -960,7 +971,7 @@ async def get_logo(theme: Optional[Theme] = Query(Theme.light)):
|
|
|
960
971
|
@router.get("/avatars/{avatar_id:str}")
|
|
961
972
|
async def get_avatar(avatar_id: str):
|
|
962
973
|
"""Get the avatar for the user based on the avatar_id."""
|
|
963
|
-
if not re.match(r"^[a-zA-Z0-9_-]+$", avatar_id):
|
|
974
|
+
if not re.match(r"^[a-zA-Z0-9_ -]+$", avatar_id):
|
|
964
975
|
raise HTTPException(status_code=400, detail="Invalid avatar_id")
|
|
965
976
|
|
|
966
977
|
if avatar_id == "default":
|
|
@@ -984,29 +995,6 @@ async def get_avatar(avatar_id: str):
|
|
|
984
995
|
return await get_favicon()
|
|
985
996
|
|
|
986
997
|
|
|
987
|
-
# post avatar/{avatar_id} (only for authenticated users)
|
|
988
|
-
@router.post("/avatars/{avatar_id}")
|
|
989
|
-
async def upload_avatar(
|
|
990
|
-
avatar_id: str,
|
|
991
|
-
file: UploadFile,
|
|
992
|
-
current_user: Annotated[
|
|
993
|
-
Union[None, User, PersistedUser], Depends(get_current_user)
|
|
994
|
-
],
|
|
995
|
-
):
|
|
996
|
-
try:
|
|
997
|
-
avatar_path = os.path.join(APP_ROOT, "public", "avatars", avatar_id)
|
|
998
|
-
|
|
999
|
-
# Ensure the avatars directory exists
|
|
1000
|
-
os.makedirs(os.path.dirname(avatar_path), exist_ok=True)
|
|
1001
|
-
|
|
1002
|
-
with open(avatar_path, "wb") as f:
|
|
1003
|
-
f.write(await file.read())
|
|
1004
|
-
except Exception as e:
|
|
1005
|
-
raise HTTPException(status_code=500, detail=str(e))
|
|
1006
|
-
|
|
1007
|
-
return {"id": avatar_id}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
998
|
@router.head("/")
|
|
1011
999
|
def status_check():
|
|
1012
1000
|
"""Check if the site is operational."""
|
chainlit/session.py
CHANGED
|
@@ -3,26 +3,14 @@ import json
|
|
|
3
3
|
import mimetypes
|
|
4
4
|
import shutil
|
|
5
5
|
import uuid
|
|
6
|
-
from typing import
|
|
7
|
-
TYPE_CHECKING,
|
|
8
|
-
Any,
|
|
9
|
-
Callable,
|
|
10
|
-
Deque,
|
|
11
|
-
Dict,
|
|
12
|
-
List,
|
|
13
|
-
Literal,
|
|
14
|
-
Optional,
|
|
15
|
-
Union,
|
|
16
|
-
)
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Callable, Deque, Dict, Literal, Optional, Union
|
|
17
7
|
|
|
18
8
|
import aiofiles
|
|
19
|
-
from chainlit.assistant import Assistant
|
|
20
9
|
from chainlit.logger import logger
|
|
10
|
+
from chainlit.types import FileReference
|
|
21
11
|
|
|
22
12
|
if TYPE_CHECKING:
|
|
23
|
-
from chainlit.
|
|
24
|
-
from chainlit.step import Step
|
|
25
|
-
from chainlit.types import FileDict, FileReference
|
|
13
|
+
from chainlit.types import FileDict
|
|
26
14
|
from chainlit.user import PersistedUser, User
|
|
27
15
|
|
|
28
16
|
ClientType = Literal["webapp", "copilot", "teams", "slack", "discord"]
|
|
@@ -73,12 +61,8 @@ class BaseSession:
|
|
|
73
61
|
user_env: Optional[Dict[str, str]],
|
|
74
62
|
# Chat profile selected before the session was created
|
|
75
63
|
chat_profile: Optional[str] = None,
|
|
76
|
-
# Selected assistant
|
|
77
|
-
selected_assistant: Optional[Assistant] = None,
|
|
78
64
|
# Origin of the request
|
|
79
65
|
http_referer: Optional[str] = None,
|
|
80
|
-
# assistant settings
|
|
81
|
-
assistant_settings: Optional[Dict[str, Any]] = None,
|
|
82
66
|
):
|
|
83
67
|
if thread_id:
|
|
84
68
|
self.thread_id_to_resume = thread_id
|
|
@@ -91,13 +75,11 @@ class BaseSession:
|
|
|
91
75
|
self.chat_profile = chat_profile
|
|
92
76
|
self.http_referer = http_referer
|
|
93
77
|
|
|
94
|
-
self.files
|
|
78
|
+
self.files: Dict[str, FileDict] = {}
|
|
95
79
|
|
|
96
80
|
self.id = id
|
|
97
81
|
|
|
98
|
-
self.assistant_settings = assistant_settings
|
|
99
82
|
self.chat_settings: Dict[str, Any] = {}
|
|
100
|
-
self.selected_assistant = selected_assistant
|
|
101
83
|
|
|
102
84
|
@property
|
|
103
85
|
def files_dir(self):
|
|
@@ -111,7 +93,7 @@ class BaseSession:
|
|
|
111
93
|
mime: str,
|
|
112
94
|
path: Optional[str] = None,
|
|
113
95
|
content: Optional[Union[bytes, str]] = None,
|
|
114
|
-
) ->
|
|
96
|
+
) -> FileReference:
|
|
115
97
|
if not path and not content:
|
|
116
98
|
raise ValueError(
|
|
117
99
|
"Either path or content must be provided to persist a file"
|
|
@@ -160,7 +142,6 @@ class BaseSession:
|
|
|
160
142
|
user_session = user_sessions.get(self.id) or {} # type: Dict
|
|
161
143
|
user_session["chat_settings"] = self.chat_settings
|
|
162
144
|
user_session["chat_profile"] = self.chat_profile
|
|
163
|
-
user_session["selected_assistant"] = self.selected_assistant
|
|
164
145
|
user_session["http_referer"] = self.http_referer
|
|
165
146
|
user_session["client_type"] = self.client_type
|
|
166
147
|
metadata = clean_metadata(user_session)
|
|
@@ -184,10 +165,6 @@ class HTTPSession(BaseSession):
|
|
|
184
165
|
user_env: Optional[Dict[str, str]] = None,
|
|
185
166
|
# Origin of the request
|
|
186
167
|
http_referer: Optional[str] = None,
|
|
187
|
-
# assistant settings
|
|
188
|
-
assistant_settings: Optional[Dict[str, Any]] = None,
|
|
189
|
-
# selected assistant
|
|
190
|
-
selected_assistant: Optional[Assistant] = None,
|
|
191
168
|
):
|
|
192
169
|
super().__init__(
|
|
193
170
|
id=id,
|
|
@@ -197,8 +174,6 @@ class HTTPSession(BaseSession):
|
|
|
197
174
|
client_type=client_type,
|
|
198
175
|
user_env=user_env,
|
|
199
176
|
http_referer=http_referer,
|
|
200
|
-
assistant_settings=assistant_settings,
|
|
201
|
-
selected_assistant=selected_assistant,
|
|
202
177
|
)
|
|
203
178
|
|
|
204
179
|
def delete(self):
|
|
@@ -245,14 +220,10 @@ class WebsocketSession(BaseSession):
|
|
|
245
220
|
token: Optional[str] = None,
|
|
246
221
|
# Chat profile selected before the session was created
|
|
247
222
|
chat_profile: Optional[str] = None,
|
|
248
|
-
# Selected assistant
|
|
249
|
-
selected_assistant: Optional[Assistant] = None,
|
|
250
223
|
# Languages of the user's browser
|
|
251
224
|
languages: Optional[str] = None,
|
|
252
225
|
# Origin of the request
|
|
253
226
|
http_referer: Optional[str] = None,
|
|
254
|
-
# chat settings
|
|
255
|
-
assistant_settings: Optional[Dict[str, Any]] = None,
|
|
256
227
|
):
|
|
257
228
|
super().__init__(
|
|
258
229
|
id=id,
|
|
@@ -262,9 +233,7 @@ class WebsocketSession(BaseSession):
|
|
|
262
233
|
user_env=user_env,
|
|
263
234
|
client_type=client_type,
|
|
264
235
|
chat_profile=chat_profile,
|
|
265
|
-
selected_assistant=selected_assistant,
|
|
266
236
|
http_referer=http_referer,
|
|
267
|
-
assistant_settings=assistant_settings,
|
|
268
237
|
)
|
|
269
238
|
|
|
270
239
|
self.socket_id = socket_id
|
chainlit/socket.py
CHANGED
|
@@ -6,7 +6,6 @@ from typing import Any, Dict, Literal
|
|
|
6
6
|
from urllib.parse import unquote
|
|
7
7
|
|
|
8
8
|
from chainlit.action import Action
|
|
9
|
-
from chainlit.assistant import Assistant
|
|
10
9
|
from chainlit.auth import get_current_user, require_login
|
|
11
10
|
from chainlit.chat_context import chat_context
|
|
12
11
|
from chainlit.config import config
|
|
@@ -120,7 +119,7 @@ async def connect(sid, environ):
|
|
|
120
119
|
authorization_header = environ.get("HTTP_AUTHORIZATION")
|
|
121
120
|
token = authorization_header.split(" ")[1] if authorization_header else None
|
|
122
121
|
user = await get_current_user(token=token)
|
|
123
|
-
except Exception
|
|
122
|
+
except Exception:
|
|
124
123
|
logger.info("Authentication failed")
|
|
125
124
|
return False
|
|
126
125
|
|
|
@@ -146,7 +145,7 @@ async def connect(sid, environ):
|
|
|
146
145
|
unquote(url_encoded_chat_profile) if url_encoded_chat_profile else None
|
|
147
146
|
)
|
|
148
147
|
|
|
149
|
-
|
|
148
|
+
WebsocketSession(
|
|
150
149
|
id=session_id,
|
|
151
150
|
socket_id=sid,
|
|
152
151
|
emit=emit_fn,
|
|
@@ -407,51 +406,3 @@ async def change_settings(sid, settings: Dict[str, Any]):
|
|
|
407
406
|
|
|
408
407
|
if config.code.on_settings_update:
|
|
409
408
|
await config.code.on_settings_update(settings)
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
@sio.on("on_create_assistant")
|
|
413
|
-
async def on_create_assistant(sid, options):
|
|
414
|
-
context = init_ws_context(sid)
|
|
415
|
-
logger.info(f"Received request to create assistant {options['settings_values']}")
|
|
416
|
-
if not options["settings_values"].get("id"):
|
|
417
|
-
options["settings_values"]["id"] = str(uuid.uuid4())
|
|
418
|
-
if not options["settings_values"].get("created_by"):
|
|
419
|
-
options["settings_values"]["created_by"] = context.session.user.identifier
|
|
420
|
-
logger.info(
|
|
421
|
-
f"Added id: {options['settings_values']['id']} and created_by: {options['settings_values']['created_by']} to the assistant options"
|
|
422
|
-
)
|
|
423
|
-
if config.code.on_create_assistant:
|
|
424
|
-
new_assistant = Assistant(
|
|
425
|
-
input_widgets=options["input_widgets"],
|
|
426
|
-
settings_values=options["settings_values"],
|
|
427
|
-
)
|
|
428
|
-
await config.code.on_create_assistant(context.session.user, new_assistant)
|
|
429
|
-
return new_assistant.to_dict()
|
|
430
|
-
logger.info("Assistant creation process completed")
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
@sio.on("on_list_assistants")
|
|
434
|
-
async def on_list_assistants(sid):
|
|
435
|
-
context = init_ws_context(sid)
|
|
436
|
-
if config.code.on_list_assistants:
|
|
437
|
-
assistants = await config.code.on_list_assistants(context.session.user)
|
|
438
|
-
return [assistant.to_dict() for assistant in assistants]
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
@sio.on("select_assistant")
|
|
442
|
-
async def select_assistant(sid, selected_assistant: Dict):
|
|
443
|
-
session = WebsocketSession.require(sid)
|
|
444
|
-
|
|
445
|
-
new_assistant = Assistant(
|
|
446
|
-
input_widgets=selected_assistant.get("input_widgets", []),
|
|
447
|
-
settings_values=selected_assistant.get("settings_values", {}),
|
|
448
|
-
)
|
|
449
|
-
|
|
450
|
-
session.selected_assistant = new_assistant
|
|
451
|
-
|
|
452
|
-
user_identifier = session.user.identifier if session.user else "Anonymous user"
|
|
453
|
-
logger.info(
|
|
454
|
-
f"{user_identifier} selected assistant {new_assistant.settings_values.get('name', 'Unknown')} for session with id {session.id}"
|
|
455
|
-
)
|
|
456
|
-
|
|
457
|
-
return new_assistant.to_dict()
|
chainlit/step.py
CHANGED
|
@@ -16,7 +16,7 @@ from chainlit.telemetry import trace_event
|
|
|
16
16
|
from chainlit.types import FeedbackDict
|
|
17
17
|
from literalai import BaseGeneration
|
|
18
18
|
from literalai.helper import utc_now
|
|
19
|
-
from literalai.step import StepType, TrueStepType
|
|
19
|
+
from literalai.observability.step import StepType, TrueStepType
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def check_add_step_in_cot(step: "Step"):
|
|
@@ -30,7 +30,7 @@ def check_add_step_in_cot(step: "Step"):
|
|
|
30
30
|
return True
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def stub_step(step: "Step"):
|
|
33
|
+
def stub_step(step: "Step") -> "StepDict":
|
|
34
34
|
return {
|
|
35
35
|
"type": step.type,
|
|
36
36
|
"name": step.name,
|
|
@@ -65,7 +65,7 @@ class StepDict(TypedDict, total=False):
|
|
|
65
65
|
feedback: Optional[FeedbackDict]
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
def flatten_args_kwargs(func,
|
|
68
|
+
def flatten_args_kwargs(func, args, kwargs):
|
|
69
69
|
signature = inspect.signature(func)
|
|
70
70
|
bound_arguments = signature.bind(*args, **kwargs)
|
|
71
71
|
bound_arguments.apply_defaults()
|
|
@@ -189,12 +189,13 @@ class Step:
|
|
|
189
189
|
tags: Optional[List[str]] = None,
|
|
190
190
|
language: Optional[str] = None,
|
|
191
191
|
show_input: Union[bool, str] = "json",
|
|
192
|
+
thread_id: Optional[str] = None,
|
|
192
193
|
):
|
|
193
194
|
trace_event(f"init {self.__class__.__name__} {type}")
|
|
194
195
|
time.sleep(0.001)
|
|
195
196
|
self._input = ""
|
|
196
197
|
self._output = ""
|
|
197
|
-
self.thread_id = context.session.thread_id
|
|
198
|
+
self.thread_id = thread_id or context.session.thread_id
|
|
198
199
|
self.name = name or ""
|
|
199
200
|
self.type = type
|
|
200
201
|
self.id = id or str(uuid.uuid4())
|
|
@@ -433,7 +434,6 @@ class Step:
|
|
|
433
434
|
if not self.parent_id:
|
|
434
435
|
if parent_step:
|
|
435
436
|
self.parent_id = parent_step.id
|
|
436
|
-
context.active_steps.append(self)
|
|
437
437
|
local_steps.set(previous_steps + [self])
|
|
438
438
|
await self.send()
|
|
439
439
|
return self
|
|
@@ -445,13 +445,10 @@ class Step:
|
|
|
445
445
|
self.output = str(exc_val)
|
|
446
446
|
self.is_error = True
|
|
447
447
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
if local_active_steps and self in local_active_steps:
|
|
453
|
-
local_active_steps.remove(self)
|
|
454
|
-
local_steps.set(local_active_steps)
|
|
448
|
+
current_steps = local_steps.get()
|
|
449
|
+
if current_steps and self in current_steps:
|
|
450
|
+
current_steps.remove(self)
|
|
451
|
+
local_steps.set(current_steps)
|
|
455
452
|
|
|
456
453
|
await self.update()
|
|
457
454
|
|
|
@@ -464,7 +461,6 @@ class Step:
|
|
|
464
461
|
if not self.parent_id:
|
|
465
462
|
if parent_step:
|
|
466
463
|
self.parent_id = parent_step.id
|
|
467
|
-
context.active_steps.append(self)
|
|
468
464
|
local_steps.set(previous_steps + [self])
|
|
469
465
|
|
|
470
466
|
asyncio.create_task(self.send())
|
|
@@ -477,12 +473,9 @@ class Step:
|
|
|
477
473
|
self.output = str(exc_val)
|
|
478
474
|
self.is_error = True
|
|
479
475
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
if local_active_steps and self in local_active_steps:
|
|
485
|
-
local_active_steps.remove(self)
|
|
486
|
-
local_steps.set(local_active_steps)
|
|
476
|
+
current_steps = local_steps.get()
|
|
477
|
+
if current_steps and self in current_steps:
|
|
478
|
+
current_steps.remove(self)
|
|
479
|
+
local_steps.set(current_steps)
|
|
487
480
|
|
|
488
481
|
asyncio.create_task(self.update())
|
chainlit/translations/en-US.json
CHANGED
|
@@ -16,9 +16,6 @@
|
|
|
16
16
|
"newChatButton": {
|
|
17
17
|
"newChat": "New Chat"
|
|
18
18
|
},
|
|
19
|
-
"newAssistantButton": {
|
|
20
|
-
"newAssistant": "New Assistant"
|
|
21
|
-
},
|
|
22
19
|
"tasklist": {
|
|
23
20
|
"TaskList": {
|
|
24
21
|
"title": "🗒️ Task List",
|
|
@@ -112,9 +109,6 @@
|
|
|
112
109
|
}
|
|
113
110
|
},
|
|
114
111
|
"organisms": {
|
|
115
|
-
"assistantCreationModal": {
|
|
116
|
-
"title": "Create new assistant"
|
|
117
|
-
},
|
|
118
112
|
"chat": {
|
|
119
113
|
"history": {
|
|
120
114
|
"index": {
|