Implement feedback option in Chat Interface and capture selected feedback response using streamlit_feedback library


I am trying to implement the feedback option for Chat response using streamlit_feedback library. I can get the โ€œthumbsโ€ or โ€œfacesโ€ bottom displayed. However, i canโ€™t capture the user selected feedback. Below is my sample code.

I am seeking two helps as below.

  1. How to capture the response of the feedback selected by the user ?
  2. Right now below code display the feedback only for last response, how to keep the feedback button for all past responses also? So that if user want to go back and give feedback for any of the past response, it should be possible.

Any suggestion here would be very helpful for me.

import streamlit as st
from streamlit_feedback import streamlit_feedback
from langchain.schema import (SystemMessage, HumanMessage, AIMessage)

if "messages" not in st.session_state:
    st.session_state.messages = [
    AIMessage(content= f"\n \n Welcome! How can I assist you today?")

if "response" not in st.session_state:
    st.session_state["response"] = ""
if "feedback_key" not in st.session_state:
    st.session_state.feedback_key = 0

def _submit_feedback(user_response, emoji=None):
    st.toast(f"Feedback submitted: {user_response}", icon=emoji)
    return user_response.update({"some metadata": 123})

# Display chat history
messages = st.session_state.get("messages", [])  
for message in messages:  
    if isinstance(message, AIMessage):  
        with st.chat_message("assistant", avatar='๐Ÿฆ™'):  
    elif isinstance(message, HumanMessage):  
        with st.chat_message("user",avatar= "๐Ÿฆ–"): 

if user_question :=st.chat_input("Input your question! ",):
    with st.chat_message("user",avatar= "๐Ÿฆ–"):  
    with st.chat_message("assistant",avatar='๐Ÿฆ™'):
        st.markdown("LLM Response")
        st.session_state.feedback_key += 1  # overwrite feedback component
        st.session_state.messages.append(AIMessage(content=f"LLM Response"))
        # with st.form('form'):
        score_mappings = { 
            "thumbs": {"๐Ÿ‘": 1, "๐Ÿ‘Ž": 0},
            "faces": {"๐Ÿ˜€": 1, "๐Ÿ™‚": 0.75, "๐Ÿ˜": 0.5, "๐Ÿ™": 0.25, "๐Ÿ˜ž": 0},
    feedback = streamlit_feedback(
                # optional_text_label="[Optional] Please provide an explanation",
    if feedback:
        st.write(":orange[Component output:]")

Above is tricky and is a major issue because of:

if user_question :=st.chat_input("Input your question! ",):

The streamlit_feedback() can rerun the code from top to bottom. Once it did, it could not enter again because of:

if user_question :=st.chat_input("Input your question! ",):

We can dissect that with:

user_question = st.chat_input("Input your question! ",)
if user_question:
    # blah blah

When users enter a question, streamlit reruns the code from top to bottom. It can reenter again in the line:
# blah blah

However streamlit_feedback() also triggers a rerun when users complete their feedback. And you know what, it cannot pass through the below blocker,

if user_question:
    # blah blah

because that user_question is now None. As a result, we were not able to execute below.

if feedback:
    st.write(":orange[Component output:]")

Try to search the word โ€œfeedbackโ€ and similar in the search button located at the top-right of the page. I did some analysis/solution of this behavior in other threads.