The ChatFeed
is a mid-level layout, that lets you manage a list of ChatMessage
items.
This layout provides backend methods to:
Send (append) messages to the chat log.
Stream tokens to the latest
ChatMessage
in the chat log.Execute callbacks when a user sends a message.
Undo a number of sent
ChatMessage
objects.Clear the chat log of all
ChatMessage
objects.
See ChatInterface
for a high-level, easy to use, ChatGPT like interface.
Check out the panel-chat-examples docs to see applicable examples related to LangChain, OpenAI, Mistral, Llama, etc. If you have an example to demo, we'd love to add it to the panel-chat-examples gallery!
Parameters:
Core
objects
(List[ChatMessage]
): The messages added to the chat feed.renderers
(List[Callable]): A callable or list of callables that accept the value and return a Panel object to render the value. If a list is provided, will attempt to use the first renderer that does not raise an exception. If None, will attempt to infer the renderer from the value.callback
(callable): Callback to execute when a user sends a message or whenrespond
is called. The signature must include the previous message valuecontents
, the previoususer
name, and the componentinstance
.
Styling
card_params
(Dict): Parameters to pass to Card, such asheader
,header_background
,header_color
, etc.message_params
(Dict): Parameters to pass to each ChatMessage, such asreaction_icons
,timestamp_format
,show_avatar
,show_user
, andshow_timestamp
Params passed that are not ChatFeed params will be forwarded intomessage_params
.
Other
header
(Any): The header of the chat feed; commonly used for the title. Can be a string, pane, or widget.callback_user
(str): The default user name to use for the message provided by the callback.callback_avatar
(str, BytesIO, bytes, ImageBase): The default avatar to use for the entry provided by the callback. Takes precedence overChatMessage.default_avatars
if set; else, if None, defaults to the avatar set inChatMessage.default_avatars
if matching key exists. Otherwise defaults to the first character of thecallback_user
.callback_exception
(str, Callable): How to handle exceptions raised by the callback. If "raise", the exception will be raised. If "summary", a summary will be sent to the chat feed. If "verbose" or "traceback", the full traceback will be sent to the chat feed. If "ignore", the exception will be ignored. If a callable is provided, the signature must contain theexception
andinstance
arguments and it will be called with the exception.edit_callback
(callable): Callback to execute when a user edits a message. The signature must include the previous message valuecontents
, the previoususer
name, and the componentinstance
.help_text
(str): If provided, initializes a chat message in the chat log using the provided help text as the message object andhelp
as the user. This is useful for providing instructions, and will not be included in theserialize
method by default.placeholder_text
(str): The text to display next to the placeholder icon.placeholder_params
(dict) Defaults to{"user": " ", "reaction_icons": {}, "show_copy_icon": False, "show_timestamp": False}
Params to pass to the placeholderChatMessage
, likereaction_icons
,timestamp_format
,show_avatar
,show_user
,show_timestamp
.placeholder_threshold
(float): Min duration in seconds of buffering before displaying the placeholder. If 0, the placeholder will be disabled. Defaults to 0.2.post_hook
(callable): A hook to execute after a new message is completely added, i.e. the generator is exhausted. Thestream
method will trigger this callback on every call. The signature must include themessage
andinstance
arguments.auto_scroll_limit
(int): Max pixel distance from the latest object in the Column to activate automatic scrolling upon update. Setting to 0 disables auto-scrolling.scroll_button_threshold
(int): Min pixel distance from the latest object in the Column to display the scroll button. Setting to 0 disables the scroll button.load_buffer
(int): The number of objects loaded on each side of the visible objects. When scrolled halfway into the buffer, the feed will automatically load additional objects while unloading objects on the opposite side.show_activity_dot
(bool): Whether to show an activity dot on the ChatMessage while streaming the callback response.view_latest
(bool): Whether to scroll to the latest object on init. If not enabled the view will be on the first object. Defaults to True.
Methods
Core
send
: Sends a value and creates a new message in the chat log. Ifrespond
isTrue
, additionally executes the callback, if provided.serialize
: Exports the chat log as a dict; primarily for use withtransformers
.stream
: Streams a token and updates the provided message, if provided. Otherwise creates a new message in the chat log, so be sure the returned message is passed back into the method, e.g.message = chat.stream(token, message=message)
. This method is primarily for outputs that are not generators--notably LangChain. For most cases, use the send method instead.
Other
clear
: Clears the chat log and returns the messages that were cleared.respond
: Executes the callback with the latest message in the chat log. Typically called after streaming is completed, i.e. after a for loop wherestream
is called multiple times. If not streaming, use therespond
keyword argument inside thesend
method instead.trigger_post_hook
: Triggers the post hook with the latest message in the chat log. Typically called after streaming is completed, i.e. after a for loop wherestream
is called multiple times. If not streaming, use thetrigger_post_hook
keyword argument inside thesend
method instead.stop
: Cancels the current callback task if possible.scroll_to(index: int)
: Column will scroll to the object at the specified index.undo
: Removes the lastcount
of messages from the chat log and returns them. Defaultcount
is 1.
Basics
ChatFeed
can be initialized without any arguments.
You can send chat messages with the send
method.
The send
method returns a ChatEntry
, which can display any object that Panel can display. You can interact with chat messages like any other Panel component. You can find examples in the ChatEntry
Reference Notebook.
Besides messages of str
type, the send
method can also accept dict
s containing the key value
and ChatEntry
objects.
avatar
can also accept emojis, paths/URLs to images, and/or file-like objects.
Note if you provide both the user/avatar in the dict
and keyword argument, the keyword argument takes precedence.
:::{note} Code Highlighting To enable code highlighting in code blocks, pip install pygments
:::
Callbacks
A callback
can be attached for a much more interesting ChatFeed
.
The signature must include the latest available message value contents
.
In addition to contents
, the signature can also include the latest available user
name and the chat instance
.
However, not all three arguments need to be in the signature.
If there's only one, it will be
contents
.If there's two, it will be
contents
anduser
.If there's three, it will be
contents
,user
, andinstance
.
Update callback_user
to change the default name and callback_avatar
to update the default avatar of the responder.
The specified callback
can also return a dict
and ChatEntry
object, which must contain a value
key, and optionally a user
and a avatar
key, that overrides the default callback_user
and callback_avatar
.
If you do not want the callback to be triggered alongside send
, set respond=False
.
You can surface exceptions by setting callback_exception
to "summary"
.
To see the entire traceback, you can set it to "verbose"
.
Alternatively, you can provide a callable that accepts the exception and the instance as arguments to handle different exception scenarios.
Async Callbacks
The ChatFeed
also support async callback
s.
In fact, we recommend using async callback
s whenever possible to keep your app fast and responsive, as long as there's nothing blocking the event loop in the function.
Do not mark the function as async if there's something blocking your event loop--if you do, the placeholder will not appear.
The easiest and most optimal way to stream output is through async generators.
If you're unfamiliar with this term, don't fret!
It's simply prefixing your function with async
and replacing return
with yield
.
You can also continuously replace the original message if you do not concatenate the characters.
This works extremely well with OpenAI's create
and acreate
functions--just be sure that stream
is set to True
!
It's also possible to manually trigger the callback with respond
. This could be useful to achieve a chain of responses from the initial message!
Edit Callbacks
An edit_callback
can be attached to the ChatFeed
to handle message edits.
The signature must include the latest available message value contents
, the index of the edited message, and the chat instance
.
Here, when the user edits the first message, the downstream message is updated to match the edited message.
Steps
Intermediate steps, like chain of thoughts, can be provided through a series of ChatStep
s.
These can easily be added using the .add_step
method:
By default this method will attempt to append the step to an existing message as long as the last message is a step and the user matches.
If the user does not match a new message will be created:
See ChatStep
for more details on how to use those components.
Prompt User
It is possible to temporarily pause the execution of code and prompt the user to answer a question, or fill out a form, using prompt_user
, which accepts any Panel component
and a follow-up callback
(with component
and instance
as args) to execute upon submission.
You can also set a predicate
to evaluate the component's state, e.g. widget has value. If provided, the submit button will be enabled when the predicate returns True
. The predicate
should accept the component as an argument.
You can also set a timeout
in seconds and timeout_message
to prevent submission after a certain time.
Lastly, use button_params
and timeout_button_params
to customize the appearance of the buttons and timeout button, respectively.
Serialize
The chat history can be serialized for use with the transformers
or openai
packages through either serialize
with format="transformers"
.
role_names
can be set to explicitly map the role to the ChatMessage's user name.
A default_role
can also be set to use if the user name is not found in role_names
.
If this is set to None, raises a ValueError if the user name is not found.
The messages can be filtered by using a custom filter_by
function.
help_text
is an easy way to provide instructions to the users about what the feed does.
By default, the serialize
method will exclude the user help
from its output. It can be changed by updating exclude_users
.
If the output is complex, you can pass a custom_serializer
to only keep the text part.
Here's the output without:
Here's the output with a custom_serializer
:
It can be fun to watch bots talking to each other. Beware of the token usage!
Stream
If a returned object is not a generator (notably LangChain output), it's still possible to stream the output with the stream
method.
Note, if you're working with generator
s, use yield
in your callback instead.
Be sure to check out the panel-chat-examples docs for more examples related to LangChain, OpenAI, Mistral, Llama, etc.
The stream
method is commonly used with for loops; here, we use time.sleep
, but if you're using async
, it's better to use asyncio.sleep
.
Customization
You can pass ChatEntry
params through message_params
.
Alternatively, directly pass those params to the ChatFeed constructor and it'll be forwarded into message_params
automatically.
It's possible to customize the appearance of the chat feed by setting the message_params
parameter.
Please visit ChatMessage
for a full list of customizable, target CSS classes (e.g. .avatar
, .name
, etc).
You can build your own custom chat interface too on top of ChatFeed
, but remember there's a pre-built ChatInterface
!
For an example on renderers
, see ChatInterface.
Also, if you haven't already, check out the panel-chat-examples docs for more examples related to LangChain, OpenAI, Mistral, Llama, etc.