Hello Streamlit Community!
I’m excited to share a new package I’ve been working on called streamlit-rich-message-history. This library makes it easy to create message objects that can contain many components of differing data types (dataframes, matplotlib figures, plotly figures, etc).
What it does
This package allows you to:
- Build chat UIs with different message types (user, assistant, error)
- Include multiple components within a single message (text, code, dataframes, etc.)
- Automatically detect content types
- Present content with optional titles and descriptions
- Organize complex content in expandable sections
These objects have render()
functions that can be called to render out the underlying matching streamlit component.
This was created mainly to make it easier for me when creating chat apps which allow the LLM to write and execute code. I am able to pass the result off when creating a message object, and it does the rest of the work of mapping the data to the proper streamlit component.
As an example, here is how I use it in a chat app that lets a user talk with a dataframe:
if user_input:
# Add user message to history
user_message = UserMessage(avatar=user_avatar, text=user_input)
st.session_state["message_history"].add_user_message(user_message)
# Display user message
with st.chat_message(name="user", avatar=user_avatar):
st.markdown(user_input)
# Process with assistant
assistant_message = AssistantMessage(avatar=bot_avatar)
with st.chat_message(name="assistant", avatar=bot_avatar) as message_container:
df = data_manager.df
async for result in df.ask.__aiter__(user_input, provider_type="ollama", model="gemma3:12b"):
if result.kind == ResultKind.CODE_BLOCK:
assistant_message.add_code(code=result.content, language="python", title="Here is the code I generated.")
elif result.kind == ResultKind.DESCRIPTION:
assistant_message.add(content=result.content, title="Here is an overview of the code.")
elif result.kind == ResultKind.RESULT:
assistant_message.add(content=result.content)
if (result.kind not in (ResultKind.START, ResultKind.END)):
# Render the component after adding it
assistant_message.components[-1].render()
st.session_state["message_history"].add_assistant_message(assistant_message)
Feel free to take a look!