Using buttons in st.chat_input()

Summary

I am attempting to add feedback buttons to LLM generated output from a chatbot ‘assistant’. Depending on what button is pushed, values will be dictated and then saved as messages under session_state. These values will also be used to run an additional function (send_feedback) with an AP call. I am able to make the buttons appear at the bottom of the generated output, however, when I click on them, the conditional values are not being saved in the session_states, nor is the additional function being run.

Steps to reproduce

Code snippet:

import streamlit as st
from functions import generate_llm_response, send_feedback

# Store LLM generated responses
if "messages" not in st.session_state.keys():
    st.session_state.messages = [{"role": "assistant", "content": "How may I help you?", "correct_answer": None, "correct_doc": None}]

for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.write(message["content"])

if prompt := st.chat_input():
    st.session_state.messages.append({"role": "user", "content": prompt, correct_answer: None, correct_doc: None})
    with st.chat_message("user"):
        st.write(prompt)

if st.session_state.messages[-1]["role"] != "assistant":
    with st.chat_message("assistant"):
        with st.spinner("Thinking..."):
        correct_answer = None
        correct_doc = None
            response = generate_response(prompt) 
            st.write(response) 

        button_col1, button_col2, button_col3, _ = st.columns([1,1,1,6])

        if button_col1.button("A", key=f"{documents[0]}1", help="Correct answer"):
            correct_answer = True
            correct_doc = True
        if button_col2.button("B", key=f"{documents[0]}2", help="Wrong answer and wrong document"):
           correct_answer = False
           correct_doc = False
        if button_col3.button("C", key=f"{documents[0]}3", help="Wrong answer, but right document"):
           correct_answer = False
           correct_doc = True

        message = {"role": "assistant", "content": response, "correct_answer": correct_answer, "correct_doc": correct_doc}
        st.session_state.messages.append(message)

        if correct_answer is not None and correct_doc is not None:
            send_feedback(prompt, question, correct_answer, correct_doc)

Expected behavior:

When I click one of the three buttons, I expect the session_state info for correct_answer and correct_doc to be altered to either True or False. I also expect the send_feedback() function to run.

Actual behavior:

The correct_answer and correct_doc session state values are being saved as None. The send_feedback function does not run.

Any help would be greatly appreciated. Does this have something to do with how chat implementation in Streamlit works? It’s kind of driving me crazy seeing how this works easily when not suspended in st.chat_input().

I’ve tried moving where correct_answer and correct_doc are initialized. I’ve tried moving which with/if loops the send_feedback() function is nested in.

Thank you!

Hi @David_Kersey and welcome to the community.

This is one case where the button event is been overwritten when another event happens. You will need to implement a callback function to maintain your app stateful. I strongly recommend reading this article about the differences of these approaches using buttons.

Regards

2 Likes

Thank you Carlos, that did it!

I turned the adding message to session_state and send_feedback into functions and used the ‘on_click’ argument to run it similar to this:

st.button('Jane', on_click=change_name, args=['Jane Doe'])
st.button('John', on_click=change_name, args=['John Doe'])

Thank you again.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.