chainlit 0.4.1__py3-none-any.whl → 0.4.3__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/client.py DELETED
@@ -1,287 +0,0 @@
1
- from typing import Dict, Any, Optional
2
- from abc import ABC, abstractmethod
3
- import uuid
4
-
5
- import asyncio
6
- import aiohttp
7
- from python_graphql_client import GraphqlClient
8
-
9
- from chainlit.types import ElementType, ElementSize
10
- from chainlit.logger import logger
11
- from chainlit.config import config
12
-
13
-
14
- class BaseClient(ABC):
15
- project_id: str
16
- session_id: str
17
-
18
- @abstractmethod
19
- async def is_project_member(self, access_token: str) -> bool:
20
- pass
21
-
22
- @abstractmethod
23
- async def create_conversation(self, session_id: str) -> int:
24
- pass
25
-
26
- @abstractmethod
27
- async def create_message(self, variables: Dict[str, Any]) -> int:
28
- pass
29
-
30
- @abstractmethod
31
- async def update_message(self, message_id: int, variables: Dict[str, Any]) -> bool:
32
- pass
33
-
34
- @abstractmethod
35
- async def delete_message(self, message_id: int) -> bool:
36
- pass
37
-
38
- @abstractmethod
39
- async def upload_element(self, content: bytes, mime: str) -> str:
40
- pass
41
-
42
- @abstractmethod
43
- async def create_element(
44
- self,
45
- type: ElementType,
46
- url: str,
47
- name: str,
48
- display: str,
49
- size: ElementSize = None,
50
- language: str = None,
51
- for_id: str = None,
52
- ) -> Dict[str, Any]:
53
- pass
54
-
55
-
56
- conversation_lock = asyncio.Lock()
57
-
58
-
59
- class CloudClient(BaseClient):
60
- conversation_id: Optional[str] = None
61
-
62
- def __init__(self, project_id: str, session_id: str, access_token: str):
63
- self.project_id = project_id
64
- self.session_id = session_id
65
- self.headers = {
66
- "Authorization": access_token,
67
- "content-type": "application/json",
68
- }
69
- graphql_endpoint = f"{config.chainlit_server}/api/graphql"
70
- self.graphql_client = GraphqlClient(
71
- endpoint=graphql_endpoint, headers=self.headers
72
- )
73
-
74
- def query(self, query: str, variables: Dict[str, Any] = {}) -> Dict[str, Any]:
75
- """
76
- Execute a GraphQL query.
77
-
78
- :param query: The GraphQL query string.
79
- :param variables: A dictionary of variables for the query.
80
- :return: The response data as a dictionary.
81
- """
82
- return self.graphql_client.execute_async(query=query, variables=variables)
83
-
84
- def check_for_errors(self, response: Dict[str, Any]):
85
- if "errors" in response:
86
- logger.error(response["errors"])
87
- return True
88
- return False
89
-
90
- def mutation(self, mutation: str, variables: Dict[str, Any] = {}) -> Dict[str, Any]:
91
- """
92
- Execute a GraphQL mutation.
93
-
94
- :param mutation: The GraphQL mutation string.
95
- :param variables: A dictionary of variables for the mutation.
96
- :return: The response data as a dictionary.
97
- """
98
- return self.graphql_client.execute_async(query=mutation, variables=variables)
99
-
100
- async def is_project_member(self) -> bool:
101
- data = {"projectId": self.project_id}
102
- async with aiohttp.ClientSession() as session:
103
- async with session.post(
104
- f"{config.chainlit_server}/api/role",
105
- json=data,
106
- headers=self.headers,
107
- ) as r:
108
- if not r.ok:
109
- reason = await r.text()
110
- logger.error(f"Failed to get user role. {r.status}: {reason}")
111
- return False
112
- json = await r.json()
113
- role = json.get("role", "ANONYMOUS")
114
- return role != "ANONYMOUS"
115
-
116
- async def create_conversation(self, session_id: str) -> int:
117
- # If we run multiple send concurrently, we need to make sure we don't create multiple conversations.
118
- async with conversation_lock:
119
- if self.conversation_id:
120
- return self.conversation_id
121
-
122
- mutation = """
123
- mutation ($projectId: String!, $sessionId: String!) {
124
- createConversation(projectId: $projectId, sessionId: $sessionId) {
125
- id
126
- }
127
- }
128
- """
129
- variables = {"projectId": self.project_id, "sessionId": session_id}
130
- res = await self.mutation(mutation, variables)
131
-
132
- if self.check_for_errors(res):
133
- logger.warning("Could not create conversation.")
134
- return None
135
-
136
- return int(res["data"]["createConversation"]["id"])
137
-
138
- async def get_conversation_id(self):
139
- self.conversation_id = await self.create_conversation(self.session_id)
140
-
141
- return self.conversation_id
142
-
143
- async def create_message(self, variables: Dict[str, Any]) -> int:
144
- c_id = await self.get_conversation_id()
145
-
146
- if not c_id:
147
- logger.warning("Missing conversation ID, could not persist the message.")
148
- return None
149
-
150
- variables["conversationId"] = c_id
151
-
152
- mutation = """
153
- mutation ($conversationId: ID!, $author: String!, $content: String!, $language: String, $prompt: String, $llmSettings: Json, $isError: Boolean, $indent: Int, $authorIsUser: Boolean, $waitForAnswer: Boolean, $createdAt: Float) {
154
- createMessage(conversationId: $conversationId, author: $author, content: $content, language: $language, prompt: $prompt, llmSettings: $llmSettings, isError: $isError, indent: $indent, authorIsUser: $authorIsUser, waitForAnswer: $waitForAnswer, createdAt: $createdAt) {
155
- id
156
- }
157
- }
158
- """
159
- res = await self.mutation(mutation, variables)
160
- if self.check_for_errors(res):
161
- logger.warning("Could not create message.")
162
- return None
163
-
164
- return int(res["data"]["createMessage"]["id"])
165
-
166
- async def update_message(self, message_id: int, variables: Dict[str, Any]) -> bool:
167
- mutation = """
168
- mutation ($messageId: ID!, $author: String!, $content: String!, $language: String, $prompt: String, $llmSettings: Json) {
169
- updateMessage(messageId: $messageId, author: $author, content: $content, language: $language, prompt: $prompt, llmSettings: $llmSettings) {
170
- id
171
- }
172
- }
173
- """
174
- variables["messageId"] = message_id
175
- res = await self.mutation(mutation, variables)
176
-
177
- if self.check_for_errors(res):
178
- logger.warning("Could not update message.")
179
- return False
180
-
181
- return True
182
-
183
- async def delete_message(self, message_id: int) -> bool:
184
- mutation = """
185
- mutation ($messageId: ID!) {
186
- deleteMessage(messageId: $messageId) {
187
- id
188
- }
189
- }
190
- """
191
- res = await self.mutation(mutation, {"messageId": message_id})
192
-
193
- if self.check_for_errors(res):
194
- logger.warning("Could not delete message.")
195
- return False
196
-
197
- return True
198
-
199
- async def create_element(
200
- self,
201
- type: ElementType,
202
- url: str,
203
- name: str,
204
- display: str,
205
- size: ElementSize = None,
206
- language: str = None,
207
- for_id: str = None,
208
- ) -> Dict[str, Any]:
209
- c_id = await self.get_conversation_id()
210
-
211
- if not c_id:
212
- logger.warning("Missing conversation ID, could not persist the element.")
213
- return None
214
-
215
- mutation = """
216
- mutation ($conversationId: ID!, $type: String!, $url: String!, $name: String!, $display: String!, $size: String, $language: String, $forId: String) {
217
- createElement(conversationId: $conversationId, type: $type, url: $url, name: $name, display: $display, size: $size, language: $language, forId: $forId) {
218
- id,
219
- type,
220
- url,
221
- name,
222
- display,
223
- size,
224
- language,
225
- forId
226
- }
227
- }
228
- """
229
- variables = {
230
- "conversationId": c_id,
231
- "type": type,
232
- "url": url,
233
- "name": name,
234
- "display": display,
235
- "size": size,
236
- "language": language,
237
- "forId": for_id,
238
- }
239
- res = await self.mutation(mutation, variables)
240
-
241
- if self.check_for_errors(res):
242
- logger.warning("Could not persist element.")
243
- return None
244
-
245
- return res["data"]["createElement"]
246
-
247
- async def upload_element(self, content: bytes, mime: str) -> str:
248
- id = f"{uuid.uuid4()}"
249
- body = {"projectId": self.project_id, "fileName": id, "contentType": mime}
250
-
251
- path = f"/api/upload/file"
252
-
253
- async with aiohttp.ClientSession() as session:
254
- async with session.post(
255
- f"{config.chainlit_server}{path}",
256
- json=body,
257
- headers=self.headers,
258
- ) as r:
259
- if not r.ok:
260
- reason = await r.text()
261
- logger.error(f"Failed to upload file: {reason}")
262
- return ""
263
- json_res = await r.json()
264
-
265
- upload_details = json_res["post"]
266
- permanent_url = json_res["permanentUrl"]
267
-
268
- form_data = aiohttp.FormData()
269
-
270
- # Add fields to the form_data
271
- for field_name, field_value in upload_details["fields"].items():
272
- form_data.add_field(field_name, field_value)
273
-
274
- # Add file to the form_data
275
- form_data.add_field("file", content, content_type="multipart/form-data")
276
- async with aiohttp.ClientSession() as session:
277
- async with session.post(
278
- upload_details["url"],
279
- data=form_data,
280
- ) as upload_response:
281
- if not upload_response.ok:
282
- reason = await upload_response.text()
283
- logger.error(f"Failed to upload file: {reason}")
284
- return ""
285
-
286
- url = f'{upload_details["url"]}/{upload_details["fields"]["key"]}'
287
- return permanent_url