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

Streamlit聊天应用Spinner不显示,任务完成后才更新UI

Streamlit聊天应用Spinner不显示问题修复

问题原因

  1. st.rerun()时机错误:原代码在st.spinner块内直接调用st.rerun(),导致Spinner还未完成前端渲染就触发页面重载,用户看不到加载状态。
  2. UI批量更新机制:Streamlit会在脚本执行完毕或遇到特定交互时才批量更新UI,阻塞式的time.sleep()会让整个脚本暂停,直到休眠结束才一次性渲染所有UI变化,包括Spinner和新消息,因此用户看不到中间的加载动画。

修复方案

调整代码流程,确保Spinner先渲染完成再执行阻塞操作,同时避免不必要的提前页面重载:

修改后的主应用代码

import streamlit as st
import time

from sensei.ui import text, utils

# 处理用户输入
if user_response := st.chat_input(placeholder="Your response..."):
    st.session_state.messages.append({"name": "user", "avatar": "user", "content": user_response})

# 初始化聊天会话
if "messages" not in st.session_state:
    st.session_state["messages"] = [
        {"name": "Sensei", "avatar": "🥷", "content": message, "translated": True, "printed": False}
        for message in text.ONBOARDING_START_MESSAGES[st.session_state.source_language]
    ]

# 添加处理状态标记,防止重复执行响应生成逻辑
if "processing_response" not in st.session_state:
    st.session_state.processing_response = False

# 渲染历史聊天消息
for message in st.session_state.messages:
    with st.chat_message(name=message["name"], avatar=message["avatar"]):
        if message["name"] == "Sensei" and not message["printed"]:
            utils.stream_message(message=message["content"])
            message["printed"] = True
        else:
            st.markdown(body=message["content"])

# 生成Sensei的响应
if st.session_state.messages[-1]["name"] == "user" and not st.session_state.processing_response:
    st.session_state.processing_response = True
    with st.spinner("Thinking..."):
        # 模拟LLM响应生成
        sensei_response = utils.temp_get_response()
        # 添加响应到会话
        st.session_state.messages.append(
            {"name": "Sensei", "avatar": "🥷", "content": sensei_response, "translated": True, "printed": False}
        )
    st.session_state.processing_response = False
    # 刷新页面显示新消息
    st.rerun()

关键修改点

  • 移除重复的st.chat_input,避免组件冲突。
  • 添加processing_response状态标记,防止Streamlit脚本重复执行响应生成逻辑(因为Streamlit会多次重跑脚本)。
  • 将st.rerun()移至st.spinner块外部,确保Spinner在休眠期间正常显示,完成响应生成后再触发页面刷新。
  • 调整代码顺序,让用户输入处理、会话初始化、消息渲染、响应生成的流程更清晰。

可选优化:使用st.status增强加载体验

如果需要更灵活的状态提示,可以替换st.spinner为st.status,支持状态更新:

if st.session_state.messages[-1]["name"] == "user" and not st.session_state.processing_response:
    st.session_state.processing_response = True
    with st.status("Thinking...", expanded=True) as status:
        sensei_response = utils.temp_get_response()
        status.update(label="Response ready!", state="complete", expanded=False)
    st.session_state.messages.append(
        {"name": "Sensei", "avatar": "🥷", "content": sensei_response, "translated": True, "printed": False}
    )
    st.session_state.processing_response = False
    st.rerun()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 08:00:35