chainlit 1.1.300rc4__py3-none-any.whl → 1.1.301__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/__init__.py +3 -1
- chainlit/cli/__init__.py +53 -6
- chainlit/config.py +4 -0
- chainlit/context.py +9 -0
- chainlit/copilot/dist/index.js +180 -180
- chainlit/data/__init__.py +6 -3
- chainlit/data/sql_alchemy.py +3 -3
- chainlit/element.py +33 -9
- chainlit/emitter.py +4 -4
- chainlit/frontend/dist/assets/{DailyMotion-1a2b7d60.js → DailyMotion-578b63e6.js} +1 -1
- chainlit/frontend/dist/assets/{Facebook-8422f48c.js → Facebook-b825e5bb.js} +1 -1
- chainlit/frontend/dist/assets/{FilePlayer-a0a41349.js → FilePlayer-bcba3b4e.js} +1 -1
- chainlit/frontend/dist/assets/{Kaltura-aa7990f2.js → Kaltura-fc1c9497.js} +1 -1
- chainlit/frontend/dist/assets/{Mixcloud-1647b3e4.js → Mixcloud-4cfb2724.js} +1 -1
- chainlit/frontend/dist/assets/{Mux-7e57be81.js → Mux-aa92055c.js} +1 -1
- chainlit/frontend/dist/assets/{Preview-cb89b2c6.js → Preview-9f55905a.js} +1 -1
- chainlit/frontend/dist/assets/{SoundCloud-c0d86d55.js → SoundCloud-f991fe03.js} +1 -1
- chainlit/frontend/dist/assets/{Streamable-57c43c18.js → Streamable-53128f49.js} +1 -1
- chainlit/frontend/dist/assets/{Twitch-bed3f21d.js → Twitch-fce8b9f5.js} +1 -1
- chainlit/frontend/dist/assets/{Vidyard-4dd76e44.js → Vidyard-e35c6102.js} +1 -1
- chainlit/frontend/dist/assets/{Vimeo-93bb5ae2.js → Vimeo-fff35f8e.js} +1 -1
- chainlit/frontend/dist/assets/{Wistia-97199246.js → Wistia-ec07dc64.js} +1 -1
- chainlit/frontend/dist/assets/{YouTube-fe1a7afe.js → YouTube-ad068e2a.js} +1 -1
- chainlit/frontend/dist/assets/index-d40d41cc.js +727 -0
- chainlit/frontend/dist/assets/{react-plotly-b416b8f9.js → react-plotly-b2c6442b.js} +1 -1
- chainlit/frontend/dist/index.html +1 -2
- chainlit/message.py +13 -8
- chainlit/oauth_providers.py +96 -4
- chainlit/server.py +182 -57
- chainlit/slack/app.py +2 -2
- chainlit/socket.py +24 -21
- chainlit/step.py +12 -3
- chainlit/teams/__init__.py +6 -0
- chainlit/teams/app.py +332 -0
- chainlit/translations/en-US.json +1 -1
- chainlit/types.py +7 -17
- chainlit/user.py +9 -1
- chainlit/utils.py +43 -0
- {chainlit-1.1.300rc4.dist-info → chainlit-1.1.301.dist-info}/METADATA +2 -2
- chainlit-1.1.301.dist-info/RECORD +79 -0
- chainlit/cli/utils.py +0 -24
- chainlit/frontend/dist/assets/index-919bea8f.js +0 -727
- chainlit-1.1.300rc4.dist-info/RECORD +0 -78
- {chainlit-1.1.300rc4.dist-info → chainlit-1.1.301.dist-info}/WHEEL +0 -0
- {chainlit-1.1.300rc4.dist-info → chainlit-1.1.301.dist-info}/entry_points.txt +0 -0
chainlit/step.py
CHANGED
|
@@ -295,7 +295,10 @@ class Step:
|
|
|
295
295
|
tasks = [el.send(for_id=self.id) for el in self.elements]
|
|
296
296
|
await asyncio.gather(*tasks)
|
|
297
297
|
|
|
298
|
-
if config.ui.hide_cot and
|
|
298
|
+
if config.ui.hide_cot and self.type not in [
|
|
299
|
+
"user_message",
|
|
300
|
+
"assistant_message",
|
|
301
|
+
]:
|
|
299
302
|
return True
|
|
300
303
|
|
|
301
304
|
await context.emitter.update_step(step_dict)
|
|
@@ -349,7 +352,10 @@ class Step:
|
|
|
349
352
|
tasks = [el.send(for_id=self.id) for el in self.elements]
|
|
350
353
|
await asyncio.gather(*tasks)
|
|
351
354
|
|
|
352
|
-
if config.ui.hide_cot and
|
|
355
|
+
if config.ui.hide_cot and self.type not in [
|
|
356
|
+
"user_message",
|
|
357
|
+
"assistant_message",
|
|
358
|
+
]:
|
|
353
359
|
return self
|
|
354
360
|
|
|
355
361
|
await context.emitter.send_step(step_dict)
|
|
@@ -374,7 +380,10 @@ class Step:
|
|
|
374
380
|
|
|
375
381
|
assert self.id
|
|
376
382
|
|
|
377
|
-
if config.ui.hide_cot and
|
|
383
|
+
if config.ui.hide_cot and self.type not in [
|
|
384
|
+
"user_message",
|
|
385
|
+
"assistant_message",
|
|
386
|
+
]:
|
|
378
387
|
return
|
|
379
388
|
|
|
380
389
|
if not self.streaming:
|
chainlit/teams/app.py
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import base64
|
|
3
|
+
import mimetypes
|
|
4
|
+
import os
|
|
5
|
+
import uuid
|
|
6
|
+
from typing import TYPE_CHECKING, Dict, List, Literal, Optional, Union
|
|
7
|
+
|
|
8
|
+
import filetype
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from botbuilder.core import TurnContext
|
|
12
|
+
from botbuilder.schema import Activity
|
|
13
|
+
|
|
14
|
+
import httpx
|
|
15
|
+
from botbuilder.core import (
|
|
16
|
+
BotFrameworkAdapter,
|
|
17
|
+
BotFrameworkAdapterSettings,
|
|
18
|
+
MessageFactory,
|
|
19
|
+
TurnContext,
|
|
20
|
+
)
|
|
21
|
+
from botbuilder.schema import (
|
|
22
|
+
ActionTypes,
|
|
23
|
+
Activity,
|
|
24
|
+
ActivityTypes,
|
|
25
|
+
Attachment,
|
|
26
|
+
CardAction,
|
|
27
|
+
ChannelAccount,
|
|
28
|
+
HeroCard,
|
|
29
|
+
)
|
|
30
|
+
from chainlit.config import config
|
|
31
|
+
from chainlit.context import ChainlitContext, HTTPSession, context_var
|
|
32
|
+
from chainlit.data import get_data_layer
|
|
33
|
+
from chainlit.element import Element, ElementDict
|
|
34
|
+
from chainlit.emitter import BaseChainlitEmitter
|
|
35
|
+
from chainlit.logger import logger
|
|
36
|
+
from chainlit.message import Message, StepDict
|
|
37
|
+
from chainlit.telemetry import trace
|
|
38
|
+
from chainlit.types import Feedback
|
|
39
|
+
from chainlit.user import PersistedUser, User
|
|
40
|
+
from chainlit.user_session import user_session
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class TeamsEmitter(BaseChainlitEmitter):
|
|
44
|
+
def __init__(self, session: HTTPSession, turn_context: TurnContext, enabled=False):
|
|
45
|
+
super().__init__(session)
|
|
46
|
+
self.turn_context = turn_context
|
|
47
|
+
self.enabled = enabled
|
|
48
|
+
|
|
49
|
+
async def send_element(self, element_dict: ElementDict):
|
|
50
|
+
if not self.enabled or element_dict.get("display") != "inline":
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
persisted_file = self.session.files.get(element_dict.get("chainlitKey") or "")
|
|
54
|
+
attachment: Optional[Attachment] = None
|
|
55
|
+
mime: Optional[str] = None
|
|
56
|
+
|
|
57
|
+
element_name: str = element_dict.get("name", "Untitled")
|
|
58
|
+
|
|
59
|
+
if mime:
|
|
60
|
+
file_extension = mimetypes.guess_extension(mime)
|
|
61
|
+
if file_extension:
|
|
62
|
+
element_name += file_extension
|
|
63
|
+
|
|
64
|
+
if persisted_file:
|
|
65
|
+
mime = element_dict.get("mime")
|
|
66
|
+
with open(persisted_file["path"], "rb") as file:
|
|
67
|
+
dencoded_string = base64.b64encode(file.read()).decode()
|
|
68
|
+
content_url = f"data:{mime};base64,{dencoded_string}"
|
|
69
|
+
attachment = Attachment(
|
|
70
|
+
content_type=mime, content_url=content_url, name=element_name
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
elif url := element_dict.get("url"):
|
|
74
|
+
attachment = Attachment(
|
|
75
|
+
content_type=mime, content_url=url, name=element_name
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
if not attachment:
|
|
79
|
+
return
|
|
80
|
+
|
|
81
|
+
await self.turn_context.send_activity(Activity(attachments=[attachment]))
|
|
82
|
+
|
|
83
|
+
async def send_step(self, step_dict: StepDict):
|
|
84
|
+
if not self.enabled:
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
step_type = step_dict.get("type")
|
|
88
|
+
is_message = step_type in [
|
|
89
|
+
"user_message",
|
|
90
|
+
"assistant_message",
|
|
91
|
+
]
|
|
92
|
+
is_chain_of_thought = bool(step_dict.get("parentId"))
|
|
93
|
+
is_empty_output = not step_dict.get("output")
|
|
94
|
+
|
|
95
|
+
if is_chain_of_thought or is_empty_output or not is_message:
|
|
96
|
+
return
|
|
97
|
+
else:
|
|
98
|
+
reply = MessageFactory.text(step_dict["output"])
|
|
99
|
+
enable_feedback = not step_dict.get("disableFeedback") and get_data_layer()
|
|
100
|
+
if enable_feedback:
|
|
101
|
+
like_button = CardAction(
|
|
102
|
+
type=ActionTypes.message_back,
|
|
103
|
+
title="👍",
|
|
104
|
+
text="like",
|
|
105
|
+
value={"feedback": "like", "step_id": step_dict["id"]},
|
|
106
|
+
)
|
|
107
|
+
dislike_button = CardAction(
|
|
108
|
+
type=ActionTypes.message_back,
|
|
109
|
+
title="👎",
|
|
110
|
+
text="dislike",
|
|
111
|
+
value={"feedback": "dislike", "step_id": step_dict["id"]},
|
|
112
|
+
)
|
|
113
|
+
card = HeroCard(buttons=[like_button, dislike_button])
|
|
114
|
+
attachment = Attachment(
|
|
115
|
+
content_type="application/vnd.microsoft.card.hero", content=card
|
|
116
|
+
)
|
|
117
|
+
reply.attachments = [attachment]
|
|
118
|
+
|
|
119
|
+
await self.turn_context.send_activity(reply)
|
|
120
|
+
|
|
121
|
+
async def update_step(self, step_dict: StepDict):
|
|
122
|
+
if not self.enabled:
|
|
123
|
+
return
|
|
124
|
+
|
|
125
|
+
await self.send_step(step_dict)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
adapter_settings = BotFrameworkAdapterSettings(
|
|
129
|
+
app_id=os.environ.get("TEAMS_APP_ID"),
|
|
130
|
+
app_password=os.environ.get("TEAMS_APP_PASSWORD"),
|
|
131
|
+
)
|
|
132
|
+
adapter = BotFrameworkAdapter(adapter_settings)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@trace
|
|
136
|
+
def init_teams_context(
|
|
137
|
+
session: HTTPSession,
|
|
138
|
+
turn_context: TurnContext,
|
|
139
|
+
) -> ChainlitContext:
|
|
140
|
+
emitter = TeamsEmitter(session=session, turn_context=turn_context)
|
|
141
|
+
context = ChainlitContext(session=session, emitter=emitter)
|
|
142
|
+
context_var.set(context)
|
|
143
|
+
user_session.set("teams_turn_context", turn_context)
|
|
144
|
+
return context
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
users_by_teams_id: Dict[str, Union[User, PersistedUser]] = {}
|
|
148
|
+
|
|
149
|
+
USER_PREFIX = "teams_"
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
async def get_user(teams_user: ChannelAccount):
|
|
153
|
+
if teams_user.id in users_by_teams_id:
|
|
154
|
+
return users_by_teams_id[teams_user.id]
|
|
155
|
+
|
|
156
|
+
metadata = {
|
|
157
|
+
"name": teams_user.name,
|
|
158
|
+
"id": teams_user.id,
|
|
159
|
+
}
|
|
160
|
+
user = User(identifier=USER_PREFIX + str(teams_user.name), metadata=metadata)
|
|
161
|
+
|
|
162
|
+
users_by_teams_id[teams_user.id] = user
|
|
163
|
+
|
|
164
|
+
if data_layer := get_data_layer():
|
|
165
|
+
try:
|
|
166
|
+
persisted_user = await data_layer.create_user(user)
|
|
167
|
+
if persisted_user:
|
|
168
|
+
users_by_teams_id[teams_user.id] = persisted_user
|
|
169
|
+
except Exception as e:
|
|
170
|
+
logger.error(f"Error creating user: {e}")
|
|
171
|
+
|
|
172
|
+
return users_by_teams_id[teams_user.id]
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
async def download_teams_file(url: str):
|
|
176
|
+
async with httpx.AsyncClient() as client:
|
|
177
|
+
response = await client.get(url)
|
|
178
|
+
if response.status_code == 200:
|
|
179
|
+
return response.content
|
|
180
|
+
else:
|
|
181
|
+
return None
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
async def download_teams_files(
|
|
185
|
+
session: HTTPSession, attachments: Optional[List[Attachment]] = None
|
|
186
|
+
):
|
|
187
|
+
if not attachments:
|
|
188
|
+
return []
|
|
189
|
+
|
|
190
|
+
attachments = [
|
|
191
|
+
attachment for attachment in attachments if isinstance(attachment.content, dict)
|
|
192
|
+
]
|
|
193
|
+
download_coros = [
|
|
194
|
+
download_teams_file(attachment.content.get("downloadUrl"))
|
|
195
|
+
for attachment in attachments
|
|
196
|
+
]
|
|
197
|
+
file_bytes_list = await asyncio.gather(*download_coros)
|
|
198
|
+
file_refs = []
|
|
199
|
+
for idx, file_bytes in enumerate(file_bytes_list):
|
|
200
|
+
if file_bytes:
|
|
201
|
+
name = attachments[idx].name
|
|
202
|
+
mime_type = filetype.guess_mime(file_bytes) or "application/octet-stream"
|
|
203
|
+
file_ref = await session.persist_file(
|
|
204
|
+
name=name, mime=mime_type, content=file_bytes
|
|
205
|
+
)
|
|
206
|
+
file_refs.append(file_ref)
|
|
207
|
+
|
|
208
|
+
files_dicts = [
|
|
209
|
+
session.files[file["id"]] for file in file_refs if file["id"] in session.files
|
|
210
|
+
]
|
|
211
|
+
|
|
212
|
+
file_elements = [Element.from_dict(file_dict) for file_dict in files_dicts]
|
|
213
|
+
|
|
214
|
+
return file_elements
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def clean_content(activity: Activity):
|
|
218
|
+
return activity.text.strip()
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
async def process_teams_message(
|
|
222
|
+
turn_context: TurnContext,
|
|
223
|
+
thread_name: str,
|
|
224
|
+
):
|
|
225
|
+
user = await get_user(turn_context.activity.from_property)
|
|
226
|
+
|
|
227
|
+
thread_id = str(
|
|
228
|
+
uuid.uuid5(uuid.NAMESPACE_DNS, str(turn_context.activity.conversation.id))
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
text = clean_content(turn_context.activity)
|
|
232
|
+
teams_files = turn_context.activity.attachments
|
|
233
|
+
|
|
234
|
+
session_id = str(uuid.uuid4())
|
|
235
|
+
|
|
236
|
+
session = HTTPSession(
|
|
237
|
+
id=session_id,
|
|
238
|
+
thread_id=thread_id,
|
|
239
|
+
user=user,
|
|
240
|
+
client_type="teams",
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
ctx = init_teams_context(
|
|
244
|
+
session=session,
|
|
245
|
+
turn_context=turn_context,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
file_elements = await download_teams_files(session, teams_files)
|
|
249
|
+
|
|
250
|
+
msg = Message(
|
|
251
|
+
content=text,
|
|
252
|
+
elements=file_elements,
|
|
253
|
+
type="user_message",
|
|
254
|
+
author=user.metadata.get("name"),
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
await msg.send()
|
|
258
|
+
|
|
259
|
+
ctx.emitter.enabled = True
|
|
260
|
+
|
|
261
|
+
if on_chat_start := config.code.on_chat_start:
|
|
262
|
+
await on_chat_start()
|
|
263
|
+
|
|
264
|
+
if on_message := config.code.on_message:
|
|
265
|
+
await on_message(msg)
|
|
266
|
+
|
|
267
|
+
if on_chat_end := config.code.on_chat_end:
|
|
268
|
+
await on_chat_end()
|
|
269
|
+
|
|
270
|
+
if data_layer := get_data_layer():
|
|
271
|
+
if isinstance(user, PersistedUser):
|
|
272
|
+
try:
|
|
273
|
+
await data_layer.update_thread(
|
|
274
|
+
thread_id=thread_id,
|
|
275
|
+
name=thread_name,
|
|
276
|
+
metadata=ctx.session.to_persistable(),
|
|
277
|
+
user_id=user.id,
|
|
278
|
+
)
|
|
279
|
+
except Exception as e:
|
|
280
|
+
logger.error(f"Error updating thread: {e}")
|
|
281
|
+
|
|
282
|
+
ctx.session.delete()
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
async def handle_message(turn_context: TurnContext):
|
|
286
|
+
if turn_context.activity.type == ActivityTypes.message:
|
|
287
|
+
if (
|
|
288
|
+
turn_context.activity.text == "like"
|
|
289
|
+
or turn_context.activity.text == "dislike"
|
|
290
|
+
):
|
|
291
|
+
feedback_value: Literal[0, 1] = (
|
|
292
|
+
0 if turn_context.activity.text == "dislike" else 1
|
|
293
|
+
)
|
|
294
|
+
step_id = turn_context.activity.value.get("step_id")
|
|
295
|
+
if data_layer := get_data_layer():
|
|
296
|
+
await data_layer.upsert_feedback(
|
|
297
|
+
Feedback(forId=step_id, value=feedback_value)
|
|
298
|
+
)
|
|
299
|
+
updated_text = "👍" if turn_context.activity.text == "like" else "👎"
|
|
300
|
+
# Update the existing message to remove the buttons
|
|
301
|
+
updated_message = Activity(
|
|
302
|
+
type=ActivityTypes.message,
|
|
303
|
+
id=turn_context.activity.reply_to_id,
|
|
304
|
+
text=updated_text,
|
|
305
|
+
attachments=[],
|
|
306
|
+
)
|
|
307
|
+
await turn_context.update_activity(updated_message)
|
|
308
|
+
else:
|
|
309
|
+
# Send typing activity
|
|
310
|
+
typing_activity = Activity(
|
|
311
|
+
type=ActivityTypes.typing,
|
|
312
|
+
from_property=turn_context.activity.recipient,
|
|
313
|
+
recipient=turn_context.activity.from_property,
|
|
314
|
+
conversation=turn_context.activity.conversation,
|
|
315
|
+
)
|
|
316
|
+
await turn_context.send_activity(typing_activity)
|
|
317
|
+
thread_name = f"{turn_context.activity.from_property.name} Teams DM"
|
|
318
|
+
await process_teams_message(turn_context, thread_name)
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
async def on_turn(turn_context: TurnContext):
|
|
322
|
+
await handle_message(turn_context)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
# Create the main bot class
|
|
326
|
+
class TeamsBot:
|
|
327
|
+
async def on_turn(self, turn_context: TurnContext):
|
|
328
|
+
await on_turn(turn_context)
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
# Create the bot instance
|
|
332
|
+
bot = TeamsBot()
|
chainlit/translations/en-US.json
CHANGED
chainlit/types.py
CHANGED
|
@@ -150,11 +150,16 @@ class FileDict(TypedDict):
|
|
|
150
150
|
type: str
|
|
151
151
|
|
|
152
152
|
|
|
153
|
-
class
|
|
153
|
+
class MessagePayload(TypedDict):
|
|
154
154
|
message: "StepDict"
|
|
155
155
|
fileReferences: Optional[List[FileReference]]
|
|
156
156
|
|
|
157
157
|
|
|
158
|
+
class SystemMessagePayload(TypedDict):
|
|
159
|
+
content: str
|
|
160
|
+
metadata: Optional[Dict[str, Any]]
|
|
161
|
+
|
|
162
|
+
|
|
158
163
|
class AudioChunkPayload(TypedDict):
|
|
159
164
|
isStart: bool
|
|
160
165
|
mimeType: str
|
|
@@ -193,21 +198,6 @@ class AskActionResponse(TypedDict):
|
|
|
193
198
|
collapsed: bool
|
|
194
199
|
|
|
195
200
|
|
|
196
|
-
class GenerationRequest(BaseModel):
|
|
197
|
-
chatGeneration: Optional[ChatGeneration] = None
|
|
198
|
-
completionGeneration: Optional[CompletionGeneration] = None
|
|
199
|
-
userEnv: Dict[str, str]
|
|
200
|
-
|
|
201
|
-
@property
|
|
202
|
-
def generation(self):
|
|
203
|
-
if self.chatGeneration:
|
|
204
|
-
return self.chatGeneration
|
|
205
|
-
return self.completionGeneration
|
|
206
|
-
|
|
207
|
-
def is_chat(self):
|
|
208
|
-
return self.chatGeneration is not None
|
|
209
|
-
|
|
210
|
-
|
|
211
201
|
class DeleteThreadRequest(BaseModel):
|
|
212
202
|
threadId: str
|
|
213
203
|
|
|
@@ -259,8 +249,8 @@ class FeedbackDict(TypedDict):
|
|
|
259
249
|
@dataclass
|
|
260
250
|
class Feedback:
|
|
261
251
|
forId: str
|
|
262
|
-
threadId: Optional[str]
|
|
263
252
|
value: Literal[0, 1]
|
|
253
|
+
threadId: Optional[str] = None
|
|
264
254
|
id: Optional[str] = None
|
|
265
255
|
comment: Optional[str] = None
|
|
266
256
|
|
chainlit/user.py
CHANGED
|
@@ -4,7 +4,15 @@ from dataclasses_json import DataClassJsonMixin
|
|
|
4
4
|
from pydantic.dataclasses import Field, dataclass
|
|
5
5
|
|
|
6
6
|
Provider = Literal[
|
|
7
|
-
"credentials",
|
|
7
|
+
"credentials",
|
|
8
|
+
"header",
|
|
9
|
+
"github",
|
|
10
|
+
"google",
|
|
11
|
+
"azure-ad",
|
|
12
|
+
"azure-ad-hybrid",
|
|
13
|
+
"okta",
|
|
14
|
+
"auth0",
|
|
15
|
+
"descope",
|
|
8
16
|
]
|
|
9
17
|
|
|
10
18
|
|
chainlit/utils.py
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import importlib
|
|
3
3
|
import inspect
|
|
4
|
+
import os
|
|
4
5
|
from asyncio import CancelledError
|
|
5
6
|
from typing import Callable
|
|
6
7
|
|
|
8
|
+
import click
|
|
9
|
+
from chainlit.auth import ensure_jwt_secret
|
|
7
10
|
from chainlit.context import context
|
|
8
11
|
from chainlit.logger import logger
|
|
9
12
|
from chainlit.message import ErrorMessage
|
|
13
|
+
from fastapi import FastAPI
|
|
10
14
|
from packaging import version
|
|
11
15
|
|
|
12
16
|
|
|
@@ -87,3 +91,42 @@ def check_module_version(name, required_version):
|
|
|
87
91
|
except ModuleNotFoundError:
|
|
88
92
|
return False
|
|
89
93
|
return version.parse(module.__version__) >= version.parse(required_version)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def check_file(target: str):
|
|
97
|
+
# Define accepted file extensions for Chainlit
|
|
98
|
+
ACCEPTED_FILE_EXTENSIONS = ("py", "py3")
|
|
99
|
+
|
|
100
|
+
_, extension = os.path.splitext(target)
|
|
101
|
+
|
|
102
|
+
# Check file extension
|
|
103
|
+
if extension[1:] not in ACCEPTED_FILE_EXTENSIONS:
|
|
104
|
+
if extension[1:] == "":
|
|
105
|
+
raise click.BadArgumentUsage(
|
|
106
|
+
"Chainlit requires raw Python (.py) files, but the provided file has no extension."
|
|
107
|
+
)
|
|
108
|
+
else:
|
|
109
|
+
raise click.BadArgumentUsage(
|
|
110
|
+
f"Chainlit requires raw Python (.py) files, not {extension}."
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
if not os.path.exists(target):
|
|
114
|
+
raise click.BadParameter(f"File does not exist: {target}")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def mount_chainlit(app: FastAPI, target: str, path="/chainlit"):
|
|
118
|
+
os.environ["CHAINLIT_ROOT_PATH"] = path
|
|
119
|
+
os.environ["CHAINLIT_SUBMOUNT"] = "true"
|
|
120
|
+
from chainlit.config import config, load_module
|
|
121
|
+
from chainlit.server import combined_asgi_app as chainlit_app
|
|
122
|
+
|
|
123
|
+
config.run.root_path = path
|
|
124
|
+
|
|
125
|
+
check_file(target)
|
|
126
|
+
# Load the module provided by the user
|
|
127
|
+
config.run.module_name = target
|
|
128
|
+
load_module(config.run.module_name)
|
|
129
|
+
|
|
130
|
+
ensure_jwt_secret()
|
|
131
|
+
|
|
132
|
+
app.mount("/", chainlit_app)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: chainlit
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.301
|
|
4
4
|
Summary: Build Conversational AI.
|
|
5
5
|
Home-page: https://github.com/Chainlit/chainlit
|
|
6
6
|
License: Apache-2.0 license
|
|
@@ -18,7 +18,6 @@ Requires-Dist: asyncer (>=0.0.2,<0.0.3)
|
|
|
18
18
|
Requires-Dist: click (>=8.1.3,<9.0.0)
|
|
19
19
|
Requires-Dist: dataclasses_json (>=0.5.7,<0.6.0)
|
|
20
20
|
Requires-Dist: fastapi (>=0.110.1,<0.111.0)
|
|
21
|
-
Requires-Dist: fastapi-socketio (>=0.0.10,<0.0.11)
|
|
22
21
|
Requires-Dist: filetype (>=1.2.0,<2.0.0)
|
|
23
22
|
Requires-Dist: httpx (>=0.23.0)
|
|
24
23
|
Requires-Dist: lazify (>=0.4.0,<0.5.0)
|
|
@@ -31,6 +30,7 @@ Requires-Dist: pydantic (>=1,<3)
|
|
|
31
30
|
Requires-Dist: pyjwt (>=2.8.0,<3.0.0)
|
|
32
31
|
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
|
33
32
|
Requires-Dist: python-multipart (>=0.0.9,<0.0.10)
|
|
33
|
+
Requires-Dist: python-socketio (>=5.11.0,<6.0.0)
|
|
34
34
|
Requires-Dist: starlette (>=0.37.2,<0.38.0)
|
|
35
35
|
Requires-Dist: syncer (>=2.0.3,<3.0.0)
|
|
36
36
|
Requires-Dist: tomli (>=2.0.1,<3.0.0)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
chainlit/__init__.py,sha256=g6MbN4Vuf8PbJTpTE2XNqVt-GklWQCk8g5_JZGbrB8M,11052
|
|
2
|
+
chainlit/__main__.py,sha256=7Vg3w3T3qDuz4KDu5lQhLH6lQ3cYdume7gHH7Z1V97U,87
|
|
3
|
+
chainlit/action.py,sha256=k-GsblVHI4DnDWFyF-RZgq3KfdfAFICFh2OBeU4w8N8,1410
|
|
4
|
+
chainlit/auth.py,sha256=lLHePwmwKzX0LiWqpTAtKTdSecrDLqCMSY9Yw4c-TD8,2681
|
|
5
|
+
chainlit/cache.py,sha256=Bv3dT4eHhE6Fq3c6Do0ZTpiyoXgXYewdxTgpYghEd9g,1361
|
|
6
|
+
chainlit/chat_settings.py,sha256=2ByenmwS8O6jQjDVJjhhbLrBPGA5aY2F7R3VvQQxXPk,877
|
|
7
|
+
chainlit/cli/__init__.py,sha256=iLyxU_9db-2n_MaSr6V0VNoQDxhwRIT10-OGlENlq7o,6163
|
|
8
|
+
chainlit/config.py,sha256=o2eF5q6O2xSYXAryW8xljuj98HH8u_AFWpTq6bHbrqM,16712
|
|
9
|
+
chainlit/context.py,sha256=wVtOHIAS9NufvnIW8e4VPHgD7W7pyrstEQGt29FtILc,3075
|
|
10
|
+
chainlit/copilot/dist/assets/logo_dark-2a3cf740.svg,sha256=Kjz3QMh-oh-ag4YatjU0YCPqGF7F8nHh8VUQoJIs01E,8887
|
|
11
|
+
chainlit/copilot/dist/assets/logo_light-b078e7bc.svg,sha256=sHjnvEq1rfqh3bcexJNYUY7WEDdTQZq3aKZYpi4w4ck,8889
|
|
12
|
+
chainlit/copilot/dist/index.js,sha256=nnRtMY1HcLmpOTmwk9ah8tLwgp8_dpDSUJb1voFRW7w,6752568
|
|
13
|
+
chainlit/data/__init__.py,sha256=cUT49s5AhIm5WDlESQEpahSl7k6nzlMAYSJgO_00kO0,17092
|
|
14
|
+
chainlit/data/acl.py,sha256=5EwZuKVcZediw77L661MohGce3JzGIaYmw6NutmMTw0,578
|
|
15
|
+
chainlit/data/dynamodb.py,sha256=u5L9xqp0FG6J2VuGqUjMiJmIddL5jXs4MUcoZb4mXsM,19420
|
|
16
|
+
chainlit/data/sql_alchemy.py,sha256=OFjNnNcswZOgYZfnc7sH2_lJQQDQF6olw2xW8-JMqsg,26805
|
|
17
|
+
chainlit/data/storage_clients.py,sha256=D9KY1XKDjZh2uuh01ECxeoEtjw-JlrCR-WCuOuePVQI,3007
|
|
18
|
+
chainlit/discord/__init__.py,sha256=kZ_AAMaCToqO-1FdeQ8_IHS2pqNT0QJ-yyd8bCMaHHs,198
|
|
19
|
+
chainlit/discord/app.py,sha256=KvBS-bL89tKzzz2-lqCQVaI2hb4qYTyhl_TzCdhMfHQ,10540
|
|
20
|
+
chainlit/element.py,sha256=sjOgHjDaTuQ-t663dmBT-iBOgSVTn3mTlbSGjE42LjE,10990
|
|
21
|
+
chainlit/emitter.py,sha256=BbZ0GwEY9DQu7cN2khgMqT7GzRK3dShPIJMRRwnGuag,13082
|
|
22
|
+
chainlit/frontend/dist/assets/DailyMotion-578b63e6.js,sha256=FljqIxuYhDmbN82fvg-_8c_mlTZPj_G_DefTX4TKuUk,2961
|
|
23
|
+
chainlit/frontend/dist/assets/Facebook-b825e5bb.js,sha256=SML0392XsEaiAX-umB3X4P1VxMmeyNGKSwNrf16504A,3216
|
|
24
|
+
chainlit/frontend/dist/assets/FilePlayer-bcba3b4e.js,sha256=YxE74TiGD3kSs4tUhlyV39d2axLSOZ7ogfzsZq1MQdo,9041
|
|
25
|
+
chainlit/frontend/dist/assets/Kaltura-fc1c9497.js,sha256=6GrAMBk1kETlbpFzcPMOOYkbjk_CUQem-nuiD2FimTw,2790
|
|
26
|
+
chainlit/frontend/dist/assets/Mixcloud-4cfb2724.js,sha256=DLVwQ7RLYm4dvfClyoSFDB6rjG7vCFv8hiNbSN-vNYY,2638
|
|
27
|
+
chainlit/frontend/dist/assets/Mux-aa92055c.js,sha256=unvszOgiIQfmZhFtEeIXJE5eiSr6w8Jx1sRpGZX4VlQ,5360
|
|
28
|
+
chainlit/frontend/dist/assets/Preview-9f55905a.js,sha256=RXuDNVigADyu5lGUk-y5QrhiPp1RHqcE5-RylFprdBo,3011
|
|
29
|
+
chainlit/frontend/dist/assets/SoundCloud-f991fe03.js,sha256=z8XVOBBfaskYyC-bRCsXb6qDFTH4mebmR5jsR5IiH44,2923
|
|
30
|
+
chainlit/frontend/dist/assets/Streamable-53128f49.js,sha256=7WZSefvfRi_qnIS9LTa3PFrs-pgr48YiXM1DXplb1LI,2935
|
|
31
|
+
chainlit/frontend/dist/assets/Twitch-fce8b9f5.js,sha256=H3rQ8YEW6AcejSWtvaVAcfjzQdYgdULPye5mTZ_nc_4,3083
|
|
32
|
+
chainlit/frontend/dist/assets/Vidyard-e35c6102.js,sha256=UW5ad17Jlo5U1BjQG6sFEHvAp8ic6en2Uvb-4DuVb04,2857
|
|
33
|
+
chainlit/frontend/dist/assets/Vimeo-fff35f8e.js,sha256=brWSILraomEKxRDGFR56wwZl81gvxvAvSVbGMCbHvB0,3627
|
|
34
|
+
chainlit/frontend/dist/assets/Wistia-ec07dc64.js,sha256=VU557IGXuda6KYDPVrohXQWDoyIX385ooBt2eIn6LZA,3514
|
|
35
|
+
chainlit/frontend/dist/assets/YouTube-ad068e2a.js,sha256=h-dP39j7ZP7AeqCrJLKlv_ZMD20GSc8nQeMJSaEiMLI,4448
|
|
36
|
+
chainlit/frontend/dist/assets/index-aaf974a9.css,sha256=qvl0qUmR5u0JcmJAfkzaZpN-0ZKdQjzqCSE9cnrQpZQ,2559
|
|
37
|
+
chainlit/frontend/dist/assets/index-d40d41cc.js,sha256=q548b7K04T5yFuuKXr3Z7_y24V5iM7ti_BNfLkRNgoQ,2753963
|
|
38
|
+
chainlit/frontend/dist/assets/logo_dark-2a3cf740.svg,sha256=Kjz3QMh-oh-ag4YatjU0YCPqGF7F8nHh8VUQoJIs01E,8887
|
|
39
|
+
chainlit/frontend/dist/assets/logo_light-b078e7bc.svg,sha256=sHjnvEq1rfqh3bcexJNYUY7WEDdTQZq3aKZYpi4w4ck,8889
|
|
40
|
+
chainlit/frontend/dist/assets/react-plotly-b2c6442b.js,sha256=zOhmPUI82UBQWmBpKFKuAQF_bQT-sXGbG3-kigjMQQ4,3739251
|
|
41
|
+
chainlit/frontend/dist/favicon.svg,sha256=0Cy8x28obT5eWW3nxZRhsEvu6_zMqrqbg0y6hT3D0Q0,6455
|
|
42
|
+
chainlit/frontend/dist/index.html,sha256=cIwIROqkmnFNLWkOz4N_7S91qPJA6r9SuYe4pNguwS8,965
|
|
43
|
+
chainlit/haystack/__init__.py,sha256=uZ77YiPy-qleSTi3dQCDO9HE6S6F6GpJWmh7jO4cxXA,217
|
|
44
|
+
chainlit/haystack/callbacks.py,sha256=tItLc6OmskPeDEJH2Qjtg7KgAgIy1TuYQYHTZm9cr3U,5209
|
|
45
|
+
chainlit/hello.py,sha256=LwENQWo5s5r8nNDn4iKSV77vX60Ky5r_qGjQhyi7qlY,416
|
|
46
|
+
chainlit/input_widget.py,sha256=KmOn1nPTBvnld3iIBHR0Vih0KsCxVnTbo2t_xBNANzo,4949
|
|
47
|
+
chainlit/langchain/__init__.py,sha256=zErMw0_3ufSGeF9ye7X0ZX3wDat4mTOx97T40ePDO2g,217
|
|
48
|
+
chainlit/langchain/callbacks.py,sha256=MHl_m6FYZmCzn0e2KOlZpd6ld0rSP1LzuCKs4Eh_N_8,20517
|
|
49
|
+
chainlit/langflow/__init__.py,sha256=wxhxdsl1yxdsRyNTgZticxFF_8VFtJJ4OdIy3tnEIyM,817
|
|
50
|
+
chainlit/llama_index/__init__.py,sha256=weRoIWCaRBGvA1LczCEfsqhWsltQSVlhtRnTovtdo8w,227
|
|
51
|
+
chainlit/llama_index/callbacks.py,sha256=THFmwotSF_ibqFuaQgxGvEjgKmmzoGJKNlVI75SI2ig,7267
|
|
52
|
+
chainlit/logger.py,sha256=wTwRSZsLfXwWy6U4351IgWAm4KCMThgxm9EZpjGUEr4,373
|
|
53
|
+
chainlit/markdown.py,sha256=VUpqW7MqgjiPIQYHU4funwqC4GmHZBu_TGZTjTI4B0k,2025
|
|
54
|
+
chainlit/message.py,sha256=aEw2VNZ0-4mAC3PSG-0j5ZjO1qZ9MaUFDnfiAXLM_q8,17997
|
|
55
|
+
chainlit/oauth_providers.py,sha256=Mv31biQ84EBJfQGBxqhFfnbpl-jfQ_Zn6IxKY3XZg6Q,22972
|
|
56
|
+
chainlit/openai/__init__.py,sha256=DJP_ptclLUM5Zylr4RO1Vk0lCufo3yDqXyH5J9izYS8,1814
|
|
57
|
+
chainlit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
|
+
chainlit/secret.py,sha256=cQvIFGTQ7r2heC8EOGdgifSZZYqslh-qQxhUhKhD8vU,295
|
|
59
|
+
chainlit/server.py,sha256=H8Oj4rEqY9OulwbNoZzcTc53U0vuYXUPREhYUNKLqpM,28626
|
|
60
|
+
chainlit/session.py,sha256=SOX2zFct3apiSNcIzCDWgDRsUFgUG_6hewqWU8gfIZE,9694
|
|
61
|
+
chainlit/slack/__init__.py,sha256=Q41ztJHeVmpoXVgVqAcwGOufQp_bjf7dDT7eEXDdhPI,207
|
|
62
|
+
chainlit/slack/app.py,sha256=FgrlaupsCo-_1m8FiFcS5s-wFg_28bCjfKnawvlVbEM,11646
|
|
63
|
+
chainlit/socket.py,sha256=0xUoHRQXqhTb9IB9k7rMM7gYIoLQgZed6jV337KtL54,11824
|
|
64
|
+
chainlit/step.py,sha256=rLlK_dhZNKidK5Q7FtP_sNmlm-zUyjF4gHLPxl3PHA8,14213
|
|
65
|
+
chainlit/sync.py,sha256=G1n-7-3WgXsN8y1bJkEyws_YwmHZIyDZoZUwhprigag,1235
|
|
66
|
+
chainlit/teams/__init__.py,sha256=ZSEbsRJHT_mKfGn6yuzM5NX-xItleSDS0af7vt8Z1OA,217
|
|
67
|
+
chainlit/teams/app.py,sha256=i4uu5BizcPH_h824ZFBNbpqM0weCfpPt3zb8YpQ-5po,10378
|
|
68
|
+
chainlit/telemetry.py,sha256=Rk4dnZv0OnGOgV4kD-VHdhgl4i7i3ypqhSE_R-LZceM,3060
|
|
69
|
+
chainlit/translations/en-US.json,sha256=J46wpkc01XLnytWNLSziillMvfmwXsc-mIUeYDIy59M,7741
|
|
70
|
+
chainlit/translations.py,sha256=WG_r7HzxBYns-zk9tVvoGdoofv71okTZx8k1RlcoTIg,2034
|
|
71
|
+
chainlit/types.py,sha256=1W_IexztYW5ewOfxXtdL6qJHWYLWJ5qC9JG0iu6Rnv4,5329
|
|
72
|
+
chainlit/user.py,sha256=8PgRJvv59b7BKTNguObo68gyFoOGNJfVkT3WW-fvhAM,671
|
|
73
|
+
chainlit/user_session.py,sha256=G1amgs1_h2tVn4mtAXZmunm9nlBHQ_rCYvJQh3nsVwQ,1645
|
|
74
|
+
chainlit/utils.py,sha256=w3UIzvaQ72y5VrycFoWaqS_NocS40No7mzPWqkelzCE,3939
|
|
75
|
+
chainlit/version.py,sha256=iosXhlXclBwBqlADFKEilxAC2wWKbtuBKi87AmPi7s8,196
|
|
76
|
+
chainlit-1.1.301.dist-info/METADATA,sha256=Kh2rf0xg4Cm4O8G67VjEVp7a2h1OaHLW6ukJ4bLsY7w,6315
|
|
77
|
+
chainlit-1.1.301.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
78
|
+
chainlit-1.1.301.dist-info/entry_points.txt,sha256=FrkqdjrFl8juSnvBndniyX7XuKojmUwO4ghRh-CFMQc,45
|
|
79
|
+
chainlit-1.1.301.dist-info/RECORD,,
|
chainlit/cli/utils.py
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
|
-
import click
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def check_file(target: str):
|
|
7
|
-
# Define accepted file extensions for Chainlit
|
|
8
|
-
ACCEPTED_FILE_EXTENSIONS = ("py", "py3")
|
|
9
|
-
|
|
10
|
-
_, extension = os.path.splitext(target)
|
|
11
|
-
|
|
12
|
-
# Check file extension
|
|
13
|
-
if extension[1:] not in ACCEPTED_FILE_EXTENSIONS:
|
|
14
|
-
if extension[1:] == "":
|
|
15
|
-
raise click.BadArgumentUsage(
|
|
16
|
-
"Chainlit requires raw Python (.py) files, but the provided file has no extension."
|
|
17
|
-
)
|
|
18
|
-
else:
|
|
19
|
-
raise click.BadArgumentUsage(
|
|
20
|
-
f"Chainlit requires raw Python (.py) files, not {extension}."
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
if not os.path.exists(target):
|
|
24
|
-
raise click.BadParameter(f"File does not exist: {target}")
|