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.

Files changed (85) hide show
  1. {chainlit-2.7.0.dist-info → chainlit-2.7.1.dist-info}/METADATA +1 -1
  2. chainlit-2.7.1.dist-info/RECORD +4 -0
  3. chainlit/__init__.py +0 -207
  4. chainlit/__main__.py +0 -4
  5. chainlit/_utils.py +0 -8
  6. chainlit/action.py +0 -33
  7. chainlit/auth/__init__.py +0 -95
  8. chainlit/auth/cookie.py +0 -197
  9. chainlit/auth/jwt.py +0 -42
  10. chainlit/cache.py +0 -45
  11. chainlit/callbacks.py +0 -433
  12. chainlit/chat_context.py +0 -64
  13. chainlit/chat_settings.py +0 -34
  14. chainlit/cli/__init__.py +0 -235
  15. chainlit/config.py +0 -621
  16. chainlit/context.py +0 -112
  17. chainlit/data/__init__.py +0 -111
  18. chainlit/data/acl.py +0 -19
  19. chainlit/data/base.py +0 -107
  20. chainlit/data/chainlit_data_layer.py +0 -687
  21. chainlit/data/dynamodb.py +0 -616
  22. chainlit/data/literalai.py +0 -501
  23. chainlit/data/sql_alchemy.py +0 -741
  24. chainlit/data/storage_clients/__init__.py +0 -0
  25. chainlit/data/storage_clients/azure.py +0 -84
  26. chainlit/data/storage_clients/azure_blob.py +0 -94
  27. chainlit/data/storage_clients/base.py +0 -28
  28. chainlit/data/storage_clients/gcs.py +0 -101
  29. chainlit/data/storage_clients/s3.py +0 -88
  30. chainlit/data/utils.py +0 -29
  31. chainlit/discord/__init__.py +0 -6
  32. chainlit/discord/app.py +0 -364
  33. chainlit/element.py +0 -454
  34. chainlit/emitter.py +0 -450
  35. chainlit/hello.py +0 -12
  36. chainlit/input_widget.py +0 -182
  37. chainlit/langchain/__init__.py +0 -6
  38. chainlit/langchain/callbacks.py +0 -682
  39. chainlit/langflow/__init__.py +0 -25
  40. chainlit/llama_index/__init__.py +0 -6
  41. chainlit/llama_index/callbacks.py +0 -206
  42. chainlit/logger.py +0 -16
  43. chainlit/markdown.py +0 -57
  44. chainlit/mcp.py +0 -99
  45. chainlit/message.py +0 -619
  46. chainlit/mistralai/__init__.py +0 -50
  47. chainlit/oauth_providers.py +0 -835
  48. chainlit/openai/__init__.py +0 -53
  49. chainlit/py.typed +0 -0
  50. chainlit/secret.py +0 -9
  51. chainlit/semantic_kernel/__init__.py +0 -111
  52. chainlit/server.py +0 -1616
  53. chainlit/session.py +0 -304
  54. chainlit/sidebar.py +0 -55
  55. chainlit/slack/__init__.py +0 -6
  56. chainlit/slack/app.py +0 -427
  57. chainlit/socket.py +0 -381
  58. chainlit/step.py +0 -490
  59. chainlit/sync.py +0 -43
  60. chainlit/teams/__init__.py +0 -6
  61. chainlit/teams/app.py +0 -348
  62. chainlit/translations/bn.json +0 -214
  63. chainlit/translations/el-GR.json +0 -214
  64. chainlit/translations/en-US.json +0 -214
  65. chainlit/translations/fr-FR.json +0 -214
  66. chainlit/translations/gu.json +0 -214
  67. chainlit/translations/he-IL.json +0 -214
  68. chainlit/translations/hi.json +0 -214
  69. chainlit/translations/ja.json +0 -214
  70. chainlit/translations/kn.json +0 -214
  71. chainlit/translations/ml.json +0 -214
  72. chainlit/translations/mr.json +0 -214
  73. chainlit/translations/nl.json +0 -214
  74. chainlit/translations/ta.json +0 -214
  75. chainlit/translations/te.json +0 -214
  76. chainlit/translations/zh-CN.json +0 -214
  77. chainlit/translations.py +0 -60
  78. chainlit/types.py +0 -334
  79. chainlit/user.py +0 -43
  80. chainlit/user_session.py +0 -153
  81. chainlit/utils.py +0 -173
  82. chainlit/version.py +0 -8
  83. chainlit-2.7.0.dist-info/RECORD +0 -84
  84. {chainlit-2.7.0.dist-info → chainlit-2.7.1.dist-info}/WHEEL +0 -0
  85. {chainlit-2.7.0.dist-info → chainlit-2.7.1.dist-info}/entry_points.txt +0 -0
chainlit/element.py DELETED
@@ -1,454 +0,0 @@
1
- import json
2
- import mimetypes
3
- import uuid
4
- from enum import Enum
5
- from io import BytesIO
6
- from typing import (
7
- Any,
8
- ClassVar,
9
- Dict,
10
- List,
11
- Literal,
12
- Optional,
13
- TypedDict,
14
- TypeVar,
15
- Union,
16
- )
17
-
18
- import filetype
19
- from pydantic import Field
20
- from pydantic.dataclasses import dataclass
21
- from syncer import asyncio
22
-
23
- from chainlit.context import context
24
- from chainlit.data import get_data_layer
25
- from chainlit.logger import logger
26
-
27
- mime_types = {
28
- "text": "text/plain",
29
- "tasklist": "application/json",
30
- "plotly": "application/json",
31
- }
32
-
33
- ElementType = Literal[
34
- "image",
35
- "text",
36
- "pdf",
37
- "tasklist",
38
- "audio",
39
- "video",
40
- "file",
41
- "plotly",
42
- "dataframe",
43
- "custom",
44
- ]
45
- ElementDisplay = Literal["inline", "side", "page"]
46
- ElementSize = Literal["small", "medium", "large"]
47
-
48
-
49
- class ElementDict(TypedDict, total=False):
50
- id: str
51
- threadId: Optional[str]
52
- type: ElementType
53
- chainlitKey: Optional[str]
54
- path: Optional[str]
55
- url: Optional[str]
56
- objectKey: Optional[str]
57
- name: str
58
- display: ElementDisplay
59
- size: Optional[ElementSize]
60
- language: Optional[str]
61
- page: Optional[int]
62
- props: Optional[Dict]
63
- autoPlay: Optional[bool]
64
- playerConfig: Optional[dict]
65
- forId: Optional[str]
66
- mime: Optional[str]
67
-
68
-
69
- @dataclass
70
- class Element:
71
- # Thread id
72
- thread_id: str = Field(default_factory=lambda: context.session.thread_id)
73
- # The type of the element. This will be used to determine how to display the element in the UI.
74
- type: ClassVar[ElementType]
75
- # Name of the element, this will be used to reference the element in the UI.
76
- name: str = ""
77
- # The ID of the element. This is set automatically when the element is sent to the UI.
78
- id: str = Field(default_factory=lambda: str(uuid.uuid4()))
79
- # The key of the element hosted on Chainlit.
80
- chainlit_key: Optional[str] = None
81
- # The URL of the element if already hosted somewhere else.
82
- url: Optional[str] = None
83
- # The S3 object key.
84
- object_key: Optional[str] = None
85
- # The local path of the element.
86
- path: Optional[str] = None
87
- # The byte content of the element.
88
- content: Optional[Union[bytes, str]] = None
89
- # Controls how the image element should be displayed in the UI. Choices are “side” (default), “inline”, or “page”.
90
- display: ElementDisplay = Field(default="inline")
91
- # Controls element size
92
- size: Optional[ElementSize] = None
93
- # The ID of the message this element is associated with.
94
- for_id: Optional[str] = None
95
- # The language, if relevant
96
- language: Optional[str] = None
97
- # Mime type, inferred based on content if not provided
98
- mime: Optional[str] = None
99
-
100
- def __post_init__(self) -> None:
101
- self.persisted = False
102
- self.updatable = False
103
-
104
- if not self.url and not self.path and not self.content:
105
- raise ValueError("Must provide url, path or content to instantiate element")
106
-
107
- def to_dict(self) -> ElementDict:
108
- _dict = ElementDict(
109
- {
110
- "id": self.id,
111
- "threadId": self.thread_id,
112
- "type": self.type,
113
- "url": self.url,
114
- "chainlitKey": self.chainlit_key,
115
- "name": self.name,
116
- "display": self.display,
117
- "objectKey": getattr(self, "object_key", None),
118
- "size": getattr(self, "size", None),
119
- "props": getattr(self, "props", None),
120
- "page": getattr(self, "page", None),
121
- "autoPlay": getattr(self, "auto_play", None),
122
- "playerConfig": getattr(self, "player_config", None),
123
- "language": getattr(self, "language", None),
124
- "forId": getattr(self, "for_id", None),
125
- "mime": getattr(self, "mime", None),
126
- }
127
- )
128
- return _dict
129
-
130
- @classmethod
131
- def from_dict(cls, e_dict: ElementDict):
132
- """
133
- Create an Element instance from a dictionary representation.
134
-
135
- Args:
136
- _dict (ElementDict): Dictionary containing element data
137
-
138
- Returns:
139
- Element: An instance of the appropriate Element subclass
140
- """
141
- element_id = e_dict.get("id", str(uuid.uuid4()))
142
- for_id = e_dict.get("forId")
143
- name = e_dict.get("name", "")
144
- type = e_dict.get("type", "file")
145
- path = str(e_dict.get("path")) if e_dict.get("path") else None
146
- url = str(e_dict.get("url")) if e_dict.get("url") else None
147
- content = str(e_dict.get("content")) if e_dict.get("content") else None
148
- object_key = e_dict.get("objectKey")
149
- chainlit_key = e_dict.get("chainlitKey")
150
- display = e_dict.get("display", "inline")
151
- mime_type = e_dict.get("mime", "")
152
-
153
- # Common parameters for all element types
154
- common_params = {
155
- "id": element_id,
156
- "for_id": for_id,
157
- "name": name,
158
- "content": content,
159
- "path": path,
160
- "url": url,
161
- "object_key": object_key,
162
- "chainlit_key": chainlit_key,
163
- "display": display,
164
- "mime": mime_type,
165
- }
166
-
167
- if type == "image":
168
- return Image(size="medium", **common_params) # type: ignore[arg-type]
169
-
170
- elif type == "audio":
171
- return Audio(auto_play=e_dict.get("autoPlay", False), **common_params) # type: ignore[arg-type]
172
-
173
- elif type == "video":
174
- return Video(
175
- player_config=e_dict.get("playerConfig"),
176
- **common_params, # type: ignore[arg-type]
177
- )
178
-
179
- elif type == "plotly":
180
- return Plotly(size=e_dict.get("size", "medium"), **common_params) # type: ignore[arg-type]
181
-
182
- elif type == "custom":
183
- return CustomElement(props=e_dict.get("props", {}), **common_params) # type: ignore[arg-type]
184
- else:
185
- # Default to File for any other type
186
- return File(**common_params) # type: ignore[arg-type]
187
-
188
- @classmethod
189
- def infer_type_from_mime(cls, mime_type: str):
190
- """Infer the element type from a mime type. Useful to know which element to instantiate from a file upload."""
191
- if "image" in mime_type:
192
- return "image"
193
-
194
- elif mime_type == "application/pdf":
195
- return "pdf"
196
-
197
- elif "audio" in mime_type:
198
- return "audio"
199
-
200
- elif "video" in mime_type:
201
- return "video"
202
-
203
- else:
204
- return "file"
205
-
206
- async def _create(self, persist=True) -> bool:
207
- if self.persisted and not self.updatable:
208
- return True
209
-
210
- if (data_layer := get_data_layer()) and persist:
211
- try:
212
- asyncio.create_task(data_layer.create_element(self))
213
- except Exception as e:
214
- logger.error(f"Failed to create element: {e!s}")
215
- if not self.url and (not self.chainlit_key or self.updatable):
216
- file_dict = await context.session.persist_file(
217
- name=self.name,
218
- path=self.path,
219
- content=self.content,
220
- mime=self.mime or "",
221
- )
222
- self.chainlit_key = file_dict["id"]
223
-
224
- self.persisted = True
225
-
226
- return True
227
-
228
- async def remove(self):
229
- data_layer = get_data_layer()
230
- if data_layer:
231
- await data_layer.delete_element(self.id, self.thread_id)
232
- await context.emitter.emit("remove_element", {"id": self.id})
233
-
234
- async def send(self, for_id: str, persist=True):
235
- self.for_id = for_id
236
-
237
- if not self.mime:
238
- if self.type in mime_types:
239
- self.mime = mime_types[self.type]
240
- elif self.path or isinstance(self.content, (bytes, bytearray)):
241
- file_type = filetype.guess(self.path or self.content)
242
- if file_type:
243
- self.mime = file_type.mime
244
- elif self.url:
245
- self.mime = mimetypes.guess_type(self.url)[0]
246
-
247
- await self._create(persist=persist)
248
-
249
- if not self.url and not self.chainlit_key:
250
- raise ValueError("Must provide url or chainlit key to send element")
251
-
252
- await context.emitter.send_element(self.to_dict())
253
-
254
-
255
- ElementBased = TypeVar("ElementBased", bound=Element)
256
-
257
-
258
- @dataclass
259
- class Image(Element):
260
- type: ClassVar[ElementType] = "image"
261
-
262
- size: ElementSize = "medium"
263
-
264
-
265
- @dataclass
266
- class Text(Element):
267
- """Useful to send a text (not a message) to the UI."""
268
-
269
- type: ClassVar[ElementType] = "text"
270
- language: Optional[str] = None
271
-
272
-
273
- @dataclass
274
- class Pdf(Element):
275
- """Useful to send a pdf to the UI."""
276
-
277
- mime: str = "application/pdf"
278
- page: Optional[int] = None
279
- type: ClassVar[ElementType] = "pdf"
280
-
281
-
282
- @dataclass
283
- class Pyplot(Element):
284
- """Useful to send a pyplot to the UI."""
285
-
286
- # We reuse the frontend image element to display the chart
287
- type: ClassVar[ElementType] = "image"
288
-
289
- size: ElementSize = "medium"
290
- # The type is set to Any because the figure is not serializable
291
- # and its actual type is checked in __post_init__.
292
- figure: Any = None
293
-
294
- def __post_init__(self) -> None:
295
- from matplotlib.figure import Figure
296
-
297
- if not isinstance(self.figure, Figure):
298
- raise TypeError("figure must be a matplotlib.figure.Figure")
299
-
300
- image = BytesIO()
301
- self.figure.savefig(
302
- image, dpi=200, bbox_inches="tight", backend="Agg", format="png"
303
- )
304
- self.content = image.getvalue()
305
-
306
- super().__post_init__()
307
-
308
-
309
- class TaskStatus(Enum):
310
- READY = "ready"
311
- RUNNING = "running"
312
- FAILED = "failed"
313
- DONE = "done"
314
-
315
-
316
- @dataclass
317
- class Task:
318
- title: str
319
- status: TaskStatus = TaskStatus.READY
320
- forId: Optional[str] = None
321
-
322
- def __init__(
323
- self,
324
- title: str,
325
- status: TaskStatus = TaskStatus.READY,
326
- forId: Optional[str] = None,
327
- ):
328
- self.title = title
329
- self.status = status
330
- self.forId = forId
331
-
332
-
333
- @dataclass
334
- class TaskList(Element):
335
- type: ClassVar[ElementType] = "tasklist"
336
- tasks: List[Task] = Field(default_factory=list, exclude=True)
337
- status: str = "Ready"
338
- name: str = "tasklist"
339
- content: str = "dummy content to pass validation"
340
-
341
- def __post_init__(self) -> None:
342
- super().__post_init__()
343
- self.updatable = True
344
-
345
- async def add_task(self, task: Task):
346
- self.tasks.append(task)
347
-
348
- async def update(self):
349
- await self.send()
350
-
351
- async def send(self):
352
- await self.preprocess_content()
353
- await super().send(for_id="")
354
-
355
- async def preprocess_content(self):
356
- # serialize enum
357
- tasks = [
358
- {"title": task.title, "status": task.status.value, "forId": task.forId}
359
- for task in self.tasks
360
- ]
361
-
362
- # store stringified json in content so that it's correctly stored in the database
363
- self.content = json.dumps(
364
- {
365
- "status": self.status,
366
- "tasks": tasks,
367
- },
368
- indent=4,
369
- ensure_ascii=False,
370
- )
371
-
372
-
373
- @dataclass
374
- class Audio(Element):
375
- type: ClassVar[ElementType] = "audio"
376
- auto_play: bool = False
377
-
378
-
379
- @dataclass
380
- class Video(Element):
381
- type: ClassVar[ElementType] = "video"
382
-
383
- size: ElementSize = "medium"
384
- # Override settings for each type of player in ReactPlayer
385
- # https://github.com/cookpete/react-player?tab=readme-ov-file#config-prop
386
- player_config: Optional[dict] = None
387
-
388
-
389
- @dataclass
390
- class File(Element):
391
- type: ClassVar[ElementType] = "file"
392
-
393
-
394
- @dataclass
395
- class Plotly(Element):
396
- """Useful to send a plotly to the UI."""
397
-
398
- type: ClassVar[ElementType] = "plotly"
399
-
400
- size: ElementSize = "medium"
401
- # The type is set to Any because the figure is not serializable
402
- # and its actual type is checked in __post_init__.
403
- figure: Any = None
404
- content: str = ""
405
-
406
- def __post_init__(self) -> None:
407
- from plotly import graph_objects as go, io as pio
408
-
409
- if not isinstance(self.figure, go.Figure):
410
- raise TypeError("figure must be a plotly.graph_objects.Figure")
411
-
412
- self.figure.layout.autosize = True
413
- self.figure.layout.width = None
414
- self.figure.layout.height = None
415
- self.content = pio.to_json(self.figure, validate=True)
416
- self.mime = "application/json"
417
-
418
- super().__post_init__()
419
-
420
-
421
- @dataclass
422
- class Dataframe(Element):
423
- """Useful to send a pandas DataFrame to the UI."""
424
-
425
- type: ClassVar[ElementType] = "dataframe"
426
- size: ElementSize = "large"
427
- data: Any = None # The type is Any because it is checked in __post_init__.
428
-
429
- def __post_init__(self) -> None:
430
- """Ensures the data is a pandas DataFrame and converts it to JSON."""
431
- from pandas import DataFrame
432
-
433
- if not isinstance(self.data, DataFrame):
434
- raise TypeError("data must be a pandas.DataFrame")
435
-
436
- self.content = self.data.to_json(orient="split", date_format="iso")
437
- super().__post_init__()
438
-
439
-
440
- @dataclass
441
- class CustomElement(Element):
442
- """Useful to send a custom element to the UI."""
443
-
444
- type: ClassVar[ElementType] = "custom"
445
- mime: str = "application/json"
446
- props: Dict = Field(default_factory=dict)
447
-
448
- def __post_init__(self) -> None:
449
- self.content = json.dumps(self.props)
450
- super().__post_init__()
451
- self.updatable = True
452
-
453
- async def update(self):
454
- await super().send(self.for_id)