chainlit 2.7.0__py3-none-any.whl → 2.7.1__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-2.7.0.dist-info → chainlit-2.7.1.dist-info}/METADATA +1 -1
- chainlit-2.7.1.dist-info/RECORD +4 -0
- chainlit/__init__.py +0 -207
- chainlit/__main__.py +0 -4
- chainlit/_utils.py +0 -8
- chainlit/action.py +0 -33
- chainlit/auth/__init__.py +0 -95
- chainlit/auth/cookie.py +0 -197
- chainlit/auth/jwt.py +0 -42
- chainlit/cache.py +0 -45
- chainlit/callbacks.py +0 -433
- chainlit/chat_context.py +0 -64
- chainlit/chat_settings.py +0 -34
- chainlit/cli/__init__.py +0 -235
- chainlit/config.py +0 -621
- chainlit/context.py +0 -112
- chainlit/data/__init__.py +0 -111
- chainlit/data/acl.py +0 -19
- chainlit/data/base.py +0 -107
- chainlit/data/chainlit_data_layer.py +0 -687
- chainlit/data/dynamodb.py +0 -616
- chainlit/data/literalai.py +0 -501
- chainlit/data/sql_alchemy.py +0 -741
- chainlit/data/storage_clients/__init__.py +0 -0
- chainlit/data/storage_clients/azure.py +0 -84
- chainlit/data/storage_clients/azure_blob.py +0 -94
- chainlit/data/storage_clients/base.py +0 -28
- chainlit/data/storage_clients/gcs.py +0 -101
- chainlit/data/storage_clients/s3.py +0 -88
- chainlit/data/utils.py +0 -29
- chainlit/discord/__init__.py +0 -6
- chainlit/discord/app.py +0 -364
- chainlit/element.py +0 -454
- chainlit/emitter.py +0 -450
- chainlit/hello.py +0 -12
- chainlit/input_widget.py +0 -182
- chainlit/langchain/__init__.py +0 -6
- chainlit/langchain/callbacks.py +0 -682
- chainlit/langflow/__init__.py +0 -25
- chainlit/llama_index/__init__.py +0 -6
- chainlit/llama_index/callbacks.py +0 -206
- chainlit/logger.py +0 -16
- chainlit/markdown.py +0 -57
- chainlit/mcp.py +0 -99
- chainlit/message.py +0 -619
- chainlit/mistralai/__init__.py +0 -50
- chainlit/oauth_providers.py +0 -835
- chainlit/openai/__init__.py +0 -53
- chainlit/py.typed +0 -0
- chainlit/secret.py +0 -9
- chainlit/semantic_kernel/__init__.py +0 -111
- chainlit/server.py +0 -1616
- chainlit/session.py +0 -304
- chainlit/sidebar.py +0 -55
- chainlit/slack/__init__.py +0 -6
- chainlit/slack/app.py +0 -427
- chainlit/socket.py +0 -381
- chainlit/step.py +0 -490
- chainlit/sync.py +0 -43
- chainlit/teams/__init__.py +0 -6
- chainlit/teams/app.py +0 -348
- chainlit/translations/bn.json +0 -214
- chainlit/translations/el-GR.json +0 -214
- chainlit/translations/en-US.json +0 -214
- chainlit/translations/fr-FR.json +0 -214
- chainlit/translations/gu.json +0 -214
- chainlit/translations/he-IL.json +0 -214
- chainlit/translations/hi.json +0 -214
- chainlit/translations/ja.json +0 -214
- chainlit/translations/kn.json +0 -214
- chainlit/translations/ml.json +0 -214
- chainlit/translations/mr.json +0 -214
- chainlit/translations/nl.json +0 -214
- chainlit/translations/ta.json +0 -214
- chainlit/translations/te.json +0 -214
- chainlit/translations/zh-CN.json +0 -214
- chainlit/translations.py +0 -60
- chainlit/types.py +0 -334
- chainlit/user.py +0 -43
- chainlit/user_session.py +0 -153
- chainlit/utils.py +0 -173
- chainlit/version.py +0 -8
- chainlit-2.7.0.dist-info/RECORD +0 -84
- {chainlit-2.7.0.dist-info → chainlit-2.7.1.dist-info}/WHEEL +0 -0
- {chainlit-2.7.0.dist-info → chainlit-2.7.1.dist-info}/entry_points.txt +0 -0
chainlit/emitter.py
DELETED
|
@@ -1,450 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import uuid
|
|
3
|
-
from typing import Any, Dict, List, Literal, Optional, Union, cast, get_args
|
|
4
|
-
|
|
5
|
-
from socketio.exceptions import TimeoutError
|
|
6
|
-
|
|
7
|
-
from chainlit.chat_context import chat_context
|
|
8
|
-
from chainlit.config import config
|
|
9
|
-
from chainlit.data import get_data_layer
|
|
10
|
-
from chainlit.element import Element, ElementDict, File
|
|
11
|
-
from chainlit.logger import logger
|
|
12
|
-
from chainlit.message import Message
|
|
13
|
-
from chainlit.session import BaseSession, WebsocketSession
|
|
14
|
-
from chainlit.step import StepDict
|
|
15
|
-
from chainlit.types import (
|
|
16
|
-
AskActionResponse,
|
|
17
|
-
AskElementResponse,
|
|
18
|
-
AskFileSpec,
|
|
19
|
-
AskSpec,
|
|
20
|
-
CommandDict,
|
|
21
|
-
FileDict,
|
|
22
|
-
FileReference,
|
|
23
|
-
MessagePayload,
|
|
24
|
-
OutputAudioChunk,
|
|
25
|
-
ThreadDict,
|
|
26
|
-
ToastType,
|
|
27
|
-
)
|
|
28
|
-
from chainlit.user import PersistedUser
|
|
29
|
-
from chainlit.utils import utc_now
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class BaseChainlitEmitter:
|
|
33
|
-
"""
|
|
34
|
-
Chainlit Emitter Stub class. This class is used for testing purposes.
|
|
35
|
-
It stubs the ChainlitEmitter class and does nothing on function calls.
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
session: BaseSession
|
|
39
|
-
enabled: bool = True
|
|
40
|
-
|
|
41
|
-
def __init__(self, session: BaseSession) -> None:
|
|
42
|
-
"""Initialize with the user session."""
|
|
43
|
-
self.session = session
|
|
44
|
-
|
|
45
|
-
async def emit(self, event: str, data: Any):
|
|
46
|
-
"""Stub method to get the 'emit' property from the session."""
|
|
47
|
-
pass
|
|
48
|
-
|
|
49
|
-
async def emit_call(self):
|
|
50
|
-
"""Stub method to get the 'emit_call' property from the session."""
|
|
51
|
-
pass
|
|
52
|
-
|
|
53
|
-
async def resume_thread(self, thread_dict: ThreadDict):
|
|
54
|
-
"""Stub method to resume a thread."""
|
|
55
|
-
pass
|
|
56
|
-
|
|
57
|
-
async def send_resume_thread_error(self, error: str):
|
|
58
|
-
"""Stub method to send a resume thread error."""
|
|
59
|
-
pass
|
|
60
|
-
|
|
61
|
-
async def send_element(self, element_dict: ElementDict):
|
|
62
|
-
"""Stub method to send an element to the UI."""
|
|
63
|
-
pass
|
|
64
|
-
|
|
65
|
-
async def update_audio_connection(self, state: Literal["on", "off"]):
|
|
66
|
-
"""Audio connection signaling."""
|
|
67
|
-
pass
|
|
68
|
-
|
|
69
|
-
async def send_audio_chunk(self, chunk: OutputAudioChunk):
|
|
70
|
-
"""Stub method to send an audio chunk to the UI."""
|
|
71
|
-
pass
|
|
72
|
-
|
|
73
|
-
async def send_audio_interrupt(self):
|
|
74
|
-
"""Stub method to interrupt the current audio response."""
|
|
75
|
-
pass
|
|
76
|
-
|
|
77
|
-
async def send_step(self, step_dict: StepDict):
|
|
78
|
-
"""Stub method to send a message to the UI."""
|
|
79
|
-
pass
|
|
80
|
-
|
|
81
|
-
async def update_step(self, step_dict: StepDict):
|
|
82
|
-
"""Stub method to update a message in the UI."""
|
|
83
|
-
pass
|
|
84
|
-
|
|
85
|
-
async def delete_step(self, step_dict: StepDict):
|
|
86
|
-
"""Stub method to delete a message in the UI."""
|
|
87
|
-
pass
|
|
88
|
-
|
|
89
|
-
def send_timeout(self, event: Literal["ask_timeout", "call_fn_timeout"]):
|
|
90
|
-
"""Stub method to send a timeout to the UI."""
|
|
91
|
-
pass
|
|
92
|
-
|
|
93
|
-
def clear(self, event: Literal["clear_ask", "clear_call_fn"]):
|
|
94
|
-
pass
|
|
95
|
-
|
|
96
|
-
async def init_thread(self, interaction: str):
|
|
97
|
-
pass
|
|
98
|
-
|
|
99
|
-
async def process_message(self, payload: MessagePayload) -> Message:
|
|
100
|
-
"""Stub method to process user message."""
|
|
101
|
-
return Message(content="")
|
|
102
|
-
|
|
103
|
-
async def send_ask_user(
|
|
104
|
-
self, step_dict: StepDict, spec: AskSpec, raise_on_timeout=False
|
|
105
|
-
) -> Optional[
|
|
106
|
-
Union["StepDict", "AskActionResponse", "AskElementResponse", List["FileDict"]]
|
|
107
|
-
]:
|
|
108
|
-
"""Stub method to send a prompt to the UI and wait for a response."""
|
|
109
|
-
pass
|
|
110
|
-
|
|
111
|
-
async def send_call_fn(
|
|
112
|
-
self, name: str, args: Dict[str, Any], timeout=300, raise_on_timeout=False
|
|
113
|
-
) -> Optional[Dict[str, Any]]:
|
|
114
|
-
"""Stub method to send a call function event to the copilot and wait for a response."""
|
|
115
|
-
pass
|
|
116
|
-
|
|
117
|
-
async def update_token_count(self, count: int):
|
|
118
|
-
"""Stub method to update the token count for the UI."""
|
|
119
|
-
pass
|
|
120
|
-
|
|
121
|
-
async def task_start(self):
|
|
122
|
-
"""Stub method to send a task start signal to the UI."""
|
|
123
|
-
pass
|
|
124
|
-
|
|
125
|
-
async def task_end(self):
|
|
126
|
-
"""Stub method to send a task end signal to the UI."""
|
|
127
|
-
pass
|
|
128
|
-
|
|
129
|
-
async def stream_start(self, step_dict: StepDict):
|
|
130
|
-
"""Stub method to send a stream start signal to the UI."""
|
|
131
|
-
pass
|
|
132
|
-
|
|
133
|
-
async def send_token(self, id: str, token: str, is_sequence=False, is_input=False):
|
|
134
|
-
"""Stub method to send a message token to the UI."""
|
|
135
|
-
pass
|
|
136
|
-
|
|
137
|
-
async def set_chat_settings(self, settings: dict):
|
|
138
|
-
"""Stub method to set chat settings."""
|
|
139
|
-
pass
|
|
140
|
-
|
|
141
|
-
async def set_commands(self, commands: List[CommandDict]):
|
|
142
|
-
"""Stub method to send the available commands to the UI."""
|
|
143
|
-
pass
|
|
144
|
-
|
|
145
|
-
async def send_window_message(self, data: Any):
|
|
146
|
-
"""Stub method to send custom data to the host window."""
|
|
147
|
-
pass
|
|
148
|
-
|
|
149
|
-
def send_toast(self, message: str, type: Optional[ToastType] = "info"):
|
|
150
|
-
"""Stub method to send a toast message to the UI."""
|
|
151
|
-
pass
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
class ChainlitEmitter(BaseChainlitEmitter):
|
|
155
|
-
"""
|
|
156
|
-
Chainlit Emitter class. The Emitter is not directly exposed to the developer.
|
|
157
|
-
Instead, the developer interacts with the Emitter through the methods and classes exposed in the __init__ file.
|
|
158
|
-
"""
|
|
159
|
-
|
|
160
|
-
session: WebsocketSession
|
|
161
|
-
|
|
162
|
-
def __init__(self, session: WebsocketSession) -> None:
|
|
163
|
-
"""Initialize with the user session."""
|
|
164
|
-
self.session = session
|
|
165
|
-
|
|
166
|
-
def _get_session_property(self, property_name: str, raise_error=True):
|
|
167
|
-
"""Helper method to get a property from the session."""
|
|
168
|
-
if not hasattr(self, "session") or not hasattr(self.session, property_name):
|
|
169
|
-
if raise_error:
|
|
170
|
-
raise ValueError(f"Session does not have property '{property_name}'")
|
|
171
|
-
else:
|
|
172
|
-
return None
|
|
173
|
-
return getattr(self.session, property_name)
|
|
174
|
-
|
|
175
|
-
@property
|
|
176
|
-
def emit(self):
|
|
177
|
-
"""Get the 'emit' property from the session."""
|
|
178
|
-
|
|
179
|
-
return self._get_session_property("emit")
|
|
180
|
-
|
|
181
|
-
@property
|
|
182
|
-
def emit_call(self):
|
|
183
|
-
"""Get the 'emit_call' property from the session."""
|
|
184
|
-
return self._get_session_property("emit_call")
|
|
185
|
-
|
|
186
|
-
def resume_thread(self, thread_dict: ThreadDict):
|
|
187
|
-
"""Send a thread to the UI to resume it"""
|
|
188
|
-
return self.emit("resume_thread", thread_dict)
|
|
189
|
-
|
|
190
|
-
def send_resume_thread_error(self, error: str):
|
|
191
|
-
"""Send a thread resume error to the UI"""
|
|
192
|
-
return self.emit("resume_thread_error", error)
|
|
193
|
-
|
|
194
|
-
async def update_audio_connection(self, state: Literal["on", "off"]):
|
|
195
|
-
"""Audio connection signaling."""
|
|
196
|
-
await self.emit("audio_connection", state)
|
|
197
|
-
|
|
198
|
-
async def send_audio_chunk(self, chunk: OutputAudioChunk):
|
|
199
|
-
"""Send an audio chunk to the UI."""
|
|
200
|
-
await self.emit("audio_chunk", chunk)
|
|
201
|
-
|
|
202
|
-
async def send_audio_interrupt(self):
|
|
203
|
-
"""Method to interrupt the current audio response."""
|
|
204
|
-
await self.emit("audio_interrupt", {})
|
|
205
|
-
|
|
206
|
-
async def send_element(self, element_dict: ElementDict):
|
|
207
|
-
"""Stub method to send an element to the UI."""
|
|
208
|
-
await self.emit("element", element_dict)
|
|
209
|
-
|
|
210
|
-
def send_step(self, step_dict: StepDict):
|
|
211
|
-
"""Send a message to the UI."""
|
|
212
|
-
return self.emit("new_message", step_dict)
|
|
213
|
-
|
|
214
|
-
def update_step(self, step_dict: StepDict):
|
|
215
|
-
"""Update a message in the UI."""
|
|
216
|
-
return self.emit("update_message", step_dict)
|
|
217
|
-
|
|
218
|
-
def delete_step(self, step_dict: StepDict):
|
|
219
|
-
"""Delete a message in the UI."""
|
|
220
|
-
return self.emit("delete_message", step_dict)
|
|
221
|
-
|
|
222
|
-
def send_timeout(self, event: Literal["ask_timeout", "call_fn_timeout"]):
|
|
223
|
-
return self.emit(event, {})
|
|
224
|
-
|
|
225
|
-
def clear(self, event: Literal["clear_ask", "clear_call_fn"]):
|
|
226
|
-
return self.emit(event, {})
|
|
227
|
-
|
|
228
|
-
async def flush_thread_queues(self, interaction: str):
|
|
229
|
-
if data_layer := get_data_layer():
|
|
230
|
-
if isinstance(self.session.user, PersistedUser):
|
|
231
|
-
user_id = self.session.user.id
|
|
232
|
-
else:
|
|
233
|
-
user_id = None
|
|
234
|
-
try:
|
|
235
|
-
should_tag_thread = (
|
|
236
|
-
self.session.chat_profile and config.features.auto_tag_thread
|
|
237
|
-
)
|
|
238
|
-
tags = [self.session.chat_profile] if should_tag_thread else None
|
|
239
|
-
await data_layer.update_thread(
|
|
240
|
-
thread_id=self.session.thread_id,
|
|
241
|
-
name=interaction,
|
|
242
|
-
user_id=user_id,
|
|
243
|
-
tags=tags,
|
|
244
|
-
)
|
|
245
|
-
except Exception as e:
|
|
246
|
-
logger.error(f"Error updating thread: {e}")
|
|
247
|
-
asyncio.create_task(self.session.flush_method_queue())
|
|
248
|
-
|
|
249
|
-
async def init_thread(self, interaction: str):
|
|
250
|
-
await self.flush_thread_queues(interaction)
|
|
251
|
-
await self.emit(
|
|
252
|
-
"first_interaction",
|
|
253
|
-
{
|
|
254
|
-
"interaction": interaction,
|
|
255
|
-
"thread_id": self.session.thread_id,
|
|
256
|
-
},
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
async def process_message(self, payload: MessagePayload):
|
|
260
|
-
step_dict = payload["message"]
|
|
261
|
-
file_refs = payload.get("fileReferences")
|
|
262
|
-
# UUID generated by the frontend should use v4
|
|
263
|
-
assert uuid.UUID(step_dict["id"]).version == 4
|
|
264
|
-
|
|
265
|
-
message = Message.from_dict(step_dict)
|
|
266
|
-
# Overwrite the created_at timestamp with the current time
|
|
267
|
-
message.created_at = utc_now()
|
|
268
|
-
chat_context.add(message)
|
|
269
|
-
|
|
270
|
-
asyncio.create_task(message._create())
|
|
271
|
-
|
|
272
|
-
if not self.session.has_first_interaction:
|
|
273
|
-
self.session.has_first_interaction = True
|
|
274
|
-
asyncio.create_task(self.init_thread(message.content))
|
|
275
|
-
|
|
276
|
-
if file_refs:
|
|
277
|
-
files = [
|
|
278
|
-
self.session.files[file["id"]]
|
|
279
|
-
for file in file_refs
|
|
280
|
-
if file["id"] in self.session.files
|
|
281
|
-
]
|
|
282
|
-
|
|
283
|
-
elements = [
|
|
284
|
-
Element.from_dict(
|
|
285
|
-
{
|
|
286
|
-
"id": file["id"],
|
|
287
|
-
"name": file["name"],
|
|
288
|
-
"path": str(file["path"]),
|
|
289
|
-
"chainlitKey": file["id"],
|
|
290
|
-
"display": "inline",
|
|
291
|
-
"type": Element.infer_type_from_mime(file["type"]),
|
|
292
|
-
"mime": file["type"],
|
|
293
|
-
}
|
|
294
|
-
)
|
|
295
|
-
for file in files
|
|
296
|
-
]
|
|
297
|
-
|
|
298
|
-
message.elements = elements
|
|
299
|
-
|
|
300
|
-
async def send_elements():
|
|
301
|
-
for element in message.elements:
|
|
302
|
-
await element.send(for_id=message.id)
|
|
303
|
-
|
|
304
|
-
asyncio.create_task(send_elements())
|
|
305
|
-
|
|
306
|
-
return message
|
|
307
|
-
|
|
308
|
-
async def send_ask_user(
|
|
309
|
-
self, step_dict: StepDict, spec: AskSpec, raise_on_timeout=False
|
|
310
|
-
):
|
|
311
|
-
"""Send a prompt to the UI and wait for a response."""
|
|
312
|
-
parent_id = str(step_dict["parentId"])
|
|
313
|
-
try:
|
|
314
|
-
if spec.type == "file":
|
|
315
|
-
self.session.files_spec[parent_id] = cast(AskFileSpec, spec)
|
|
316
|
-
|
|
317
|
-
# Send the prompt to the UI
|
|
318
|
-
user_res = await self.emit_call(
|
|
319
|
-
"ask", {"msg": step_dict, "spec": spec.to_dict()}, spec.timeout
|
|
320
|
-
) # type: Optional[Union["StepDict", "AskActionResponse", "AskElementResponse", List["FileReference"]]]
|
|
321
|
-
|
|
322
|
-
# End the task temporarily so that the User can answer the prompt
|
|
323
|
-
await self.task_end()
|
|
324
|
-
|
|
325
|
-
final_res: Optional[
|
|
326
|
-
Union[StepDict, AskActionResponse, AskElementResponse, List[FileDict]]
|
|
327
|
-
] = None
|
|
328
|
-
|
|
329
|
-
if user_res:
|
|
330
|
-
interaction: Union[str, None] = None
|
|
331
|
-
if spec.type == "text":
|
|
332
|
-
message_dict_res = cast(StepDict, user_res)
|
|
333
|
-
await self.process_message(
|
|
334
|
-
{"message": message_dict_res, "fileReferences": None}
|
|
335
|
-
)
|
|
336
|
-
interaction = message_dict_res["output"]
|
|
337
|
-
final_res = message_dict_res
|
|
338
|
-
elif spec.type == "file":
|
|
339
|
-
file_refs = cast(List[FileReference], user_res)
|
|
340
|
-
files = [
|
|
341
|
-
self.session.files[file["id"]]
|
|
342
|
-
for file in file_refs
|
|
343
|
-
if file["id"] in self.session.files
|
|
344
|
-
]
|
|
345
|
-
final_res = files
|
|
346
|
-
interaction = ",".join([file["name"] for file in files])
|
|
347
|
-
if get_data_layer():
|
|
348
|
-
coros = [
|
|
349
|
-
File(
|
|
350
|
-
id=file["id"],
|
|
351
|
-
name=file["name"],
|
|
352
|
-
path=str(file["path"]),
|
|
353
|
-
mime=file["type"],
|
|
354
|
-
chainlit_key=file["id"],
|
|
355
|
-
for_id=step_dict["id"],
|
|
356
|
-
)._create()
|
|
357
|
-
for file in files
|
|
358
|
-
]
|
|
359
|
-
await asyncio.gather(*coros)
|
|
360
|
-
elif spec.type == "action":
|
|
361
|
-
action_res = cast(AskActionResponse, user_res)
|
|
362
|
-
final_res = action_res
|
|
363
|
-
interaction = action_res["name"]
|
|
364
|
-
elif spec.type == "element":
|
|
365
|
-
final_res = cast(AskElementResponse, user_res)
|
|
366
|
-
interaction = "custom_element"
|
|
367
|
-
|
|
368
|
-
if not self.session.has_first_interaction and interaction:
|
|
369
|
-
self.session.has_first_interaction = True
|
|
370
|
-
await self.init_thread(interaction=interaction)
|
|
371
|
-
|
|
372
|
-
await self.clear("clear_ask")
|
|
373
|
-
return final_res
|
|
374
|
-
except TimeoutError as e:
|
|
375
|
-
await self.send_timeout("ask_timeout")
|
|
376
|
-
|
|
377
|
-
if raise_on_timeout:
|
|
378
|
-
raise e
|
|
379
|
-
finally:
|
|
380
|
-
if parent_id in self.session.files_spec:
|
|
381
|
-
del self.session.files_spec[parent_id]
|
|
382
|
-
await self.task_start()
|
|
383
|
-
|
|
384
|
-
async def send_call_fn(
|
|
385
|
-
self, name: str, args: Dict[str, Any], timeout=300, raise_on_timeout=False
|
|
386
|
-
) -> Optional[Dict[str, Any]]:
|
|
387
|
-
"""Stub method to send a call function event to the copilot and wait for a response."""
|
|
388
|
-
try:
|
|
389
|
-
call_fn_res = await self.emit_call(
|
|
390
|
-
"call_fn", {"name": name, "args": args}, timeout
|
|
391
|
-
) # type: Dict
|
|
392
|
-
|
|
393
|
-
await self.clear("clear_call_fn")
|
|
394
|
-
return call_fn_res
|
|
395
|
-
except TimeoutError as e:
|
|
396
|
-
await self.send_timeout("call_fn_timeout")
|
|
397
|
-
|
|
398
|
-
if raise_on_timeout:
|
|
399
|
-
raise e
|
|
400
|
-
return None
|
|
401
|
-
|
|
402
|
-
def update_token_count(self, count: int):
|
|
403
|
-
"""Update the token count for the UI."""
|
|
404
|
-
|
|
405
|
-
return self.emit("token_usage", count)
|
|
406
|
-
|
|
407
|
-
def task_start(self):
|
|
408
|
-
"""
|
|
409
|
-
Send a task start signal to the UI.
|
|
410
|
-
"""
|
|
411
|
-
return self.emit("task_start", {})
|
|
412
|
-
|
|
413
|
-
def task_end(self):
|
|
414
|
-
"""Send a task end signal to the UI."""
|
|
415
|
-
return self.emit("task_end", {})
|
|
416
|
-
|
|
417
|
-
def stream_start(self, step_dict: StepDict):
|
|
418
|
-
"""Send a stream start signal to the UI."""
|
|
419
|
-
return self.emit(
|
|
420
|
-
"stream_start",
|
|
421
|
-
step_dict,
|
|
422
|
-
)
|
|
423
|
-
|
|
424
|
-
def send_token(self, id: str, token: str, is_sequence=False, is_input=False):
|
|
425
|
-
"""Send a message token to the UI."""
|
|
426
|
-
return self.emit(
|
|
427
|
-
"stream_token",
|
|
428
|
-
{"id": id, "token": token, "isSequence": is_sequence, "isInput": is_input},
|
|
429
|
-
)
|
|
430
|
-
|
|
431
|
-
def set_chat_settings(self, settings: Dict[str, Any]):
|
|
432
|
-
self.session.chat_settings = settings
|
|
433
|
-
|
|
434
|
-
def set_commands(self, commands: List[CommandDict]):
|
|
435
|
-
"""Send the available commands to the UI."""
|
|
436
|
-
return self.emit(
|
|
437
|
-
"set_commands",
|
|
438
|
-
commands,
|
|
439
|
-
)
|
|
440
|
-
|
|
441
|
-
def send_window_message(self, data: Any):
|
|
442
|
-
"""Send custom data to the host window."""
|
|
443
|
-
return self.emit("window_message", data)
|
|
444
|
-
|
|
445
|
-
def send_toast(self, message: str, type: Optional[ToastType] = "info"):
|
|
446
|
-
"""Send a toast message to the UI."""
|
|
447
|
-
# check that the type is valid using ToastType
|
|
448
|
-
if type not in get_args(ToastType):
|
|
449
|
-
raise ValueError(f"Invalid toast type: {type}")
|
|
450
|
-
return self.emit("toast", {"message": message, "type": type})
|
chainlit/hello.py
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# This is a simple example of a chainlit app.
|
|
2
|
-
|
|
3
|
-
from chainlit import AskUserMessage, Message, on_chat_start
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
@on_chat_start
|
|
7
|
-
async def main():
|
|
8
|
-
res = await AskUserMessage(content="What is your name?", timeout=30).send()
|
|
9
|
-
if res:
|
|
10
|
-
await Message(
|
|
11
|
-
content=f"Your name is: {res['output']}.\nChainlit installation is working!\nYou can now start building your own chainlit apps!",
|
|
12
|
-
).send()
|
chainlit/input_widget.py
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
from abc import abstractmethod
|
|
2
|
-
from typing import Any, Dict, List, Optional
|
|
3
|
-
|
|
4
|
-
from pydantic import Field
|
|
5
|
-
from pydantic.dataclasses import dataclass
|
|
6
|
-
|
|
7
|
-
from chainlit.types import InputWidgetType
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@dataclass
|
|
11
|
-
class InputWidget:
|
|
12
|
-
id: str
|
|
13
|
-
label: str
|
|
14
|
-
initial: Any = None
|
|
15
|
-
tooltip: Optional[str] = None
|
|
16
|
-
description: Optional[str] = None
|
|
17
|
-
|
|
18
|
-
def __post_init__(
|
|
19
|
-
self,
|
|
20
|
-
) -> None:
|
|
21
|
-
if not self.id or not self.label:
|
|
22
|
-
raise ValueError("Must provide key and label to load InputWidget")
|
|
23
|
-
|
|
24
|
-
@abstractmethod
|
|
25
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
26
|
-
pass
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@dataclass
|
|
30
|
-
class Switch(InputWidget):
|
|
31
|
-
"""Useful to create a switch input."""
|
|
32
|
-
|
|
33
|
-
type: InputWidgetType = "switch"
|
|
34
|
-
initial: bool = False
|
|
35
|
-
|
|
36
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
37
|
-
return {
|
|
38
|
-
"type": self.type,
|
|
39
|
-
"id": self.id,
|
|
40
|
-
"label": self.label,
|
|
41
|
-
"initial": self.initial,
|
|
42
|
-
"tooltip": self.tooltip,
|
|
43
|
-
"description": self.description,
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
@dataclass
|
|
48
|
-
class Slider(InputWidget):
|
|
49
|
-
"""Useful to create a slider input."""
|
|
50
|
-
|
|
51
|
-
type: InputWidgetType = "slider"
|
|
52
|
-
initial: float = 0
|
|
53
|
-
min: float = 0
|
|
54
|
-
max: float = 10
|
|
55
|
-
step: float = 1
|
|
56
|
-
|
|
57
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
58
|
-
return {
|
|
59
|
-
"type": self.type,
|
|
60
|
-
"id": self.id,
|
|
61
|
-
"label": self.label,
|
|
62
|
-
"initial": self.initial,
|
|
63
|
-
"min": self.min,
|
|
64
|
-
"max": self.max,
|
|
65
|
-
"step": self.step,
|
|
66
|
-
"tooltip": self.tooltip,
|
|
67
|
-
"description": self.description,
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
@dataclass
|
|
72
|
-
class Select(InputWidget):
|
|
73
|
-
"""Useful to create a select input."""
|
|
74
|
-
|
|
75
|
-
type: InputWidgetType = "select"
|
|
76
|
-
initial: Optional[str] = None
|
|
77
|
-
initial_index: Optional[int] = None
|
|
78
|
-
initial_value: Optional[str] = None
|
|
79
|
-
values: List[str] = Field(default_factory=list)
|
|
80
|
-
items: Dict[str, str] = Field(default_factory=dict)
|
|
81
|
-
|
|
82
|
-
def __post_init__(
|
|
83
|
-
self,
|
|
84
|
-
) -> None:
|
|
85
|
-
super().__post_init__()
|
|
86
|
-
|
|
87
|
-
if not self.values and not self.items:
|
|
88
|
-
raise ValueError("Must provide values or items to create a Select")
|
|
89
|
-
|
|
90
|
-
if self.values and self.items:
|
|
91
|
-
raise ValueError(
|
|
92
|
-
"You can only provide either values or items to create a Select"
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
if not self.values and self.initial_index is not None:
|
|
96
|
-
raise ValueError(
|
|
97
|
-
"Initial_index can only be used in combination with values to create a Select"
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
if self.items:
|
|
101
|
-
self.initial = self.initial_value
|
|
102
|
-
elif self.values:
|
|
103
|
-
self.items = {value: value for value in self.values}
|
|
104
|
-
self.initial = (
|
|
105
|
-
self.values[self.initial_index]
|
|
106
|
-
if self.initial_index is not None
|
|
107
|
-
else self.initial_value
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
111
|
-
return {
|
|
112
|
-
"type": self.type,
|
|
113
|
-
"id": self.id,
|
|
114
|
-
"label": self.label,
|
|
115
|
-
"initial": self.initial,
|
|
116
|
-
"items": [
|
|
117
|
-
{"label": id, "value": value} for id, value in self.items.items()
|
|
118
|
-
],
|
|
119
|
-
"tooltip": self.tooltip,
|
|
120
|
-
"description": self.description,
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
@dataclass
|
|
125
|
-
class TextInput(InputWidget):
|
|
126
|
-
"""Useful to create a text input."""
|
|
127
|
-
|
|
128
|
-
type: InputWidgetType = "textinput"
|
|
129
|
-
initial: Optional[str] = None
|
|
130
|
-
placeholder: Optional[str] = None
|
|
131
|
-
multiline: bool = False
|
|
132
|
-
|
|
133
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
134
|
-
return {
|
|
135
|
-
"type": self.type,
|
|
136
|
-
"id": self.id,
|
|
137
|
-
"label": self.label,
|
|
138
|
-
"initial": self.initial,
|
|
139
|
-
"placeholder": self.placeholder,
|
|
140
|
-
"tooltip": self.tooltip,
|
|
141
|
-
"description": self.description,
|
|
142
|
-
"multiline": self.multiline,
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
@dataclass
|
|
147
|
-
class NumberInput(InputWidget):
|
|
148
|
-
"""Useful to create a number input."""
|
|
149
|
-
|
|
150
|
-
type: InputWidgetType = "numberinput"
|
|
151
|
-
initial: Optional[float] = None
|
|
152
|
-
placeholder: Optional[str] = None
|
|
153
|
-
|
|
154
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
155
|
-
return {
|
|
156
|
-
"type": self.type,
|
|
157
|
-
"id": self.id,
|
|
158
|
-
"label": self.label,
|
|
159
|
-
"initial": self.initial,
|
|
160
|
-
"placeholder": self.placeholder,
|
|
161
|
-
"tooltip": self.tooltip,
|
|
162
|
-
"description": self.description,
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
@dataclass
|
|
167
|
-
class Tags(InputWidget):
|
|
168
|
-
"""Useful to create an input for an array of strings."""
|
|
169
|
-
|
|
170
|
-
type: InputWidgetType = "tags"
|
|
171
|
-
initial: List[str] = Field(default_factory=list)
|
|
172
|
-
values: List[str] = Field(default_factory=list)
|
|
173
|
-
|
|
174
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
175
|
-
return {
|
|
176
|
-
"type": self.type,
|
|
177
|
-
"id": self.id,
|
|
178
|
-
"label": self.label,
|
|
179
|
-
"initial": self.initial,
|
|
180
|
-
"tooltip": self.tooltip,
|
|
181
|
-
"description": self.description,
|
|
182
|
-
}
|