Passing input values to nested buttons w/ session states

Summary

I’m new to Streamlit (loving it so far!) and I’m having issues in passing values from one input button to the next. I had a look at various posts that suggest to use session states, but unfortunately I didn’t manage to make it work, yet. I was wondering if someone in the community could help me find the error in my approach

Steps to reproduce

Code snippet:

[...]



def main() -> None:
     
    st.set_page_config(page_title="talesGPT", page_icon=":heart:")
    st.subheader("Tell me a story")

    if "button1" not in st.session_state:
        st.session_state["button1"] = False        
    
    if "button2" not in st.session_state:
        st.session_state["button2"] = False

    if "button3" not in st.session_state:
        st.session_state["button3"] = False


    if st.button("Button1"):
        # toggle button1 session state  
        st.session_state["button1"] = not st.session_state["button1"]
        try:
            with st.spinner("Recording audio..."):
                # Trigger audio recording
                user_input = recognize_from_microphone(language2code(language))
                st.write(user_input)
    
        except Exception as e:
            st.exception(f"Exception: {e}")


    if st.session_state["button1"]:
        if st.checkbox("Button2"):
            print(f"user_input: {user_input}")
            # toggle button2 session state
            st.session_state["button2"] = not st.session_state["button2"]
            
            #story = generate_story(user_input, language, model_name, temperature, openai_api_kei)
            story = 'hello world'
            print(f"story: {story}")
            st.text(story)


    if st.session_state["button1"] and st.session_state["button2"]:
        if st.button("Button3"):
            # toggle button3 session state
            st.session_state["button3"] = not st.session_state["button3"]
            synthetise_speech(story, language, gender)


    if st.session_state["button3"]:
        st.write("End")


    # Print the session state to make it easier to see what's happening
    st.write(
        f"""
        ## Session state:
        {st.session_state["button1"]=}

        {st.session_state["button2"]=}

        {st.session_state["button3"]=}
        """
    )

if __name__ == '__main__':
    main()

Expected behavior:

The expected behavior is the following:

  1. when pressing button1, the user is asked to talk to the microphone, and the voice is recognised as user_input. This step works well
  2. when pressing button2, I’d like to use the user_input above as input, and pass it to a function that would call an LLM to generate a story. → The problem is that the system doesn’t recognise user_input and raises the error: “UnboundLocalError: cannot access local variable ‘user_input’ where it is not associated with a value”. If instead of a button, I use a checkbox, step 1 is also retriggered, when I press step 2.

Debug info

  • Streamlit version: latest
  • Python version: 3.11
  • OS version: Venture 13.1
  • Browser version: Chrome Version 113.0.5672.126

Links

When you press the second button, the script runs again, user_input is forgotten and not assigned again. Store it in session_state.

Thanks, I confirm this helps!

The code below still needs some clean up, but the basic functionality now works as intended. I’m pasting it here, in case it can be helpful to other people in the community

import os

import streamlit as st

from speech import recognize_from_microphone, synthetise_speech
from utils import generate_story, load_api_keys, language2code


language = 'Portuguese'
gender = 'male'
model_name = 'gpt-3.5-turbo'
temperature = 1

load_api_keys()
openai_api_kei = os.environ.get('OPENAI_API_KEY')


def main() -> None:
     
    st.set_page_config(page_title="talesGPT", page_icon=":heart:")
    st.subheader("Tell me a story")

    if "button1" not in st.session_state:
        st.session_state["button1"] = False        
    
    if "button2" not in st.session_state:
        st.session_state["button2"] = False

    if "button3" not in st.session_state:
        st.session_state["button3"] = False 

    if st.button("Button1"):
        # toggle button1 session state  
        st.session_state["button1"] = not st.session_state["button1"]
        try:
            with st.spinner("Recording audio..."):
                # Trigger audio recording
                user_input = recognize_from_microphone(language2code(language))
                st.session_state["user_input"] = user_input
                st.write(user_input)
    
        except Exception as e:
            st.exception(f"Exception: {e}")


    if st.session_state["button1"]:
        if st.button("Button2"):
            user_input = st.session_state["user_input"]
            print(f"user_input: {user_input}")
            # toggle button2 session state
            st.session_state["button2"] = not st.session_state["button2"]

            story = generate_story(user_input, language, model_name, temperature, openai_api_kei)
            st.session_state["story"] = story

            st.write(user_input)
            st.text(story)


    if st.session_state["button1"] and st.session_state["button2"]:
        if st.button("Button3"):
            # toggle button3 session state
            st.session_state["button3"] = not st.session_state["button3"]
            user_input = st.session_state["user_input"]
            story = st.session_state["story"]
            synthetise_speech(story, language, gender)


    if st.session_state["button3"]:
        st.write("End")


if __name__ == '__main__':
    main()

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