chainlit 1.0.0rc3__py3-none-any.whl → 1.0.100__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 +14 -1
- chainlit/auth.py +4 -3
- chainlit/config.py +2 -6
- chainlit/data/__init__.py +97 -24
- chainlit/emitter.py +9 -5
- chainlit/frontend/dist/assets/index-c4f40824.js +723 -0
- chainlit/frontend/dist/assets/{react-plotly-c9578a93.js → react-plotly-259d6961.js} +1 -1
- chainlit/frontend/dist/index.html +1 -1
- chainlit/haystack/callbacks.py +32 -6
- chainlit/langchain/callbacks.py +8 -6
- chainlit/llama_index/callbacks.py +13 -5
- chainlit/message.py +1 -1
- chainlit/oauth_providers.py +67 -0
- chainlit/playground/config.py +2 -0
- chainlit/playground/provider.py +1 -1
- chainlit/playground/providers/__init__.py +1 -0
- chainlit/playground/providers/anthropic.py +1 -1
- chainlit/playground/providers/langchain.py +8 -7
- chainlit/playground/providers/vertexai.py +51 -6
- chainlit/server.py +35 -15
- chainlit/session.py +5 -1
- chainlit/socket.py +56 -18
- chainlit/step.py +4 -4
- chainlit/telemetry.py +2 -6
- chainlit/types.py +1 -1
- {chainlit-1.0.0rc3.dist-info → chainlit-1.0.100.dist-info}/METADATA +3 -3
- {chainlit-1.0.0rc3.dist-info → chainlit-1.0.100.dist-info}/RECORD +29 -29
- chainlit/frontend/dist/assets/index-15bb372a.js +0 -697
- {chainlit-1.0.0rc3.dist-info → chainlit-1.0.100.dist-info}/WHEEL +0 -0
- {chainlit-1.0.0rc3.dist-info → chainlit-1.0.100.dist-info}/entry_points.txt +0 -0
chainlit/__init__.py
CHANGED
|
@@ -7,6 +7,7 @@ env_found = load_dotenv(dotenv_path=os.path.join(os.getcwd(), ".env"))
|
|
|
7
7
|
import asyncio
|
|
8
8
|
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional
|
|
9
9
|
|
|
10
|
+
from fastapi import Request, Response
|
|
10
11
|
from starlette.datastructures import Headers
|
|
11
12
|
|
|
12
13
|
if TYPE_CHECKING:
|
|
@@ -54,7 +55,7 @@ from chainlit.user import PersistedUser, User
|
|
|
54
55
|
from chainlit.user_session import user_session
|
|
55
56
|
from chainlit.utils import make_module_getattr, wrap_user_function
|
|
56
57
|
from chainlit.version import __version__
|
|
57
|
-
from
|
|
58
|
+
from literalai import ChatGeneration, CompletionGeneration, GenerationMessage
|
|
58
59
|
|
|
59
60
|
if env_found:
|
|
60
61
|
logger.info("Loaded .env file")
|
|
@@ -127,6 +128,17 @@ def oauth_callback(
|
|
|
127
128
|
return func
|
|
128
129
|
|
|
129
130
|
|
|
131
|
+
@trace
|
|
132
|
+
def on_logout(func: Callable[[Request, Response], Any]) -> Callable:
|
|
133
|
+
"""
|
|
134
|
+
Function called when the user logs out.
|
|
135
|
+
Takes the FastAPI request and response as parameters.
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
config.code.on_logout = wrap_user_function(func)
|
|
139
|
+
return func
|
|
140
|
+
|
|
141
|
+
|
|
130
142
|
@trace
|
|
131
143
|
def on_message(func: Callable) -> Callable:
|
|
132
144
|
"""
|
|
@@ -320,6 +332,7 @@ __all__ = [
|
|
|
320
332
|
"ChatGeneration",
|
|
321
333
|
"CompletionGeneration",
|
|
322
334
|
"GenerationMessage",
|
|
335
|
+
"on_logout",
|
|
323
336
|
"on_chat_start",
|
|
324
337
|
"on_chat_end",
|
|
325
338
|
"on_chat_resume",
|
chainlit/auth.py
CHANGED
|
@@ -20,7 +20,7 @@ def get_jwt_secret():
|
|
|
20
20
|
def ensure_jwt_secret():
|
|
21
21
|
if require_login() and get_jwt_secret() is None:
|
|
22
22
|
raise ValueError(
|
|
23
|
-
"You must provide a JWT secret in the environment to use
|
|
23
|
+
"You must provide a JWT secret in the environment to use authentication. Run `chainlit create-secret` to generate one."
|
|
24
24
|
)
|
|
25
25
|
|
|
26
26
|
|
|
@@ -30,7 +30,8 @@ def is_oauth_enabled():
|
|
|
30
30
|
|
|
31
31
|
def require_login():
|
|
32
32
|
return (
|
|
33
|
-
|
|
33
|
+
bool(os.environ.get("CHAINLIT_CUSTOM_AUTH"))
|
|
34
|
+
or config.code.password_auth_callback is not None
|
|
34
35
|
or config.code.header_auth_callback is not None
|
|
35
36
|
or is_oauth_enabled()
|
|
36
37
|
)
|
|
@@ -74,7 +75,7 @@ async def authenticate_user(token: str = Depends(reuseable_oauth)):
|
|
|
74
75
|
try:
|
|
75
76
|
persisted_user = await data_layer.get_user(user.identifier)
|
|
76
77
|
except Exception as e:
|
|
77
|
-
|
|
78
|
+
return user
|
|
78
79
|
if persisted_user == None:
|
|
79
80
|
raise HTTPException(status_code=401, detail="User does not exist")
|
|
80
81
|
|
chainlit/config.py
CHANGED
|
@@ -15,6 +15,7 @@ if TYPE_CHECKING:
|
|
|
15
15
|
from chainlit.action import Action
|
|
16
16
|
from chainlit.types import ChatProfile, ThreadDict
|
|
17
17
|
from chainlit.user import User
|
|
18
|
+
from fastapi import Request, Response
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
BACKEND_ROOT = os.path.dirname(__file__)
|
|
@@ -118,8 +119,6 @@ hide_cot = false
|
|
|
118
119
|
generated_by = "{__version__}"
|
|
119
120
|
"""
|
|
120
121
|
|
|
121
|
-
chainlit_prod_url = os.environ.get("CHAINLIT_PROD_URL")
|
|
122
|
-
|
|
123
122
|
|
|
124
123
|
DEFAULT_HOST = "0.0.0.0"
|
|
125
124
|
DEFAULT_PORT = 8000
|
|
@@ -200,6 +199,7 @@ class CodeSettings:
|
|
|
200
199
|
oauth_callback: Optional[
|
|
201
200
|
Callable[[str, str, Dict[str, str], "User"], Optional["User"]]
|
|
202
201
|
] = None
|
|
202
|
+
on_logout: Optional[Callable[["Request", "Response"], Any]] = None
|
|
203
203
|
on_stop: Optional[Callable[[], Any]] = None
|
|
204
204
|
on_chat_start: Optional[Callable[[], Any]] = None
|
|
205
205
|
on_chat_end: Optional[Callable[[], Any]] = None
|
|
@@ -234,9 +234,6 @@ class ChainlitConfig:
|
|
|
234
234
|
root = APP_ROOT
|
|
235
235
|
# Chainlit server URL. Used only for cloud features
|
|
236
236
|
chainlit_server: str
|
|
237
|
-
# The url of the deployed app. Only set if the app is deployed.
|
|
238
|
-
chainlit_prod_url = chainlit_prod_url
|
|
239
|
-
|
|
240
237
|
run: RunSettings
|
|
241
238
|
features: FeaturesSettings
|
|
242
239
|
ui: UISettings
|
|
@@ -347,7 +344,6 @@ def load_config():
|
|
|
347
344
|
|
|
348
345
|
config = ChainlitConfig(
|
|
349
346
|
chainlit_server=chainlit_server,
|
|
350
|
-
chainlit_prod_url=chainlit_prod_url,
|
|
351
347
|
run=RunSettings(),
|
|
352
348
|
**settings,
|
|
353
349
|
)
|
chainlit/data/__init__.py
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import os
|
|
3
3
|
from collections import deque
|
|
4
|
-
from typing import TYPE_CHECKING, Dict, List, Optional
|
|
4
|
+
from typing import TYPE_CHECKING, Dict, List, Optional, Union
|
|
5
5
|
|
|
6
|
+
import aiofiles
|
|
6
7
|
from chainlit.config import config
|
|
7
8
|
from chainlit.context import context
|
|
8
9
|
from chainlit.logger import logger
|
|
9
10
|
from chainlit.session import WebsocketSession
|
|
10
11
|
from chainlit.types import Feedback, Pagination, ThreadDict, ThreadFilter
|
|
11
12
|
from chainlit.user import PersistedUser, User, UserDict
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
13
|
+
from literalai import Attachment
|
|
14
|
+
from literalai import Feedback as ClientFeedback
|
|
15
|
+
from literalai import PageInfo, PaginatedResponse
|
|
16
|
+
from literalai import Step as ClientStep
|
|
17
|
+
from literalai.thread import NumberListFilter, StringFilter, StringListFilter
|
|
18
|
+
from literalai.thread import ThreadFilter as ClientThreadFilter
|
|
18
19
|
|
|
19
20
|
if TYPE_CHECKING:
|
|
20
21
|
from chainlit.element import Element, ElementDict
|
|
@@ -112,14 +113,29 @@ class BaseDataLayer:
|
|
|
112
113
|
):
|
|
113
114
|
pass
|
|
114
115
|
|
|
116
|
+
async def create_user_session(
|
|
117
|
+
self,
|
|
118
|
+
id: str,
|
|
119
|
+
started_at: str,
|
|
120
|
+
anon_user_id: str,
|
|
121
|
+
user_id: Optional[str],
|
|
122
|
+
) -> Dict:
|
|
123
|
+
return {}
|
|
124
|
+
|
|
125
|
+
async def update_user_session(
|
|
126
|
+
self, id: str, is_interactive: bool, ended_at: Optional[str]
|
|
127
|
+
) -> Dict:
|
|
128
|
+
return {}
|
|
129
|
+
|
|
130
|
+
async def delete_user_session(self, id: str) -> bool:
|
|
131
|
+
return True
|
|
132
|
+
|
|
115
133
|
|
|
116
134
|
class ChainlitDataLayer:
|
|
117
|
-
def __init__(
|
|
118
|
-
|
|
119
|
-
):
|
|
120
|
-
from chainlit_client import ChainlitClient
|
|
135
|
+
def __init__(self, api_key: str, server: Optional[str]):
|
|
136
|
+
from literalai import LiteralClient
|
|
121
137
|
|
|
122
|
-
self.client =
|
|
138
|
+
self.client = LiteralClient(api_key=api_key, url=server)
|
|
123
139
|
logger.info("Chainlit data layer initialized")
|
|
124
140
|
|
|
125
141
|
def attachment_to_element_dict(self, attachment: Attachment) -> "ElementDict":
|
|
@@ -194,6 +210,8 @@ class ChainlitDataLayer:
|
|
|
194
210
|
_user = await self.client.api.create_user(
|
|
195
211
|
identifier=user.identifier, metadata=user.metadata
|
|
196
212
|
)
|
|
213
|
+
elif _user.id:
|
|
214
|
+
await self.client.api.update_user(id=_user.id, metadata=user.metadata)
|
|
197
215
|
return PersistedUser(
|
|
198
216
|
id=_user.id or "",
|
|
199
217
|
identifier=_user.identifier or "",
|
|
@@ -237,15 +255,38 @@ class ChainlitDataLayer:
|
|
|
237
255
|
if not element.for_id:
|
|
238
256
|
return
|
|
239
257
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
258
|
+
object_key = None
|
|
259
|
+
|
|
260
|
+
if not element.url:
|
|
261
|
+
if element.path:
|
|
262
|
+
async with aiofiles.open(element.path, "rb") as f:
|
|
263
|
+
content = await f.read() # type: Union[bytes, str]
|
|
264
|
+
elif element.content:
|
|
265
|
+
content = element.content
|
|
266
|
+
else:
|
|
267
|
+
raise ValueError("Either path or content must be provided")
|
|
268
|
+
uploaded = await self.client.api.upload_file(
|
|
269
|
+
content=content, mime=element.mime, thread_id=element.thread_id
|
|
270
|
+
)
|
|
271
|
+
object_key = uploaded["object_key"]
|
|
272
|
+
|
|
273
|
+
await self.client.api.send_steps(
|
|
274
|
+
[
|
|
275
|
+
{
|
|
276
|
+
"id": element.for_id,
|
|
277
|
+
"threadId": element.thread_id,
|
|
278
|
+
"attachments": [
|
|
279
|
+
{
|
|
280
|
+
"id": element.id,
|
|
281
|
+
"name": element.name,
|
|
282
|
+
"metadata": metadata,
|
|
283
|
+
"mime": element.mime,
|
|
284
|
+
"url": element.url,
|
|
285
|
+
"objectKey": object_key,
|
|
286
|
+
}
|
|
287
|
+
],
|
|
288
|
+
}
|
|
289
|
+
]
|
|
249
290
|
)
|
|
250
291
|
|
|
251
292
|
async def get_element(
|
|
@@ -342,6 +383,8 @@ class ChainlitDataLayer:
|
|
|
342
383
|
continue
|
|
343
384
|
for attachment in step.attachments:
|
|
344
385
|
elements.append(self.attachment_to_element_dict(attachment))
|
|
386
|
+
if not config.features.prompt_playground and step.generation:
|
|
387
|
+
step.generation = None
|
|
345
388
|
steps.append(self.step_to_step_dict(step))
|
|
346
389
|
|
|
347
390
|
user = None # type: Optional["UserDict"]
|
|
@@ -377,10 +420,40 @@ class ChainlitDataLayer:
|
|
|
377
420
|
tags=tags,
|
|
378
421
|
)
|
|
379
422
|
|
|
423
|
+
async def create_user_session(
|
|
424
|
+
self,
|
|
425
|
+
id: str,
|
|
426
|
+
started_at: str,
|
|
427
|
+
anon_user_id: str,
|
|
428
|
+
user_id: Optional[str],
|
|
429
|
+
) -> Dict:
|
|
430
|
+
existing_session = await self.client.api.get_user_session(id=id)
|
|
431
|
+
if existing_session:
|
|
432
|
+
return existing_session
|
|
433
|
+
session = await self.client.api.create_user_session(
|
|
434
|
+
id=id,
|
|
435
|
+
started_at=started_at,
|
|
436
|
+
participant_identifier=user_id,
|
|
437
|
+
anon_participant_identifier=anon_user_id,
|
|
438
|
+
)
|
|
439
|
+
return session
|
|
440
|
+
|
|
441
|
+
async def update_user_session(
|
|
442
|
+
self, id: str, is_interactive: bool, ended_at: Optional[str]
|
|
443
|
+
) -> Dict:
|
|
444
|
+
session = await self.client.api.update_user_session(
|
|
445
|
+
id=id, is_interactive=is_interactive, ended_at=ended_at
|
|
446
|
+
)
|
|
447
|
+
return session
|
|
448
|
+
|
|
449
|
+
async def delete_user_session(self, id: str) -> bool:
|
|
450
|
+
await self.client.api.delete_user_session(id=id)
|
|
451
|
+
return True
|
|
452
|
+
|
|
380
453
|
|
|
381
|
-
if api_key := os.environ.get("
|
|
382
|
-
|
|
383
|
-
_data_layer = ChainlitDataLayer(api_key=api_key,
|
|
454
|
+
if api_key := os.environ.get("LITERAL_API_KEY"):
|
|
455
|
+
server = os.environ.get("LITERAL_SERVER")
|
|
456
|
+
_data_layer = ChainlitDataLayer(api_key=api_key, server=server)
|
|
384
457
|
|
|
385
458
|
|
|
386
459
|
def get_data_layer():
|
chainlit/emitter.py
CHANGED
|
@@ -5,6 +5,7 @@ from typing import Any, Dict, List, Optional, Union, cast
|
|
|
5
5
|
|
|
6
6
|
from chainlit.data import get_data_layer
|
|
7
7
|
from chainlit.element import Element, File
|
|
8
|
+
from chainlit.logger import logger
|
|
8
9
|
from chainlit.message import Message
|
|
9
10
|
from chainlit.session import BaseSession, WebsocketSession
|
|
10
11
|
from chainlit.step import StepDict
|
|
@@ -172,11 +173,14 @@ class ChainlitEmitter(BaseChainlitEmitter):
|
|
|
172
173
|
user_id = self.session.user.id
|
|
173
174
|
else:
|
|
174
175
|
user_id = None
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
176
|
+
try:
|
|
177
|
+
await data_layer.update_thread(
|
|
178
|
+
thread_id=self.session.thread_id,
|
|
179
|
+
user_id=user_id,
|
|
180
|
+
metadata={"name": interaction},
|
|
181
|
+
)
|
|
182
|
+
except Exception as e:
|
|
183
|
+
logger.error(f"Error updating thread: {e}")
|
|
180
184
|
await self.session.flush_method_queue()
|
|
181
185
|
|
|
182
186
|
async def init_thread(self, interaction: str):
|