You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Streamlit应用:文件夹按钮加载数据后聊天窗口消失问题

问题:Streamlit聊天机器人文件夹加载后聊天窗口消失

问题描述

开发基于文件构建的Streamlit聊天机器人应用,支持两种文件上传方式:拖拽上传框与侧边栏的“Use Data from folder”按钮。拖拽上传功能正常,但使用文件夹按钮加载数据后,聊天窗口仅首次显示,在聊天框输入问题并点击发送后,聊天窗口会莫名消失。

核心原因

  1. Streamlit按钮状态特性:按钮use_example_file仅在点击瞬间返回True,页面重新渲染(如发送消息触发重跑)时会自动变回False,导致handle_upload函数重新执行时进入拖拽上传分支,uploaded_file变为None,聊天窗口的逻辑分支(if uploaded_file:)不再执行,窗口消失。
  2. 文件对象未持久化:通过open("example.csv", "rb")创建的文件对象未存入会话状态,页面重跑时无法复用,按钮状态重置后该分支不会再被触发。

解决方案

1. 用会话状态持久化示例文件状态

修改主应用中的按钮逻辑,将按钮状态和加载的文件对象存入st.session_state,确保页面重跑时状态不丢失:

# 初始化会话状态
if "use_example_file" not in st.session_state:
    st.session_state["use_example_file"] = False
if "example_uploaded_file" not in st.session_state:
    st.session_state["example_uploaded_file"] = None

# 按钮点击时切换状态并加载/释放文件
if st.sidebar.button("Use Data from folder"):
    st.session_state["use_example_file"] = not st.session_state["use_example_file"]
    if st.session_state["use_example_file"]:
        st.session_state["example_uploaded_file"] = open("example.csv", "rb")
    else:
        # 关闭文件避免资源占用
        if st.session_state["example_uploaded_file"]:
            st.session_state["example_uploaded_file"].close()
        st.session_state["example_uploaded_file"] = None

# 确定最终的uploaded_file
if st.session_state["use_example_file"]:
    uploaded_file = st.session_state["example_uploaded_file"]
else:
    uploaded_file = utils.handle_upload(["pdf", "txt", "csv"])

2. 调整handle_upload函数

移除原函数中对use_example_file的处理,让它专注处理拖拽上传场景:

@staticmethod
def handle_upload(file_types):
    """
    Handles and display uploaded_file
    :param file_types: List of accepted file types, e.g., ["csv", "pdf", "txt"]
    """
    uploaded_file = st.sidebar.file_uploader("upload", type=file_types, label_visibility="collapsed")

    if uploaded_file is not None:
        def show_csv_file(uploaded_file):
            file_container = st.expander("Your CSV file :")
            uploaded_file.seek(0)
            shows = pd.read_csv(uploaded_file)
            file_container.write(shows)

        def show_pdf_file(uploaded_file):
            file_container = st.expander("Your PDF file :")
            with pdfplumber.open(uploaded_file) as pdf:
                pdf_text = ""
                for page in pdf.pages:
                    pdf_text += page.extract_text() + "\n\n"
            file_container.write(pdf_text)
        
        def show_txt_file(uploaded_file):
            file_container = st.expander("Your TXT file:")
            uploaded_file.seek(0)
            content = uploaded_file.read().decode("utf-8")
            file_container.write(content)
        
        def get_file_extension(uploaded_file):
            return os.path.splitext(uploaded_file.name)[1].lower()
        
        file_extension = get_file_extension(uploaded_file.name)

        if file_extension == ".csv":
            show_csv_file(uploaded_file)
        elif file_extension == ".pdf": 
            show_pdf_file(uploaded_file)
        elif file_extension == ".txt": 
            show_txt_file(uploaded_file)

    else:
        st.session_state["reset_chat"] = True

    return uploaded_file

3. 重置文件指针确保复用

示例文件对象在页面重跑时可能处于文件末尾,使用前需重置指针,可在setup_chatbot函数或文件处理逻辑开头添加:

if uploaded_file:
    uploaded_file.seek(0)
    # 后续文件处理逻辑

关键逻辑说明

Streamlit每次交互都会触发整个脚本重新执行,所有局部变量都会重置,只有st.session_state中的数据会保留。通过将示例文件的状态和文件对象存入会话状态,能确保发送消息触发页面重跑时,uploaded_file不会变为None,聊天窗口的逻辑分支能持续执行。

内容的提问来源于stack exchange,提问作者illuminato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 03:12:00