Skip to content

Commit 03fb84c

Browse files
authored
update for 0.3.0 (#5)
* update for 0.3.0 * add callbacks to doc * update to make_async * rework migration guide
1 parent 903ec8a commit 03fb84c

26 files changed

+523
-189
lines changed

api-reference/action.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,17 @@ The `Action` class is designed to create and manage actions to be sent and displ
3131
import chainlit as cl
3232

3333
@cl.action_callback("action_button")
34-
def on_action(action):
35-
cl.Message(content=f"Executed {action.name}").send()
34+
async def on_action(action):
35+
await cl.Message(content=f"Executed {action.name}").send()
3636
# Optionally remove the action button from the chatbot user interface
37-
action.remove()
37+
await action.remove()
3838

3939
@cl.on_chat_start
40-
def start():
40+
async def start():
4141
# Sending an action button within a chatbot message
4242
actions = [
4343
cl.Action(name="action_button", value="example_value", description="Click me!")
4444
]
4545

46-
cl.Message(content="Interact with this action button:", actions=actions).send()
46+
await cl.Message(content="Interact with this action button:", actions=actions).send()
4747
```

api-reference/ask/ask-for-file.mdx

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ If a project ID is configured, the messages will be uploaded to the cloud storag
1818
<ParamField path="max_size_mb" type="int" optional>
1919
Maximum file size in MB. Defaults to 2. Max 100.
2020
</ParamField>
21+
<ParamField path="max_files" type="int" optional>
22+
Maximum number of files to upload. Defaults to 1. Maximum value is 10.
23+
</ParamField>
2124
<ParamField path="timeout" type="int" optional>
2225
The number of seconds to wait for an answer before raising a TimeoutError.
2326
</ParamField>
@@ -27,8 +30,8 @@ If a project ID is configured, the messages will be uploaded to the cloud storag
2730

2831
### Returns
2932

30-
<ResponseField name="response" type="AskFileResponse" required>
31-
The file uploaded by the user.
33+
<ResponseField name="response" type="List[AskFileResponse]" required>
34+
The files uploaded by the user.
3235
</ResponseField>
3336

3437
### Usage
@@ -38,20 +41,21 @@ import chainlit as cl
3841

3942

4043
@cl.on_chat_start
41-
def start():
44+
async def start():
4245
file = None
4346

4447
# Wait for the user to upload a file
45-
while file == None:
46-
file = cl.AskFileMessage(
48+
while files == None:
49+
files = await cl.AskFileMessage(
4750
content="Please upload a text file to begin!", accept=["text/plain"]
4851
).send()
4952
# Decode the file
50-
text = file.content.decode("utf-8")
53+
text_file = files[0]
54+
text = text_file.content.decode("utf-8")
5155

5256
# Let the user know that the system is ready
53-
cl.Message(
54-
content=f"`{file.name}` uploaded, it contains {len(text)} characters!"
57+
await cl.Message(
58+
content=f"`{text_file.name}` uploaded, it contains {len(text)} characters!"
5559
).send()
5660
```
5761

@@ -60,7 +64,7 @@ You can also pass a dict to the `accept` parameter to precise the file extension
6064
```python Code Example
6165
import chainlit as cl
6266

63-
file = cl.AskFileMessage(
67+
file = await cl.AskFileMessage(
6468
content="Please upload a python file to begin!", accept={"text/plain": [".py"]}
6569
).send()
6670
```

api-reference/ask/ask-for-input.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ If a project ID is configured, the messages will be uploaded to the cloud storag
2424

2525
### Returns
2626

27-
<ResponseField name="response" type="str" required>
27+
<ResponseField name="response" type="AskResponse" required>
2828
The response of the user.
2929
</ResponseField>
3030

@@ -35,10 +35,10 @@ import chainlit as cl
3535

3636

3737
@cl.on_chat_start
38-
def main():
39-
res = cl.AskUserMessage(content="What is your name?", timeout=10).send()
38+
async def main():
39+
res = await cl.AskUserMessage(content="What is your name?", timeout=10).send()
4040
if res:
41-
cl.Message(
41+
await cl.Message(
4242
content=f"Your name is: {res['content']}",
4343
).send()
4444
```

api-reference/elements/avatar.mdx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
title: "Avatar"
3+
---
4+
5+
The `Avatar` class allows you to display an avatar image next to a message instead of the author name.
6+
7+
You need to send the element once. Next if the name of an avatar matches the name of an author, the avatar will be automatically displayed.
8+
9+
You must provide either an url or a path or content bytes.
10+
11+
### Attributes
12+
13+
<ParamField path="name" type="str">
14+
The name of the avatar. This will be used to replace author names.
15+
</ParamField>
16+
17+
<ParamField path="url" type="str" optional>
18+
The remote URL of the avatar image source.
19+
</ParamField>
20+
21+
<ParamField path="path" type="str" optional>
22+
The local file path of the avatar image.
23+
</ParamField>
24+
25+
<ParamField path="content" type="bytes" optional>
26+
The file content of the avatar image in bytes format.
27+
</ParamField>
28+
29+
### Usage
30+
31+
```python Code Example
32+
import chainlit as cl
33+
34+
35+
@cl.on_chat_start
36+
async def start():
37+
await cl.Avatar(
38+
name="Tool 1",
39+
url="https://avatars.githubusercontent.com/u/128686189?s=400&u=a1d1553023f8ea0921fba0debbe92a8c5f840dd9&v=4",
40+
).send()
41+
42+
await cl.Message(
43+
content="This message should not have an avatar!", author="Tool 0"
44+
).send()
45+
46+
await cl.Message(
47+
content="This message should have an avatar!", author="Tool 1"
48+
).send()
49+
50+
await cl.Message(
51+
content="This message should not have an avatar!", author="Tool 2"
52+
).send()
53+
54+
```
Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
---
2-
title: "Local Image"
2+
title: "Image"
33
---
44

5-
The `LocalImage` class is designed to create and handle local image elements to be sent and displayed in the chatbot user interface.
5+
The `Image` class is designed to create and handle image elements to be sent and displayed in the chatbot user interface.
6+
7+
You must provide either an url or a path or content bytes.
68

79
### Attributes
810

@@ -20,13 +22,16 @@ The `LocalImage` class is designed to create and handle local image elements to
2022
are "small", "medium" (default), or "large".
2123
</ParamField>
2224

25+
<ParamField path="url" type="str" optional>
26+
The remote URL of the image source.
27+
</ParamField>
28+
2329
<ParamField path="path" type="str" optional>
24-
The local file path of the image. Must provide either path or content.
30+
The local file path of the image.
2531
</ParamField>
2632

2733
<ParamField path="content" type="bytes" optional>
28-
The file content of the image in bytes format. Must provide either path or
29-
content.
34+
The file content of the image in bytes format.
3035
</ParamField>
3136

3237
### Usage with message scope
@@ -36,24 +41,25 @@ import chainlit as cl
3641

3742
# Sending an image with the local file path
3843
elements = [
39-
cl.LocalImage(name="image1", display="inline", path="./image1.jpg")
44+
cl.Image(name="image1", display="inline", path="./image1.jpg")
4045
]
4146

42-
cl.Message(content="Look at this local image!", elements=elements).send()
47+
await cl.Message(content="Look at this local image!", elements=elements).send()
4348
```
4449

4550
### Usage without scope
4651

4752
```python Code Example
4853
import chainlit as cl
54+
import aiofiles
4955

5056
# Sending an image with the local file path
51-
image1 = cl.LocalImage(name="image1", display="inline", path="./image1.jpg")
52-
image1.send()
57+
image1 = cl.Image(name="image1", display="inline", path="./image1.jpg")
58+
await image1.send()
5359

5460
# Sending an image with file content as bytes
55-
with open("./image2.jpg", "rb") as f:
56-
image_content = f.read()
57-
image2 = cl.LocalImage(name="image2", display="inline", content=image_content)
58-
image2.send()
61+
async with aiofiles.open("./image2.jpg", "rb") as f:
62+
image_content = await f.read()
63+
image2 = cl.Image(name="image2", display="inline", content=image_content)
64+
await image2.send()
5965
```

api-reference/elements/remote-image.mdx

Lines changed: 0 additions & 47 deletions
This file was deleted.

api-reference/elements/text.mdx

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,27 @@ title: "Text"
33
---
44

55
The `Text` class allows you to display a text element in the chatbot UI. This class takes a string and creates a text element that can be sent to the UI.
6+
It supports the markdown syntax for formatting text.
7+
8+
You must provide either an url or a path or content bytes.
69

710
### Attributes
811

912
<ParamField path="name" type="str">
1013
The name of the text element to be displayed in the UI.
1114
</ParamField>
1215

13-
<ParamField path="text" type="str">
14-
The text string that should be displayed as the content of the text element.
16+
<ParamField path="content" type="Union[str, bytes]" optional>
17+
The text string or bytes that should be displayed as the content of the text
18+
element.
19+
</ParamField>
20+
21+
<ParamField path="url" type="str" optional>
22+
The remote URL of the text source.
23+
</ParamField>
24+
25+
<ParamField path="path" type="str" optional>
26+
The local file path of the text file.
1527
</ParamField>
1628

1729
<ParamField path="display" type="ElementDisplay" optional>
@@ -32,10 +44,10 @@ import chainlit as cl
3244

3345
text_content = "Hello, this is a text element."
3446
elements = [
35-
cl.Text(name="simple_text", text=text_content, display="inline")
47+
cl.Text(name="simple_text", content=text_content, display="inline")
3648
]
3749

38-
cl.Message(content="Check out this text element!", elements=elements).send()
50+
await cl.Message(content="Check out this text element!", elements=elements).send()
3951
```
4052

4153
### Usage without scope
@@ -44,5 +56,5 @@ cl.Message(content="Check out this text element!", elements=elements).send()
4456
import chainlit as cl
4557

4658
text_content = "Hello, this is a text element."
47-
cl.Text(name="simple_text", text=text_content, display="inline").send()
59+
await cl.Text(name="simple_text", content=text_content, display="inline").send()
4860
```
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
title: "Callback Handlers"
3+
---
4+
5+
When running your own LangChain agent, typically using [langchain_run](/api-reference/langchain/langchain-run), it is essential to provide the appropriate callback handler. This ensures seamless communication between the Chainlit UI and your agent.
6+
7+
There are two ways to pass the callback handler:
8+
9+
1. Pass the callback handler during runtime. This will apply the handler to all calls made by your agent.
10+
2. Pass the callback handler to individual components, such as an `llm`, allowing you to control what information is returned to the UI.
11+
12+
### Asynchronous Callback Handler
13+
14+
The following code example demonstrates how to pass an asynchronous callback handler.
15+
16+
```python
17+
@cl.langchain_run
18+
async def run(agent, input_str):
19+
res = await agent.acall(input_str, callbacks=[cl.AsyncChainlitCallbackHandler()])
20+
await cl.Message(content=res["text"]).send()
21+
```
22+
23+
Notice the `acall` here, that could also be `arun` or any other async function. Since we are calling the asynchronous implementation of the agent, we need to use the asynchronous callback handler.
24+
25+
### Synchronous Callback Handler
26+
27+
Alternatively, you can pass a synchronous callback handler, as shown in the example below:
28+
29+
```python
30+
@cl.langchain_run
31+
async def run(agent, input_str):
32+
res = await cl.make_async(agent)(input_str, callbacks=[cl.ChainlitCallbackHandler()])
33+
await cl.Message(content=res["text"]).send()
34+
```
35+
36+
Since we are calling a long running synchronous function, we need to wrap it in `cl.make_async` to make it asynchronous and not block the event loop.
37+
The function will still run synchronously in its own thread, hence we use the synchronous callback handler.
38+
39+
Choose the appropriate callback handler based on your specific requirements, ensuring seamless interaction between your LangChain agent and the Chainlit UI.

api-reference/langchain/langchain-factory.mdx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
---
22
title: "langchain_factory"
33
---
4-
Plug and play decorator for the LangChain library.
4+
5+
Plug and play decorator for the LangChain library.
56

67
The decorated function should instantiate a new LangChain instance (Chain, Agent...). One instance per user session is created and cached. The per user instance is called every time a new message is received.
78

8-
<RequestExample>
9+
### Parameters
10+
11+
<ParamField path="use_async" type="bool">
12+
Whether to use the async implementation of the agent or not.
13+
</ParamField>
14+
15+
### Usage
16+
917
```python Code Example
1018
from langchain import OpenAI, LLMMathChain
1119
from chainlit import langchain_factory
1220

13-
@langchain_factory
21+
@langchain_factory(use_async=True)
1422
def load():
1523
llm = OpenAI(temperature=0)
1624
llm_math = LLMMathChain.from_llm(llm=llm)
1725

1826
return llm_math
1927
```
20-
</RequestExample>

0 commit comments

Comments
 (0)