chainlit 0.1.103__tar.gz → 0.2.1__tar.gz
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-0.1.103 → chainlit-0.2.1}/PKG-INFO +2 -2
- {chainlit-0.1.103 → chainlit-0.2.1}/README.md +1 -1
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/__init__.py +47 -80
- chainlit-0.2.1/chainlit/action.py +29 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/client.py +16 -9
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/config.py +5 -3
- chainlit-0.2.1/chainlit/element.py +122 -0
- chainlit-0.1.103/chainlit/frontend/dist/assets/index-2dad8c58.js → chainlit-0.2.1/chainlit/frontend/dist/assets/index-03f89089.js +120 -119
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/frontend/dist/index.html +1 -1
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/lc/utils.py +1 -2
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/sdk.py +14 -85
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/server.py +8 -6
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/types.py +0 -6
- {chainlit-0.1.103 → chainlit-0.2.1}/pyproject.toml +1 -1
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/__main__.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/cli/__init__.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/cli/auth.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/cli/deploy.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/cli/utils.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/frontend/dist/assets/index-bdffdaa0.css +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/frontend/dist/assets/logo_dark-bc7401f6.svg +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/frontend/dist/assets/logo_light-f19fc2ea.svg +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/frontend/dist/favicon.svg +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/hello.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/lc/__init__.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/lc/chainlit_handler.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/lc/monkey.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/lc/new_monkey.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/lc/old_monkey.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/logger.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/markdown.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/session.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/telemetry.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/user_session.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/version.py +0 -0
- {chainlit-0.1.103 → chainlit-0.2.1}/chainlit/watch.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: chainlit
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: A faster way to build chatbot UIs.
|
|
5
5
|
Home-page: https://github.com/Chainlit/chainlit
|
|
6
6
|
License: Apache-2.0 license
|
|
@@ -37,7 +37,7 @@ Description-Content-Type: text/markdown
|
|
|
37
37
|
|
|
38
38
|
**A faster way to build chatbot UIs.**
|
|
39
39
|
|
|
40
|
-
Chainlit lets you create chatbot UIs on top of any Python code in minutes. It’s all Python, open-source, and free!
|
|
40
|
+
Chainlit lets you create chatbot UIs on top of any Python code in minutes. It’s all Python, open-source, and free! Some of the key features include intermediary steps visualisation, element management & display (images, text, carousel, etc.) as well as cloud deployment.
|
|
41
41
|
|
|
42
42
|
[](https://discord.gg/ZThrUxbAYw)
|
|
43
43
|
[](https://twitter.com/chainlit_io)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**A faster way to build chatbot UIs.**
|
|
4
4
|
|
|
5
|
-
Chainlit lets you create chatbot UIs on top of any Python code in minutes. It’s all Python, open-source, and free!
|
|
5
|
+
Chainlit lets you create chatbot UIs on top of any Python code in minutes. It’s all Python, open-source, and free! Some of the key features include intermediary steps visualisation, element management & display (images, text, carousel, etc.) as well as cloud deployment.
|
|
6
6
|
|
|
7
7
|
[](https://discord.gg/ZThrUxbAYw)
|
|
8
8
|
[](https://twitter.com/chainlit_io)
|
|
@@ -8,21 +8,21 @@ from chainlit.lc import monkey
|
|
|
8
8
|
monkey.patch()
|
|
9
9
|
|
|
10
10
|
from chainlit.sdk import get_sdk
|
|
11
|
-
from chainlit.user_session import user_session
|
|
12
11
|
from chainlit.config import config
|
|
13
12
|
from chainlit.types import (
|
|
14
|
-
ElementDisplay,
|
|
15
13
|
LLMSettings,
|
|
16
14
|
AskSpec,
|
|
17
15
|
AskFileSpec,
|
|
18
16
|
AskFileResponse,
|
|
19
17
|
AskResponse,
|
|
20
|
-
Action,
|
|
21
18
|
)
|
|
22
19
|
from chainlit.telemetry import trace
|
|
23
20
|
from chainlit.version import __version__
|
|
24
21
|
from chainlit.logger import logger
|
|
25
22
|
from chainlit.server import socketio
|
|
23
|
+
from chainlit.action import Action
|
|
24
|
+
from chainlit.element import LocalImage, RemoteImage, Text
|
|
25
|
+
from chainlit.user_session import user_session
|
|
26
26
|
from typing import Callable, Any, List, Union
|
|
27
27
|
from dotenv import load_dotenv
|
|
28
28
|
import inspect
|
|
@@ -73,55 +73,6 @@ def wrap_user_function(user_function: Callable, with_task=False) -> Callable:
|
|
|
73
73
|
return wrapper
|
|
74
74
|
|
|
75
75
|
|
|
76
|
-
@trace
|
|
77
|
-
def send_text(text: str, name: str, display: ElementDisplay = "side"):
|
|
78
|
-
"""
|
|
79
|
-
Send a text element to the chatbot UI.
|
|
80
|
-
If a project ID is configured, the element will be uploaded to the cloud storage.
|
|
81
|
-
|
|
82
|
-
Args:
|
|
83
|
-
text (str): The content of the text element.
|
|
84
|
-
name (str): The name of the text element to be displayed in the UI.
|
|
85
|
-
display (ElementDisplay, optional): Determines how the element should be displayed in the UI.
|
|
86
|
-
Choices are "side" (default) or "inline" or "page".
|
|
87
|
-
"""
|
|
88
|
-
sdk = get_sdk()
|
|
89
|
-
if sdk:
|
|
90
|
-
sdk.send_text(text, name, display)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
@trace
|
|
94
|
-
def send_local_image(path: str, name: str, display: ElementDisplay = "side"):
|
|
95
|
-
"""
|
|
96
|
-
Send a local image to the chatbot UI.
|
|
97
|
-
If a project ID is configured, the image will be uploaded to the cloud storage.
|
|
98
|
-
|
|
99
|
-
Args:
|
|
100
|
-
path (str): The local file path of the image.
|
|
101
|
-
name (str): The name of the image to be displayed in the UI.
|
|
102
|
-
display (ElementDisplay, optional): Determines how the image should be displayed in the UI.
|
|
103
|
-
Choices are "side" (default) or "inline" or "page".
|
|
104
|
-
"""
|
|
105
|
-
sdk = get_sdk()
|
|
106
|
-
if sdk:
|
|
107
|
-
sdk.send_local_image(path, name, display)
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
@trace
|
|
111
|
-
def send_image(url: str, name: str, display: ElementDisplay = "side"):
|
|
112
|
-
"""
|
|
113
|
-
Send an image to the chatbot UI.
|
|
114
|
-
Args:
|
|
115
|
-
url (str): The URL of the image.
|
|
116
|
-
name (str): The name of the image to be displayed in the UI.
|
|
117
|
-
display (ElementDisplay, optional): Determines how the image should be displayed in the UI.
|
|
118
|
-
Choices are "side" (default) or "inline" or "page".
|
|
119
|
-
"""
|
|
120
|
-
sdk = get_sdk()
|
|
121
|
-
if sdk:
|
|
122
|
-
sdk.send_image(url, name, display)
|
|
123
|
-
|
|
124
|
-
|
|
125
76
|
@trace
|
|
126
77
|
def send_message(
|
|
127
78
|
content: str,
|
|
@@ -131,6 +82,8 @@ def send_message(
|
|
|
131
82
|
indent=0,
|
|
132
83
|
llm_settings: LLMSettings = None,
|
|
133
84
|
end_stream=False,
|
|
85
|
+
actions: List[Action] = [],
|
|
86
|
+
elements: List[Union[LocalImage, RemoteImage, Text]] = [],
|
|
134
87
|
):
|
|
135
88
|
"""
|
|
136
89
|
Send a message to the chatbot UI.
|
|
@@ -144,10 +97,13 @@ def send_message(
|
|
|
144
97
|
indent (int, optional): If positive, the message will be nested in the UI.
|
|
145
98
|
llm_settings (LLMSettings, optional): Settings of the LLM used to generate the prompt. This is useful for debug purposes in the prompt playground.
|
|
146
99
|
end_stream (bool, optional): Pass True if this message was streamed.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
str: The message ID.
|
|
147
103
|
"""
|
|
148
104
|
sdk = get_sdk()
|
|
149
105
|
if sdk:
|
|
150
|
-
sdk.send_message(
|
|
106
|
+
msg_id = sdk.send_message(
|
|
151
107
|
author=author,
|
|
152
108
|
content=content,
|
|
153
109
|
prompt=prompt,
|
|
@@ -157,6 +113,12 @@ def send_message(
|
|
|
157
113
|
end_stream=end_stream,
|
|
158
114
|
)
|
|
159
115
|
|
|
116
|
+
for action in actions:
|
|
117
|
+
action.send(for_id=msg_id)
|
|
118
|
+
|
|
119
|
+
for element in elements:
|
|
120
|
+
element.send(for_id=msg_id)
|
|
121
|
+
|
|
160
122
|
|
|
161
123
|
@trace
|
|
162
124
|
def send_error_message(content: str, author=config.chatbot_name, indent=0):
|
|
@@ -237,20 +199,6 @@ def ask_for_file(
|
|
|
237
199
|
return None
|
|
238
200
|
|
|
239
201
|
|
|
240
|
-
@trace
|
|
241
|
-
def send_action(name: str, trigger: str, description=""):
|
|
242
|
-
"""
|
|
243
|
-
Send an action to the chatbot UI.
|
|
244
|
-
Args:
|
|
245
|
-
name (str): The name of the action to send.
|
|
246
|
-
trigger (str): The text that should trigger the action when clicked.
|
|
247
|
-
description (str, optional): The description of the action. Defaults to "".
|
|
248
|
-
"""
|
|
249
|
-
sdk = get_sdk()
|
|
250
|
-
if sdk:
|
|
251
|
-
sdk.send_action(name=name, trigger=trigger, description=description)
|
|
252
|
-
|
|
253
|
-
|
|
254
202
|
@trace
|
|
255
203
|
def start_stream(
|
|
256
204
|
author=config.chatbot_name,
|
|
@@ -301,7 +249,6 @@ def langchain_factory(func: Callable) -> Callable:
|
|
|
301
249
|
Returns:
|
|
302
250
|
Callable[[], Any]: The decorated factory function.
|
|
303
251
|
"""
|
|
304
|
-
from chainlit.config import config
|
|
305
252
|
|
|
306
253
|
config.lc_factory = wrap_user_function(func, with_task=True)
|
|
307
254
|
return func
|
|
@@ -311,7 +258,8 @@ def langchain_factory(func: Callable) -> Callable:
|
|
|
311
258
|
def langchain_postprocess(func: Callable[[Any], str]) -> Callable:
|
|
312
259
|
"""
|
|
313
260
|
Useful to post process the response a LangChain object instantiated with @langchain_factory.
|
|
314
|
-
The decorated function takes the raw output of the LangChain object
|
|
261
|
+
The decorated function takes the raw output of the LangChain object as input.
|
|
262
|
+
The response will NOT be automatically sent to the UI, you need to call send_message.
|
|
315
263
|
|
|
316
264
|
Args:
|
|
317
265
|
func (Callable[[Any], str]): The post-processing function to apply after generating a response. Takes the response as parameter.
|
|
@@ -319,7 +267,6 @@ def langchain_postprocess(func: Callable[[Any], str]) -> Callable:
|
|
|
319
267
|
Returns:
|
|
320
268
|
Callable[[Any], str]: The decorated post-processing function.
|
|
321
269
|
"""
|
|
322
|
-
from chainlit.config import config
|
|
323
270
|
|
|
324
271
|
config.lc_postprocess = wrap_user_function(func)
|
|
325
272
|
return func
|
|
@@ -337,7 +284,6 @@ def on_message(func: Callable) -> Callable:
|
|
|
337
284
|
Returns:
|
|
338
285
|
Callable[[str], Any]: The decorated on_message function.
|
|
339
286
|
"""
|
|
340
|
-
from chainlit.config import config
|
|
341
287
|
|
|
342
288
|
config.on_message = wrap_user_function(func)
|
|
343
289
|
return func
|
|
@@ -348,14 +294,14 @@ def langchain_run(func: Callable[[Any, str], str]) -> Callable:
|
|
|
348
294
|
"""
|
|
349
295
|
Useful to override the default behavior of the LangChain object instantiated with @langchain_factory.
|
|
350
296
|
Use when your agent run method has custom parameters.
|
|
351
|
-
|
|
297
|
+
Takes the LangChain agent and the user input as parameters.
|
|
298
|
+
The response will NOT be automatically sent to the UI, you need to call send_message.
|
|
352
299
|
Args:
|
|
353
300
|
func (Callable[[Any, str], str]): The function to be called when a new message is received. Takes the agent and user input as parameters and returns the output string.
|
|
354
301
|
|
|
355
302
|
Returns:
|
|
356
303
|
Callable[[Any, str], Any]: The decorated function.
|
|
357
304
|
"""
|
|
358
|
-
from chainlit.config import config
|
|
359
305
|
|
|
360
306
|
config.lc_run = wrap_user_function(func)
|
|
361
307
|
return func
|
|
@@ -371,7 +317,6 @@ def langchain_rename(func: Callable[[str], str]) -> Callable[[str], str]:
|
|
|
371
317
|
Returns:
|
|
372
318
|
Callable[[Any, str], Any]: The decorated function.
|
|
373
319
|
"""
|
|
374
|
-
from chainlit.config import config
|
|
375
320
|
|
|
376
321
|
config.lc_rename = wrap_user_function(func)
|
|
377
322
|
return func
|
|
@@ -388,7 +333,6 @@ def on_chat_start(func: Callable) -> Callable:
|
|
|
388
333
|
Returns:
|
|
389
334
|
Callable[], Any]: The decorated hook.
|
|
390
335
|
"""
|
|
391
|
-
from chainlit.config import config
|
|
392
336
|
|
|
393
337
|
config.on_chat_start = wrap_user_function(func, with_task=True)
|
|
394
338
|
return func
|
|
@@ -405,20 +349,20 @@ def on_stop(func: Callable) -> Callable:
|
|
|
405
349
|
Returns:
|
|
406
350
|
Callable[[], Any]: The decorated stop hook.
|
|
407
351
|
"""
|
|
408
|
-
from chainlit.config import config
|
|
409
352
|
|
|
410
353
|
config.on_stop = wrap_user_function(func)
|
|
411
354
|
return func
|
|
412
355
|
|
|
413
356
|
|
|
414
|
-
def
|
|
357
|
+
def action_callback(name: str) -> Callable:
|
|
415
358
|
"""
|
|
416
|
-
Callback to call when an action is
|
|
359
|
+
Callback to call when an action is clicked in the UI.
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
func (Callable[[Action], Any]): The action callback to exexute. First parameter is the action.
|
|
417
363
|
"""
|
|
418
364
|
|
|
419
365
|
def decorator(func: Callable[[Action], Any]):
|
|
420
|
-
from chainlit.config import config
|
|
421
|
-
|
|
422
366
|
config.action_callbacks[name] = wrap_user_function(func, with_task=True)
|
|
423
367
|
return func
|
|
424
368
|
|
|
@@ -432,3 +376,26 @@ def sleep(duration: int):
|
|
|
432
376
|
duration (int): The duration in seconds.
|
|
433
377
|
"""
|
|
434
378
|
return socketio.sleep(duration)
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
__all__ = [
|
|
382
|
+
"user_session",
|
|
383
|
+
"Action",
|
|
384
|
+
"LocalImage",
|
|
385
|
+
"RemoteImage",
|
|
386
|
+
"Text",
|
|
387
|
+
"send_message",
|
|
388
|
+
"send_error_message",
|
|
389
|
+
"ask_for_input",
|
|
390
|
+
"ask_for_file",
|
|
391
|
+
"start_stream",
|
|
392
|
+
"send_token",
|
|
393
|
+
"langchain_factory",
|
|
394
|
+
"langchain_postprocess",
|
|
395
|
+
"langchain_run",
|
|
396
|
+
"langchain_rename",
|
|
397
|
+
"on_chat_start",
|
|
398
|
+
"on_stop",
|
|
399
|
+
"action",
|
|
400
|
+
"sleep",
|
|
401
|
+
]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from pydantic.dataclasses import dataclass
|
|
2
|
+
from dataclasses_json import dataclass_json
|
|
3
|
+
from chainlit.sdk import get_emit
|
|
4
|
+
from chainlit.telemetry import trace_event
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass_json
|
|
8
|
+
@dataclass
|
|
9
|
+
class Action:
|
|
10
|
+
name: str
|
|
11
|
+
value: str
|
|
12
|
+
description: str = ""
|
|
13
|
+
forId: str = None
|
|
14
|
+
|
|
15
|
+
def __post_init__(self) -> None:
|
|
16
|
+
trace_event(f"init {self.__class__.__name__}")
|
|
17
|
+
|
|
18
|
+
def send(self, for_id: str):
|
|
19
|
+
emit = get_emit()
|
|
20
|
+
if emit:
|
|
21
|
+
trace_event(f"send {self.__class__.__name__}")
|
|
22
|
+
self.forId = for_id
|
|
23
|
+
emit("action", self.to_dict())
|
|
24
|
+
|
|
25
|
+
def remove(self):
|
|
26
|
+
emit = get_emit()
|
|
27
|
+
if emit:
|
|
28
|
+
trace_event(f"remove {self.__class__.__name__}")
|
|
29
|
+
emit("remove_action", self.to_dict())
|
|
@@ -20,13 +20,18 @@ class BaseClient(ABC):
|
|
|
20
20
|
pass
|
|
21
21
|
|
|
22
22
|
@abstractmethod
|
|
23
|
-
def upload_element(self,
|
|
23
|
+
def upload_element(self, content: bytes) -> int:
|
|
24
24
|
pass
|
|
25
25
|
|
|
26
26
|
@abstractmethod
|
|
27
27
|
def create_element(
|
|
28
|
-
self,
|
|
29
|
-
|
|
28
|
+
self,
|
|
29
|
+
type: ElementType,
|
|
30
|
+
url: str,
|
|
31
|
+
name: str,
|
|
32
|
+
display: str,
|
|
33
|
+
for_id: str = None,
|
|
34
|
+
) -> Dict[str, Any]:
|
|
30
35
|
pass
|
|
31
36
|
|
|
32
37
|
|
|
@@ -95,18 +100,19 @@ class CloudClient(BaseClient):
|
|
|
95
100
|
return int(res["data"]["createMessage"]["id"])
|
|
96
101
|
|
|
97
102
|
def create_element(
|
|
98
|
-
self, type: ElementType, url: str, name: str, display: str
|
|
103
|
+
self, type: ElementType, url: str, name: str, display: str, for_id: str = None
|
|
99
104
|
) -> Dict[str, Any]:
|
|
100
105
|
c_id = self.get_conversation_id()
|
|
101
106
|
|
|
102
107
|
mutation = """
|
|
103
|
-
mutation ($conversationId: ID!, $type: String!, $url: String!, $name: String!, $display: String
|
|
104
|
-
createElement(conversationId: $conversationId, type: $type, url: $url, name: $name, display: $display) {
|
|
108
|
+
mutation ($conversationId: ID!, $type: String!, $url: String!, $name: String!, $display: String!, $forId: String) {
|
|
109
|
+
createElement(conversationId: $conversationId, type: $type, url: $url, name: $name, display: $display, forId: $forId) {
|
|
105
110
|
id,
|
|
106
111
|
type,
|
|
107
112
|
url,
|
|
108
113
|
name,
|
|
109
|
-
display
|
|
114
|
+
display,
|
|
115
|
+
forId
|
|
110
116
|
}
|
|
111
117
|
}
|
|
112
118
|
"""
|
|
@@ -116,12 +122,13 @@ class CloudClient(BaseClient):
|
|
|
116
122
|
"url": url,
|
|
117
123
|
"name": name,
|
|
118
124
|
"display": display,
|
|
125
|
+
"forId": for_id,
|
|
119
126
|
}
|
|
120
127
|
res = self.mutation(mutation, variables)
|
|
121
128
|
return res["data"]["createElement"]
|
|
122
129
|
|
|
123
|
-
def upload_element(self,
|
|
124
|
-
id = f"{uuid.uuid4()}
|
|
130
|
+
def upload_element(self, content: bytes) -> str:
|
|
131
|
+
id = f"{uuid.uuid4()}"
|
|
125
132
|
url = f"{self.url}/api/upload/file"
|
|
126
133
|
body = {"projectId": self.project_id, "fileName": id}
|
|
127
134
|
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
|
-
from typing import Optional, Literal, Any, Callable, List, Dict
|
|
3
|
+
from typing import Optional, Literal, Any, Callable, List, Dict, TYPE_CHECKING
|
|
4
4
|
import tomli
|
|
5
|
-
from chainlit.types import Action
|
|
6
5
|
from pydantic.dataclasses import dataclass
|
|
7
6
|
from importlib import machinery
|
|
8
7
|
from chainlit.logger import logger
|
|
9
8
|
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from chainlit.action import Action
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
# Get the directory the script is running from
|
|
12
14
|
root = os.getcwd()
|
|
@@ -71,7 +73,7 @@ class ChainlitConfig:
|
|
|
71
73
|
# Path to the local langchain cache database
|
|
72
74
|
lc_cache_path: str
|
|
73
75
|
# Developer defined callbacks for each action. Key is the action name, value is the callback function.
|
|
74
|
-
action_callbacks: Dict[str, Callable[[Action], Any]]
|
|
76
|
+
action_callbacks: Dict[str, Callable[["Action"], Any]]
|
|
75
77
|
# Directory where the Chainlit project is located
|
|
76
78
|
root = root
|
|
77
79
|
# Link to your github repo. This will add a github button in the UI's header.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
from pydantic.dataclasses import dataclass
|
|
2
|
+
from dataclasses_json import dataclass_json
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from abc import ABC, abstractmethod
|
|
5
|
+
from chainlit.sdk import get_sdk, BaseClient
|
|
6
|
+
from chainlit.telemetry import trace_event
|
|
7
|
+
from chainlit.types import ElementType, ElementDisplay
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass_json
|
|
11
|
+
@dataclass
|
|
12
|
+
class Element(ABC):
|
|
13
|
+
name: str
|
|
14
|
+
type: ElementType
|
|
15
|
+
display: ElementDisplay = "side"
|
|
16
|
+
forId: str = None
|
|
17
|
+
|
|
18
|
+
def __post_init__(self) -> None:
|
|
19
|
+
trace_event(f"init {self.__class__.__name__}")
|
|
20
|
+
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def persist(self, client: BaseClient, for_id: str = None) -> Dict:
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
def before_emit(self, element: Dict) -> Dict:
|
|
26
|
+
return element
|
|
27
|
+
|
|
28
|
+
def send(self, for_id: str = None):
|
|
29
|
+
sdk = get_sdk()
|
|
30
|
+
|
|
31
|
+
# Cloud is enabled, upload the element to S3
|
|
32
|
+
if sdk.client:
|
|
33
|
+
element = self.persist(sdk.client, for_id)
|
|
34
|
+
else:
|
|
35
|
+
element = self.to_dict()
|
|
36
|
+
if for_id:
|
|
37
|
+
element["forId"] = for_id
|
|
38
|
+
|
|
39
|
+
if sdk.emit and element:
|
|
40
|
+
trace_event(f"send {self.__class__.__name__}")
|
|
41
|
+
element = self.before_emit(element)
|
|
42
|
+
sdk.emit("element", element)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class LocalElementBase:
|
|
47
|
+
content: bytes
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass
|
|
51
|
+
class LocalElement(Element, LocalElementBase):
|
|
52
|
+
def persist(self, client: BaseClient, for_id: str = None):
|
|
53
|
+
url = client.upload_element(content=self.content)
|
|
54
|
+
if url:
|
|
55
|
+
element = client.create_element(
|
|
56
|
+
name=self.name,
|
|
57
|
+
url=url,
|
|
58
|
+
type=self.type,
|
|
59
|
+
display=self.display,
|
|
60
|
+
for_id=for_id,
|
|
61
|
+
)
|
|
62
|
+
return element
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass
|
|
66
|
+
class RemoteElementBase:
|
|
67
|
+
url: str
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dataclass
|
|
71
|
+
class RemoteElement(Element, RemoteElementBase):
|
|
72
|
+
def persist(self, client: BaseClient, for_id: str = None):
|
|
73
|
+
element = client.create_element(
|
|
74
|
+
name=self.name,
|
|
75
|
+
url=self.url,
|
|
76
|
+
type=self.type,
|
|
77
|
+
display=self.display,
|
|
78
|
+
for_id=for_id,
|
|
79
|
+
)
|
|
80
|
+
return element
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class LocalImage(LocalElement):
|
|
84
|
+
def __init__(
|
|
85
|
+
self,
|
|
86
|
+
name: str,
|
|
87
|
+
display: ElementDisplay = "side",
|
|
88
|
+
path: str = None,
|
|
89
|
+
content: bytes = None,
|
|
90
|
+
):
|
|
91
|
+
if path:
|
|
92
|
+
with open(path, "rb") as f:
|
|
93
|
+
self.content = f.read()
|
|
94
|
+
elif content:
|
|
95
|
+
self.content = content
|
|
96
|
+
else:
|
|
97
|
+
raise ValueError("Must provide either path or content")
|
|
98
|
+
|
|
99
|
+
self.name = name
|
|
100
|
+
self.display = display
|
|
101
|
+
self.type = "image"
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class RemoteImage(RemoteElement):
|
|
105
|
+
def __init__(self, name: str, url: str, display: ElementDisplay = "side"):
|
|
106
|
+
self.name = name
|
|
107
|
+
self.display = display
|
|
108
|
+
self.type = "image"
|
|
109
|
+
self.url = url
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class Text(LocalElement):
|
|
113
|
+
def __init__(self, name: str, text: str, display: ElementDisplay = "side"):
|
|
114
|
+
self.name = name
|
|
115
|
+
self.display = display
|
|
116
|
+
self.type = "text"
|
|
117
|
+
self.content = bytes(text, "utf-8")
|
|
118
|
+
|
|
119
|
+
def before_emit(self, text_element):
|
|
120
|
+
if "content" in text_element and isinstance(text_element["content"], bytes):
|
|
121
|
+
text_element["content"] = text_element["content"].decode("utf-8")
|
|
122
|
+
return text_element
|