I’m testing out Streamlit’s chatbot interface. I wanted to incorporate the Streamlit spinner. This is the code block that gets a pre-generated chart from a getChart function. The charts are randomly selected in the function.
# Accept user input
if prompt := st.chat_input("Enter your question here"):
# Add user message to chat history
st.session_state.messages[dataset.id].append({"role": "user", "content": prompt})
# Display user message in chat message container
with st.chat_message("user"):
st.markdown(prompt)
# Display assistant response in chat message container
with st.chat_message("assistant"), st.spinner("Answering your question..."):
data = getChart()
st.write(data)
# Add assistant response to chat history
st.session_state.messages[dataset.id].append({"role": "assistant", "content": data})
When I enter in a second prompt, I get a weird effect when the second image is loading in. It looks like this:
The faded element is what we call “stale.” Streamlit removes stale elements when it knows they won’t be re-rendered. Streamilt keeps track of elements by the order they appear on the page.
Consider this very simplified example. If one script run renders:
A title
A header
A chart
A button
And the next script run renders:
A title
A chart
A button
Streamlit will briefly have two charts at step 2 of the rerun (when it replaces the header with the new chart). Then, when the button renders, it replaces the chart from the previous run. Finally when the script run ends, the fourth element (the button from the first run) gets removed because Streamlit knows it’s the end and there are no more elements.
In your case, the spinner is replaced by the chart on the rerun and Streamlit won’t know to remove the stale chart until it “gets to the end.”
You can fix this by using empty. Something like this:
with st.chat_message("agent"), st.empty():
with st.spinner("Getting chart..."):
data = getChart()
st.write(data)
Here’s a toy example to compare the two. If you need the message from the assistant to have more than one Streamlit element, you can insert a container after the empty so that the container gets swapped out instead of the single chart element.
import streamlit as st
import time
import random
if "history" not in st.session_state:
st.session_state.history = []
add = st.button("Add")
def getChart():
time.sleep(5)
return random.choice(range(10))
for message in st.session_state.history:
with st.chat_message(message["role"]):
st.write(message["content"])
if add:
with st.chat_message("assistant"), st.empty():
with st.spinner("Getting chart..."):
data = getChart()
st.write(data)
st.session_state.history.append({"role":"assistant", "content":data})
# if add:
# with st.chat_message("assistant"), st.spinner("Getting chart..."):
# data = getChart()
# st.write(data)
# st.session_state.history.append({"role":"assistant", "content":data})
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.