chainlit 1.3.1__py3-none-any.whl → 2.0.0__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 (82) hide show
  1. chainlit/__init__.py +58 -56
  2. chainlit/action.py +12 -10
  3. chainlit/{auth.py → auth/__init__.py} +24 -34
  4. chainlit/auth/cookie.py +123 -0
  5. chainlit/auth/jwt.py +37 -0
  6. chainlit/cache.py +4 -6
  7. chainlit/callbacks.py +65 -11
  8. chainlit/chat_context.py +2 -2
  9. chainlit/chat_settings.py +3 -1
  10. chainlit/cli/__init__.py +15 -2
  11. chainlit/config.py +46 -90
  12. chainlit/context.py +4 -3
  13. chainlit/copilot/dist/index.js +8608 -642
  14. chainlit/data/__init__.py +96 -8
  15. chainlit/data/acl.py +3 -2
  16. chainlit/data/base.py +1 -15
  17. chainlit/data/chainlit_data_layer.py +584 -0
  18. chainlit/data/dynamodb.py +7 -4
  19. chainlit/data/literalai.py +4 -6
  20. chainlit/data/sql_alchemy.py +9 -8
  21. chainlit/data/storage_clients/__init__.py +0 -0
  22. chainlit/data/{storage_clients.py → storage_clients/azure.py} +2 -33
  23. chainlit/data/storage_clients/azure_blob.py +80 -0
  24. chainlit/data/storage_clients/base.py +22 -0
  25. chainlit/data/storage_clients/gcs.py +78 -0
  26. chainlit/data/storage_clients/s3.py +49 -0
  27. chainlit/discord/__init__.py +4 -4
  28. chainlit/discord/app.py +2 -1
  29. chainlit/element.py +41 -9
  30. chainlit/emitter.py +37 -16
  31. chainlit/frontend/dist/assets/{DailyMotion-CwoOhIL8.js → DailyMotion-DgRzV5GZ.js} +1 -1
  32. chainlit/frontend/dist/assets/Dataframe-DVgwSMU2.js +22 -0
  33. chainlit/frontend/dist/assets/{Facebook-BhnGXlzq.js → Facebook-C0vx6HWv.js} +1 -1
  34. chainlit/frontend/dist/assets/{FilePlayer-CPSVT6fz.js → FilePlayer-CdhzeHPP.js} +1 -1
  35. chainlit/frontend/dist/assets/{Kaltura-COYaLzsL.js → Kaltura-5iVmeUct.js} +1 -1
  36. chainlit/frontend/dist/assets/{Mixcloud-JdadNiQ5.js → Mixcloud-C2zi77Ex.js} +1 -1
  37. chainlit/frontend/dist/assets/{Mux-CBN7RO2u.js → Mux-Vkebogdf.js} +1 -1
  38. chainlit/frontend/dist/assets/{Preview-CxAFvvjV.js → Preview-DwY_sEIl.js} +1 -1
  39. chainlit/frontend/dist/assets/{SoundCloud-JlgmASWm.js → SoundCloud-CREBXAWo.js} +1 -1
  40. chainlit/frontend/dist/assets/{Streamable-CUWgr6Zw.js → Streamable-B5Lu25uy.js} +1 -1
  41. chainlit/frontend/dist/assets/{Twitch-BiN1HEDM.js → Twitch-y9iKCcM1.js} +1 -1
  42. chainlit/frontend/dist/assets/{Vidyard-qhPmrhDm.js → Vidyard-ClYvcuEu.js} +1 -1
  43. chainlit/frontend/dist/assets/{Vimeo-CrZVSCaT.js → Vimeo-D6HvM2jt.js} +1 -1
  44. chainlit/frontend/dist/assets/Wistia-Cu4zZ2Ci.js +1 -0
  45. chainlit/frontend/dist/assets/{YouTube-DKjw5Hbn.js → YouTube-D10tR6CJ.js} +1 -1
  46. chainlit/frontend/dist/assets/index-CI4qFOt5.js +8665 -0
  47. chainlit/frontend/dist/assets/index-CrrqM0nZ.css +1 -0
  48. chainlit/frontend/dist/assets/{react-plotly-Dpmqg5Sy.js → react-plotly-BpxUS-ab.js} +1 -1
  49. chainlit/frontend/dist/index.html +2 -2
  50. chainlit/haystack/callbacks.py +5 -4
  51. chainlit/input_widget.py +6 -4
  52. chainlit/langchain/callbacks.py +56 -47
  53. chainlit/langflow/__init__.py +1 -0
  54. chainlit/llama_index/callbacks.py +7 -7
  55. chainlit/message.py +8 -10
  56. chainlit/mistralai/__init__.py +3 -2
  57. chainlit/oauth_providers.py +70 -3
  58. chainlit/openai/__init__.py +3 -2
  59. chainlit/secret.py +1 -1
  60. chainlit/server.py +481 -182
  61. chainlit/session.py +7 -5
  62. chainlit/slack/__init__.py +3 -3
  63. chainlit/slack/app.py +3 -2
  64. chainlit/socket.py +89 -112
  65. chainlit/step.py +12 -12
  66. chainlit/sync.py +2 -1
  67. chainlit/teams/__init__.py +3 -3
  68. chainlit/teams/app.py +1 -0
  69. chainlit/translations/en-US.json +2 -1
  70. chainlit/translations/nl-NL.json +229 -0
  71. chainlit/types.py +24 -8
  72. chainlit/user.py +2 -1
  73. chainlit/utils.py +3 -2
  74. chainlit/version.py +3 -2
  75. {chainlit-1.3.1.dist-info → chainlit-2.0.0.dist-info}/METADATA +17 -37
  76. chainlit-2.0.0.dist-info/RECORD +106 -0
  77. chainlit/frontend/dist/assets/Wistia-C891KrBP.js +0 -1
  78. chainlit/frontend/dist/assets/index-CwmincdQ.css +0 -1
  79. chainlit/frontend/dist/assets/index-DLRdQOIx.js +0 -723
  80. chainlit-1.3.1.dist-info/RECORD +0 -96
  81. {chainlit-1.3.1.dist-info → chainlit-2.0.0.dist-info}/WHEEL +0 -0
  82. {chainlit-1.3.1.dist-info → chainlit-2.0.0.dist-info}/entry_points.txt +0 -0
chainlit/cli/__init__.py CHANGED
@@ -9,6 +9,7 @@ import uvicorn
9
9
  nest_asyncio.apply()
10
10
 
11
11
  # ruff: noqa: E402
12
+ from chainlit.auth import ensure_jwt_secret
12
13
  from chainlit.cache import init_lc_cache
13
14
  from chainlit.config import (
14
15
  BACKEND_ROOT,
@@ -24,7 +25,18 @@ from chainlit.logger import logger
24
25
  from chainlit.markdown import init_markdown
25
26
  from chainlit.secret import random_secret
26
27
  from chainlit.telemetry import trace_event
27
- from chainlit.utils import check_file, ensure_jwt_secret
28
+ from chainlit.utils import check_file
29
+
30
+
31
+ def assert_app():
32
+ if (
33
+ not config.code.on_chat_start
34
+ and not config.code.on_message
35
+ and not config.code.on_audio_chunk
36
+ ):
37
+ raise Exception(
38
+ "You need to configure at least one of on_chat_start, on_message or on_audio_chunk callback"
39
+ )
28
40
 
29
41
 
30
42
  # Create the main command group for Chainlit CLI
@@ -66,6 +78,7 @@ def run_chainlit(target: str):
66
78
  load_module(config.run.module_name)
67
79
 
68
80
  ensure_jwt_secret()
81
+ assert_app()
69
82
 
70
83
  # Create the chainlit.md file if it doesn't exist
71
84
  init_markdown(config.root)
@@ -186,7 +199,7 @@ def chainlit_run(
186
199
  # This is required to have OpenAI LLM providers available for the CI run
187
200
  os.environ["OPENAI_API_KEY"] = "sk-FAKE-OPENAI-API-KEY"
188
201
  # This is required for authentication tests
189
- os.environ["CHAINLIT_AUTH_SECRET"] = "SUPER_SECRET"
202
+ os.environ["CHAINLIT_AUTH_SECRET"] = "SUPER_SECRET" # nosec B105
190
203
  else:
191
204
  trace_event("chainlit run")
192
205
 
chainlit/config.py CHANGED
@@ -17,23 +17,30 @@ from typing import (
17
17
  )
18
18
 
19
19
  import tomli
20
+ from dataclasses_json import DataClassJsonMixin
21
+ from pydantic import Field
22
+ from pydantic.dataclasses import dataclass
23
+ from starlette.datastructures import Headers
24
+
25
+ from chainlit.data.base import BaseDataLayer
20
26
  from chainlit.logger import logger
21
27
  from chainlit.translations import lint_translation_json
22
28
  from chainlit.version import __version__
23
- from dataclasses_json import DataClassJsonMixin
24
- from pydantic.dataclasses import Field, dataclass
25
- from starlette.datastructures import Headers
26
29
 
27
30
  from ._utils import is_path_inside
28
31
 
29
32
  if TYPE_CHECKING:
33
+ from fastapi import Request, Response
34
+
30
35
  from chainlit.action import Action
31
- from chainlit.element import ElementBased
32
36
  from chainlit.message import Message
33
- from chainlit.types import AudioChunk, ChatProfile, Starter, ThreadDict
37
+ from chainlit.types import ChatProfile, InputAudioChunk, Starter, ThreadDict
34
38
  from chainlit.user import User
35
- from fastapi import Request, Response
36
-
39
+ else:
40
+ # Pydantic needs to resolve forward annotations. Because all of these are used
41
+ # within `typing.Callable`, alias to `Any` as Pydantic does not perform validation
42
+ # of callable argument/return types anyway.
43
+ Request = Response = Action = Message = ChatProfile = InputAudioChunk = Starter = ThreadDict = User = Any # fmt: off
37
44
 
38
45
  BACKEND_ROOT = os.path.dirname(__file__)
39
46
  PACKAGE_ROOT = os.path.dirname(os.path.dirname(BACKEND_ROOT))
@@ -48,6 +55,7 @@ FILES_DIRECTORY = Path(APP_ROOT) / ".files"
48
55
  FILES_DIRECTORY.mkdir(exist_ok=True)
49
56
 
50
57
  config_dir = os.path.join(APP_ROOT, ".chainlit")
58
+ public_dir = os.path.join(APP_ROOT, "public")
51
59
  config_file = os.path.join(config_dir, "config.toml")
52
60
  config_translation_dir = os.path.join(config_dir, "translations")
53
61
 
@@ -63,15 +71,15 @@ user_env = []
63
71
  # Duration (in seconds) during which the session is saved when the connection is lost
64
72
  session_timeout = 3600
65
73
 
74
+ # Duration (in seconds) of the user session expiry
75
+ user_session_timeout = 1296000 # 15 days
76
+
66
77
  # Enable third parties caching (e.g LangChain cache)
67
78
  cache = false
68
79
 
69
80
  # Authorized origins
70
81
  allow_origins = ["*"]
71
82
 
72
- # Follow symlink for asset mount (see https://github.com/Chainlit/chainlit/issues/317)
73
- # follow_symlink = false
74
-
75
83
  [features]
76
84
  # Process and display HTML in messages. This can be a security risk (see https://stackoverflow.com/questions/19603097/why-is-it-dangerous-to-render-user-generated-html-or-javascript)
77
85
  unsafe_allow_html = false
@@ -93,29 +101,20 @@ edit_message = true
93
101
  max_size_mb = 500
94
102
 
95
103
  [features.audio]
96
- # Threshold for audio recording
97
- min_decibels = -45
98
- # Delay for the user to start speaking in MS
99
- initial_silence_timeout = 3000
100
- # Delay for the user to continue speaking in MS. If the user stops speaking for this duration, the recording will stop.
101
- silence_timeout = 1500
102
- # Above this duration (MS), the recording will forcefully stop.
103
- max_duration = 15000
104
- # Duration of the audio chunks in MS
105
- chunk_duration = 1000
106
104
  # Sample rate of the audio
107
- sample_rate = 44100
105
+ sample_rate = 24000
108
106
 
109
107
  [UI]
110
108
  # Name of the assistant.
111
109
  name = "Assistant"
112
110
 
111
+ # default_theme = "dark"
112
+
113
+ # layout = "wide"
114
+
113
115
  # Description of the assistant. This is used for HTML tags.
114
116
  # description = ""
115
117
 
116
- # Large size content are by default collapsed for a cleaner ui
117
- default_collapse_content = true
118
-
119
118
  # Chain of Thought (CoT) display mode. Can be "hidden", "tool_call" or "full".
120
119
  cot = "full"
121
120
 
@@ -130,9 +129,6 @@ cot = "full"
130
129
  # The Javascript file can be served from the public directory.
131
130
  # custom_js = "/public/test.js"
132
131
 
133
- # Specify a custom font url.
134
- # custom_font = "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap"
135
-
136
132
  # Specify a custom meta image url.
137
133
  # custom_meta_image_url = "https://chainlit-cloud.s3.eu-west-3.amazonaws.com/logo/chainlit_banner.png"
138
134
 
@@ -141,36 +137,6 @@ cot = "full"
141
137
  # Be careful: If this is a relative path, it should not start with a slash.
142
138
  # custom_build = "./public/build"
143
139
 
144
- [UI.theme]
145
- default = "dark"
146
- #layout = "wide"
147
- #font_family = "Inter, sans-serif"
148
- # Override default MUI light theme. (Check theme.ts)
149
- [UI.theme.light]
150
- #background = "#FAFAFA"
151
- #paper = "#FFFFFF"
152
-
153
- [UI.theme.light.primary]
154
- #main = "#F80061"
155
- #dark = "#980039"
156
- #light = "#FFE7EB"
157
- [UI.theme.light.text]
158
- #primary = "#212121"
159
- #secondary = "#616161"
160
-
161
- # Override default MUI dark theme. (Check theme.ts)
162
- [UI.theme.dark]
163
- #background = "#FAFAFA"
164
- #paper = "#FFFFFF"
165
-
166
- [UI.theme.dark.primary]
167
- #main = "#F80061"
168
- #dark = "#980039"
169
- #light = "#FFE7EB"
170
- [UI.theme.dark.text]
171
- #primary = "#EEEEEE"
172
- #secondary = "#BDBDBD"
173
-
174
140
  [meta]
175
141
  generated_by = "{__version__}"
176
142
  """
@@ -218,15 +184,6 @@ class Palette(DataClassJsonMixin):
218
184
  text: Optional[TextOptions] = None
219
185
 
220
186
 
221
- @dataclass()
222
- class Theme(DataClassJsonMixin):
223
- font_family: Optional[str] = None
224
- default: Optional[Literal["light", "dark"]] = "dark"
225
- layout: Optional[Literal["default", "wide"]] = "default"
226
- light: Optional[Palette] = None
227
- dark: Optional[Palette] = None
228
-
229
-
230
187
  @dataclass
231
188
  class SpontaneousFileUploadFeature(DataClassJsonMixin):
232
189
  enabled: Optional[bool] = None
@@ -237,12 +194,7 @@ class SpontaneousFileUploadFeature(DataClassJsonMixin):
237
194
 
238
195
  @dataclass
239
196
  class AudioFeature(DataClassJsonMixin):
240
- min_decibels: int = -45
241
- initial_silence_timeout: int = 2000
242
- silence_timeout: int = 1500
243
- chunk_duration: int = 1000
244
- max_duration: int = 15000
245
- sample_rate: int = 44100
197
+ sample_rate: int = 24000
246
198
  enabled: bool = False
247
199
 
248
200
 
@@ -261,14 +213,13 @@ class UISettings(DataClassJsonMixin):
261
213
  name: str
262
214
  description: str = ""
263
215
  cot: Literal["hidden", "tool_call", "full"] = "full"
264
- # Large size content are by default collapsed for a cleaner ui
265
- default_collapse_content: bool = True
216
+ font_family: Optional[str] = None
217
+ default_theme: Optional[Literal["light", "dark"]] = "dark"
218
+ layout: Optional[Literal["default", "wide"]] = "default"
266
219
  github: Optional[str] = None
267
- theme: Optional[Theme] = None
268
220
  # Optional custom CSS file that allows you to customize the UI
269
221
  custom_css: Optional[str] = None
270
222
  custom_js: Optional[str] = None
271
- custom_font: Optional[str] = None
272
223
  # Optional custom meta tag for image preview
273
224
  custom_meta_image_url: Optional[str] = None
274
225
  # Optional custom build directory for the frontend
@@ -285,9 +236,9 @@ class CodeSettings:
285
236
  password_auth_callback: Optional[
286
237
  Callable[[str, str], Awaitable[Optional["User"]]]
287
238
  ] = None
288
- header_auth_callback: Optional[
289
- Callable[[Headers], Awaitable[Optional["User"]]]
290
- ] = None
239
+ header_auth_callback: Optional[Callable[[Headers], Awaitable[Optional["User"]]]] = (
240
+ None
241
+ )
291
242
  oauth_callback: Optional[
292
243
  Callable[[str, str, Dict[str, str], "User"], Awaitable[Optional["User"]]]
293
244
  ] = None
@@ -297,22 +248,27 @@ class CodeSettings:
297
248
  on_chat_end: Optional[Callable[[], Any]] = None
298
249
  on_chat_resume: Optional[Callable[["ThreadDict"], Any]] = None
299
250
  on_message: Optional[Callable[["Message"], Any]] = None
300
- on_audio_chunk: Optional[Callable[["AudioChunk"], Any]] = None
301
- on_audio_end: Optional[Callable[[List["ElementBased"]], Any]] = None
251
+ on_window_message: Optional[Callable[[str], Any]] = None
252
+ on_audio_start: Optional[Callable[[], Any]] = None
253
+ on_audio_chunk: Optional[Callable[["InputAudioChunk"], Any]] = None
254
+ on_audio_end: Optional[Callable[[], Any]] = None
302
255
 
303
256
  author_rename: Optional[Callable[[str], Awaitable[str]]] = None
304
257
  on_settings_update: Optional[Callable[[Dict[str, Any]], Any]] = None
305
258
  set_chat_profiles: Optional[
306
259
  Callable[[Optional["User"]], Awaitable[List["ChatProfile"]]]
307
260
  ] = None
308
- set_starters: Optional[
309
- Callable[[Optional["User"]], Awaitable[List["Starter"]]]
310
- ] = None
261
+ set_starters: Optional[Callable[[Optional["User"]], Awaitable[List["Starter"]]]] = (
262
+ None
263
+ )
264
+ data_layer: Optional[Callable[[], BaseDataLayer]] = None
311
265
 
312
266
 
313
267
  @dataclass()
314
268
  class ProjectSettings(DataClassJsonMixin):
315
269
  allow_origins: List[str] = Field(default_factory=lambda: ["*"])
270
+ # Socket.io client transports option
271
+ transports: Optional[List[str]] = None
316
272
  enable_telemetry: bool = True
317
273
  # List of environment variables to be provided by each user to use the app. If empty, no environment variables will be asked to the user.
318
274
  user_env: Optional[List[str]] = None
@@ -321,10 +277,10 @@ class ProjectSettings(DataClassJsonMixin):
321
277
  # Path to the local chat db
322
278
  # Duration (in seconds) during which the session is saved when the connection is lost
323
279
  session_timeout: int = 3600
280
+ # Duration (in seconds) of the user session expiry
281
+ user_session_timeout: int = 1296000 # 15 days
324
282
  # Enable third parties caching (e.g LangChain cache)
325
283
  cache: bool = False
326
- # Follow symlink for asset mount (see https://github.com/Chainlit/chainlit/issues/317)
327
- follow_symlink: bool = False
328
284
 
329
285
 
330
286
  @dataclass()
@@ -405,7 +361,7 @@ def init_config(log=False):
405
361
  dst = os.path.join(config_translation_dir, file)
406
362
  if not os.path.exists(dst):
407
363
  src = os.path.join(TRANSLATIONS_DIR, file)
408
- with open(src, "r", encoding="utf-8") as f:
364
+ with open(src, encoding="utf-8") as f:
409
365
  translation = json.load(f)
410
366
  with open(dst, "w", encoding="utf-8") as f:
411
367
  json.dump(translation, f, indent=4)
@@ -462,7 +418,7 @@ def load_settings():
462
418
 
463
419
  if not meta or meta.get("generated_by") <= "0.3.0":
464
420
  raise ValueError(
465
- "Your config file is outdated. Please delete it and restart the app to regenerate it."
421
+ f"Your config file '{config_file}' is outdated. Please delete it and restart the app to regenerate it."
466
422
  )
467
423
 
468
424
  lc_cache_path = os.path.join(config_dir, ".langchain.db")
@@ -520,7 +476,7 @@ def load_config():
520
476
  def lint_translations():
521
477
  # Load the ground truth (en-US.json file from chainlit source code)
522
478
  src = os.path.join(TRANSLATIONS_DIR, "en-US.json")
523
- with open(src, "r", encoding="utf-8") as f:
479
+ with open(src, encoding="utf-8") as f:
524
480
  truth = json.load(f)
525
481
 
526
482
  # Find the local app translations
@@ -528,7 +484,7 @@ def lint_translations():
528
484
  if file.endswith(".json"):
529
485
  # Load the translation file
530
486
  to_lint = os.path.join(config_translation_dir, file)
531
- with open(to_lint, "r", encoding="utf-8") as f:
487
+ with open(to_lint, encoding="utf-8") as f:
532
488
  translation = json.load(f)
533
489
 
534
490
  # Lint the translation file
chainlit/context.py CHANGED
@@ -3,9 +3,10 @@ import uuid
3
3
  from contextvars import ContextVar
4
4
  from typing import TYPE_CHECKING, Dict, List, Optional, Union
5
5
 
6
- from chainlit.session import ClientType, HTTPSession, WebsocketSession
7
6
  from lazify import LazyProxy
8
7
 
8
+ from chainlit.session import ClientType, HTTPSession, WebsocketSession
9
+
9
10
  if TYPE_CHECKING:
10
11
  from chainlit.emitter import BaseChainlitEmitter
11
12
  from chainlit.step import Step
@@ -103,8 +104,8 @@ def init_http_context(
103
104
  def get_context() -> ChainlitContext:
104
105
  try:
105
106
  return context_var.get()
106
- except LookupError:
107
- raise ChainlitContextException()
107
+ except LookupError as e:
108
+ raise ChainlitContextException from e
108
109
 
109
110
 
110
111
  context: ChainlitContext = LazyProxy(get_context, enable_cache=False)