chainlit 0.2.111__py3-none-any.whl → 0.3.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.

@@ -6,22 +6,25 @@ from socketio.exceptions import TimeoutError
6
6
  import inspect
7
7
 
8
8
 
9
- class Chainlit:
9
+ class ChainlitEmitter:
10
10
  """
11
- Chainlit SDK class. The SDK is not directly exposed to the developer.
12
- Instead, the developer interacts with the SDK through the methods exposed in the __init__ file.
11
+ Chainlit Emitter class. The Emitter is not directly exposed to the developer.
12
+ Instead, the developer interacts with the Emitter through the methods and classes exposed in the __init__ file.
13
13
  """
14
14
 
15
15
  session: Session
16
16
 
17
17
  def __init__(self, session: Session) -> None:
18
- """Initialize Chainlit with the user session."""
18
+ """Initialize with the user session."""
19
19
  self.session = session
20
20
 
21
- def _get_session_property(self, property_name: str):
21
+ def _get_session_property(self, property_name: str, raise_error=True):
22
22
  """Helper method to get a property from the session."""
23
23
  if not hasattr(self, "session") or property_name not in self.session:
24
- return None
24
+ if raise_error:
25
+ raise ValueError(f"Session does not have property '{property_name}'")
26
+ else:
27
+ return None
25
28
  return self.session[property_name]
26
29
 
27
30
  @property
@@ -37,50 +40,47 @@ class Chainlit:
37
40
  @property
38
41
  def client(self) -> Union[BaseClient, None]:
39
42
  """Get the 'client' property from the session."""
40
- return self._get_session_property("client")
43
+ return self._get_session_property("client", raise_error=False)
41
44
 
42
45
  def send_message(self, msg_dict: Dict):
43
46
  """Send a message to the UI."""
44
- if not self.emit:
45
- return
46
47
 
47
- self.emit("message", msg_dict)
48
+ return self.emit("new_message", msg_dict)
48
49
 
49
50
  def update_message(self, msg_dict: Dict):
50
51
  """Update a message in the UI."""
51
- if not self.emit:
52
- return
53
52
 
54
- self.emit("update_message", msg_dict)
53
+ return self.emit("update_message", msg_dict)
55
54
 
56
- def delete_message(self, message_id: Union[str, int]):
55
+ def delete_message(self, msg_dict):
57
56
  """Delete a message in the UI."""
58
- if not self.emit:
59
- return
60
57
 
61
- self.emit("delete_message", {"messageId": message_id})
58
+ return self.emit("delete_message", msg_dict)
62
59
 
63
60
  def send_ask_timeout(self):
64
61
  """Send a prompt timeout message to the UI."""
65
62
 
66
- if self.emit:
67
- self.emit("ask_timeout", {})
63
+ return self.emit("ask_timeout", {})
68
64
 
69
65
  def clear_ask(self):
70
66
  """Clear the prompt from the UI."""
71
- if self.emit:
72
- self.emit("clear_ask", {})
73
67
 
74
- def send_ask_user(self, msg_dict: Dict, spec: AskSpec, raise_on_timeout=False):
68
+ return self.emit("clear_ask", {})
69
+
70
+ async def send_ask_user(
71
+ self, msg_dict: Dict, spec: AskSpec, raise_on_timeout=False
72
+ ):
75
73
  """Send a prompt to the UI and wait for a response."""
76
- if not self.ask_user:
77
- return
78
74
 
79
75
  try:
80
- # End the task temporarily so that the User can answer the prompt
81
- self.task_end()
82
76
  # Send the prompt to the UI
83
- res = self.ask_user({"msg": msg_dict, "spec": spec.to_dict()}, spec.timeout)
77
+ res = await self.ask_user(
78
+ {"msg": msg_dict, "spec": spec.to_dict()}, spec.timeout
79
+ )
80
+
81
+ # End the task temporarily so that the User can answer the prompt
82
+ await self.task_end()
83
+
84
84
  if self.client and res:
85
85
  # If cloud is enabled, store the response in the database/S3
86
86
  if spec.type == "text":
@@ -89,80 +89,71 @@ class Chainlit:
89
89
  "authorIsUser": True,
90
90
  "content": res["content"],
91
91
  }
92
- self.client.create_message(res_msg)
92
+ await self.client.create_message(res_msg)
93
93
  elif spec.type == "file":
94
94
  # TODO: upload file to S3
95
95
  pass
96
96
 
97
- self.clear_ask()
97
+ await self.clear_ask()
98
98
  return res
99
99
  except TimeoutError as e:
100
- self.send_ask_timeout()
100
+ await self.send_ask_timeout()
101
101
 
102
102
  if raise_on_timeout:
103
103
  raise e
104
104
  finally:
105
- self.task_start()
105
+ await self.task_start()
106
106
 
107
107
  def update_token_count(self, count: int):
108
108
  """Update the token count for the UI."""
109
- if not self.emit:
110
- return
111
- self.emit("token_usage", count)
109
+
110
+ return self.emit("token_usage", count)
112
111
 
113
112
  def task_start(self):
114
113
  """
115
114
  Send a task start signal to the UI.
116
115
  """
117
- if self.emit:
118
- self.emit("task_start", {})
116
+ return self.emit("task_start", {})
119
117
 
120
118
  def task_end(self):
121
119
  """Send a task end signal to the UI."""
122
- if self.emit:
123
- self.emit("task_end", {})
120
+ return self.emit("task_end", {})
124
121
 
125
122
  def stream_start(self, msg_dict: Dict):
126
123
  """Send a stream start signal to the UI."""
127
- if self.emit:
128
- self.emit(
129
- "stream_start",
130
- msg_dict,
131
- )
124
+ return self.emit(
125
+ "stream_start",
126
+ msg_dict,
127
+ )
132
128
 
133
- def send_token(self, token: str):
129
+ def send_token(self, id: Union[str, int], token: str):
134
130
  """Send a message token to the UI."""
135
- if self.emit:
136
- self.emit("stream_token", token)
131
+ return self.emit("stream_token", {"id": id, "token": token})
137
132
 
138
- def stream_end(self, msg):
139
- """Send a stream end signal to the UI."""
140
- if self.emit:
141
- self.emit("stream_end", msg)
142
133
 
143
-
144
- def get_sdk() -> Union[Chainlit, None]:
134
+ def get_emitter() -> Union[ChainlitEmitter, None]:
145
135
  """
146
- Get the Chainlit SDK instance from the current call stack.
136
+ Get the Chainlit Emitter instance from the current call stack.
147
137
  This unusual approach is necessary because:
148
- - we need to get the right SDK instance with the right websocket connection
149
- - to preserve a lean developer experience, we do not pass the SDK instance to every function call
138
+ - we need to get the right Emitter instance with the right websocket connection
139
+ - to preserve a lean developer experience, we do not pass the Emitter instance to every function call
150
140
 
151
- What happens is that we set __chainlit_sdk__ in the local variables when we receive a websocket message.
141
+ What happens is that we set __chainlit_emitter__ in the local variables when we receive a websocket message.
152
142
  Then we can retrieve it from the call stack when we need it, even if the developer's code has no idea about it.
153
143
  """
154
- attr = "__chainlit_sdk__"
144
+ attr = "__chainlit_emitter__"
155
145
  candidates = [i[0].f_locals.get(attr) for i in inspect.stack()]
156
- sdk = None
146
+ emitter = None
157
147
  for candidate in candidates:
158
148
  if candidate:
159
- sdk = candidate
149
+ emitter = candidate
160
150
  break
161
- return sdk
151
+
152
+ return emitter
162
153
 
163
154
 
164
- def get_emit():
165
- sdk = get_sdk()
166
- if sdk:
167
- return sdk.emit
155
+ def get_emit_fn():
156
+ emitter = get_emitter()
157
+ if emitter:
158
+ return emitter.emit
168
159
  return None