chainlit 0.7.700__py3-none-any.whl → 1.0.0rc1__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 +32 -23
- chainlit/auth.py +9 -10
- chainlit/cli/__init__.py +1 -2
- chainlit/config.py +13 -12
- chainlit/context.py +7 -3
- chainlit/data/__init__.py +375 -9
- chainlit/data/acl.py +6 -5
- chainlit/element.py +86 -123
- chainlit/emitter.py +117 -50
- chainlit/frontend/dist/assets/{index-71698725.js → index-6aee009a.js} +118 -292
- chainlit/frontend/dist/assets/{react-plotly-2c0acdf0.js → react-plotly-2f07c02a.js} +1 -1
- chainlit/frontend/dist/index.html +1 -1
- chainlit/haystack/callbacks.py +45 -43
- chainlit/hello.py +1 -1
- chainlit/langchain/callbacks.py +132 -120
- chainlit/llama_index/callbacks.py +68 -48
- chainlit/message.py +179 -207
- chainlit/oauth_providers.py +39 -34
- chainlit/playground/provider.py +44 -30
- chainlit/playground/providers/anthropic.py +4 -4
- chainlit/playground/providers/huggingface.py +2 -2
- chainlit/playground/providers/langchain.py +8 -10
- chainlit/playground/providers/openai.py +19 -13
- chainlit/server.py +155 -99
- chainlit/session.py +109 -40
- chainlit/socket.py +47 -36
- chainlit/step.py +393 -0
- chainlit/types.py +78 -21
- chainlit/user.py +32 -0
- chainlit/user_session.py +1 -5
- {chainlit-0.7.700.dist-info → chainlit-1.0.0rc1.dist-info}/METADATA +12 -31
- chainlit-1.0.0rc1.dist-info/RECORD +60 -0
- chainlit/client/base.py +0 -169
- chainlit/client/cloud.py +0 -502
- chainlit/prompt.py +0 -40
- chainlit-0.7.700.dist-info/RECORD +0 -61
- {chainlit-0.7.700.dist-info → chainlit-1.0.0rc1.dist-info}/WHEEL +0 -0
- {chainlit-0.7.700.dist-info → chainlit-1.0.0rc1.dist-info}/entry_points.txt +0 -0
chainlit/message.py
CHANGED
|
@@ -1,76 +1,87 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import json
|
|
2
3
|
import uuid
|
|
3
|
-
from abc import ABC
|
|
4
|
-
from datetime import datetime
|
|
4
|
+
from abc import ABC
|
|
5
|
+
from datetime import datetime
|
|
5
6
|
from typing import Dict, List, Optional, Union, cast
|
|
6
7
|
|
|
7
8
|
from chainlit.action import Action
|
|
8
|
-
from chainlit.client.base import MessageDict
|
|
9
9
|
from chainlit.config import config
|
|
10
10
|
from chainlit.context import context
|
|
11
|
-
from chainlit.data import
|
|
11
|
+
from chainlit.data import get_data_layer
|
|
12
12
|
from chainlit.element import ElementBased
|
|
13
13
|
from chainlit.logger import logger
|
|
14
|
-
from chainlit.
|
|
14
|
+
from chainlit.step import StepDict
|
|
15
15
|
from chainlit.telemetry import trace_event
|
|
16
16
|
from chainlit.types import (
|
|
17
17
|
AskActionResponse,
|
|
18
18
|
AskActionSpec,
|
|
19
19
|
AskFileResponse,
|
|
20
20
|
AskFileSpec,
|
|
21
|
-
AskResponse,
|
|
22
21
|
AskSpec,
|
|
22
|
+
FileDict,
|
|
23
23
|
)
|
|
24
|
-
from
|
|
24
|
+
from chainlit_client.step import MessageStepType
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class MessageBase(ABC):
|
|
28
28
|
id: str
|
|
29
|
+
thread_id: str
|
|
29
30
|
author: str
|
|
30
31
|
content: str = ""
|
|
32
|
+
type: MessageStepType = "assistant_message"
|
|
33
|
+
disable_feedback = False
|
|
31
34
|
streaming = False
|
|
32
|
-
created_at: Union[
|
|
35
|
+
created_at: Union[str, None] = None
|
|
33
36
|
fail_on_persist_error: bool = False
|
|
34
37
|
persisted = False
|
|
38
|
+
is_error = False
|
|
39
|
+
language: Optional[str] = None
|
|
40
|
+
wait_for_answer = False
|
|
41
|
+
indent: Optional[int] = None
|
|
35
42
|
|
|
36
43
|
def __post_init__(self) -> None:
|
|
37
44
|
trace_event(f"init {self.__class__.__name__}")
|
|
45
|
+
self.thread_id = context.session.thread_id
|
|
46
|
+
|
|
38
47
|
if not getattr(self, "id", None):
|
|
39
48
|
self.id = str(uuid.uuid4())
|
|
40
|
-
if not self.created_at:
|
|
41
|
-
self.created_at = datetime.now(timezone.utc).isoformat()
|
|
42
|
-
|
|
43
|
-
@abstractmethod
|
|
44
|
-
def to_dict(self) -> Dict:
|
|
45
|
-
pass
|
|
46
|
-
|
|
47
|
-
async def with_conversation_id(self):
|
|
48
|
-
_dict = self.to_dict()
|
|
49
|
-
_dict["conversationId"] = await context.session.get_conversation_id()
|
|
50
|
-
return _dict
|
|
51
|
-
|
|
52
|
-
async def _create(self):
|
|
53
|
-
msg_dict = await self.with_conversation_id()
|
|
54
|
-
asyncio.create_task(self._persist_create(msg_dict))
|
|
55
49
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
@classmethod
|
|
51
|
+
def from_dict(self, _dict: StepDict):
|
|
52
|
+
type = _dict.get("type", "assistant_message")
|
|
53
|
+
message = Message(
|
|
54
|
+
id=_dict["id"],
|
|
55
|
+
created_at=_dict["createdAt"],
|
|
56
|
+
content=_dict["output"],
|
|
57
|
+
author=_dict.get("name", config.ui.name),
|
|
58
|
+
type=type, # type: ignore
|
|
59
|
+
disable_feedback=_dict.get("disableFeedback", False),
|
|
60
|
+
language=_dict.get("language"),
|
|
61
|
+
)
|
|
59
62
|
|
|
60
|
-
|
|
61
|
-
if not chainlit_client or self.persisted:
|
|
62
|
-
return
|
|
63
|
+
return message
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
def to_dict(self) -> StepDict:
|
|
66
|
+
_dict: StepDict = {
|
|
67
|
+
"id": self.id,
|
|
68
|
+
"threadId": self.thread_id,
|
|
69
|
+
"createdAt": self.created_at,
|
|
70
|
+
"start": self.created_at,
|
|
71
|
+
"end": self.created_at,
|
|
72
|
+
"output": self.content,
|
|
73
|
+
"name": self.author,
|
|
74
|
+
"type": self.type,
|
|
75
|
+
"createdAt": self.created_at,
|
|
76
|
+
"language": self.language,
|
|
77
|
+
"streaming": self.streaming,
|
|
78
|
+
"disableFeedback": self.disable_feedback,
|
|
79
|
+
"isError": self.is_error,
|
|
80
|
+
"waitForAnswer": self.wait_for_answer,
|
|
81
|
+
"indent": self.indent,
|
|
82
|
+
}
|
|
66
83
|
|
|
67
|
-
|
|
68
|
-
self.id = persisted_id
|
|
69
|
-
self.persisted = True
|
|
70
|
-
except Exception as e:
|
|
71
|
-
if self.fail_on_persist_error:
|
|
72
|
-
raise e
|
|
73
|
-
logger.error(f"Failed to persist message creation: {str(e)}")
|
|
84
|
+
return _dict
|
|
74
85
|
|
|
75
86
|
async def update(
|
|
76
87
|
self,
|
|
@@ -79,51 +90,63 @@ class MessageBase(ABC):
|
|
|
79
90
|
Update a message already sent to the UI.
|
|
80
91
|
"""
|
|
81
92
|
trace_event("update_message")
|
|
93
|
+
|
|
82
94
|
if self.streaming:
|
|
83
95
|
self.streaming = False
|
|
84
|
-
msg_dict = self.to_dict()
|
|
85
|
-
asyncio.create_task(self._persist_update(msg_dict))
|
|
86
|
-
await context.emitter.update_message(msg_dict)
|
|
87
96
|
|
|
88
|
-
|
|
97
|
+
step_dict = self.to_dict()
|
|
98
|
+
|
|
99
|
+
data_layer = get_data_layer()
|
|
100
|
+
if data_layer:
|
|
101
|
+
try:
|
|
102
|
+
asyncio.create_task(data_layer.update_step(step_dict))
|
|
103
|
+
except Exception as e:
|
|
104
|
+
if self.fail_on_persist_error:
|
|
105
|
+
raise e
|
|
106
|
+
logger.error(f"Failed to persist message update: {str(e)}")
|
|
89
107
|
|
|
90
|
-
|
|
91
|
-
if not chainlit_client or not self.id:
|
|
92
|
-
return
|
|
108
|
+
await context.emitter.update_step(step_dict)
|
|
93
109
|
|
|
94
|
-
|
|
95
|
-
await chainlit_client.update_message(self.id, message)
|
|
96
|
-
except Exception as e:
|
|
97
|
-
if self.fail_on_persist_error:
|
|
98
|
-
raise e
|
|
99
|
-
logger.error(f"Failed to persist message update: {str(e)}")
|
|
110
|
+
return True
|
|
100
111
|
|
|
101
112
|
async def remove(self):
|
|
102
113
|
"""
|
|
103
114
|
Remove a message already sent to the UI.
|
|
104
|
-
This will not automatically remove potential nested messages and could lead to undesirable side effects in the UI.
|
|
105
115
|
"""
|
|
106
116
|
trace_event("remove_message")
|
|
107
117
|
|
|
108
|
-
|
|
109
|
-
|
|
118
|
+
step_dict = self.to_dict()
|
|
119
|
+
data_layer = get_data_layer()
|
|
120
|
+
if data_layer:
|
|
121
|
+
try:
|
|
122
|
+
asyncio.create_task(data_layer.delete_step(step_dict["id"]))
|
|
123
|
+
except Exception as e:
|
|
124
|
+
if self.fail_on_persist_error:
|
|
125
|
+
raise e
|
|
126
|
+
logger.error(f"Failed to persist message deletion: {str(e)}")
|
|
110
127
|
|
|
111
|
-
await context.emitter.
|
|
128
|
+
await context.emitter.delete_step(step_dict)
|
|
112
129
|
|
|
113
130
|
return True
|
|
114
131
|
|
|
115
|
-
async def
|
|
116
|
-
|
|
117
|
-
|
|
132
|
+
async def _create(self):
|
|
133
|
+
step_dict = self.to_dict()
|
|
134
|
+
data_layer = get_data_layer()
|
|
135
|
+
if data_layer and not self.persisted:
|
|
136
|
+
try:
|
|
137
|
+
asyncio.create_task(data_layer.create_step(step_dict))
|
|
138
|
+
self.persisted = True
|
|
139
|
+
except Exception as e:
|
|
140
|
+
if self.fail_on_persist_error:
|
|
141
|
+
raise e
|
|
142
|
+
logger.error(f"Failed to persist message creation: {str(e)}")
|
|
118
143
|
|
|
119
|
-
|
|
120
|
-
await chainlit_client.delete_message(self.id)
|
|
121
|
-
except Exception as e:
|
|
122
|
-
if self.fail_on_persist_error:
|
|
123
|
-
raise e
|
|
124
|
-
logger.error(f"Failed to persist message deletion: {str(e)}")
|
|
144
|
+
return step_dict
|
|
125
145
|
|
|
126
146
|
async def send(self):
|
|
147
|
+
if not self.created_at:
|
|
148
|
+
self.created_at = datetime.utcnow().isoformat()
|
|
149
|
+
|
|
127
150
|
if self.content is None:
|
|
128
151
|
self.content = ""
|
|
129
152
|
|
|
@@ -133,9 +156,9 @@ class MessageBase(ABC):
|
|
|
133
156
|
if self.streaming:
|
|
134
157
|
self.streaming = False
|
|
135
158
|
|
|
136
|
-
|
|
159
|
+
step_dict = await self._create()
|
|
137
160
|
|
|
138
|
-
await context.emitter.
|
|
161
|
+
await context.emitter.send_step(step_dict)
|
|
139
162
|
|
|
140
163
|
return self.id
|
|
141
164
|
|
|
@@ -147,8 +170,8 @@ class MessageBase(ABC):
|
|
|
147
170
|
|
|
148
171
|
if not self.streaming:
|
|
149
172
|
self.streaming = True
|
|
150
|
-
|
|
151
|
-
await context.emitter.stream_start(
|
|
173
|
+
step_dict = self.to_dict()
|
|
174
|
+
await context.emitter.stream_start(step_dict)
|
|
152
175
|
|
|
153
176
|
if is_sequence:
|
|
154
177
|
self.content = token
|
|
@@ -164,33 +187,27 @@ class MessageBase(ABC):
|
|
|
164
187
|
class Message(MessageBase):
|
|
165
188
|
"""
|
|
166
189
|
Send a message to the UI
|
|
167
|
-
If a project ID is configured, the message will be persisted in the cloud.
|
|
168
190
|
|
|
169
191
|
Args:
|
|
170
192
|
content (Union[str, Dict]): The content of the message.
|
|
171
193
|
author (str, optional): The author of the message, this will be used in the UI. Defaults to the chatbot name (see config).
|
|
172
|
-
prompt (Prompt, optional): The prompt used to generate the message. If provided, enables the prompt playground for this message.
|
|
173
194
|
language (str, optional): Language of the code is the content is code. See https://react-code-blocks-rajinwonderland.vercel.app/?path=/story/codeblock--supported-languages for a list of supported languages.
|
|
174
|
-
parent_id (str, optional): If provided, the message will be nested inside the parent in the UI.
|
|
175
|
-
indent (int, optional): If positive, the message will be nested in the UI. (deprecated, use parent_id instead)
|
|
176
195
|
actions (List[Action], optional): A list of actions to send with the message.
|
|
177
196
|
elements (List[ElementBased], optional): A list of elements to send with the message.
|
|
178
|
-
|
|
197
|
+
disable_feedback (bool, optional): Hide the feedback buttons for this specific message
|
|
179
198
|
"""
|
|
180
199
|
|
|
181
200
|
def __init__(
|
|
182
201
|
self,
|
|
183
202
|
content: Union[str, Dict],
|
|
184
203
|
author: str = config.ui.name,
|
|
185
|
-
prompt: Optional[Prompt] = None,
|
|
186
204
|
language: Optional[str] = None,
|
|
187
|
-
parent_id: Optional[str] = None,
|
|
188
|
-
indent: int = 0,
|
|
189
205
|
actions: Optional[List[Action]] = None,
|
|
190
206
|
elements: Optional[List[ElementBased]] = None,
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
id: Optional[
|
|
207
|
+
disable_feedback: bool = False,
|
|
208
|
+
type: MessageStepType = "assistant_message",
|
|
209
|
+
id: Optional[str] = None,
|
|
210
|
+
created_at: Union[str, None] = None,
|
|
194
211
|
):
|
|
195
212
|
self.language = language
|
|
196
213
|
|
|
@@ -200,87 +217,45 @@ class Message(MessageBase):
|
|
|
200
217
|
self.language = "json"
|
|
201
218
|
except TypeError:
|
|
202
219
|
self.content = str(content)
|
|
203
|
-
self.language = "
|
|
220
|
+
self.language = "text"
|
|
204
221
|
elif isinstance(content, str):
|
|
205
222
|
self.content = content
|
|
206
223
|
else:
|
|
207
224
|
self.content = str(content)
|
|
208
|
-
self.language = "
|
|
225
|
+
self.language = "text"
|
|
209
226
|
|
|
210
227
|
if id:
|
|
211
228
|
self.id = str(id)
|
|
212
229
|
|
|
230
|
+
if created_at:
|
|
231
|
+
self.created_at = created_at
|
|
232
|
+
|
|
213
233
|
self.author = author
|
|
214
|
-
self.
|
|
215
|
-
self.prompt = prompt
|
|
216
|
-
self.parent_id = parent_id
|
|
217
|
-
self.indent = indent
|
|
234
|
+
self.type = type
|
|
218
235
|
self.actions = actions if actions is not None else []
|
|
219
236
|
self.elements = elements if elements is not None else []
|
|
220
|
-
self.
|
|
237
|
+
self.disable_feedback = disable_feedback
|
|
221
238
|
|
|
222
239
|
super().__post_init__()
|
|
223
240
|
|
|
224
|
-
@classmethod
|
|
225
|
-
def from_dict(self, _dict: MessageDict):
|
|
226
|
-
message = Message(
|
|
227
|
-
content=_dict["content"],
|
|
228
|
-
author=_dict.get("author", config.ui.name),
|
|
229
|
-
prompt=_dict.get("prompt"),
|
|
230
|
-
language=_dict.get("language"),
|
|
231
|
-
parent_id=_dict.get("parentId"),
|
|
232
|
-
indent=_dict.get("indent") or 0,
|
|
233
|
-
disable_human_feedback=_dict.get("disableHumanFeedback"),
|
|
234
|
-
author_is_user=_dict.get("authorIsUser"),
|
|
235
|
-
)
|
|
236
|
-
|
|
237
|
-
if _id := _dict.get("id"):
|
|
238
|
-
message.id = _id
|
|
239
|
-
if created_at := _dict.get("createdAt"):
|
|
240
|
-
message.created_at = created_at
|
|
241
|
-
|
|
242
|
-
return message
|
|
243
|
-
|
|
244
|
-
def to_dict(self):
|
|
245
|
-
_dict = {
|
|
246
|
-
"createdAt": self.created_at,
|
|
247
|
-
"content": self.content,
|
|
248
|
-
"author": self.author,
|
|
249
|
-
"authorIsUser": self.author_is_user,
|
|
250
|
-
"language": self.language,
|
|
251
|
-
"parentId": self.parent_id,
|
|
252
|
-
"indent": self.indent,
|
|
253
|
-
"streaming": self.streaming,
|
|
254
|
-
"disableHumanFeedback": self.disable_human_feedback,
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
if self.prompt:
|
|
258
|
-
_dict["prompt"] = self.prompt.to_dict()
|
|
259
|
-
|
|
260
|
-
if self.id:
|
|
261
|
-
_dict["id"] = self.id
|
|
262
|
-
|
|
263
|
-
return _dict
|
|
264
|
-
|
|
265
241
|
async def send(self) -> str:
|
|
266
242
|
"""
|
|
267
243
|
Send the message to the UI and persist it in the cloud if a project ID is configured.
|
|
268
244
|
Return the ID of the message.
|
|
269
245
|
"""
|
|
270
246
|
trace_event("send_message")
|
|
271
|
-
|
|
247
|
+
await super().send()
|
|
272
248
|
|
|
273
|
-
|
|
274
|
-
context.session.root_message = self
|
|
249
|
+
context.session.root_message = self
|
|
275
250
|
|
|
276
251
|
# Create tasks for all actions and elements
|
|
277
|
-
tasks = [action.send(for_id=id) for action in self.actions]
|
|
278
|
-
tasks.extend(element.send(for_id=id) for element in self.elements)
|
|
252
|
+
tasks = [action.send(for_id=self.id) for action in self.actions]
|
|
253
|
+
tasks.extend(element.send(for_id=self.id) for element in self.elements)
|
|
279
254
|
|
|
280
255
|
# Run all tasks concurrently
|
|
281
256
|
await asyncio.gather(*tasks)
|
|
282
257
|
|
|
283
|
-
return id
|
|
258
|
+
return self.id
|
|
284
259
|
|
|
285
260
|
async def update(self):
|
|
286
261
|
"""
|
|
@@ -290,15 +265,16 @@ class Message(MessageBase):
|
|
|
290
265
|
trace_event("send_message")
|
|
291
266
|
await super().update()
|
|
292
267
|
|
|
293
|
-
|
|
268
|
+
# Update tasks for all actions and elements
|
|
269
|
+
tasks = [
|
|
270
|
+
action.send(for_id=self.id)
|
|
271
|
+
for action in self.actions
|
|
272
|
+
if action.forId is None
|
|
273
|
+
]
|
|
274
|
+
tasks.extend(element.send(for_id=self.id) for element in self.elements)
|
|
294
275
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
for action in actions_to_update:
|
|
298
|
-
await action.send(for_id=self.id)
|
|
299
|
-
|
|
300
|
-
for element in elements_to_update:
|
|
301
|
-
await element.send(for_id=self.id)
|
|
276
|
+
# Run all tasks concurrently
|
|
277
|
+
await asyncio.gather(*tasks)
|
|
302
278
|
|
|
303
279
|
return True
|
|
304
280
|
|
|
@@ -323,29 +299,16 @@ class ErrorMessage(MessageBase):
|
|
|
323
299
|
self,
|
|
324
300
|
content: str,
|
|
325
301
|
author: str = config.ui.name,
|
|
326
|
-
parent_id: Optional[str] = None,
|
|
327
|
-
indent: int = 0,
|
|
328
302
|
fail_on_persist_error: bool = False,
|
|
329
303
|
):
|
|
330
304
|
self.content = content
|
|
331
305
|
self.author = author
|
|
332
|
-
self.
|
|
333
|
-
self.
|
|
306
|
+
self.type = "system_message"
|
|
307
|
+
self.is_error = True
|
|
334
308
|
self.fail_on_persist_error = fail_on_persist_error
|
|
335
309
|
|
|
336
310
|
super().__post_init__()
|
|
337
311
|
|
|
338
|
-
def to_dict(self):
|
|
339
|
-
return {
|
|
340
|
-
"id": self.id,
|
|
341
|
-
"createdAt": self.created_at,
|
|
342
|
-
"content": self.content,
|
|
343
|
-
"author": self.author,
|
|
344
|
-
"parentId": self.parent_id,
|
|
345
|
-
"indent": self.indent,
|
|
346
|
-
"isError": True,
|
|
347
|
-
}
|
|
348
|
-
|
|
349
312
|
async def send(self):
|
|
350
313
|
"""
|
|
351
314
|
Send the error message to the UI and persist it in the cloud if a project ID is configured.
|
|
@@ -371,7 +334,7 @@ class AskUserMessage(AskMessageBase):
|
|
|
371
334
|
Args:
|
|
372
335
|
content (str): The content of the prompt.
|
|
373
336
|
author (str, optional): The author of the message, this will be used in the UI. Defaults to the chatbot name (see config).
|
|
374
|
-
|
|
337
|
+
disable_feedback (bool, optional): Hide the feedback buttons for this specific message
|
|
375
338
|
timeout (int, optional): The number of seconds to wait for an answer before raising a TimeoutError.
|
|
376
339
|
raise_on_timeout (bool, optional): Whether to raise a socketio TimeoutError if the user does not answer in time.
|
|
377
340
|
"""
|
|
@@ -380,45 +343,46 @@ class AskUserMessage(AskMessageBase):
|
|
|
380
343
|
self,
|
|
381
344
|
content: str,
|
|
382
345
|
author: str = config.ui.name,
|
|
383
|
-
|
|
346
|
+
type: MessageStepType = "assistant_message",
|
|
347
|
+
disable_feedback: bool = False,
|
|
384
348
|
timeout: int = 60,
|
|
385
349
|
raise_on_timeout: bool = False,
|
|
386
350
|
):
|
|
387
351
|
self.content = content
|
|
388
352
|
self.author = author
|
|
389
353
|
self.timeout = timeout
|
|
390
|
-
self.
|
|
354
|
+
self.type = type
|
|
355
|
+
self.disable_feedback = disable_feedback
|
|
391
356
|
self.raise_on_timeout = raise_on_timeout
|
|
392
357
|
|
|
393
358
|
super().__post_init__()
|
|
394
359
|
|
|
395
|
-
def
|
|
396
|
-
return {
|
|
397
|
-
"id": self.id,
|
|
398
|
-
"createdAt": self.created_at,
|
|
399
|
-
"content": self.content,
|
|
400
|
-
"author": self.author,
|
|
401
|
-
"waitForAnswer": True,
|
|
402
|
-
"disableHumanFeedback": self.disable_human_feedback,
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
async def send(self) -> Union[AskResponse, None]:
|
|
360
|
+
async def send(self) -> Union[StepDict, None]:
|
|
406
361
|
"""
|
|
407
362
|
Sends the question to ask to the UI and waits for the reply.
|
|
408
363
|
"""
|
|
409
364
|
trace_event("send_ask_user")
|
|
365
|
+
if not self.created_at:
|
|
366
|
+
self.created_at = datetime.utcnow().isoformat()
|
|
367
|
+
|
|
368
|
+
if config.code.author_rename:
|
|
369
|
+
self.author = await config.code.author_rename(self.author)
|
|
410
370
|
|
|
411
371
|
if self.streaming:
|
|
412
372
|
self.streaming = False
|
|
413
373
|
|
|
414
|
-
|
|
415
|
-
self.author = await config.code.author_rename(self.author)
|
|
374
|
+
self.wait_for_answer = True
|
|
416
375
|
|
|
417
|
-
|
|
376
|
+
step_dict = await self._create()
|
|
418
377
|
|
|
419
378
|
spec = AskSpec(type="text", timeout=self.timeout)
|
|
420
379
|
|
|
421
|
-
res =
|
|
380
|
+
res = cast(
|
|
381
|
+
Union[None, StepDict],
|
|
382
|
+
await context.emitter.send_ask_user(step_dict, spec, self.raise_on_timeout),
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
self.wait_for_answer = False
|
|
422
386
|
|
|
423
387
|
return res
|
|
424
388
|
|
|
@@ -435,7 +399,7 @@ class AskFileMessage(AskMessageBase):
|
|
|
435
399
|
max_size_mb (int, optional): Maximum size per file in MB. Maximum value is 100.
|
|
436
400
|
max_files (int, optional): Maximum number of files to upload. Maximum value is 10.
|
|
437
401
|
author (str, optional): The author of the message, this will be used in the UI. Defaults to the chatbot name (see config).
|
|
438
|
-
|
|
402
|
+
disable_feedback (bool, optional): Hide the feedback buttons for this specific message
|
|
439
403
|
timeout (int, optional): The number of seconds to wait for an answer before raising a TimeoutError.
|
|
440
404
|
raise_on_timeout (bool, optional): Whether to raise a socketio TimeoutError if the user does not answer in time.
|
|
441
405
|
"""
|
|
@@ -447,7 +411,8 @@ class AskFileMessage(AskMessageBase):
|
|
|
447
411
|
max_size_mb=2,
|
|
448
412
|
max_files=1,
|
|
449
413
|
author=config.ui.name,
|
|
450
|
-
|
|
414
|
+
type: MessageStepType = "assistant_message",
|
|
415
|
+
disable_feedback: bool = False,
|
|
451
416
|
timeout=90,
|
|
452
417
|
raise_on_timeout=False,
|
|
453
418
|
):
|
|
@@ -455,36 +420,32 @@ class AskFileMessage(AskMessageBase):
|
|
|
455
420
|
self.max_size_mb = max_size_mb
|
|
456
421
|
self.max_files = max_files
|
|
457
422
|
self.accept = accept
|
|
423
|
+
self.type = type
|
|
458
424
|
self.author = author
|
|
459
425
|
self.timeout = timeout
|
|
460
426
|
self.raise_on_timeout = raise_on_timeout
|
|
461
|
-
self.
|
|
427
|
+
self.disable_feedback = disable_feedback
|
|
462
428
|
|
|
463
429
|
super().__post_init__()
|
|
464
430
|
|
|
465
|
-
def to_dict(self):
|
|
466
|
-
return {
|
|
467
|
-
"id": self.id,
|
|
468
|
-
"createdAt": self.created_at,
|
|
469
|
-
"content": self.content,
|
|
470
|
-
"author": self.author,
|
|
471
|
-
"waitForAnswer": True,
|
|
472
|
-
"disableHumanFeedback": self.disable_human_feedback,
|
|
473
|
-
}
|
|
474
|
-
|
|
475
431
|
async def send(self) -> Union[List[AskFileResponse], None]:
|
|
476
432
|
"""
|
|
477
433
|
Sends the message to request a file from the user to the UI and waits for the reply.
|
|
478
434
|
"""
|
|
479
435
|
trace_event("send_ask_file")
|
|
480
436
|
|
|
437
|
+
if not self.created_at:
|
|
438
|
+
self.created_at = datetime.utcnow().isoformat()
|
|
439
|
+
|
|
481
440
|
if self.streaming:
|
|
482
441
|
self.streaming = False
|
|
483
442
|
|
|
484
443
|
if config.code.author_rename:
|
|
485
444
|
self.author = await config.code.author_rename(self.author)
|
|
486
445
|
|
|
487
|
-
|
|
446
|
+
self.wait_for_answer = True
|
|
447
|
+
|
|
448
|
+
step_dict = await self._create()
|
|
488
449
|
|
|
489
450
|
spec = AskFileSpec(
|
|
490
451
|
type="file",
|
|
@@ -494,10 +455,24 @@ class AskFileMessage(AskMessageBase):
|
|
|
494
455
|
timeout=self.timeout,
|
|
495
456
|
)
|
|
496
457
|
|
|
497
|
-
res =
|
|
458
|
+
res = cast(
|
|
459
|
+
Union[None, List[FileDict]],
|
|
460
|
+
await context.emitter.send_ask_user(step_dict, spec, self.raise_on_timeout),
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
self.wait_for_answer = False
|
|
498
464
|
|
|
499
465
|
if res:
|
|
500
|
-
return [
|
|
466
|
+
return [
|
|
467
|
+
AskFileResponse(
|
|
468
|
+
id=r["id"],
|
|
469
|
+
name=r["name"],
|
|
470
|
+
path=str(r["path"]),
|
|
471
|
+
size=r["size"],
|
|
472
|
+
type=r["type"],
|
|
473
|
+
)
|
|
474
|
+
for r in res
|
|
475
|
+
]
|
|
501
476
|
else:
|
|
502
477
|
return None
|
|
503
478
|
|
|
@@ -513,55 +488,49 @@ class AskActionMessage(AskMessageBase):
|
|
|
513
488
|
content: str,
|
|
514
489
|
actions: List[Action],
|
|
515
490
|
author=config.ui.name,
|
|
516
|
-
|
|
491
|
+
disable_feedback=False,
|
|
517
492
|
timeout=90,
|
|
518
493
|
raise_on_timeout=False,
|
|
519
494
|
):
|
|
520
495
|
self.content = content
|
|
521
496
|
self.actions = actions
|
|
522
497
|
self.author = author
|
|
523
|
-
self.
|
|
498
|
+
self.disable_feedback = disable_feedback
|
|
524
499
|
self.timeout = timeout
|
|
525
500
|
self.raise_on_timeout = raise_on_timeout
|
|
526
501
|
|
|
527
502
|
super().__post_init__()
|
|
528
503
|
|
|
529
|
-
def to_dict(self):
|
|
530
|
-
return {
|
|
531
|
-
"id": self.id,
|
|
532
|
-
"createdAt": self.created_at,
|
|
533
|
-
"content": self.content,
|
|
534
|
-
"author": self.author,
|
|
535
|
-
"waitForAnswer": True,
|
|
536
|
-
"disableHumanFeedback": self.disable_human_feedback,
|
|
537
|
-
"timeout": self.timeout,
|
|
538
|
-
"raiseOnTimeout": self.raise_on_timeout,
|
|
539
|
-
}
|
|
540
|
-
|
|
541
504
|
async def send(self) -> Union[AskActionResponse, None]:
|
|
542
505
|
"""
|
|
543
506
|
Sends the question to ask to the UI and waits for the reply
|
|
544
507
|
"""
|
|
545
508
|
trace_event("send_ask_action")
|
|
546
509
|
|
|
510
|
+
if not self.created_at:
|
|
511
|
+
self.created_at = datetime.utcnow().isoformat()
|
|
512
|
+
|
|
547
513
|
if self.streaming:
|
|
548
514
|
self.streaming = False
|
|
549
515
|
|
|
550
516
|
if config.code.author_rename:
|
|
551
517
|
self.author = await config.code.author_rename(self.author)
|
|
552
518
|
|
|
553
|
-
|
|
519
|
+
self.wait_for_answer = True
|
|
520
|
+
|
|
521
|
+
step_dict = await self._create()
|
|
522
|
+
|
|
554
523
|
action_keys = []
|
|
555
524
|
|
|
556
525
|
for action in self.actions:
|
|
557
526
|
action_keys.append(action.id)
|
|
558
|
-
await action.send(for_id=str(
|
|
527
|
+
await action.send(for_id=str(step_dict["id"]))
|
|
559
528
|
|
|
560
529
|
spec = AskActionSpec(type="action", timeout=self.timeout, keys=action_keys)
|
|
561
530
|
|
|
562
531
|
res = cast(
|
|
563
532
|
Union[AskActionResponse, None],
|
|
564
|
-
await context.emitter.send_ask_user(
|
|
533
|
+
await context.emitter.send_ask_user(step_dict, spec, self.raise_on_timeout),
|
|
565
534
|
)
|
|
566
535
|
|
|
567
536
|
for action in self.actions:
|
|
@@ -570,6 +539,9 @@ class AskActionMessage(AskMessageBase):
|
|
|
570
539
|
self.content = "Timed out: no action was taken"
|
|
571
540
|
else:
|
|
572
541
|
self.content = f'**Selected action:** {res["label"]}'
|
|
542
|
+
|
|
543
|
+
self.wait_for_answer = False
|
|
544
|
+
|
|
573
545
|
await self.update()
|
|
574
546
|
|
|
575
547
|
return res
|