chainlit 1.2.0__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/auth.py +9 -7
- chainlit/cli/__init__.py +3 -1
- chainlit/context.py +4 -6
- chainlit/copilot/dist/index.js +252 -261
- chainlit/data/__init__.py +11 -6
- chainlit/data/dynamodb.py +10 -6
- chainlit/data/literalai.py +168 -59
- chainlit/data/sql_alchemy.py +91 -16
- chainlit/element.py +3 -2
- 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-f52a41eb.js → react-plotly-Dpmqg5Sy.js} +94 -94
- chainlit/frontend/dist/index.html +2 -3
- chainlit/haystack/callbacks.py +1 -3
- 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 +19 -9
- chainlit/session.py +8 -19
- chainlit/socket.py +3 -3
- chainlit/step.py +13 -20
- {chainlit-1.2.0.dist-info → chainlit-1.3.0.dist-info}/METADATA +24 -16
- {chainlit-1.2.0.dist-info → chainlit-1.3.0.dist-info}/RECORD +45 -45
- chainlit/frontend/dist/assets/DailyMotion-05f4fe48.js +0 -1
- chainlit/frontend/dist/assets/Facebook-f25411d1.js +0 -1
- chainlit/frontend/dist/assets/FilePlayer-40ff3414.js +0 -1
- chainlit/frontend/dist/assets/Kaltura-6cbf3897.js +0 -1
- chainlit/frontend/dist/assets/Mixcloud-34e7c912.js +0 -1
- chainlit/frontend/dist/assets/Mux-8aaff6ac.js +0 -1
- chainlit/frontend/dist/assets/Preview-2d3bf558.js +0 -1
- chainlit/frontend/dist/assets/SoundCloud-b835f90f.js +0 -1
- chainlit/frontend/dist/assets/Streamable-1293e4f3.js +0 -1
- chainlit/frontend/dist/assets/Twitch-c69660cd.js +0 -1
- chainlit/frontend/dist/assets/Vidyard-43bda599.js +0 -1
- chainlit/frontend/dist/assets/Vimeo-54150039.js +0 -1
- chainlit/frontend/dist/assets/Wistia-aa3c721b.js +0 -1
- chainlit/frontend/dist/assets/YouTube-dd0f3cc2.js +0 -1
- chainlit/frontend/dist/assets/index-cf48bedd.js +0 -729
- /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.0.dist-info → chainlit-1.3.0.dist-info}/WHEEL +0 -0
- {chainlit-1.2.0.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/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,
|
|
@@ -645,7 +646,7 @@ async def oauth_azure_hf_callback(
|
|
|
645
646
|
|
|
646
647
|
|
|
647
648
|
_language_pattern = (
|
|
648
|
-
"^[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})?$"
|
|
649
650
|
)
|
|
650
651
|
|
|
651
652
|
|
|
@@ -839,11 +840,9 @@ async def delete_thread(
|
|
|
839
840
|
|
|
840
841
|
@router.post("/project/file")
|
|
841
842
|
async def upload_file(
|
|
843
|
+
current_user: Annotated[Union[User, PersistedUser], Depends(get_current_user)],
|
|
842
844
|
session_id: str,
|
|
843
845
|
file: UploadFile,
|
|
844
|
-
current_user: Annotated[
|
|
845
|
-
Union[None, User, PersistedUser], Depends(get_current_user)
|
|
846
|
-
],
|
|
847
846
|
):
|
|
848
847
|
"""Upload a file to the session files directory."""
|
|
849
848
|
|
|
@@ -868,17 +867,21 @@ async def upload_file(
|
|
|
868
867
|
|
|
869
868
|
content = await file.read()
|
|
870
869
|
|
|
870
|
+
assert file.filename, "No filename for uploaded file"
|
|
871
|
+
assert file.content_type, "No content type for uploaded file"
|
|
872
|
+
|
|
871
873
|
file_response = await session.persist_file(
|
|
872
874
|
name=file.filename, content=content, mime=file.content_type
|
|
873
875
|
)
|
|
874
876
|
|
|
875
|
-
return JSONResponse(file_response)
|
|
877
|
+
return JSONResponse(content=file_response)
|
|
876
878
|
|
|
877
879
|
|
|
878
880
|
@router.get("/project/file/{file_id}")
|
|
879
881
|
async def get_file(
|
|
880
882
|
file_id: str,
|
|
881
|
-
session_id:
|
|
883
|
+
session_id: str,
|
|
884
|
+
current_user: Annotated[Union[User, PersistedUser], Depends(get_current_user)],
|
|
882
885
|
):
|
|
883
886
|
"""Get a file from the session files directory."""
|
|
884
887
|
|
|
@@ -888,10 +891,17 @@ async def get_file(
|
|
|
888
891
|
|
|
889
892
|
if not session:
|
|
890
893
|
raise HTTPException(
|
|
891
|
-
status_code=
|
|
892
|
-
detail="
|
|
894
|
+
status_code=401,
|
|
895
|
+
detail="Unauthorized",
|
|
893
896
|
)
|
|
894
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
|
+
|
|
895
905
|
if file_id in session.files:
|
|
896
906
|
file = session.files[file_id]
|
|
897
907
|
return FileResponse(file["path"], media_type=file["type"])
|
|
@@ -961,7 +971,7 @@ async def get_logo(theme: Optional[Theme] = Query(Theme.light)):
|
|
|
961
971
|
@router.get("/avatars/{avatar_id:str}")
|
|
962
972
|
async def get_avatar(avatar_id: str):
|
|
963
973
|
"""Get the avatar for the user based on the avatar_id."""
|
|
964
|
-
if not re.match(r"^[a-zA-Z0-9_-]+$", avatar_id):
|
|
974
|
+
if not re.match(r"^[a-zA-Z0-9_ -]+$", avatar_id):
|
|
965
975
|
raise HTTPException(status_code=400, detail="Invalid avatar_id")
|
|
966
976
|
|
|
967
977
|
if avatar_id == "default":
|
chainlit/session.py
CHANGED
|
@@ -3,25 +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
9
|
from chainlit.logger import logger
|
|
10
|
+
from chainlit.types import FileReference
|
|
20
11
|
|
|
21
12
|
if TYPE_CHECKING:
|
|
22
|
-
from chainlit.
|
|
23
|
-
from chainlit.step import Step
|
|
24
|
-
from chainlit.types import FileDict, FileReference
|
|
13
|
+
from chainlit.types import FileDict
|
|
25
14
|
from chainlit.user import PersistedUser, User
|
|
26
15
|
|
|
27
16
|
ClientType = Literal["webapp", "copilot", "teams", "slack", "discord"]
|
|
@@ -64,7 +53,7 @@ class BaseSession:
|
|
|
64
53
|
client_type: ClientType,
|
|
65
54
|
# Thread id
|
|
66
55
|
thread_id: Optional[str],
|
|
67
|
-
# Logged-in user
|
|
56
|
+
# Logged-in user information
|
|
68
57
|
user: Optional[Union["User", "PersistedUser"]],
|
|
69
58
|
# Logged-in user token
|
|
70
59
|
token: Optional[str],
|
|
@@ -86,7 +75,7 @@ class BaseSession:
|
|
|
86
75
|
self.chat_profile = chat_profile
|
|
87
76
|
self.http_referer = http_referer
|
|
88
77
|
|
|
89
|
-
self.files
|
|
78
|
+
self.files: Dict[str, FileDict] = {}
|
|
90
79
|
|
|
91
80
|
self.id = id
|
|
92
81
|
|
|
@@ -104,7 +93,7 @@ class BaseSession:
|
|
|
104
93
|
mime: str,
|
|
105
94
|
path: Optional[str] = None,
|
|
106
95
|
content: Optional[Union[bytes, str]] = None,
|
|
107
|
-
) ->
|
|
96
|
+
) -> FileReference:
|
|
108
97
|
if not path and not content:
|
|
109
98
|
raise ValueError(
|
|
110
99
|
"Either path or content must be provided to persist a file"
|
|
@@ -169,7 +158,7 @@ class HTTPSession(BaseSession):
|
|
|
169
158
|
client_type: ClientType,
|
|
170
159
|
# Thread id
|
|
171
160
|
thread_id: Optional[str] = None,
|
|
172
|
-
# Logged-in user
|
|
161
|
+
# Logged-in user information
|
|
173
162
|
user: Optional[Union["User", "PersistedUser"]] = None,
|
|
174
163
|
# Logged-in user token
|
|
175
164
|
token: Optional[str] = None,
|
|
@@ -225,7 +214,7 @@ class WebsocketSession(BaseSession):
|
|
|
225
214
|
client_type: ClientType,
|
|
226
215
|
# Thread id
|
|
227
216
|
thread_id: Optional[str] = None,
|
|
228
|
-
# Logged-in user
|
|
217
|
+
# Logged-in user information
|
|
229
218
|
user: Optional[Union["User", "PersistedUser"]] = None,
|
|
230
219
|
# Logged-in user token
|
|
231
220
|
token: Optional[str] = None,
|
chainlit/socket.py
CHANGED
|
@@ -119,7 +119,7 @@ async def connect(sid, environ):
|
|
|
119
119
|
authorization_header = environ.get("HTTP_AUTHORIZATION")
|
|
120
120
|
token = authorization_header.split(" ")[1] if authorization_header else None
|
|
121
121
|
user = await get_current_user(token=token)
|
|
122
|
-
except Exception
|
|
122
|
+
except Exception:
|
|
123
123
|
logger.info("Authentication failed")
|
|
124
124
|
return False
|
|
125
125
|
|
|
@@ -145,7 +145,7 @@ async def connect(sid, environ):
|
|
|
145
145
|
unquote(url_encoded_chat_profile) if url_encoded_chat_profile else None
|
|
146
146
|
)
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
WebsocketSession(
|
|
149
149
|
id=session_id,
|
|
150
150
|
socket_id=sid,
|
|
151
151
|
emit=emit_fn,
|
|
@@ -392,7 +392,7 @@ async def call_action(sid, action):
|
|
|
392
392
|
except Exception as e:
|
|
393
393
|
logger.exception(e)
|
|
394
394
|
await context.emitter.send_action_response(
|
|
395
|
-
id=action.id, status=False, response="An error
|
|
395
|
+
id=action.id, status=False, response="An error occurred"
|
|
396
396
|
)
|
|
397
397
|
|
|
398
398
|
|
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())
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: chainlit
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Build Conversational AI.
|
|
5
|
-
Home-page: https://
|
|
6
|
-
License:
|
|
5
|
+
Home-page: https://chainlit.io/
|
|
6
|
+
License: Apache-2.0
|
|
7
7
|
Keywords: LLM,Agents,gen ai,chat ui,chatbot ui,openai,copilot,langchain,conversational ai
|
|
8
|
-
Author:
|
|
8
|
+
Author: Willy Douhard
|
|
9
9
|
Requires-Python: >=3.9,<4.0.0
|
|
10
|
+
Classifier: Environment :: Web Environment
|
|
11
|
+
Classifier: Framework :: FastAPI
|
|
10
12
|
Classifier: License :: Other/Proprietary License
|
|
13
|
+
Classifier: Programming Language :: JavaScript
|
|
11
14
|
Classifier: Programming Language :: Python :: 3
|
|
12
15
|
Classifier: Programming Language :: Python :: 3.9
|
|
13
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Communications :: Chat
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
16
23
|
Requires-Dist: aiofiles (>=23.1.0,<24.0.0)
|
|
17
24
|
Requires-Dist: asyncer (>=0.0.7,<0.0.8)
|
|
18
25
|
Requires-Dist: click (>=8.1.3,<9.0.0)
|
|
@@ -21,7 +28,7 @@ Requires-Dist: fastapi (>=0.110.1,<0.113)
|
|
|
21
28
|
Requires-Dist: filetype (>=1.2.0,<2.0.0)
|
|
22
29
|
Requires-Dist: httpx (>=0.23.0)
|
|
23
30
|
Requires-Dist: lazify (>=0.4.0,<0.5.0)
|
|
24
|
-
Requires-Dist: literalai (==0.0.
|
|
31
|
+
Requires-Dist: literalai (==0.0.623)
|
|
25
32
|
Requires-Dist: nest-asyncio (>=1.6.0,<2.0.0)
|
|
26
33
|
Requires-Dist: numpy (>=1.26,<2.0)
|
|
27
34
|
Requires-Dist: packaging (>=23.1,<24.0)
|
|
@@ -36,6 +43,7 @@ Requires-Dist: tomli (>=2.0.1,<3.0.0)
|
|
|
36
43
|
Requires-Dist: uptrace (>=1.22.0,<2.0.0)
|
|
37
44
|
Requires-Dist: uvicorn (>=0.25.0,<0.26.0)
|
|
38
45
|
Requires-Dist: watchfiles (>=0.20.0,<0.21.0)
|
|
46
|
+
Project-URL: Documentation, https://docs.chainlit.io/
|
|
39
47
|
Project-URL: Repository, https://github.com/Chainlit/chainlit
|
|
40
48
|
Description-Content-Type: text/markdown
|
|
41
49
|
|
|
@@ -60,20 +68,21 @@ Chainlit is an open-source async Python framework which allows developers to bui
|
|
|
60
68
|
Full documentation is available [here](https://docs.chainlit.io). You can ask Chainlit related questions to [Chainlit Help](https://help.chainlit.io/), an app built using Chainlit!
|
|
61
69
|
|
|
62
70
|
> [!NOTE]
|
|
63
|
-
> Contact us [here](https://forms.gle/BX3UNBLmTF75KgZVA) for **Enterprise Support**.
|
|
64
71
|
> Check out [Literal AI](https://literalai.com), our product to monitor and evaluate LLM applications! It works with any Python or TypeScript applications and [seamlessly](https://docs.chainlit.io/data-persistence/overview) with Chainlit by adding a `LITERAL_API_KEY` in your project.
|
|
72
|
+
>
|
|
73
|
+
> Chainlit is developed and maintained by the Literal AI team, which is currently focused on expanding the capabilities of Literal AI. While we continue to support and maintain Chainlit, we are also committed to enabling the community to contribute, particularly in areas like integrations and data layers.
|
|
65
74
|
|
|
66
75
|
<p align="center">
|
|
67
|
-
<img src="https://github.com/Chainlit/chainlit/assets/13104895/0c2cc7a9-766c-41d3-aae2-117a2d0eb8ed" width="80%"
|
|
76
|
+
<img src="https://github.com/Chainlit/chainlit/assets/13104895/0c2cc7a9-766c-41d3-aae2-117a2d0eb8ed" alt="Chainlit user interface" width="80%"></img>
|
|
68
77
|
</p>
|
|
69
78
|
|
|
70
79
|
## Installation
|
|
71
80
|
|
|
72
81
|
Open a terminal and run:
|
|
73
82
|
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
|
|
83
|
+
```sh
|
|
84
|
+
pip install chainlit
|
|
85
|
+
chainlit hello
|
|
77
86
|
```
|
|
78
87
|
|
|
79
88
|
If this opens the `hello app` in your browser, you're all set!
|
|
@@ -108,18 +117,17 @@ async def main(message: cl.Message):
|
|
|
108
117
|
None.
|
|
109
118
|
"""
|
|
110
119
|
|
|
111
|
-
final_answer = await cl.Message(content="").send()
|
|
112
120
|
|
|
113
121
|
# Call the tool
|
|
114
|
-
|
|
122
|
+
tool_res = await tool()
|
|
115
123
|
|
|
116
|
-
await
|
|
124
|
+
await cl.Message(content=tool_res).send()
|
|
117
125
|
```
|
|
118
126
|
|
|
119
127
|
Now run it!
|
|
120
128
|
|
|
121
|
-
```
|
|
122
|
-
|
|
129
|
+
```sh
|
|
130
|
+
chainlit run demo.py -w
|
|
123
131
|
```
|
|
124
132
|
|
|
125
133
|
<img src="/images/quick-start.png" alt="Quick Start"></img>
|
|
@@ -129,7 +137,7 @@ $ chainlit run demo.py -w
|
|
|
129
137
|
Full documentation is available [here](https://docs.chainlit.io). Key features:
|
|
130
138
|
|
|
131
139
|
- [💬 Multi Modal chats](https://docs.chainlit.io/advanced-features/multi-modal)
|
|
132
|
-
- [💭 Chain of Thought
|
|
140
|
+
- [💭 Chain of Thought visualization](https://docs.chainlit.io/concepts/step)
|
|
133
141
|
- [💾 Data persistence + human feedback](https://docs.chainlit.io/data-persistence/overview)
|
|
134
142
|
- [🐛 Debug Mode](https://docs.chainlit.io/data-persistence/enterprise#debug-mode)
|
|
135
143
|
- [👤 Authentication](https://docs.chainlit.io/authentication/overview)
|