Streamlit feedback not getting saved in st.form!

I am trying to use streamlit feedback and save the user feedback to a log file but its not working properly in a st.form and i am always getting None in my feedback, any suggestions??

With st.form("main"):
     generate_answer()
   
    feedback = streamlit_feedback(
    feedback_type="thumbs",
    optional_text_label="[Optional] Please provide an explanation",
    align="flex-start")

   logging.info(f"feedback log -{feedback}")

Your code has errors.

Here is the correct one.

import streamlit as st
from streamlit_feedback import streamlit_feedback

with st.form("main", clear_on_submit=True):
    st.write('answer ...')
   
    feedback = streamlit_feedback(
        feedback_type="thumbs",
        optional_text_label="[Optional] Please provide an explanation",
        align="flex-start"
    )
    st.form_submit_button('save')

st.write(f"feedback log -{feedback}")

Thank you for the reply but my requirement entails for every generated result it should have a feedback saved but i guess a form cannot have two submit button?.

query = st.text_area("enter your query")
with st.form("main", clear_on_submit=True):
    st.form_submit_button('generate answer')
    generate_answer(query) ## which generates an answer as per query input

    feedback = streamlit_feedback(
        feedback_type="thumbs",
        optional_text_label="[Optional] Please provide an explanation",
        align="flex-start"
    )
    
     ..... 2nd submit/save button will throw error!
     st.write(f"feedback log -{feedback}")

Could you show what generate_answer() function is?

It’s a very long patch using genai models to generate answers.
In general like any app like chatgpt,

  1. I write a query in natural language.
  2. I click generate answer in a form taking query as an input
  3. The app will provide an answer (generated result).
  4. Now i want to take user feedback on the generated answer.

Add form for query, user presses the query button and see the response. Show the feedback and record feedback’s reply.

import streamlit as st
from streamlit import session_state as ss
from streamlit_feedback import streamlit_feedback


if 'qr' not in ss:
    ss.qr = None


def ai_response(query):
    ss.qr = "Hey, what's up?" 


with st.form("query_form_k", clear_on_submit=False):
    query = st.text_area("Enter your query")
    st.form_submit_button('Get response', on_click=ai_response, args=(query,))

with st.container(border=True):
    st.write('Ai Response:')

    if ss.qr is not None:
        st.write(ss.qr)

with st.container(border=True):
    st.write('Your feedback:')

    feedback = streamlit_feedback(
        feedback_type="thumbs",
        optional_text_label="[Optional] Please provide an explanation",
        align="flex-start"
    )

    if ss.qr is not None and feedback:
        st.write(feedback)

Thank you for the quick help!

One doubt: is your feedback also not getting cleared after submitting a new query?
Once a feedback is submitted, I don’t get an option to clear and submit new feedback for new ai reponse or a new query.
image

I make some revisions to the code. I added a button to restart the input/response/feedback session. There are also some comments in the code,

Sample Output

Code

import streamlit as st
from streamlit import session_state as ss
from streamlit_feedback import streamlit_feedback
import uuid


# The key of feedback is ss.fbk. Its value is ss.[ss.fbk]
# We do this to get a new feedback prompt.
# We use uuid to generate unique key converted to str.
if 'fbk' not in ss:
    ss.fbk = str(uuid.uuid4())

# Query response
if 'qr' not in ss:
    ss.qr = ''


def reset_cb():
    """Reset callback for feedback, etc.
    
    This can be used to save interactions.
    """
    ss.fbk = str(uuid.uuid4())  # use new key to display new feedback prompt
    ss.qt = ''  # reset query text
    ss.qr = ''  # reset query response


def ai_response():
    """Gets query text and use it to build a response.
    
    It assigns its response to the query response.
    """
    res = "Hey, what's up?"
    ss.qr = f"Your query is {ss.qt}. My response is: {res}" 


# Build a form to receive user query input.
with st.form("query_form_k", clear_on_submit=False):
    st.text_area("Enter your query", key='qt')
    st.form_submit_button('Get response', on_click=ai_response)

# Build a container to display ai response.
with st.container(border=True):
    st.write('Ai Response:')

    if ss.qr is not None:
        st.write(ss.qr)

# Manage the feedback.
with st.container(border=True):
    st.write('Your feedback:')

    streamlit_feedback(
        feedback_type="thumbs",
        optional_text_label="[Optional] Please provide an explanation",
        align="flex-start",
        key=ss.fbk
    )

    fb = ss[ss.fbk]
    if ss.qr != '' and fb:
        st.write(fb)

if st.button('Restart', on_click=reset_cb):
    st.rerun()

Thanks. I slightly modified this to reduce the number of buttons. On submitting ‘Get_response’ i run reset_cb. This works fine except 1 last bug.

  • on submitting the feedback, since the app reruns. The ai_response get’s cleared,
    Any solution to keep the content as is in the form on submitting the feedback? Since the ai_response function is expensive, i don’t want to rerun it on submitting feedback.
import streamlit as st
from streamlit import session_state as ss
from streamlit_feedback import streamlit_feedback
import uuid

if 'fbk' not in ss:
    ss.fbk = str(uuid.uuid4())

def reset_cb():
    """Reset callback for feedback, etc.
    
    This can be used to save interactions.
    """
    ss.fbk = str(uuid.uuid4())  # use new key to display new feedback prompt


def ai_response():
    """Gets query text and use it to build a response.
    
    It assigns its response to the query response.
    """
    res = "Hey, what's up?"
    ss.qr = f"My response is: {res}"
    st.write(ss.qr)


# Build a form to receive user query input.
with st.form("query_form_k", clear_on_submit=False):
    st.text_area("Enter your query", key='qt')
    check = st.form_submit_button('Get response', on_click=reset_cb)
    if check:
        st.write('Ai Response:')
        ai_response()

# Manage the feedback.
with st.container():
    st.write('Your feedback:')

    streamlit_feedback(
        feedback_type="thumbs",
        optional_text_label="[Optional] Please provide an explanation",
        align="flex-start",
        key=ss.fbk
    )

Let’s get back from the code I posted.

  1. Comment the start button code.
# if st.button('Restart', on_click=reset_cb):
#     st.rerun()
  1. Comment setting the query and response boxes to empty.
def reset_cb():
    """Reset callback for feedback, etc.
    
    This can be used to save interactions.
    """
    ss.fbk = str(uuid.uuid4())  # use new key to display new feedback prompt
    # ss.qt = ''  # reset query text
    # ss.qr = ''  # reset query response
  1. Call the reset_cb inside the ai_response
def ai_response():
    """Gets query text and use it to build a response.
    
    It assigns its response to the query response.
    """
    res = "Hey, what's up?"
    ss.qr = f"Your query is {ss.qt}. My response is: {res}" 
    reset_cb()  # Creates a new feedback prompt
  1. Refactor the code if necessary including updating the docstrings.

The Get response button has now two functions. To get ai response and to generate a new feedback prompt.

Hello @Himanshu_Gupta,

Here’s the revised that should help ensure your feedback gets captured correctly:

import streamlit as st
import logging

logging.basicConfig(level=logging.INFO)

with st.form("main"):
    generate_answer_placeholder = st.empty()  # Placeholder for where you want to generate the answer
    
    feedback = streamlit_feedback(
        feedback_type="thumbs",
        optional_text_label="[Optional] Please provide an explanation",
        align="flex-start"
    )
    
    submitted = st.form_submit_button("Submit Feedback")
    
    if submitted:
        # Log feedback only if the form has been submitted
        logging.info(f"Feedback log - {feedback}")
        st.write(f"Feedback received: {feedback}")  # Display feedback for confirmation
        
        # Replace this with the logic to save feedback to a log file
        # For example: save_feedback_to_log(feedback)

Hope this helps!

Kind Regards,
Sahir Maharaj
Data Scientist | AI Engineer

P.S. Lets connect on LinkedIn!

➤ Want me to build your solution? Lets chat about how I can assist!
➤ Join my Medium community of 30k readers! Sharing my knowledge about data science and AI
➤ Website: https://sahirmaharaj.com
➤ Email: sahir@sahirmaharaj.com
➤ 100+ FREE Power BI Themes: Download Now

2 Likes

Thanks @sahirmaharaj but this will not work. Generate answer needs a button, submit feedback has a separate button. 2 buttons will not work within the same form.