Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 160 additions & 21 deletions api-reference/action.mdx
Original file line number Diff line number Diff line change
@@ -1,49 +1,188 @@
---
title: "Action"
title: Action
---

The `Action` class is designed to create and manage actions to be sent and displayed in the chatbot user interface. Actions consist of buttons that the user can interact with, and these interactions trigger specific functionalities within your app.
The `Action` class is designed to create and manage interactive buttons within the Chainlit user interface. These actions allow users to trigger specific functionalities in your application, and their interactions are handled by `@cl.action_callback` decorated functions.

## Attributes
## `cl.Action` Properties

<ParamField path="name" type="str">
Name of the action, this should match the action callback.
</ParamField>
The `cl.Action` class has the following properties:

<ParamField path="payload" type="Dict">
The payload associated with the action.
<ParamField path="id" type="str">
A unique string identifier for the action. This is automatically generated using `uuid.uuid4()` and should not be set manually.
</ParamField>

<ParamField path="icon" type="str" optional>
The lucide icon name for the action button. See https://lucide.dev/icons/.
<ParamField path="name" type="str">
A string that identifies the action. This name is crucial as it links the action to its corresponding `@cl.action_callback` function.
</ParamField>

<ParamField path="label" type="str" optional>
The label of the action. This is what the user will see. If no label and no icon is provided, the name is display as a fallback.
The text displayed on the action button in the UI. If no label is provided, the `name` will be used as a fallback.
</ParamField>

<ParamField path="payload" type="dict">
A dictionary containing parameters to be passed to the action's callback function when it is triggered. This property replaced the `value` field in version 2.0.0.
</ParamField>

<ParamField path="tooltip" type="str" optional>
The description of the action. This is what the user will see when they hover
the action.
A string that provides additional information when the user hovers over the action button.
</ParamField>

<ParamField path="icon" type="str" optional>
The name of a Lucid icon to be displayed alongside the action label. This field was added in version 2.0.0.
</ParamField>

<ParamField path="forId" type="str" optional>
An optional string used internally to associate an action with a specific message or element. This should not be set manually.
</ParamField>

## Usage

### Defining Actions and Callbacks

Actions are defined using the `cl.Action` class and can be attached to messages. The `name` property of the `Action` object corresponds to the name used in the `@cl.action_callback` decorator.

```python
import chainlit as cl

@cl.action_callback("action_button")
async def on_action(action):
await cl.Message(content=f"Executed {action.name}").send()
# Optionally remove the action button from the chatbot user interface
await action.remove()
@cl.action_callback("test action")
async def on_test_action(action: cl.Action):
await cl.Message(content=f"Executed {action.name} with payload: {action.payload['value']}!").send()

@cl.on_chat_start
async def start():
# Sending an action button within a chatbot message
actions = [
cl.Action(name="action_button", payload={"value": "example_value"}, label="Click me!")
cl.Action(id="test-action-1", name="test action", payload={"value": "test1"}, label="Test Action 1"),
cl.Action(id="test-action-2", name="test action", payload={"value": "test2"}, label="Test Action 2", tooltip="This is a tooltip", icon="Settings"),
]
await cl.Message("Hello, this is a test message with actions!", actions=actions).send()
```
In this example, clicking either "Test Action 1" or "Test Action 2" will trigger the `on_test_action` callback. The `action` object passed to the callback will contain the `payload` specific to the clicked button.

await cl.Message(content="Interact with this action button:", actions=actions).send()
### Asking the User for an Action

You can use `cl.AskActionMessage` to prompt the user to select an action, blocking further code execution until an action is chosen or a timeout occurs.

```python
import chainlit as cl

@cl.action_callback("first_action")
async def on_first_action(action: cl.Action):
await cl.Message(content=f"You chose: {action.label}").send()

@cl.action_callback("second_action")
async def on_second_action(action: cl.Action):
await cl.Message(content=f"You chose: {action.label}").send()

@cl.on_chat_start
async def start():
result = await cl.AskActionMessage(
content="Please, pick an action!",
actions=[
cl.Action(
id="first-action-id",
name="first_action",
payload={"value": "first-action"},
label="First action",
),
cl.Action(
id="second-action-id",
name="second_action",
payload={"value": "second-action"},
label="Second action",
),
],
).send()

if result is not None:
await cl.Message(f"Thanks for pressing: {result['payload']['value']}").send()
```
The `result` from `send()` will be an `AskActionResponse` dictionary containing the `name`, `payload`, `label`, `tooltip`, `forId`, and `id` of the selected action.

## Action Lifecycle and Removal

Actions have a lifecycle that includes creation, display, execution, and removal. You can programmatically remove actions from the UI.

### Removing Individual Actions

To remove an individual action, call the `remove()` method on an `Action` object within an `@cl.action_callback` function.

```python
import chainlit as cl

@cl.action_callback("removable action")
async def on_removable_action(action: cl.Action):
await cl.Message(content="Executed removable action!").send()
await action.remove() # This removes the specific action button from the UI

@cl.on_chat_start
async def start():
actions = [
cl.Action(id="removable-action-id", name="removable action", payload={"value": "remove_me"}, label="Remove Me")
]
await cl.Message("Click the button to remove it:", actions=actions).send()
```

### Removing All Actions from a Message

You can remove all actions associated with a specific message by calling the `remove_actions()` method on a `Message` object.

```python
import chainlit as cl

@cl.action_callback("all actions removed")
async def on_all_actions_removed(_: cl.Action):
await cl.Message(content="All actions have been removed!").send()
# Retrieve the message from user session (assuming it was stored)
message_with_actions = cl.user_session.get("message_with_actions")
if message_with_actions:
await message_with_actions.remove_actions() # Removes all action buttons from this message

@cl.on_chat_start
async def start():
actions = [
cl.Action(id="action-1", name="all actions removed", payload={"value": "action_1"}, label="Action 1"),
cl.Action(id="action-2", name="all actions removed", payload={"value": "action_2"}, label="Action 2")
]
message = cl.Message("Click any button to remove all actions:", actions=actions)
cl.user_session.set("message_with_actions", message) # Store message for later removal
await message.send()
```

### Multiple Actions with Same Callback

Multiple `cl.Action` instances can share the same `name` and thus trigger the same callback function. The `action` object passed to the callback contains the unique `id` and `payload` of the specific action that was triggered, allowing you to differentiate between them.

```python
import chainlit as cl

@cl.action_callback("shared_callback")
async def on_shared_callback(action: cl.Action):
await cl.Message(content=f"Action '{action.label}' (ID: {action.id}) was clicked with payload: {action.payload['value']}").send()
await action.remove()

@cl.on_chat_start
async def start():
actions = [
cl.Action(id="option-a", name="shared_callback", payload={"value": "option_a"}, label="Option A"),
cl.Action(id="option-b", name="shared_callback", payload={"value": "option_b"}, label="Option B"),
]
await cl.Message("Choose an option:", actions=actions).send()
```

## Global Actions

You can also define global actions that are always available to the user. These actions are typically displayed in the chat input area.

```python
import chainlit as cl

@cl.action_callback("global_action")
async def on_global_action(action: cl.Action):
await cl.Message(content=f"Executed global action: {action.label}").send()

@cl.on_chat_start
async def start():
# Sending a global action. It will appear in the chat input area.
cl.Action(id="global-action-id", name="global_action", payload={"value": "global_example"}, label="Global Action").send()
```
72 changes: 33 additions & 39 deletions api-reference/author-rename.mdx
Original file line number Diff line number Diff line change
@@ -1,70 +1,64 @@
---
title: "author_rename and Message author"
title: "Author Rename"
---

This documentation covers two methods for setting or renaming the author of a message to display more friendly author names in the UI: the `author_rename` decorator and the Message author specification at message creation.
In Chainlit, you can customize the author name displayed in the UI for messages. This is useful for replacing default or technical author names (like "LLMMathChain" or "Chatbot") with more user-friendly names (like "Albert Einstein" or "Assistant").

## Method 1: author_rename
There are two primary ways to control the author name:

Useful for renaming the author of a message dynamically during the message handling process.
1. **`@cl.author_rename` decorator**: A global way to dynamically rename authors for all messages.
2. **Directly on the `Message` object**: Set the author for a specific message when you create it.

## Parameters
## 1. @cl.author_rename Decorator

<ParamField path="orig_author" type="str" required>
The original author name.
</ParamField>
This decorator allows you to define a function that will be called for every message to determine the author's name. This is the recommended approach for consistent author renaming across your application.

## Returns
Your decorated function should accept the original author name as a string and return the new author name as a string. This decorated function is automatically registered in `config.code.author_rename`. The function can be synchronous or asynchronous.

<ResponseField name="author" type="str" required>
The renamed author
</ResponseField>
**Note:** While the `rename_author` function only receives the author name, you can access the current chat session context (e.g., user information, thread ID) by explicitly importing and using `chainlit.context.context` or `chainlit.user_session` within your function.

## Usage
### Usage

```python
from langchain import OpenAI, LLMMathChain
import chainlit as cl


# Synchronous example
@cl.author_rename
def rename_author(original_author: str):
rename_dict = {
"LLMMathChain": "Albert Einstein",
"Chatbot": "Assistant"
}
return rename_dict.get(original_author, original_author)

# Asynchronous example
@cl.author_rename
def rename(orig_author: str):
rename_dict = {"LLMMathChain": "Albert Einstein", "Chatbot": "Assistant"}
return rename_dict.get(orig_author, orig_author)
async def rename_author_async(original_author: str):
if original_author == "AI":
return "Assistant"
return original_author

# This renaming applies to all message types, including `cl.Message`, `cl.AskUserMessage`, `cl.AskFileMessage`, and `cl.AskActionMessage`.

@cl.on_message
async def main(message: cl.Message):
llm = OpenAI(temperature=0)
llm_math = LLMMathChain.from_llm(llm=llm)
res = await llm_math.acall(message.content, callbacks=[cl.AsyncLangchainCallbackHandler()])

await cl.Message(content="Hello").send()
# The author of this message will be renamed by the decorator
await cl.Message(content="Hello from the default author!").send()
```

## 2. Message Author Parameter

## Method 2: Message author

Allows for naming the author of a message at the moment of the message creation.
You can also specify the author for a single message directly by using the `author` parameter when creating a `cl.Message` instance. This will override any global renaming for that specific message.

### Usage

You can specify the author directly when creating a new message object:

```python
from langchain import OpenAI, LLMMathChain
import chainlit as cl

@cl.on_message
async def main(message: cl.Message):
llm = OpenAI(temperature=0)
llm_math = LLMMathChain.from_llm(llm=llm)
res = await llm_math.acall(message.content, callbacks=[cl.AsyncLangchainCallbackHandler()])

# Specify the author at message creation
response_message = cl.Message(content="Hello", author="NewChatBotName")
await response_message.send()
```



await cl.Message(
content="Hello from a specific author!",
author="CustomBot"
).send())
Loading