chainlit 1.1.201__py3-none-any.whl → 1.1.300__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 (60) hide show
  1. chainlit/__init__.py +22 -4
  2. chainlit/cli/__init__.py +53 -6
  3. chainlit/config.py +25 -18
  4. chainlit/context.py +9 -0
  5. chainlit/copilot/dist/index.js +440 -407
  6. chainlit/data/__init__.py +20 -5
  7. chainlit/data/dynamodb.py +586 -0
  8. chainlit/data/sql_alchemy.py +48 -28
  9. chainlit/discord/app.py +4 -2
  10. chainlit/element.py +41 -20
  11. chainlit/emitter.py +8 -7
  12. chainlit/frontend/dist/assets/DailyMotion-578b63e6.js +1 -0
  13. chainlit/frontend/dist/assets/Facebook-b825e5bb.js +1 -0
  14. chainlit/frontend/dist/assets/FilePlayer-bcba3b4e.js +1 -0
  15. chainlit/frontend/dist/assets/Kaltura-fc1c9497.js +1 -0
  16. chainlit/frontend/dist/assets/Mixcloud-4cfb2724.js +1 -0
  17. chainlit/frontend/dist/assets/Mux-aa92055c.js +1 -0
  18. chainlit/frontend/dist/assets/Preview-9f55905a.js +1 -0
  19. chainlit/frontend/dist/assets/SoundCloud-f991fe03.js +1 -0
  20. chainlit/frontend/dist/assets/Streamable-53128f49.js +1 -0
  21. chainlit/frontend/dist/assets/Twitch-fce8b9f5.js +1 -0
  22. chainlit/frontend/dist/assets/Vidyard-e35c6102.js +1 -0
  23. chainlit/frontend/dist/assets/Vimeo-fff35f8e.js +1 -0
  24. chainlit/frontend/dist/assets/Wistia-ec07dc64.js +1 -0
  25. chainlit/frontend/dist/assets/YouTube-ad068e2a.js +1 -0
  26. chainlit/frontend/dist/assets/index-aaf974a9.css +1 -0
  27. chainlit/frontend/dist/assets/index-d40d41cc.js +727 -0
  28. chainlit/frontend/dist/assets/{react-plotly-1ca97c0e.js → react-plotly-b2c6442b.js} +1 -1
  29. chainlit/frontend/dist/index.html +2 -3
  30. chainlit/langchain/callbacks.py +4 -2
  31. chainlit/llama_index/callbacks.py +2 -2
  32. chainlit/message.py +30 -25
  33. chainlit/oauth_providers.py +118 -0
  34. chainlit/server.py +208 -83
  35. chainlit/slack/app.py +2 -3
  36. chainlit/socket.py +27 -23
  37. chainlit/step.py +44 -30
  38. chainlit/teams/__init__.py +6 -0
  39. chainlit/teams/app.py +332 -0
  40. chainlit/translations/en-US.json +2 -4
  41. chainlit/types.py +17 -17
  42. chainlit/user.py +9 -1
  43. chainlit/utils.py +47 -3
  44. {chainlit-1.1.201.dist-info → chainlit-1.1.300.dist-info}/METADATA +22 -14
  45. chainlit-1.1.300.dist-info/RECORD +79 -0
  46. chainlit/cli/utils.py +0 -24
  47. chainlit/frontend/dist/assets/index-bf0451c6.js +0 -698
  48. chainlit/frontend/dist/assets/index-d088547c.css +0 -1
  49. chainlit/playground/__init__.py +0 -2
  50. chainlit/playground/config.py +0 -36
  51. chainlit/playground/provider.py +0 -108
  52. chainlit/playground/providers/__init__.py +0 -11
  53. chainlit/playground/providers/anthropic.py +0 -118
  54. chainlit/playground/providers/huggingface.py +0 -75
  55. chainlit/playground/providers/langchain.py +0 -89
  56. chainlit/playground/providers/openai.py +0 -386
  57. chainlit/playground/providers/vertexai.py +0 -171
  58. chainlit-1.1.201.dist-info/RECORD +0 -72
  59. {chainlit-1.1.201.dist-info → chainlit-1.1.300.dist-info}/WHEEL +0 -0
  60. {chainlit-1.1.201.dist-info → chainlit-1.1.300.dist-info}/entry_points.txt +0 -0
chainlit/socket.py CHANGED
@@ -3,6 +3,7 @@ import json
3
3
  import time
4
4
  import uuid
5
5
  from typing import Any, Dict, Literal
6
+ from urllib.parse import unquote
6
7
 
7
8
  from chainlit.action import Action
8
9
  from chainlit.auth import get_current_user, require_login
@@ -12,14 +13,15 @@ from chainlit.data import get_data_layer
12
13
  from chainlit.element import Element
13
14
  from chainlit.logger import logger
14
15
  from chainlit.message import ErrorMessage, Message
15
- from chainlit.server import socket
16
+ from chainlit.server import sio
16
17
  from chainlit.session import WebsocketSession
17
18
  from chainlit.telemetry import trace_event
18
19
  from chainlit.types import (
19
20
  AudioChunk,
20
21
  AudioChunkPayload,
21
22
  AudioEndPayload,
22
- UIMessagePayload,
23
+ MessagePayload,
24
+ SystemMessagePayload,
23
25
  )
24
26
  from chainlit.user_session import user_sessions
25
27
 
@@ -52,7 +54,7 @@ async def resume_thread(session: WebsocketSession):
52
54
  user_is_author = author == session.user.identifier
53
55
 
54
56
  if user_is_author:
55
- metadata = thread.get("metadata", {})
57
+ metadata = thread.get("metadata") or {}
56
58
  user_sessions[session.id] = metadata.copy()
57
59
  if chat_profile := metadata.get("chat_profile"):
58
60
  session.chat_profile = chat_profile
@@ -97,8 +99,8 @@ def build_anon_user_identifier(environ):
97
99
  return str(uuid.uuid5(uuid.NAMESPACE_DNS, ip))
98
100
 
99
101
 
100
- @socket.on("connect")
101
- async def connect(sid, environ, auth):
102
+ @sio.on("connect")
103
+ async def connect(sid, environ):
102
104
  if (
103
105
  not config.code.on_chat_start
104
106
  and not config.code.on_message
@@ -123,11 +125,11 @@ async def connect(sid, environ, auth):
123
125
 
124
126
  # Session scoped function to emit to the client
125
127
  def emit_fn(event, data):
126
- return socket.emit(event, data, to=sid)
128
+ return sio.emit(event, data, to=sid)
127
129
 
128
130
  # Session scoped function to emit to the client and wait for a response
129
131
  def emit_call_fn(event: Literal["ask", "call_fn"], data, timeout):
130
- return socket.call(event, data, timeout=timeout, to=sid)
132
+ return sio.call(event, data, timeout=timeout, to=sid)
131
133
 
132
134
  session_id = environ.get("HTTP_X_CHAINLIT_SESSION_ID")
133
135
  if restore_existing_session(sid, session_id, emit_fn, emit_call_fn):
@@ -138,6 +140,10 @@ async def connect(sid, environ, auth):
138
140
 
139
141
  client_type = environ.get("HTTP_X_CHAINLIT_CLIENT_TYPE")
140
142
  http_referer = environ.get("HTTP_REFERER")
143
+ url_encoded_chat_profile = environ.get("HTTP_X_CHAINLIT_CHAT_PROFILE")
144
+ chat_profile = (
145
+ unquote(url_encoded_chat_profile) if url_encoded_chat_profile else None
146
+ )
141
147
 
142
148
  ws_session = WebsocketSession(
143
149
  id=session_id,
@@ -148,7 +154,7 @@ async def connect(sid, environ, auth):
148
154
  user_env=user_env,
149
155
  user=user,
150
156
  token=token,
151
- chat_profile=environ.get("HTTP_X_CHAINLIT_CHAT_PROFILE"),
157
+ chat_profile=chat_profile,
152
158
  thread_id=environ.get("HTTP_X_CHAINLIT_THREAD_ID"),
153
159
  languages=environ.get("HTTP_ACCEPT_LANGUAGE"),
154
160
  http_referer=http_referer,
@@ -158,7 +164,7 @@ async def connect(sid, environ, auth):
158
164
  return True
159
165
 
160
166
 
161
- @socket.on("connection_successful")
167
+ @sio.on("connection_successful")
162
168
  async def connection_successful(sid):
163
169
  context = init_ws_context(sid)
164
170
 
@@ -186,14 +192,14 @@ async def connection_successful(sid):
186
192
  context.session.current_task = task
187
193
 
188
194
 
189
- @socket.on("clear_session")
195
+ @sio.on("clear_session")
190
196
  async def clean_session(sid):
191
197
  session = WebsocketSession.get(sid)
192
198
  if session:
193
199
  session.to_clear = True
194
200
 
195
201
 
196
- @socket.on("disconnect")
202
+ @sio.on("disconnect")
197
203
  async def disconnect(sid):
198
204
  session = WebsocketSession.get(sid)
199
205
 
@@ -227,15 +233,13 @@ async def disconnect(sid):
227
233
  asyncio.ensure_future(clear_on_timeout(sid))
228
234
 
229
235
 
230
- @socket.on("stop")
236
+ @sio.on("stop")
231
237
  async def stop(sid):
232
238
  if session := WebsocketSession.get(sid):
233
239
  trace_event("stop_task")
234
240
 
235
241
  init_ws_context(session)
236
- await Message(
237
- author="System", content="Task manually stopped.", disable_feedback=True
238
- ).send()
242
+ await Message(content="Task manually stopped.", disable_feedback=True).send()
239
243
 
240
244
  if session.current_task:
241
245
  session.current_task.cancel()
@@ -244,12 +248,12 @@ async def stop(sid):
244
248
  await config.code.on_stop()
245
249
 
246
250
 
247
- async def process_message(session: WebsocketSession, payload: UIMessagePayload):
251
+ async def process_message(session: WebsocketSession, payload: MessagePayload):
248
252
  """Process a message from the user."""
249
253
  try:
250
254
  context = init_ws_context(session)
251
255
  await context.emitter.task_start()
252
- message = await context.emitter.process_user_message(payload)
256
+ message = await context.emitter.process_message(payload)
253
257
 
254
258
  if config.code.on_message:
255
259
  # Sleep 1ms to make sure any children step starts after the message step start
@@ -266,8 +270,8 @@ async def process_message(session: WebsocketSession, payload: UIMessagePayload):
266
270
  await context.emitter.task_end()
267
271
 
268
272
 
269
- @socket.on("ui_message")
270
- async def message(sid, payload: UIMessagePayload):
273
+ @sio.on("client_message")
274
+ async def message(sid, payload: MessagePayload):
271
275
  """Handle a message sent by the User."""
272
276
  session = WebsocketSession.require(sid)
273
277
 
@@ -275,7 +279,7 @@ async def message(sid, payload: UIMessagePayload):
275
279
  session.current_task = task
276
280
 
277
281
 
278
- @socket.on("audio_chunk")
282
+ @sio.on("audio_chunk")
279
283
  async def audio_chunk(sid, payload: AudioChunkPayload):
280
284
  """Handle an audio chunk sent by the user."""
281
285
  session = WebsocketSession.require(sid)
@@ -286,7 +290,7 @@ async def audio_chunk(sid, payload: AudioChunkPayload):
286
290
  asyncio.create_task(config.code.on_audio_chunk(AudioChunk(**payload)))
287
291
 
288
292
 
289
- @socket.on("audio_end")
293
+ @sio.on("audio_end")
290
294
  async def audio_end(sid, payload: AudioEndPayload):
291
295
  """Handle the end of the audio stream."""
292
296
  session = WebsocketSession.require(sid)
@@ -330,7 +334,7 @@ async def process_action(action: Action):
330
334
  logger.warning("No callback found for action %s", action.name)
331
335
 
332
336
 
333
- @socket.on("action_call")
337
+ @sio.on("action_call")
334
338
  async def call_action(sid, action):
335
339
  """Handle an action call from the UI."""
336
340
  context = init_ws_context(sid)
@@ -357,7 +361,7 @@ async def call_action(sid, action):
357
361
  )
358
362
 
359
363
 
360
- @socket.on("chat_settings_change")
364
+ @sio.on("chat_settings_change")
361
365
  async def change_settings(sid, settings: Dict[str, Any]):
362
366
  """Handle change settings submit from the UI."""
363
367
  context = init_ws_context(sid)
chainlit/step.py CHANGED
@@ -50,9 +50,8 @@ def step(
50
50
  id: Optional[str] = None,
51
51
  tags: Optional[List[str]] = None,
52
52
  disable_feedback: bool = True,
53
- root: bool = False,
54
53
  language: Optional[str] = None,
55
- show_input: Union[bool, str] = False,
54
+ show_input: Union[bool, str] = "json",
56
55
  ):
57
56
  """Step decorator for async and sync functions."""
58
57
 
@@ -72,7 +71,6 @@ def step(
72
71
  name=name,
73
72
  id=id,
74
73
  disable_feedback=disable_feedback,
75
- root=root,
76
74
  tags=tags,
77
75
  language=language,
78
76
  show_input=show_input,
@@ -85,8 +83,9 @@ def step(
85
83
  try:
86
84
  if result and not step.output:
87
85
  step.output = result
88
- except:
89
- pass
86
+ except Exception as e:
87
+ step.is_error = True
88
+ step.output = str(e)
90
89
  return result
91
90
 
92
91
  return async_wrapper
@@ -99,7 +98,6 @@ def step(
99
98
  name=name,
100
99
  id=id,
101
100
  disable_feedback=disable_feedback,
102
- root=root,
103
101
  tags=tags,
104
102
  language=language,
105
103
  show_input=show_input,
@@ -113,7 +111,8 @@ def step(
113
111
  if result and not step.output:
114
112
  step.output = result
115
113
  except:
116
- pass
114
+ step.is_error = True
115
+ step.output = str(e)
117
116
  return result
118
117
 
119
118
  return sync_wrapper
@@ -136,7 +135,6 @@ class Step:
136
135
  streaming: bool
137
136
  persisted: bool
138
137
 
139
- root: bool
140
138
  show_input: Union[bool, str]
141
139
 
142
140
  is_error: Optional[bool]
@@ -161,9 +159,8 @@ class Step:
161
159
  metadata: Optional[Dict] = None,
162
160
  tags: Optional[List[str]] = None,
163
161
  disable_feedback: bool = True,
164
- root: bool = False,
165
162
  language: Optional[str] = None,
166
- show_input: Union[bool, str] = False,
163
+ show_input: Union[bool, str] = "json",
167
164
  ):
168
165
  trace_event(f"init {self.__class__.__name__} {type}")
169
166
  time.sleep(0.001)
@@ -179,7 +176,6 @@ class Step:
179
176
  self.is_error = False
180
177
  self.show_input = show_input
181
178
  self.parent_id = parent_id
182
- self.root = root
183
179
 
184
180
  self.language = language
185
181
  self.generation = None
@@ -299,11 +295,11 @@ class Step:
299
295
  tasks = [el.send(for_id=self.id) for el in self.elements]
300
296
  await asyncio.gather(*tasks)
301
297
 
302
- if config.ui.hide_cot and (self.parent_id or not self.root):
303
- return
304
-
305
- if not config.features.prompt_playground and "generation" in step_dict:
306
- step_dict.pop("generation", None)
298
+ if config.ui.hide_cot and self.type not in [
299
+ "user_message",
300
+ "assistant_message",
301
+ ]:
302
+ return True
307
303
 
308
304
  await context.emitter.update_step(step_dict)
309
305
 
@@ -356,39 +352,48 @@ class Step:
356
352
  tasks = [el.send(for_id=self.id) for el in self.elements]
357
353
  await asyncio.gather(*tasks)
358
354
 
359
- if config.ui.hide_cot and (self.parent_id or not self.root):
355
+ if config.ui.hide_cot and self.type not in [
356
+ "user_message",
357
+ "assistant_message",
358
+ ]:
360
359
  return self
361
360
 
362
- if not config.features.prompt_playground and "generation" in step_dict:
363
- step_dict.pop("generation", None)
364
-
365
361
  await context.emitter.send_step(step_dict)
366
362
 
367
363
  return self
368
364
 
369
- async def stream_token(self, token: str, is_sequence=False):
365
+ async def stream_token(self, token: str, is_sequence=False, is_input=False):
370
366
  """
371
367
  Sends a token to the UI.
372
368
  Once all tokens have been streamed, call .send() to end the stream and persist the step if persistence is enabled.
373
369
  """
374
370
  if is_sequence:
375
- self.output = token
371
+ if is_input:
372
+ self.input = token
373
+ else:
374
+ self.output = token
376
375
  else:
377
- self.output += token
376
+ if is_input:
377
+ self.input += token
378
+ else:
379
+ self.output += token
378
380
 
379
381
  assert self.id
380
382
 
381
- if config.ui.hide_cot and (self.parent_id or not self.root):
383
+ if config.ui.hide_cot and self.type not in [
384
+ "user_message",
385
+ "assistant_message",
386
+ ]:
382
387
  return
383
388
 
384
389
  if not self.streaming:
385
390
  self.streaming = True
386
391
  step_dict = self.to_dict()
387
392
  await context.emitter.stream_start(step_dict)
388
-
389
- await context.emitter.send_token(
390
- id=self.id, token=token, is_sequence=is_sequence
391
- )
393
+ else:
394
+ await context.emitter.send_token(
395
+ id=self.id, token=token, is_sequence=is_sequence, is_input=is_input
396
+ )
392
397
 
393
398
  # Handle parameter less decorator
394
399
  def __call__(self, func):
@@ -408,7 +413,7 @@ class Step:
408
413
  previous_steps = local_steps.get() or []
409
414
  parent_step = previous_steps[-1] if previous_steps else None
410
415
 
411
- if not self.parent_id and not self.root:
416
+ if not self.parent_id:
412
417
  if parent_step:
413
418
  self.parent_id = parent_step.id
414
419
  elif context.session.root_message:
@@ -421,6 +426,10 @@ class Step:
421
426
  async def __aexit__(self, exc_type, exc_val, exc_tb):
422
427
  self.end = utc_now()
423
428
 
429
+ if exc_type:
430
+ self.output = str(exc_val)
431
+ self.is_error = True
432
+
424
433
  if self in context.active_steps:
425
434
  context.active_steps.remove(self)
426
435
 
@@ -437,7 +446,7 @@ class Step:
437
446
  previous_steps = local_steps.get() or []
438
447
  parent_step = previous_steps[-1] if previous_steps else None
439
448
 
440
- if not self.parent_id and not self.root:
449
+ if not self.parent_id:
441
450
  if parent_step:
442
451
  self.parent_id = parent_step.id
443
452
  elif context.session.root_message:
@@ -450,6 +459,11 @@ class Step:
450
459
 
451
460
  def __exit__(self, exc_type, exc_val, exc_tb):
452
461
  self.end = utc_now()
462
+
463
+ if exc_type:
464
+ self.output = str(exc_val)
465
+ self.is_error = True
466
+
453
467
  if self in context.active_steps:
454
468
  context.active_steps.remove(self)
455
469
 
@@ -0,0 +1,6 @@
1
+ try:
2
+ import botbuilder
3
+ except ModuleNotFoundError:
4
+ raise ValueError(
5
+ "The botbuilder-core package is required to integrate Chainlit with a Slack app. Run `pip install botbuilder-core --upgrade`"
6
+ )