chainlit 1.0.0rc2__py3-none-any.whl → 1.0.100__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/socket.py CHANGED
@@ -1,5 +1,7 @@
1
1
  import asyncio
2
2
  import json
3
+ import uuid
4
+ from datetime import datetime
3
5
  from typing import Any, Dict
4
6
 
5
7
  from chainlit.action import Action
@@ -73,22 +75,41 @@ def load_user_env(user_env):
73
75
  return user_env
74
76
 
75
77
 
78
+ def build_anon_user_identifier(environ):
79
+ scope = environ.get("asgi.scope", {})
80
+ client_ip, _ = scope.get("client")
81
+ ip = environ.get("HTTP_X_FORWARDED_FOR", client_ip)
82
+
83
+ try:
84
+ headers = scope.get("headers", {})
85
+ user_agent = next(
86
+ (v.decode("utf-8") for k, v in headers if k.decode("utf-8") == "user-agent")
87
+ )
88
+ return str(uuid.uuid5(uuid.NAMESPACE_DNS, user_agent + ip))
89
+
90
+ except StopIteration:
91
+ return str(uuid.uuid5(uuid.NAMESPACE_DNS, ip))
92
+
93
+
76
94
  @socket.on("connect")
77
95
  async def connect(sid, environ, auth):
78
96
  if not config.code.on_chat_start and not config.code.on_message:
79
- raise ConnectionRefusedError(
97
+ logger.warning(
80
98
  "You need to configure at least an on_chat_start or an on_message callback"
81
99
  )
82
-
100
+ return False
83
101
  user = None
102
+ anon_user_identifier = build_anon_user_identifier(environ)
84
103
  token = None
104
+ login_required = require_login()
85
105
  try:
86
106
  # Check if the authentication is required
87
- if require_login():
107
+ if login_required:
88
108
  authorization_header = environ.get("HTTP_AUTHORIZATION")
89
109
  token = authorization_header.split(" ")[1] if authorization_header else None
90
110
  user = await get_current_user(token=token)
91
111
  except Exception as e:
112
+ logger.info("Authentication failed")
92
113
  return False
93
114
 
94
115
  # Function to send a message to this particular session
@@ -113,7 +134,7 @@ async def connect(sid, environ, auth):
113
134
 
114
135
  user_env_string = environ.get("HTTP_USER_ENV")
115
136
  user_env = load_user_env(user_env_string)
116
- WebsocketSession(
137
+ ws_session = WebsocketSession(
117
138
  id=session_id,
118
139
  socket_id=sid,
119
140
  emit=emit_fn,
@@ -124,6 +145,17 @@ async def connect(sid, environ, auth):
124
145
  chat_profile=environ.get("HTTP_X_CHAINLIT_CHAT_PROFILE"),
125
146
  thread_id=environ.get("HTTP_X_CHAINLIT_THREAD_ID"),
126
147
  )
148
+
149
+ if data_layer := get_data_layer():
150
+ asyncio.create_task(
151
+ data_layer.create_user_session(
152
+ id=session_id,
153
+ started_at=datetime.utcnow().isoformat(),
154
+ anon_user_id=anon_user_identifier if not user else None,
155
+ user_id=user.identifier if user else None,
156
+ )
157
+ )
158
+
127
159
  trace_event("connection_successful")
128
160
  return True
129
161
 
@@ -138,8 +170,9 @@ async def connection_successful(sid):
138
170
  if context.session.thread_id_to_resume and config.code.on_chat_resume:
139
171
  thread = await resume_thread(context.session)
140
172
  if thread:
141
- context.session.has_user_message = True
173
+ context.session.has_first_interaction = True
142
174
  await context.emitter.clear_ask()
175
+ await context.emitter.emit("first_interaction", "resume")
143
176
  await context.emitter.resume_thread(thread)
144
177
  await config.code.on_chat_resume(thread)
145
178
  return
@@ -152,32 +185,31 @@ async def connection_successful(sid):
152
185
 
153
186
  @socket.on("clear_session")
154
187
  async def clean_session(sid):
155
- if session := WebsocketSession.get(sid):
156
- if config.code.on_chat_end:
157
- init_ws_context(session)
158
- await config.code.on_chat_end()
159
- # Clean up the user session
160
- if session.id in user_sessions:
161
- user_sessions.pop(session.id)
162
-
163
- # Clean up the session
164
- session.delete()
188
+ await disconnect(sid, force_clear=True)
165
189
 
166
190
 
167
191
  @socket.on("disconnect")
168
- async def disconnect(sid):
192
+ async def disconnect(sid, force_clear=False):
169
193
  session = WebsocketSession.get(sid)
170
194
  if session:
195
+ if data_layer := get_data_layer():
196
+ asyncio.create_task(
197
+ data_layer.update_user_session(
198
+ id=session.id,
199
+ is_interactive=session.has_first_interaction,
200
+ ended_at=datetime.utcnow().isoformat(),
201
+ )
202
+ )
203
+
171
204
  init_ws_context(session)
172
205
 
173
206
  if config.code.on_chat_end and session:
174
207
  await config.code.on_chat_end()
175
208
 
176
- if session and session.thread_id and session.has_user_message:
209
+ if session and session.thread_id and session.has_first_interaction:
177
210
  await persist_user_session(session.thread_id, session.to_persistable())
178
211
 
179
- async def disconnect_on_timeout(sid):
180
- await asyncio.sleep(config.project.session_timeout)
212
+ def clear():
181
213
  if session := WebsocketSession.get(sid):
182
214
  # Clean up the user session
183
215
  if session.id in user_sessions:
@@ -185,7 +217,14 @@ async def disconnect(sid):
185
217
  # Clean up the session
186
218
  session.delete()
187
219
 
188
- asyncio.ensure_future(disconnect_on_timeout(sid))
220
+ async def clear_on_timeout(sid):
221
+ await asyncio.sleep(config.project.session_timeout)
222
+ clear()
223
+
224
+ if force_clear:
225
+ clear()
226
+ else:
227
+ asyncio.ensure_future(clear_on_timeout(sid))
189
228
 
190
229
 
191
230
  @socket.on("stop")
chainlit/step.py CHANGED
@@ -14,8 +14,8 @@ from chainlit.element import Element
14
14
  from chainlit.logger import logger
15
15
  from chainlit.telemetry import trace_event
16
16
  from chainlit.types import FeedbackDict
17
- from chainlit_client import BaseGeneration
18
- from chainlit_client.step import StepType, TrueStepType
17
+ from literalai import BaseGeneration
18
+ from literalai.step import StepType, TrueStepType
19
19
 
20
20
 
21
21
  class StepDict(TypedDict, total=False):
@@ -257,7 +257,7 @@ class Step:
257
257
 
258
258
  if data_layer:
259
259
  try:
260
- asyncio.create_task(data_layer.update_step(step_dict))
260
+ asyncio.create_task(data_layer.update_step(step_dict.copy()))
261
261
  except Exception as e:
262
262
  if self.fail_on_persist_error:
263
263
  raise e
@@ -313,7 +313,7 @@ class Step:
313
313
 
314
314
  if data_layer:
315
315
  try:
316
- asyncio.create_task(data_layer.create_step(step_dict))
316
+ asyncio.create_task(data_layer.create_step(step_dict.copy()))
317
317
  self.persisted = True
318
318
  except Exception as e:
319
319
  if self.fail_on_persist_error:
chainlit/telemetry.py CHANGED
@@ -31,9 +31,6 @@ class ChainlitTelemetry:
31
31
  if resource:
32
32
  return resource
33
33
 
34
- # If we are in production, use the URL as hostname
35
- if config.chainlit_prod_url:
36
- host_name = config.chainlit_prod_url
37
34
  # Hash the local hostname to avoid leaking it.
38
35
  else:
39
36
  host_name = gethostname()
@@ -42,7 +39,7 @@ class ChainlitTelemetry:
42
39
  attrs = {"host.name": host_name}
43
40
 
44
41
  if resource_attributes:
45
- attrs.update(resource_attributes)
42
+ attrs.update(resource_attributes) # type: ignore
46
43
  if service_name:
47
44
  attrs["service.name"] = service_name
48
45
  if service_version:
@@ -50,7 +47,7 @@ class ChainlitTelemetry:
50
47
  if deployment_environment:
51
48
  attrs["deployment.environment"] = deployment_environment
52
49
 
53
- return Resource.create(attrs)
50
+ return Resource.create(attrs) # type: ignore
54
51
 
55
52
  def configure_tracer(self):
56
53
  import uptrace
@@ -67,7 +64,6 @@ class ChainlitTelemetry:
67
64
  uptrace.configure_opentelemetry(
68
65
  dsn="https://YPa4AbDF853uCW6UWN2oYg@api.uptrace.dev/1778",
69
66
  service_name="chainlit",
70
- service_version="1.1.0",
71
67
  deployment_environment="production",
72
68
  logging_level=logging.CRITICAL,
73
69
  )
chainlit/types.py CHANGED
@@ -6,8 +6,8 @@ if TYPE_CHECKING:
6
6
  from chainlit.user import UserDict
7
7
  from chainlit.step import StepDict
8
8
 
9
- from chainlit_client import ChatGeneration, CompletionGeneration
10
9
  from dataclasses_json import DataClassJsonMixin
10
+ from literalai import ChatGeneration, CompletionGeneration
11
11
  from pydantic import BaseModel
12
12
  from pydantic.dataclasses import dataclass
13
13
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: chainlit
3
- Version: 1.0.0rc2
3
+ Version: 1.0.100
4
4
  Summary: A faster way to build chatbot UIs.
5
5
  Home-page: https://github.com/Chainlit/chainlit
6
6
  License: Apache-2.0 license
@@ -15,7 +15,6 @@ Classifier: Programming Language :: Python :: 3.11
15
15
  Classifier: Programming Language :: Python :: 3.12
16
16
  Requires-Dist: aiofiles (>=23.1.0,<24.0.0)
17
17
  Requires-Dist: asyncer (>=0.0.2,<0.0.3)
18
- Requires-Dist: chainlit_client (==0.1.0rc7)
19
18
  Requires-Dist: click (>=8.1.3,<9.0.0)
20
19
  Requires-Dist: dataclasses_json (>=0.5.7,<0.6.0)
21
20
  Requires-Dist: fastapi (>=0.100,<0.101)
@@ -23,6 +22,7 @@ Requires-Dist: fastapi-socketio (>=0.0.10,<0.0.11)
23
22
  Requires-Dist: filetype (>=1.2.0,<2.0.0)
24
23
  Requires-Dist: httpx (>=0.23.0,<0.25.0)
25
24
  Requires-Dist: lazify (>=0.4.0,<0.5.0)
25
+ Requires-Dist: literalai (==0.0.102)
26
26
  Requires-Dist: nest-asyncio (>=1.5.6,<2.0.0)
27
27
  Requires-Dist: packaging (>=23.1,<24.0)
28
28
  Requires-Dist: pydantic (>=1,<3)
@@ -32,7 +32,7 @@ Requires-Dist: python-graphql-client (>=0.4.3,<0.5.0)
32
32
  Requires-Dist: python-multipart (>=0.0.6,<0.0.7)
33
33
  Requires-Dist: syncer (>=2.0.3,<3.0.0)
34
34
  Requires-Dist: tomli (>=2.0.1,<3.0.0)
35
- Requires-Dist: uptrace (>=1.18.0,<2.0.0)
35
+ Requires-Dist: uptrace (>=1.22.0,<2.0.0)
36
36
  Requires-Dist: uvicorn (>=0.23.2,<0.24.0)
37
37
  Requires-Dist: watchfiles (>=0.20.0,<0.21.0)
38
38
  Project-URL: Repository, https://github.com/Chainlit/chainlit
@@ -0,0 +1,60 @@
1
+ chainlit/__init__.py,sha256=SPlsN7CA9RbelAfrBovwwW7h4cKTSB0xLhDfdZWjH-s,9313
2
+ chainlit/__main__.py,sha256=7Vg3w3T3qDuz4KDu5lQhLH6lQ3cYdume7gHH7Z1V97U,87
3
+ chainlit/action.py,sha256=k-GsblVHI4DnDWFyF-RZgq3KfdfAFICFh2OBeU4w8N8,1410
4
+ chainlit/auth.py,sha256=dIu37bsPVBSIf0hTGevWuHVfjNPpFWXnPNrUcICPFrg,2688
5
+ chainlit/cache.py,sha256=Bv3dT4eHhE6Fq3c6Do0ZTpiyoXgXYewdxTgpYghEd9g,1361
6
+ chainlit/chat_settings.py,sha256=2ByenmwS8O6jQjDVJjhhbLrBPGA5aY2F7R3VvQQxXPk,877
7
+ chainlit/cli/__init__.py,sha256=aMynTbqbJEvxkoIzDjsdKL6wJ0HFgLfVrbxFkwqp1FU,4733
8
+ chainlit/cli/utils.py,sha256=mE2d9oOk-B2b9ZvDV1zENoDWxjfMriGP7bVwEFduZP4,717
9
+ chainlit/config.py,sha256=RtXHJROx7r-moxu_2bsjXjsGnqKNePlUWDVemoi8wXk,10477
10
+ chainlit/context.py,sha256=Su3eabnD2sgLNx5IwlxEpG4pev64GLi-GlvbE5Mw7sM,2264
11
+ chainlit/data/__init__.py,sha256=uOrpWPwxfAGogGRKVkBGzvvaxi4-5yZnyF2y6HzxdUk,15512
12
+ chainlit/data/acl.py,sha256=hx7Othkx12EitonyZD4iFIRVHwxBmBY2TKdwjPuZMSo,461
13
+ chainlit/element.py,sha256=cjQDuCSv4OSI2Z0q9JNJf4jn08dAcym6jX8iiHaZrKA,10123
14
+ chainlit/emitter.py,sha256=H-MbWGf2KWrCRpqEfBxsjI_G0wQErb8aIo1yutb2ouQ,11272
15
+ chainlit/frontend/dist/assets/index-c4f40824.js,sha256=WwrBcZL_7OKyO6BqYlpwtcegkEEPF8tm2WMAOJJ1gOI,3177303
16
+ chainlit/frontend/dist/assets/index-d088547c.css,sha256=0IhUfCm_IY1kjvlTR2edW1qKXAFDya3LZ6mnZnP6ovk,6605
17
+ chainlit/frontend/dist/assets/logo_dark-bc7401f6.svg,sha256=vHQB9g-n5OqOmuH3Fduuc7ZMg0EmMsGyO9cEnYwLbHg,8889
18
+ chainlit/frontend/dist/assets/logo_light-f19fc2ea.svg,sha256=8Z_C6t-0V9QL9ldmLjaLfp2REcGDuaTeNynj6-6muNI,8891
19
+ chainlit/frontend/dist/assets/react-plotly-259d6961.js,sha256=djnx-4HnrUzyis8Z9IKHZ3nlEQgBLKQ83a9SiqfaTws,3739251
20
+ chainlit/frontend/dist/favicon.svg,sha256=0Cy8x28obT5eWW3nxZRhsEvu6_zMqrqbg0y6hT3D0Q0,6455
21
+ chainlit/frontend/dist/index.html,sha256=smQKmixVXuV17iimIpLLTDVddvpOTUv9B2mMf0XViuc,959
22
+ chainlit/haystack/__init__.py,sha256=uZ77YiPy-qleSTi3dQCDO9HE6S6F6GpJWmh7jO4cxXA,217
23
+ chainlit/haystack/callbacks.py,sha256=OAGPW25i5IpYGF-wd9fIsFhERnmB61vxcKZ2PKmGp9w,5168
24
+ chainlit/hello.py,sha256=LwENQWo5s5r8nNDn4iKSV77vX60Ky5r_qGjQhyi7qlY,416
25
+ chainlit/input_widget.py,sha256=1Z1qn3YwaZ7upqqxZXtbfDxBlVobDjbZ3HtlNOj-U3E,4880
26
+ chainlit/langchain/__init__.py,sha256=zErMw0_3ufSGeF9ye7X0ZX3wDat4mTOx97T40ePDO2g,217
27
+ chainlit/langchain/callbacks.py,sha256=UZrRlUDl089_cljNfBcYKoKN69pqOgoxiHPJrlhDkoE,24141
28
+ chainlit/langflow/__init__.py,sha256=wxhxdsl1yxdsRyNTgZticxFF_8VFtJJ4OdIy3tnEIyM,817
29
+ chainlit/llama_index/__init__.py,sha256=c7wIUZmKTtZPU9zpdGpKTHctQaBWTuRGqTN0kkIkBcg,218
30
+ chainlit/llama_index/callbacks.py,sha256=OZXkQjDz2gEd1fCwN3UJLKwT_j7St7uoy5VaZzHgen4,5868
31
+ chainlit/logger.py,sha256=wTwRSZsLfXwWy6U4351IgWAm4KCMThgxm9EZpjGUEr4,373
32
+ chainlit/markdown.py,sha256=L2IPPWxIlrhJZcKPfO1akomHdN3sgC2EvC2ilxR8MQs,1624
33
+ chainlit/message.py,sha256=nKBvf5RHPHE9YyoQPBWl7IMfg69irvwEJ6TqE6bkV7k,17500
34
+ chainlit/oauth_providers.py,sha256=WiKUFpNp0RRN5Vq6LHCR9V-9td_1YEn2yD8iGu8atvY,17459
35
+ chainlit/playground/__init__.py,sha256=igNRcBgqLKPTjOQtTNhhGNJFmZn-Dl1fHRQzQSjDGTQ,80
36
+ chainlit/playground/config.py,sha256=_T0ELFRfBVUIOlaNvp3Af3X7wfMEQjxZPh26X_6mXYY,1033
37
+ chainlit/playground/provider.py,sha256=Fs_gnwbz_xCKa2fNE5G7Q2xnAAGJXyTmjpTCRkYHcFU,5167
38
+ chainlit/playground/providers/__init__.py,sha256=DxVp9BbQUdAPstpDTg2koNUTMS3tJa84iPTt_gQoHGM,236
39
+ chainlit/playground/providers/anthropic.py,sha256=VZVTCMUmiQPNFyqt57vwXwU7EbANf1hMfkWsdnkvZoQ,3441
40
+ chainlit/playground/providers/huggingface.py,sha256=AmBmIzvfqBjswEI40jifb0OrMQkTk5rXCkGX7nMJ-bk,2130
41
+ chainlit/playground/providers/langchain.py,sha256=vc6p9WmcY9kxGvK5irefbIfhUtNmBQgUuSx55T-Wiis,2978
42
+ chainlit/playground/providers/openai.py,sha256=ch2Eyoz696YJ6H2P1dT6n9RAw-PsiBLVK2_MhgEEcFo,12421
43
+ chainlit/playground/providers/vertexai.py,sha256=zKy501f-MHnLrvuRzN50FqgB3xoHzfQFTVbw83Nsj20,5084
44
+ chainlit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
+ chainlit/secret.py,sha256=0MXq8YxTeL93K8IyAew5UgZmIIw9_yJ_Kg4iML6cdVM,296
46
+ chainlit/server.py,sha256=ykFDvPs-oG-kHThf_jkNRfZizDUjrhbprjI8x4cvhg0,21059
47
+ chainlit/session.py,sha256=AmPZWf7tfF4K9TkslmjztZzT51u5QoNw6YTwwdhMU7M,8517
48
+ chainlit/socket.py,sha256=RPoxOMV1twB1_O4u2brKLDJO-FiGA0Jmdesy47qWiCE,10337
49
+ chainlit/step.py,sha256=pfTkRAffl86svFSrz_W41HM0WM8766gFFLgc-9SEzJM,12186
50
+ chainlit/sync.py,sha256=G1n-7-3WgXsN8y1bJkEyws_YwmHZIyDZoZUwhprigag,1235
51
+ chainlit/telemetry.py,sha256=Rk4dnZv0OnGOgV4kD-VHdhgl4i7i3ypqhSE_R-LZceM,3060
52
+ chainlit/types.py,sha256=mEVTk_z_wJABJf92_uWkqGF4WmOqLf9HIiuTVSREImo,3355
53
+ chainlit/user.py,sha256=Cw4uGz0ffivWFszv8W__EHwkvTHQ3Lj9hqpRCPxFujo,619
54
+ chainlit/user_session.py,sha256=nyPx8vSICP8BhpPcW5h9vbHVf9ixj39SrkvJBUI_6zs,1368
55
+ chainlit/utils.py,sha256=3HzhfZ4XJhBIe9sJ_3Lxv3lMH4mFXsi6nLBGqm8Gtdw,2571
56
+ chainlit/version.py,sha256=iosXhlXclBwBqlADFKEilxAC2wWKbtuBKi87AmPi7s8,196
57
+ chainlit-1.0.100.dist-info/METADATA,sha256=YreNSwLh2etgpLlX6f56ZBwrHGUAoJM9gRH4ByE0MD8,5552
58
+ chainlit-1.0.100.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
59
+ chainlit-1.0.100.dist-info/entry_points.txt,sha256=FrkqdjrFl8juSnvBndniyX7XuKojmUwO4ghRh-CFMQc,45
60
+ chainlit-1.0.100.dist-info/RECORD,,