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/step.py
DELETED
|
@@ -1,490 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import inspect
|
|
3
|
-
import json
|
|
4
|
-
import time
|
|
5
|
-
import uuid
|
|
6
|
-
from copy import deepcopy
|
|
7
|
-
from functools import wraps
|
|
8
|
-
from typing import Callable, Dict, List, Optional, TypedDict, Union
|
|
9
|
-
|
|
10
|
-
from literalai import BaseGeneration
|
|
11
|
-
from literalai.observability.step import StepType, TrueStepType
|
|
12
|
-
|
|
13
|
-
from chainlit.config import config
|
|
14
|
-
from chainlit.context import CL_RUN_NAMES, context, local_steps
|
|
15
|
-
from chainlit.data import get_data_layer
|
|
16
|
-
from chainlit.element import Element
|
|
17
|
-
from chainlit.logger import logger
|
|
18
|
-
from chainlit.types import FeedbackDict
|
|
19
|
-
from chainlit.utils import utc_now
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def check_add_step_in_cot(step: "Step"):
|
|
23
|
-
is_message = step.type in [
|
|
24
|
-
"user_message",
|
|
25
|
-
"assistant_message",
|
|
26
|
-
]
|
|
27
|
-
is_cl_run = step.name in CL_RUN_NAMES and step.type == "run"
|
|
28
|
-
if config.ui.cot == "hidden" and not is_message and not is_cl_run:
|
|
29
|
-
return False
|
|
30
|
-
return True
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def stub_step(step: "Step") -> "StepDict":
|
|
34
|
-
return {
|
|
35
|
-
"type": step.type,
|
|
36
|
-
"name": step.name,
|
|
37
|
-
"id": step.id,
|
|
38
|
-
"parentId": step.parent_id,
|
|
39
|
-
"threadId": step.thread_id,
|
|
40
|
-
"input": "",
|
|
41
|
-
"output": "",
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class StepDict(TypedDict, total=False):
|
|
46
|
-
name: str
|
|
47
|
-
type: StepType
|
|
48
|
-
id: str
|
|
49
|
-
threadId: str
|
|
50
|
-
parentId: Optional[str]
|
|
51
|
-
command: Optional[str]
|
|
52
|
-
streaming: bool
|
|
53
|
-
waitForAnswer: Optional[bool]
|
|
54
|
-
isError: Optional[bool]
|
|
55
|
-
metadata: Dict
|
|
56
|
-
tags: Optional[List[str]]
|
|
57
|
-
input: str
|
|
58
|
-
output: str
|
|
59
|
-
createdAt: Optional[str]
|
|
60
|
-
start: Optional[str]
|
|
61
|
-
end: Optional[str]
|
|
62
|
-
generation: Optional[Dict]
|
|
63
|
-
showInput: Optional[Union[bool, str]]
|
|
64
|
-
defaultOpen: Optional[bool]
|
|
65
|
-
language: Optional[str]
|
|
66
|
-
feedback: Optional[FeedbackDict]
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def flatten_args_kwargs(func, args, kwargs):
|
|
70
|
-
signature = inspect.signature(func)
|
|
71
|
-
bound_arguments = signature.bind(*args, **kwargs)
|
|
72
|
-
bound_arguments.apply_defaults()
|
|
73
|
-
return {k: deepcopy(v) for k, v in bound_arguments.arguments.items()}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
def step(
|
|
77
|
-
original_function: Optional[Callable] = None,
|
|
78
|
-
*,
|
|
79
|
-
name: Optional[str] = "",
|
|
80
|
-
type: TrueStepType = "undefined",
|
|
81
|
-
id: Optional[str] = None,
|
|
82
|
-
parent_id: Optional[str] = None,
|
|
83
|
-
tags: Optional[List[str]] = None,
|
|
84
|
-
metadata: Optional[Dict] = None,
|
|
85
|
-
language: Optional[str] = None,
|
|
86
|
-
show_input: Union[bool, str] = "json",
|
|
87
|
-
default_open: bool = False,
|
|
88
|
-
):
|
|
89
|
-
"""Step decorator for async and sync functions."""
|
|
90
|
-
|
|
91
|
-
def wrapper(func: Callable):
|
|
92
|
-
nonlocal name
|
|
93
|
-
if not name:
|
|
94
|
-
name = func.__name__
|
|
95
|
-
|
|
96
|
-
# Handle async decorator
|
|
97
|
-
|
|
98
|
-
if inspect.iscoroutinefunction(func):
|
|
99
|
-
|
|
100
|
-
@wraps(func)
|
|
101
|
-
async def async_wrapper(*args, **kwargs):
|
|
102
|
-
async with Step(
|
|
103
|
-
type=type,
|
|
104
|
-
name=name,
|
|
105
|
-
id=id,
|
|
106
|
-
parent_id=parent_id,
|
|
107
|
-
tags=tags,
|
|
108
|
-
language=language,
|
|
109
|
-
show_input=show_input,
|
|
110
|
-
default_open=default_open,
|
|
111
|
-
metadata=metadata,
|
|
112
|
-
) as step:
|
|
113
|
-
try:
|
|
114
|
-
step.input = flatten_args_kwargs(func, args, kwargs)
|
|
115
|
-
except Exception as e:
|
|
116
|
-
logger.exception(e)
|
|
117
|
-
result = await func(*args, **kwargs)
|
|
118
|
-
try:
|
|
119
|
-
if result and not step.output:
|
|
120
|
-
step.output = result
|
|
121
|
-
except Exception as e:
|
|
122
|
-
step.is_error = True
|
|
123
|
-
step.output = str(e)
|
|
124
|
-
return result
|
|
125
|
-
|
|
126
|
-
return async_wrapper
|
|
127
|
-
else:
|
|
128
|
-
# Handle sync decorator
|
|
129
|
-
@wraps(func)
|
|
130
|
-
def sync_wrapper(*args, **kwargs):
|
|
131
|
-
with Step(
|
|
132
|
-
type=type,
|
|
133
|
-
name=name,
|
|
134
|
-
id=id,
|
|
135
|
-
parent_id=parent_id,
|
|
136
|
-
tags=tags,
|
|
137
|
-
language=language,
|
|
138
|
-
show_input=show_input,
|
|
139
|
-
default_open=default_open,
|
|
140
|
-
metadata=metadata,
|
|
141
|
-
) as step:
|
|
142
|
-
try:
|
|
143
|
-
step.input = flatten_args_kwargs(func, args, kwargs)
|
|
144
|
-
except Exception as e:
|
|
145
|
-
logger.exception(e)
|
|
146
|
-
result = func(*args, **kwargs)
|
|
147
|
-
try:
|
|
148
|
-
if result and not step.output:
|
|
149
|
-
step.output = result
|
|
150
|
-
except Exception as e:
|
|
151
|
-
step.is_error = True
|
|
152
|
-
step.output = str(e)
|
|
153
|
-
return result
|
|
154
|
-
|
|
155
|
-
return sync_wrapper
|
|
156
|
-
|
|
157
|
-
func = original_function
|
|
158
|
-
if not func:
|
|
159
|
-
return wrapper
|
|
160
|
-
else:
|
|
161
|
-
return wrapper(func)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
class Step:
|
|
165
|
-
# Constructor
|
|
166
|
-
name: str
|
|
167
|
-
type: TrueStepType
|
|
168
|
-
id: str
|
|
169
|
-
parent_id: Optional[str]
|
|
170
|
-
|
|
171
|
-
streaming: bool
|
|
172
|
-
persisted: bool
|
|
173
|
-
|
|
174
|
-
show_input: Union[bool, str]
|
|
175
|
-
|
|
176
|
-
is_error: Optional[bool]
|
|
177
|
-
metadata: Dict
|
|
178
|
-
tags: Optional[List[str]]
|
|
179
|
-
thread_id: str
|
|
180
|
-
created_at: Union[str, None]
|
|
181
|
-
start: Union[str, None]
|
|
182
|
-
end: Union[str, None]
|
|
183
|
-
generation: Optional[BaseGeneration]
|
|
184
|
-
language: Optional[str]
|
|
185
|
-
default_open: Optional[bool]
|
|
186
|
-
elements: Optional[List[Element]]
|
|
187
|
-
fail_on_persist_error: bool
|
|
188
|
-
|
|
189
|
-
def __init__(
|
|
190
|
-
self,
|
|
191
|
-
name: Optional[str] = config.ui.name,
|
|
192
|
-
type: TrueStepType = "undefined",
|
|
193
|
-
id: Optional[str] = None,
|
|
194
|
-
parent_id: Optional[str] = None,
|
|
195
|
-
elements: Optional[List[Element]] = None,
|
|
196
|
-
metadata: Optional[Dict] = None,
|
|
197
|
-
tags: Optional[List[str]] = None,
|
|
198
|
-
language: Optional[str] = None,
|
|
199
|
-
default_open: Optional[bool] = False,
|
|
200
|
-
show_input: Union[bool, str] = "json",
|
|
201
|
-
thread_id: Optional[str] = None,
|
|
202
|
-
):
|
|
203
|
-
time.sleep(0.001)
|
|
204
|
-
self._input = ""
|
|
205
|
-
self._output = ""
|
|
206
|
-
self.thread_id = thread_id or context.session.thread_id
|
|
207
|
-
self.name = name or ""
|
|
208
|
-
self.type = type
|
|
209
|
-
self.id = id or str(uuid.uuid4())
|
|
210
|
-
self.metadata = metadata or {}
|
|
211
|
-
self.tags = tags
|
|
212
|
-
self.is_error = False
|
|
213
|
-
self.show_input = show_input
|
|
214
|
-
self.parent_id = parent_id
|
|
215
|
-
|
|
216
|
-
self.language = language
|
|
217
|
-
self.default_open = default_open
|
|
218
|
-
self.generation = None
|
|
219
|
-
self.elements = elements or []
|
|
220
|
-
|
|
221
|
-
self.created_at = utc_now()
|
|
222
|
-
self.start = None
|
|
223
|
-
self.end = None
|
|
224
|
-
|
|
225
|
-
self.streaming = False
|
|
226
|
-
self.persisted = False
|
|
227
|
-
self.fail_on_persist_error = False
|
|
228
|
-
|
|
229
|
-
def _clean_content(self, content):
|
|
230
|
-
"""
|
|
231
|
-
Recursively checks and converts bytes objects in content.
|
|
232
|
-
"""
|
|
233
|
-
|
|
234
|
-
def handle_bytes(item):
|
|
235
|
-
if isinstance(item, bytes):
|
|
236
|
-
return "STRIPPED_BINARY_DATA"
|
|
237
|
-
elif isinstance(item, dict):
|
|
238
|
-
return {k: handle_bytes(v) for k, v in item.items()}
|
|
239
|
-
elif isinstance(item, list):
|
|
240
|
-
return [handle_bytes(i) for i in item]
|
|
241
|
-
elif isinstance(item, tuple):
|
|
242
|
-
return tuple(handle_bytes(i) for i in item)
|
|
243
|
-
return item
|
|
244
|
-
|
|
245
|
-
return handle_bytes(content)
|
|
246
|
-
|
|
247
|
-
def _process_content(self, content, set_language=False):
|
|
248
|
-
if content is None:
|
|
249
|
-
return ""
|
|
250
|
-
content = self._clean_content(content)
|
|
251
|
-
|
|
252
|
-
if (
|
|
253
|
-
isinstance(content, dict)
|
|
254
|
-
or isinstance(content, list)
|
|
255
|
-
or isinstance(content, tuple)
|
|
256
|
-
):
|
|
257
|
-
try:
|
|
258
|
-
processed_content = json.dumps(content, indent=4, ensure_ascii=False)
|
|
259
|
-
if set_language:
|
|
260
|
-
self.language = "json"
|
|
261
|
-
except TypeError:
|
|
262
|
-
processed_content = str(content).replace("\\n", "\n")
|
|
263
|
-
if set_language:
|
|
264
|
-
self.language = "text"
|
|
265
|
-
elif isinstance(content, str):
|
|
266
|
-
processed_content = content
|
|
267
|
-
else:
|
|
268
|
-
processed_content = str(content).replace("\\n", "\n")
|
|
269
|
-
if set_language:
|
|
270
|
-
self.language = "text"
|
|
271
|
-
return processed_content
|
|
272
|
-
|
|
273
|
-
@property
|
|
274
|
-
def input(self):
|
|
275
|
-
return self._input
|
|
276
|
-
|
|
277
|
-
@input.setter
|
|
278
|
-
def input(self, content: Union[Dict, str]):
|
|
279
|
-
self._input = self._process_content(content, set_language=False)
|
|
280
|
-
|
|
281
|
-
@property
|
|
282
|
-
def output(self):
|
|
283
|
-
return self._output
|
|
284
|
-
|
|
285
|
-
@output.setter
|
|
286
|
-
def output(self, content: Union[Dict, str]):
|
|
287
|
-
self._output = self._process_content(content, set_language=True)
|
|
288
|
-
|
|
289
|
-
def to_dict(self) -> StepDict:
|
|
290
|
-
_dict: StepDict = {
|
|
291
|
-
"name": self.name,
|
|
292
|
-
"type": self.type,
|
|
293
|
-
"id": self.id,
|
|
294
|
-
"threadId": self.thread_id,
|
|
295
|
-
"parentId": self.parent_id,
|
|
296
|
-
"streaming": self.streaming,
|
|
297
|
-
"metadata": self.metadata,
|
|
298
|
-
"tags": self.tags,
|
|
299
|
-
"input": self.input,
|
|
300
|
-
"isError": self.is_error,
|
|
301
|
-
"output": self.output,
|
|
302
|
-
"createdAt": self.created_at,
|
|
303
|
-
"start": self.start,
|
|
304
|
-
"end": self.end,
|
|
305
|
-
"language": self.language,
|
|
306
|
-
"defaultOpen": self.default_open,
|
|
307
|
-
"showInput": self.show_input,
|
|
308
|
-
"generation": self.generation.to_dict() if self.generation else None,
|
|
309
|
-
}
|
|
310
|
-
return _dict
|
|
311
|
-
|
|
312
|
-
async def update(self):
|
|
313
|
-
"""
|
|
314
|
-
Update a step already sent to the UI.
|
|
315
|
-
"""
|
|
316
|
-
if self.streaming:
|
|
317
|
-
self.streaming = False
|
|
318
|
-
|
|
319
|
-
step_dict = self.to_dict()
|
|
320
|
-
data_layer = get_data_layer()
|
|
321
|
-
|
|
322
|
-
if data_layer:
|
|
323
|
-
try:
|
|
324
|
-
asyncio.create_task(data_layer.update_step(step_dict.copy()))
|
|
325
|
-
except Exception as e:
|
|
326
|
-
if self.fail_on_persist_error:
|
|
327
|
-
raise e
|
|
328
|
-
logger.error(f"Failed to persist step update: {e!s}")
|
|
329
|
-
|
|
330
|
-
tasks = [el.send(for_id=self.id) for el in self.elements]
|
|
331
|
-
await asyncio.gather(*tasks)
|
|
332
|
-
|
|
333
|
-
if not check_add_step_in_cot(self):
|
|
334
|
-
await context.emitter.update_step(stub_step(self))
|
|
335
|
-
else:
|
|
336
|
-
await context.emitter.update_step(step_dict)
|
|
337
|
-
|
|
338
|
-
return True
|
|
339
|
-
|
|
340
|
-
async def remove(self):
|
|
341
|
-
"""
|
|
342
|
-
Remove a step already sent to the UI.
|
|
343
|
-
"""
|
|
344
|
-
step_dict = self.to_dict()
|
|
345
|
-
data_layer = get_data_layer()
|
|
346
|
-
|
|
347
|
-
if data_layer:
|
|
348
|
-
try:
|
|
349
|
-
asyncio.create_task(data_layer.delete_step(self.id))
|
|
350
|
-
except Exception as e:
|
|
351
|
-
if self.fail_on_persist_error:
|
|
352
|
-
raise e
|
|
353
|
-
logger.error(f"Failed to persist step deletion: {e!s}")
|
|
354
|
-
|
|
355
|
-
await context.emitter.delete_step(step_dict)
|
|
356
|
-
|
|
357
|
-
return True
|
|
358
|
-
|
|
359
|
-
async def send(self):
|
|
360
|
-
if self.persisted:
|
|
361
|
-
return self
|
|
362
|
-
|
|
363
|
-
if config.code.author_rename:
|
|
364
|
-
self.name = await config.code.author_rename(self.name)
|
|
365
|
-
|
|
366
|
-
if self.streaming:
|
|
367
|
-
self.streaming = False
|
|
368
|
-
|
|
369
|
-
step_dict = self.to_dict()
|
|
370
|
-
|
|
371
|
-
data_layer = get_data_layer()
|
|
372
|
-
|
|
373
|
-
if data_layer:
|
|
374
|
-
try:
|
|
375
|
-
asyncio.create_task(data_layer.create_step(step_dict.copy()))
|
|
376
|
-
self.persisted = True
|
|
377
|
-
except Exception as e:
|
|
378
|
-
if self.fail_on_persist_error:
|
|
379
|
-
raise e
|
|
380
|
-
logger.error(f"Failed to persist step creation: {e!s}")
|
|
381
|
-
|
|
382
|
-
tasks = [el.send(for_id=self.id) for el in self.elements]
|
|
383
|
-
await asyncio.gather(*tasks)
|
|
384
|
-
|
|
385
|
-
if not check_add_step_in_cot(self):
|
|
386
|
-
await context.emitter.send_step(stub_step(self))
|
|
387
|
-
else:
|
|
388
|
-
await context.emitter.send_step(step_dict)
|
|
389
|
-
|
|
390
|
-
return self
|
|
391
|
-
|
|
392
|
-
async def stream_token(self, token: str, is_sequence=False, is_input=False):
|
|
393
|
-
"""
|
|
394
|
-
Sends a token to the UI.
|
|
395
|
-
Once all tokens have been streamed, call .send() to end the stream and persist the step if persistence is enabled.
|
|
396
|
-
"""
|
|
397
|
-
if not token:
|
|
398
|
-
return
|
|
399
|
-
|
|
400
|
-
if is_sequence:
|
|
401
|
-
if is_input:
|
|
402
|
-
self.input = token
|
|
403
|
-
else:
|
|
404
|
-
self.output = token
|
|
405
|
-
else:
|
|
406
|
-
if is_input:
|
|
407
|
-
self.input += token
|
|
408
|
-
else:
|
|
409
|
-
self.output += token
|
|
410
|
-
|
|
411
|
-
assert self.id
|
|
412
|
-
|
|
413
|
-
if not check_add_step_in_cot(self):
|
|
414
|
-
await context.emitter.send_step(stub_step(self))
|
|
415
|
-
return
|
|
416
|
-
|
|
417
|
-
if not self.streaming:
|
|
418
|
-
self.streaming = True
|
|
419
|
-
step_dict = self.to_dict()
|
|
420
|
-
await context.emitter.stream_start(step_dict)
|
|
421
|
-
else:
|
|
422
|
-
await context.emitter.send_token(
|
|
423
|
-
id=self.id, token=token, is_sequence=is_sequence, is_input=is_input
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
# Handle parameter less decorator
|
|
427
|
-
def __call__(self, func):
|
|
428
|
-
return step(
|
|
429
|
-
original_function=func,
|
|
430
|
-
type=self.type,
|
|
431
|
-
name=self.name,
|
|
432
|
-
id=self.id,
|
|
433
|
-
parent_id=self.parent_id,
|
|
434
|
-
thread_id=self.thread_id,
|
|
435
|
-
)
|
|
436
|
-
|
|
437
|
-
# Handle Context Manager Protocol
|
|
438
|
-
async def __aenter__(self):
|
|
439
|
-
self.start = utc_now()
|
|
440
|
-
previous_steps = local_steps.get() or []
|
|
441
|
-
parent_step = previous_steps[-1] if previous_steps else None
|
|
442
|
-
|
|
443
|
-
if not self.parent_id:
|
|
444
|
-
if parent_step:
|
|
445
|
-
self.parent_id = parent_step.id
|
|
446
|
-
local_steps.set(previous_steps + [self])
|
|
447
|
-
await self.send()
|
|
448
|
-
return self
|
|
449
|
-
|
|
450
|
-
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
451
|
-
self.end = utc_now()
|
|
452
|
-
|
|
453
|
-
if exc_type:
|
|
454
|
-
self.output = str(exc_val)
|
|
455
|
-
self.is_error = True
|
|
456
|
-
|
|
457
|
-
current_steps = local_steps.get()
|
|
458
|
-
if current_steps and self in current_steps:
|
|
459
|
-
current_steps.remove(self)
|
|
460
|
-
local_steps.set(current_steps)
|
|
461
|
-
|
|
462
|
-
await self.update()
|
|
463
|
-
|
|
464
|
-
def __enter__(self):
|
|
465
|
-
self.start = utc_now()
|
|
466
|
-
|
|
467
|
-
previous_steps = local_steps.get() or []
|
|
468
|
-
parent_step = previous_steps[-1] if previous_steps else None
|
|
469
|
-
|
|
470
|
-
if not self.parent_id:
|
|
471
|
-
if parent_step:
|
|
472
|
-
self.parent_id = parent_step.id
|
|
473
|
-
local_steps.set(previous_steps + [self])
|
|
474
|
-
|
|
475
|
-
asyncio.create_task(self.send())
|
|
476
|
-
return self
|
|
477
|
-
|
|
478
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
479
|
-
self.end = utc_now()
|
|
480
|
-
|
|
481
|
-
if exc_type:
|
|
482
|
-
self.output = str(exc_val)
|
|
483
|
-
self.is_error = True
|
|
484
|
-
|
|
485
|
-
current_steps = local_steps.get()
|
|
486
|
-
if current_steps and self in current_steps:
|
|
487
|
-
current_steps.remove(self)
|
|
488
|
-
local_steps.set(current_steps)
|
|
489
|
-
|
|
490
|
-
asyncio.create_task(self.update())
|
chainlit/sync.py
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
from typing import Any, Coroutine, TypeVar
|
|
3
|
-
|
|
4
|
-
if sys.version_info >= (3, 10):
|
|
5
|
-
from typing import ParamSpec
|
|
6
|
-
else:
|
|
7
|
-
from typing_extensions import ParamSpec
|
|
8
|
-
|
|
9
|
-
import asyncio
|
|
10
|
-
import threading
|
|
11
|
-
|
|
12
|
-
from asyncer import asyncify
|
|
13
|
-
from syncer import sync
|
|
14
|
-
|
|
15
|
-
from chainlit.context import context_var
|
|
16
|
-
|
|
17
|
-
make_async = asyncify
|
|
18
|
-
|
|
19
|
-
T_Retval = TypeVar("T_Retval")
|
|
20
|
-
T_ParamSpec = ParamSpec("T_ParamSpec")
|
|
21
|
-
T = TypeVar("T")
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def run_sync(co: Coroutine[Any, Any, T_Retval]) -> T_Retval:
|
|
25
|
-
"""Run the coroutine synchronously."""
|
|
26
|
-
|
|
27
|
-
# Copy the current context
|
|
28
|
-
current_context = context_var.get()
|
|
29
|
-
|
|
30
|
-
# Define a wrapper coroutine that sets the context before running the original coroutine
|
|
31
|
-
async def context_preserving_coroutine():
|
|
32
|
-
# Set the copied context to the coroutine
|
|
33
|
-
context_var.set(current_context)
|
|
34
|
-
return await co
|
|
35
|
-
|
|
36
|
-
# Execute from the main thread in the main event loop
|
|
37
|
-
if threading.current_thread() == threading.main_thread():
|
|
38
|
-
return sync(context_preserving_coroutine())
|
|
39
|
-
else: # Execute from a thread in the main event loop
|
|
40
|
-
result = asyncio.run_coroutine_threadsafe(
|
|
41
|
-
context_preserving_coroutine(), loop=current_context.loop
|
|
42
|
-
)
|
|
43
|
-
return result.result()
|