Persisting Download Buttons Across Chatbot Conversations

Description: I’m developing a Streamlit-based chatbot that provides computed data to users. During a conversation, the chatbot allows users to run a function under the hood, after it finishes a download button is presented to let them download the squared numbers. However, when moving to the next conversation or after the user clicks on the button, it disappears on them. I want the previously generated download button to persist throughout the entire conversation/interaction with the chatbot.

Current Behavior:

  • Within a chatbot conversation, users can compute the squares of a given range of numbers.
  • The squared numbers are saved to a file.
  • I generate a unique key for each download button and save this key.
  • Not sure how to proceed from here

Problem:

  • Every time streamlet is rerun or the user clicks on it, the button disappears.

Goal:

  • When the user moves to a new chatbot conversation or clicks on the button, I want to display a the same download button, and at the same time, retain all previously generated download buttons.

Reproduceable Example

app.py

import streamlit as st
import utils # importing our utility function

def main():
st.title(“Square a List of Numbers”)

# User input for a range of numbers
start_num = st.number_input("Start number", value=1, format="%d")
end_num = st.number_input("End number", value=10, format="%d")

if st.button("Compute Squares and Save to File"):
    numbers = list(range(start_num, end_num+1))
    utils.compute_and_download_squares(numbers)

if name == “main”:
main()

utils.py

import os
import streamlit as st

def compute_and_download_squares(numbers):
# Compute squared numbers
squared_numbers = [num ** 2 for num in numbers]

# Save squared numbers to a file
filename = "squared_numbers.txt"
with open(filename, 'w') as f:
    for num in squared_numbers:
        f.write(f"{num}\n")

# Display download button or error message
if os.path.exists(filename):
    with open(filename, "r") as file:
        st.download_button(
            label="Download Squared Numbers",
            data=file,
            file_name="squared_numbers.txt",
            mime="text/plain"
        )
else:
    st.error("File not found!")

hi @Sharif_Amlani
In Streamlit, each time the app is rerun, the entire script is executed, and the state is reset. To persist the state across sessions, you can use a combination of Streamlit’s SessionState and st.session_state .

app.py

import streamlit as st
import utils  # importing our utility function

# Define a function to get or create session state
def get_session_state():
    if "button_keys" not in st.session_state:
        st.session_state.button_keys = []
    return st.session_state

def main():
    st.title("Square a List of Numbers")

    # User input for a range of numbers
    start_num = st.number_input("Start number", value=1, format="%d")
    end_num = st.number_input("End number", value=10, format="%d")

    if st.button("Compute Squares and Save to File"):
        numbers = list(range(start_num, end_num + 1))
        button_key = utils.compute_and_download_squares(numbers)
        get_session_state().button_keys.append(button_key)

    # Display all the download buttons
    for button_key in get_session_state().button_keys:
        st.session_state[button_key]()

if __name__ == "__main__":
    main()

utils.py

import os
import streamlit as st

def compute_and_download_squares(numbers):
    # Compute squared numbers
    squared_numbers = [num ** 2 for num in numbers]

    # Save squared numbers to a file
    filename = "squared_numbers.txt"
    with open(filename, 'w') as f:
        for num in squared_numbers:
            f.write(f"{num}\n")

    # Generate a unique key for the button
    button_key = f"download_button_{filename}"

    # Display download button or error message
    def download_button_callback():
        with open(filename, "r") as file:
            st.download_button(
                label="Download Squared Numbers",
                data=file,
                file_name="squared_numbers.txt",
                mime="text/plain"
            )

    st.session_state[button_key] = download_button_callback

    return button_key

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