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/data/literalai.py
DELETED
|
@@ -1,501 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from typing import Dict, List, Literal, Optional, Union, cast
|
|
3
|
-
|
|
4
|
-
import aiofiles
|
|
5
|
-
from httpx import HTTPStatusError, RequestError
|
|
6
|
-
from literalai import (
|
|
7
|
-
Attachment as LiteralAttachment,
|
|
8
|
-
Score as LiteralScore,
|
|
9
|
-
Step as LiteralStep,
|
|
10
|
-
Thread as LiteralThread,
|
|
11
|
-
)
|
|
12
|
-
from literalai.observability.filter import threads_filters as LiteralThreadsFilters
|
|
13
|
-
from literalai.observability.step import StepDict as LiteralStepDict
|
|
14
|
-
|
|
15
|
-
from chainlit.data.base import BaseDataLayer
|
|
16
|
-
from chainlit.data.utils import queue_until_user_message
|
|
17
|
-
from chainlit.element import Audio, Element, ElementDict, File, Image, Pdf, Text, Video
|
|
18
|
-
from chainlit.logger import logger
|
|
19
|
-
from chainlit.step import (
|
|
20
|
-
FeedbackDict,
|
|
21
|
-
Step,
|
|
22
|
-
StepDict,
|
|
23
|
-
StepType,
|
|
24
|
-
TrueStepType,
|
|
25
|
-
check_add_step_in_cot,
|
|
26
|
-
stub_step,
|
|
27
|
-
)
|
|
28
|
-
from chainlit.types import (
|
|
29
|
-
Feedback,
|
|
30
|
-
PageInfo,
|
|
31
|
-
PaginatedResponse,
|
|
32
|
-
Pagination,
|
|
33
|
-
ThreadDict,
|
|
34
|
-
ThreadFilter,
|
|
35
|
-
)
|
|
36
|
-
from chainlit.user import PersistedUser, User
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class LiteralToChainlitConverter:
|
|
40
|
-
@classmethod
|
|
41
|
-
def steptype_to_steptype(cls, step_type: Optional[StepType]) -> TrueStepType:
|
|
42
|
-
return cast(TrueStepType, step_type or "undefined")
|
|
43
|
-
|
|
44
|
-
@classmethod
|
|
45
|
-
def score_to_feedbackdict(
|
|
46
|
-
cls,
|
|
47
|
-
score: Optional[LiteralScore],
|
|
48
|
-
) -> "Optional[FeedbackDict]":
|
|
49
|
-
if not score:
|
|
50
|
-
return None
|
|
51
|
-
return {
|
|
52
|
-
"id": score.id or "",
|
|
53
|
-
"forId": score.step_id or "",
|
|
54
|
-
"value": cast(Literal[0, 1], score.value),
|
|
55
|
-
"comment": score.comment,
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
@classmethod
|
|
59
|
-
def step_to_stepdict(cls, step: LiteralStep) -> "StepDict":
|
|
60
|
-
metadata = step.metadata or {}
|
|
61
|
-
input = (step.input or {}).get("content") or (
|
|
62
|
-
json.dumps(step.input) if step.input and step.input != {} else ""
|
|
63
|
-
)
|
|
64
|
-
output = (step.output or {}).get("content") or (
|
|
65
|
-
json.dumps(step.output) if step.output and step.output != {} else ""
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
user_feedback = (
|
|
69
|
-
next(
|
|
70
|
-
(
|
|
71
|
-
s
|
|
72
|
-
for s in step.scores
|
|
73
|
-
if s.type == "HUMAN" and s.name == "user-feedback"
|
|
74
|
-
),
|
|
75
|
-
None,
|
|
76
|
-
)
|
|
77
|
-
if step.scores
|
|
78
|
-
else None
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
return {
|
|
82
|
-
"createdAt": step.created_at,
|
|
83
|
-
"id": step.id or "",
|
|
84
|
-
"threadId": step.thread_id or "",
|
|
85
|
-
"parentId": step.parent_id,
|
|
86
|
-
"feedback": cls.score_to_feedbackdict(user_feedback),
|
|
87
|
-
"start": step.start_time,
|
|
88
|
-
"end": step.end_time,
|
|
89
|
-
"type": step.type or "undefined",
|
|
90
|
-
"name": step.name or "",
|
|
91
|
-
"generation": step.generation.to_dict() if step.generation else None,
|
|
92
|
-
"input": input,
|
|
93
|
-
"output": output,
|
|
94
|
-
"showInput": metadata.get("showInput", False),
|
|
95
|
-
"language": metadata.get("language"),
|
|
96
|
-
"isError": bool(step.error),
|
|
97
|
-
"waitForAnswer": metadata.get("waitForAnswer", False),
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
@classmethod
|
|
101
|
-
def attachment_to_elementdict(cls, attachment: LiteralAttachment) -> ElementDict:
|
|
102
|
-
metadata = attachment.metadata or {}
|
|
103
|
-
return {
|
|
104
|
-
"chainlitKey": None,
|
|
105
|
-
"display": metadata.get("display", "side"),
|
|
106
|
-
"language": metadata.get("language"),
|
|
107
|
-
"autoPlay": metadata.get("autoPlay", None),
|
|
108
|
-
"playerConfig": metadata.get("playerConfig", None),
|
|
109
|
-
"page": metadata.get("page"),
|
|
110
|
-
"props": metadata.get("props"),
|
|
111
|
-
"size": metadata.get("size"),
|
|
112
|
-
"type": metadata.get("type", "file"),
|
|
113
|
-
"forId": attachment.step_id,
|
|
114
|
-
"id": attachment.id or "",
|
|
115
|
-
"mime": attachment.mime,
|
|
116
|
-
"name": attachment.name or "",
|
|
117
|
-
"objectKey": attachment.object_key,
|
|
118
|
-
"url": attachment.url,
|
|
119
|
-
"threadId": attachment.thread_id,
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
@classmethod
|
|
123
|
-
def attachment_to_element(
|
|
124
|
-
cls, attachment: LiteralAttachment, thread_id: Optional[str] = None
|
|
125
|
-
) -> Element:
|
|
126
|
-
metadata = attachment.metadata or {}
|
|
127
|
-
element_type = metadata.get("type", "file")
|
|
128
|
-
|
|
129
|
-
element_class = {
|
|
130
|
-
"file": File,
|
|
131
|
-
"image": Image,
|
|
132
|
-
"audio": Audio,
|
|
133
|
-
"video": Video,
|
|
134
|
-
"text": Text,
|
|
135
|
-
"pdf": Pdf,
|
|
136
|
-
}.get(element_type, Element)
|
|
137
|
-
|
|
138
|
-
assert thread_id or attachment.thread_id
|
|
139
|
-
|
|
140
|
-
element = element_class(
|
|
141
|
-
name=attachment.name or "",
|
|
142
|
-
display=metadata.get("display", "side"),
|
|
143
|
-
language=metadata.get("language"),
|
|
144
|
-
size=metadata.get("size"),
|
|
145
|
-
url=attachment.url,
|
|
146
|
-
mime=attachment.mime,
|
|
147
|
-
thread_id=thread_id or attachment.thread_id,
|
|
148
|
-
)
|
|
149
|
-
element.id = attachment.id or ""
|
|
150
|
-
element.for_id = attachment.step_id
|
|
151
|
-
element.object_key = attachment.object_key
|
|
152
|
-
return element
|
|
153
|
-
|
|
154
|
-
@classmethod
|
|
155
|
-
def step_to_step(cls, step: LiteralStep) -> Step:
|
|
156
|
-
chainlit_step = Step(
|
|
157
|
-
name=step.name or "",
|
|
158
|
-
type=cls.steptype_to_steptype(step.type),
|
|
159
|
-
id=step.id,
|
|
160
|
-
parent_id=step.parent_id,
|
|
161
|
-
thread_id=step.thread_id or None,
|
|
162
|
-
)
|
|
163
|
-
chainlit_step.start = step.start_time
|
|
164
|
-
chainlit_step.end = step.end_time
|
|
165
|
-
chainlit_step.created_at = step.created_at
|
|
166
|
-
chainlit_step.input = step.input.get("content", "") if step.input else ""
|
|
167
|
-
chainlit_step.output = step.output.get("content", "") if step.output else ""
|
|
168
|
-
chainlit_step.is_error = bool(step.error)
|
|
169
|
-
chainlit_step.metadata = step.metadata or {}
|
|
170
|
-
chainlit_step.tags = step.tags
|
|
171
|
-
chainlit_step.generation = step.generation
|
|
172
|
-
|
|
173
|
-
if step.attachments:
|
|
174
|
-
chainlit_step.elements = [
|
|
175
|
-
cls.attachment_to_element(attachment, chainlit_step.thread_id)
|
|
176
|
-
for attachment in step.attachments
|
|
177
|
-
]
|
|
178
|
-
|
|
179
|
-
return chainlit_step
|
|
180
|
-
|
|
181
|
-
@classmethod
|
|
182
|
-
def thread_to_threaddict(cls, thread: LiteralThread) -> ThreadDict:
|
|
183
|
-
return {
|
|
184
|
-
"id": thread.id,
|
|
185
|
-
"createdAt": getattr(thread, "created_at", ""),
|
|
186
|
-
"name": thread.name,
|
|
187
|
-
"userId": thread.participant_id,
|
|
188
|
-
"userIdentifier": thread.participant_identifier,
|
|
189
|
-
"tags": thread.tags,
|
|
190
|
-
"metadata": thread.metadata,
|
|
191
|
-
"steps": [cls.step_to_stepdict(step) for step in thread.steps]
|
|
192
|
-
if thread.steps
|
|
193
|
-
else [],
|
|
194
|
-
"elements": [
|
|
195
|
-
cls.attachment_to_elementdict(attachment)
|
|
196
|
-
for step in thread.steps
|
|
197
|
-
for attachment in step.attachments
|
|
198
|
-
]
|
|
199
|
-
if thread.steps
|
|
200
|
-
else [],
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
class LiteralDataLayer(BaseDataLayer):
|
|
205
|
-
def __init__(self, api_key: str, server: Optional[str]):
|
|
206
|
-
from literalai import AsyncLiteralClient
|
|
207
|
-
|
|
208
|
-
self.client = AsyncLiteralClient(api_key=api_key, url=server)
|
|
209
|
-
logger.info("Chainlit data layer initialized")
|
|
210
|
-
|
|
211
|
-
async def build_debug_url(self) -> str:
|
|
212
|
-
try:
|
|
213
|
-
project_id = await self.client.api.get_my_project_id()
|
|
214
|
-
return f"{self.client.api.url}/projects/{project_id}/logs/threads/[thread_id]?currentStepId=[step_id]"
|
|
215
|
-
except Exception as e:
|
|
216
|
-
logger.error(f"Error building debug url: {e}")
|
|
217
|
-
return ""
|
|
218
|
-
|
|
219
|
-
async def get_user(self, identifier: str) -> Optional[PersistedUser]:
|
|
220
|
-
user = await self.client.api.get_user(identifier=identifier)
|
|
221
|
-
if not user:
|
|
222
|
-
return None
|
|
223
|
-
return PersistedUser(
|
|
224
|
-
id=user.id or "",
|
|
225
|
-
identifier=user.identifier or "",
|
|
226
|
-
metadata=user.metadata,
|
|
227
|
-
createdAt=user.created_at or "",
|
|
228
|
-
)
|
|
229
|
-
|
|
230
|
-
async def create_user(self, user: User) -> Optional[PersistedUser]:
|
|
231
|
-
_user = await self.client.api.get_user(identifier=user.identifier)
|
|
232
|
-
if not _user:
|
|
233
|
-
_user = await self.client.api.create_user(
|
|
234
|
-
identifier=user.identifier, metadata=user.metadata
|
|
235
|
-
)
|
|
236
|
-
elif _user.id:
|
|
237
|
-
await self.client.api.update_user(id=_user.id, metadata=user.metadata)
|
|
238
|
-
return PersistedUser(
|
|
239
|
-
id=_user.id or "",
|
|
240
|
-
identifier=_user.identifier or "",
|
|
241
|
-
metadata=user.metadata,
|
|
242
|
-
createdAt=_user.created_at or "",
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
async def delete_feedback(
|
|
246
|
-
self,
|
|
247
|
-
feedback_id: str,
|
|
248
|
-
):
|
|
249
|
-
if feedback_id:
|
|
250
|
-
await self.client.api.delete_score(
|
|
251
|
-
id=feedback_id,
|
|
252
|
-
)
|
|
253
|
-
return True
|
|
254
|
-
return False
|
|
255
|
-
|
|
256
|
-
async def upsert_feedback(
|
|
257
|
-
self,
|
|
258
|
-
feedback: Feedback,
|
|
259
|
-
):
|
|
260
|
-
if feedback.id:
|
|
261
|
-
await self.client.api.update_score(
|
|
262
|
-
id=feedback.id,
|
|
263
|
-
update_params={
|
|
264
|
-
"comment": feedback.comment,
|
|
265
|
-
"value": feedback.value,
|
|
266
|
-
},
|
|
267
|
-
)
|
|
268
|
-
return feedback.id
|
|
269
|
-
else:
|
|
270
|
-
created = await self.client.api.create_score(
|
|
271
|
-
step_id=feedback.forId,
|
|
272
|
-
value=feedback.value,
|
|
273
|
-
comment=feedback.comment,
|
|
274
|
-
name="user-feedback",
|
|
275
|
-
type="HUMAN",
|
|
276
|
-
)
|
|
277
|
-
return created.id or ""
|
|
278
|
-
|
|
279
|
-
async def safely_send_steps(self, steps):
|
|
280
|
-
try:
|
|
281
|
-
await self.client.api.send_steps(steps)
|
|
282
|
-
except HTTPStatusError as e:
|
|
283
|
-
logger.error(f"HTTP Request: error sending steps: {e.response.status_code}")
|
|
284
|
-
except RequestError as e:
|
|
285
|
-
logger.error(f"HTTP Request: error for {e.request.url!r}.")
|
|
286
|
-
|
|
287
|
-
@queue_until_user_message()
|
|
288
|
-
async def create_element(self, element: "Element"):
|
|
289
|
-
metadata = {
|
|
290
|
-
"size": element.size,
|
|
291
|
-
"language": element.language,
|
|
292
|
-
"display": element.display,
|
|
293
|
-
"type": element.type,
|
|
294
|
-
"page": getattr(element, "page", None),
|
|
295
|
-
"props": getattr(element, "props", None),
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if not element.for_id:
|
|
299
|
-
return
|
|
300
|
-
|
|
301
|
-
object_key = None
|
|
302
|
-
|
|
303
|
-
if not element.url:
|
|
304
|
-
if element.path:
|
|
305
|
-
async with aiofiles.open(element.path, "rb") as f:
|
|
306
|
-
content: Union[bytes, str] = await f.read()
|
|
307
|
-
elif element.content:
|
|
308
|
-
content = element.content
|
|
309
|
-
else:
|
|
310
|
-
raise ValueError("Either path or content must be provided")
|
|
311
|
-
uploaded = await self.client.api.upload_file(
|
|
312
|
-
content=content, mime=element.mime, thread_id=element.thread_id
|
|
313
|
-
)
|
|
314
|
-
object_key = uploaded["object_key"]
|
|
315
|
-
|
|
316
|
-
await self.safely_send_steps(
|
|
317
|
-
[
|
|
318
|
-
{
|
|
319
|
-
"id": element.for_id,
|
|
320
|
-
"threadId": element.thread_id,
|
|
321
|
-
"attachments": [
|
|
322
|
-
{
|
|
323
|
-
"id": element.id,
|
|
324
|
-
"name": element.name,
|
|
325
|
-
"metadata": metadata,
|
|
326
|
-
"mime": element.mime,
|
|
327
|
-
"url": element.url,
|
|
328
|
-
"objectKey": object_key,
|
|
329
|
-
}
|
|
330
|
-
],
|
|
331
|
-
}
|
|
332
|
-
]
|
|
333
|
-
)
|
|
334
|
-
|
|
335
|
-
async def get_element(
|
|
336
|
-
self, thread_id: str, element_id: str
|
|
337
|
-
) -> Optional["ElementDict"]:
|
|
338
|
-
attachment = await self.client.api.get_attachment(id=element_id)
|
|
339
|
-
if not attachment:
|
|
340
|
-
return None
|
|
341
|
-
return LiteralToChainlitConverter.attachment_to_elementdict(attachment)
|
|
342
|
-
|
|
343
|
-
@queue_until_user_message()
|
|
344
|
-
async def delete_element(self, element_id: str, thread_id: Optional[str] = None):
|
|
345
|
-
await self.client.api.delete_attachment(id=element_id)
|
|
346
|
-
|
|
347
|
-
@queue_until_user_message()
|
|
348
|
-
async def create_step(self, step_dict: "StepDict"):
|
|
349
|
-
metadata = dict(
|
|
350
|
-
step_dict.get("metadata", {}),
|
|
351
|
-
waitForAnswer=step_dict.get("waitForAnswer"),
|
|
352
|
-
language=step_dict.get("language"),
|
|
353
|
-
showInput=step_dict.get("showInput"),
|
|
354
|
-
)
|
|
355
|
-
|
|
356
|
-
step: LiteralStepDict = {
|
|
357
|
-
"createdAt": step_dict.get("createdAt"),
|
|
358
|
-
"startTime": step_dict.get("start"),
|
|
359
|
-
"endTime": step_dict.get("end"),
|
|
360
|
-
"generation": step_dict.get("generation"),
|
|
361
|
-
"id": step_dict.get("id"),
|
|
362
|
-
"parentId": step_dict.get("parentId"),
|
|
363
|
-
"name": step_dict.get("name"),
|
|
364
|
-
"threadId": step_dict.get("threadId"),
|
|
365
|
-
"type": step_dict.get("type"),
|
|
366
|
-
"tags": step_dict.get("tags"),
|
|
367
|
-
"metadata": metadata,
|
|
368
|
-
}
|
|
369
|
-
if step_dict.get("input"):
|
|
370
|
-
step["input"] = {"content": step_dict.get("input")}
|
|
371
|
-
if step_dict.get("output"):
|
|
372
|
-
step["output"] = {"content": step_dict.get("output")}
|
|
373
|
-
if step_dict.get("isError"):
|
|
374
|
-
step["error"] = step_dict.get("output")
|
|
375
|
-
|
|
376
|
-
await self.safely_send_steps([step])
|
|
377
|
-
|
|
378
|
-
@queue_until_user_message()
|
|
379
|
-
async def update_step(self, step_dict: "StepDict"):
|
|
380
|
-
await self.create_step(step_dict)
|
|
381
|
-
|
|
382
|
-
@queue_until_user_message()
|
|
383
|
-
async def delete_step(self, step_id: str):
|
|
384
|
-
await self.client.api.delete_step(id=step_id)
|
|
385
|
-
|
|
386
|
-
async def get_thread_author(self, thread_id: str) -> str:
|
|
387
|
-
thread = await self.get_thread(thread_id)
|
|
388
|
-
if not thread:
|
|
389
|
-
return ""
|
|
390
|
-
user_identifier = thread.get("userIdentifier")
|
|
391
|
-
if not user_identifier:
|
|
392
|
-
return ""
|
|
393
|
-
|
|
394
|
-
return user_identifier
|
|
395
|
-
|
|
396
|
-
async def delete_thread(self, thread_id: str):
|
|
397
|
-
await self.client.api.delete_thread(id=thread_id)
|
|
398
|
-
|
|
399
|
-
async def list_threads(
|
|
400
|
-
self, pagination: "Pagination", filters: "ThreadFilter"
|
|
401
|
-
) -> "PaginatedResponse[ThreadDict]":
|
|
402
|
-
if not filters.userId:
|
|
403
|
-
raise ValueError("userId is required")
|
|
404
|
-
|
|
405
|
-
literal_filters: LiteralThreadsFilters = [
|
|
406
|
-
{
|
|
407
|
-
"field": "participantId",
|
|
408
|
-
"operator": "eq",
|
|
409
|
-
"value": filters.userId,
|
|
410
|
-
}
|
|
411
|
-
]
|
|
412
|
-
|
|
413
|
-
if filters.search:
|
|
414
|
-
literal_filters.append(
|
|
415
|
-
{
|
|
416
|
-
"field": "stepOutput",
|
|
417
|
-
"operator": "ilike",
|
|
418
|
-
"value": filters.search,
|
|
419
|
-
"path": "content",
|
|
420
|
-
}
|
|
421
|
-
)
|
|
422
|
-
|
|
423
|
-
if filters.feedback is not None:
|
|
424
|
-
literal_filters.append(
|
|
425
|
-
{
|
|
426
|
-
"field": "scoreValue",
|
|
427
|
-
"operator": "eq",
|
|
428
|
-
"value": filters.feedback,
|
|
429
|
-
"path": "user-feedback",
|
|
430
|
-
}
|
|
431
|
-
)
|
|
432
|
-
|
|
433
|
-
literal_response = await self.client.api.list_threads(
|
|
434
|
-
first=pagination.first,
|
|
435
|
-
after=pagination.cursor,
|
|
436
|
-
filters=literal_filters,
|
|
437
|
-
order_by={"column": "createdAt", "direction": "DESC"},
|
|
438
|
-
)
|
|
439
|
-
|
|
440
|
-
chainlit_threads = [
|
|
441
|
-
*map(LiteralToChainlitConverter.thread_to_threaddict, literal_response.data)
|
|
442
|
-
]
|
|
443
|
-
|
|
444
|
-
return PaginatedResponse(
|
|
445
|
-
pageInfo=PageInfo(
|
|
446
|
-
hasNextPage=literal_response.page_info.has_next_page,
|
|
447
|
-
startCursor=literal_response.page_info.start_cursor,
|
|
448
|
-
endCursor=literal_response.page_info.end_cursor,
|
|
449
|
-
),
|
|
450
|
-
data=chainlit_threads,
|
|
451
|
-
)
|
|
452
|
-
|
|
453
|
-
async def get_thread(self, thread_id: str) -> Optional[ThreadDict]:
|
|
454
|
-
thread = await self.client.api.get_thread(id=thread_id)
|
|
455
|
-
if not thread:
|
|
456
|
-
return None
|
|
457
|
-
|
|
458
|
-
elements: List[ElementDict] = []
|
|
459
|
-
steps: List[StepDict] = []
|
|
460
|
-
if thread.steps:
|
|
461
|
-
for step in thread.steps:
|
|
462
|
-
for attachment in step.attachments:
|
|
463
|
-
elements.append(
|
|
464
|
-
LiteralToChainlitConverter.attachment_to_elementdict(attachment)
|
|
465
|
-
)
|
|
466
|
-
|
|
467
|
-
chainlit_step = LiteralToChainlitConverter.step_to_step(step)
|
|
468
|
-
if check_add_step_in_cot(chainlit_step):
|
|
469
|
-
steps.append(
|
|
470
|
-
LiteralToChainlitConverter.step_to_stepdict(step)
|
|
471
|
-
) # TODO: chainlit_step.to_dict()
|
|
472
|
-
else:
|
|
473
|
-
steps.append(stub_step(chainlit_step))
|
|
474
|
-
|
|
475
|
-
return {
|
|
476
|
-
"createdAt": thread.created_at or "",
|
|
477
|
-
"id": thread.id,
|
|
478
|
-
"name": thread.name or None,
|
|
479
|
-
"steps": steps,
|
|
480
|
-
"elements": elements,
|
|
481
|
-
"metadata": thread.metadata,
|
|
482
|
-
"userId": thread.participant_id,
|
|
483
|
-
"userIdentifier": thread.participant_identifier,
|
|
484
|
-
"tags": thread.tags,
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
async def update_thread(
|
|
488
|
-
self,
|
|
489
|
-
thread_id: str,
|
|
490
|
-
name: Optional[str] = None,
|
|
491
|
-
user_id: Optional[str] = None,
|
|
492
|
-
metadata: Optional[Dict] = None,
|
|
493
|
-
tags: Optional[List[str]] = None,
|
|
494
|
-
):
|
|
495
|
-
await self.client.api.upsert_thread(
|
|
496
|
-
id=thread_id,
|
|
497
|
-
name=name,
|
|
498
|
-
participant_id=user_id,
|
|
499
|
-
metadata=metadata,
|
|
500
|
-
tags=tags,
|
|
501
|
-
)
|