x = st.empty()
messages = st.container(height=300)
if prompt := x.chat_input("Say something"):
x.empty()
x.chat_input("Say something", disabled=True)
time.sleep(2)
messages.chat_message("user").write(prompt)
messages.chat_message("assistant").write(f"Echo: {prompt}")
I’m trying to disable the chat_input when the bot is thinking. I’m trying to use x = st.empty() and x.empty(), but it gives me DuplicateWidgetID error.
Create a variable to set the chat_input()'s disabled parameter to true/false.
# Define a variable to enable/disable chat_input()
if 'is_chat_input_disabled' not in ss:
ss.is_chat_input_disabled = False
In the prompt, we will use that variable, to reenter the condition.
# If there is user message or chat_input() is disabled, we can enter the following block.
if prompt := st.chat_input("your message", disabled=ss.is_chat_input_disabled) or ss.is_chat_input_disabled:
# Print and save the user message if and only if the is_chat_input_disabled is false.
if not ss.is_chat_input_disabled:
ss.msg.append({"role": "user", "content": prompt})
with st.chat_message("user"):
ss.is_chat_input_disabled = True # disable the chat_input()
st.markdown(prompt)
# Rerun so that the chat_input() will be rendered disabled. This is our main goal. But we
# can still re-enter without user prompt because is_chat_input_disabled is now True.
st.rerun()
import random
import string
import time
import streamlit as st
from streamlit import session_state as ss
# Define a variable to enable/disable chat_input()
if 'is_chat_input_disabled' not in ss:
ss.is_chat_input_disabled = False
# Define a variable to save message history.
if 'msg' not in ss:
ss.msg = []
# Define a variable to store feedback object.
if 'fbdata' not in ss:
ss.fbdata = {'feedback_thumb': '👉', 'feedback_star': '☆', 'feedback_comment': ''}
def feedback_cb():
"""Processes feedback."""
ss.fbdata = {'feedback_thumb': ss.fbthuk, 'feedback_star': ss.fbstark, 'feedback_comment': ss.fbcomk}
# Save to message history
ss.msg.append({"role": "user", "content": ss.fbdata})
def generate_random_response(msg):
time.sleep(10)
letters = string.ascii_lowercase
return f'my response to {msg} is ' + ''.join(random.choice(letters) for _ in range(6))
# Show message history.
for message in ss.msg:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# If there is user message or chat_input() is disabled, we can enter thie following block.
if prompt := st.chat_input("your message", disabled=ss.is_chat_input_disabled) or ss.is_chat_input_disabled:
# Print and save the user message if and only if the is_chat_input_disabled is false.
if not ss.is_chat_input_disabled:
ss.msg.append({"role": "user", "content": prompt})
with st.chat_message("user"):
ss.is_chat_input_disabled = True # disable the chat_input()
st.markdown(prompt)
# Rerun so that the chat_input() will be rendered disabled. This is our main goal. But we
# can still re-enter without user prompt because is_chat_input_disabled is now True.
st.rerun()
# Statements below will be executed when chat_input() is disabled.
# 1. Get response.
with st.chat_message("assistant"):
response = generate_random_response(ss.msg[-1]['content'])
st.markdown(response)
ss.is_chat_input_disabled = False # reset
ss.msg.append({"role": "assistant", "content": response})
# 2. Get feedback.
with st.form('fb_form'):
st.radio('feedback thumb', options=['👉', '👍', '👎'], key='fbthuk', horizontal=True)
st.radio('feedback star', options=['☆', '⭐', '⭐⭐', '⭐⭐⭐', '⭐⭐⭐⭐', '⭐⭐⭐⭐⭐'], key='fbstark', horizontal=True)
st.text_input('feedback comment', key='fbcomk')
st.form_submit_button('Send', on_click=feedback_cb)
Thanks @ferduy for your response. I’ve used your code as reference to get it to reload. However, I’ve noticed that after several prompts and responses, each rerun call forces the page to go back and forth from top to bottom, which can be a little jarring. Do you have any thoughts on how to handle this problem?
When the elements change between reruns, Streamlit can lose its place. I suspect using the form outside of the chat message (and having it appear and disappear between reruns), may be causing some jumping. When I have a lot of changing elements on a page, I use containers to make sure the top-level view of the elements remains the same. (i.e. If the appearing and disappearing elements are in a persistent container, they will generally cause fewer issues.)
In this case, you could try to put the form inside the chat message container to possibly create more stability.
Here’s another example just using a feedback widget instead of a full form:
import streamlit as st
import time
if "messages" not in st.session_state:
st.session_state.messages = []
if "disabled" not in st.session_state:
st.session_state.disabled = False
def disable():
st.session_state.disabled = True
def save_rating(i):
st.session_state.messages[i]["feedback"] = st.session_state[f"feedback_{i}"]
for i, message in enumerate(st.session_state.messages):
with st.chat_message(message["role"]):
st.write(message["content"])
if message["role"] == "ai":
if "feedback" in message:
st.markdown(":star:"*(message["feedback"]+1))
else:
st.feedback("stars", key=f"feedback_{i}", on_change=save_rating, args=[i])
if prompt := st.chat_input("Type one word for demo", disabled=st.session_state.disabled, on_submit=disable):
with st.chat_message("user"):
st.write(prompt)
st.session_state.messages.append(
{
"role": "user",
"content": prompt
}
)
with st.chat_message("ai"):
time.sleep(2)
st.write(prompt)
st.session_state.messages.append(
{
"role": "ai",
"content": prompt
}
)
st.session_state.disabled = False
st.rerun()
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.