Streamlit 聊天界面滚动卡顿问题的终极解决方案

霞舞

霞舞

2026-08-03

940人浏览

原创

Streamlit 聊天界面滚动卡顿问题的终极解决方案

本文提供一种符合 streamlit 最佳实践的流式聊天实现方式,通过 st.chat_message + st.write_stream 替代手动 st.empty() 刷新,彻底解决 linux/windows 下滚动跳动、页面重置等渲染 glitch 问题。

本文提供一种符合 streamlit 最佳实践的流式聊天实现方式,通过 st.chat_message + st.write_stream 替代手动 st.empty() 刷新,彻底解决 linux/windows 下滚动跳动、页面重置等渲染 glitch 问题。

在构建 Streamlit 聊天应用时,频繁使用 st.empty() 配合 .write() 动态更新内容,是导致滚动异常(如页面突然跳回顶部、消息闪烁、滚动位置丢失)的根本原因。尤其在 Linux 系统上,浏览器渲染引擎(如 Chromium 的 GTK 后端)对 DOM 频繁重绘更敏感,加剧了这一问题。根本症结在于:每次 response_placeholder.write() 都会触发整个容器重渲染,破坏

的滚动锚点(scroll anchor),而 st.rerun() 的强制刷新更会中断当前视图状态。

✅ 正确做法是完全放弃手动占位符更新,转而采用 Streamlit 官方推荐的声明式流式输出模式:

CentOS Stream 9
CentOS Stream 9

CentOS Stream 9是基于RHEL 9技术路线的持续交付版本,适合需要贴近RHEL 9生态的软件开发、系统集成和测试环境。它相比传统CentOS Linux更靠近上游开发过程,用户可以更早看到RHEL 9后续小版本中的软件包变化。CentOS Stream 9仍是当前可用的官方版本线之一,适合对稳定性和新功能之间有平衡需求的团队使用。

下载

✅ 推荐方案:st.chat_message + st.write_stream

def general_chat(user_input):
    try:
        # 构建 prompt(注意:session_state 中 message 字段应统一为 'content')
        key_data = ["politics", "religion", "violence"]
        blocked_topics = "\n".join([f"Do not answer any questions about: {k}" for k in key_data])
        history_context = "\n".join(f"{msg['role']}: {msg['content']}" for msg in st.session_state.chat_history)

        prompt_input = f"""{history_context}
Instructions:
{blocked_topics}
User: {user_input}
Assistant:"""

        # ✅ 关键:在固定 chat_message 容器内流式写入,不触发重排
        with st.chat_message("assistant"):
            # 假设 generator 返回字符串流(每 chunk 为 str)
            response = st.write_stream(llm_stream_generator(prompt_input))

        st.session_state.chat_history.append({"role": "assistant", "content": response})

    except Exception as e:
        error_msg = "Server busy. Please try again later."
        st.session_state.chat_history.append({"role": "assistant", "content": error_msg})
        st.error(error_msg)

其中 llm_stream_generator 需返回一个生成器(yield 每个 token/chunk):

def llm_stream_generator(prompt):
    # 示例:适配 Ollama
    from ollama import chat
    stream = chat(model="llama3.2", messages=[{"role": "user", "content": prompt}], stream=True)
    for chunk in stream:
        yield chunk["message"]["content"]

    # 或适配其他 LLM(如 OpenAI、LiteLLM):
    # for chunk in client.chat.completions.create(..., stream=True):
    #     if chunk.choices[0].delta.content:
    #         yield chunk.choices[0].delta.content

✅ 页面渲染逻辑优化(无 rerun!)

def chat_page():
    st.title("ThinkBot")

    # 初始化历史记录(统一用 'content' 字段)
    if "chat_history" not in st.session_state:
        st.session_state.chat_history = [
            {"role": "assistant", "content": "How can I help you?"}
        ]

    # ✅ 声明式渲染全部历史 —— 不依赖 rerun,滚动自然保持
    for msg in st.session_state.chat_history:
        with st.chat_message(msg["role"]):
            st.markdown(msg["content"])

    # ✅ 输入即响应:用户发送后立即渲染 user 消息,再调用 general_chat
    if user_input := st.chat_input("Your message"):
        st.session_state.chat_history.append({"role": "user", "content": user_input})

        with st.chat_message("user"):
            st.markdown(user_input)

        general_chat(user_input)  # 内部完成 assistant 消息渲染

⚠️ 关键注意事项

  • 禁止 st.rerun():在聊天流中调用 st.rerun() 会清空当前 DOM 状态,导致滚动重置。Streamlit 的 st.chat_message 已内置滚动锚定(auto-scroll-to-bottom),无需手动干预。
  • 字段命名一致性:确保 st.session_state.chat_history 中所有消息均使用 "content" 键(而非 "message"),否则 history_context 拼接会出错。
  • CSS 覆盖慎用:.stAppScrollToBottomContainer { overflow-anchor: none !important; } 会禁用浏览器原生滚动锚定,反而加剧问题,应删除。
  • Linux 兼容性:该方案在 Wayland/X11 环境下均稳定,因底层依赖的是 Streamlit 渲染器的声明式 diff 更新,而非强制 DOM 操作。

✅ 总结

滚动 glitch 的本质是命令式 DOM 操作(st.empty().write() + st.rerun())与 Streamlit 声明式范式的冲突。采用 st.chat_message 容器 + st.write_stream 流式写入,既符合官方最佳实践,又利用了 Streamlit 内置的滚动智能管理(自动锚定最新消息),从根源上消除平台差异导致的渲染异常。重构后代码更简洁、可维护性更高,且支持任意 LLM 流式 API。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

stream 卡顿问题

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
pycharm怎么改成中文
pycharm怎么改成中文

PyCharm是一种Python IDE(Integrated Development Environment,集成开发环境),带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试、语法高亮、项目管理、代码跳转、智能提示、自动完成、单元测试、版本控制。此外,该IDE提供了一些高级功能,以用于支持Django框架下的专业Web开发。php中文网给大家带来了pycharm相关的教程以及文章,欢迎大家前来学习和阅读。

2023.07.25

1104

3

pycharm安装教程
pycharm安装教程

PyCharm是一款由JetBrains开发的Python集成开发环境(IDE),它提供了许多方便的功能和工具。本专题为大家带来pycharm安装教程,帮助大家解决问题。

2023.08.21

1954

4

如何解决pycharm找不到模块
如何解决pycharm找不到模块

解决pycharm找不到模块的方法:1、检查python解释器;2、安装缺失的模块;3、检查项目结构;4、检查系统路径;5、使用虚拟环境;6、重启PyCharm或电脑。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.12.04

691

5

如何安装pycharm
如何安装pycharm

安装pycharm的步骤:1、访问PyCharm官方网站下载最新版本的PyCharm;2、下载完成后,打开安装文件;3、安装完成后,打开PyCharm;4、在PyCharm的主界面中等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

351

5

python和pycharm的区别
python和pycharm的区别

Python和PyCharm是两个不同的概念,它们的区别如下:1、Python是一种编程语言,而PyCharm是一款Python集成开发环境;2、Python可以运行在各种不同的开发环境中,而PyCharm是专门为Python开发而设计的IDE等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

402

5

pycharm环境如何配置
pycharm环境如何配置

配置教程:1、下载并安装PyCharm;2、选择Python解释器;3、配置虚拟环境;4、配置代码风格;5、配置调试器;6、配置版本控制工具;7、配置插件;8、配置Python路径和环境变量;9、配置其他选项。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

337

5

pycharm解释器如何安装
pycharm解释器如何安装

安装步骤:1、打开PyCharm并打开你的项目;2、转到"File">“Settings”;3、在设置窗口中选择"Project">“Python Interpreter”;4、 点击“+” 符号添加新的解释器等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

278

5

pycharm并行运行是啥意思
pycharm并行运行是啥意思

pycharm中的并行运行功能允许并发运行代码块,提高开发和测试效率。通过启用该功能和设置进程数,可以:加快开发和调试过程;缩短测试套件的运行时间;充分利用多核处理器;简化复杂代码的结构和维护。想了解更多pycharm的相关内容,可以阅读本专题下面的文章。

2024.04.18

935

11

pycharm的作用
pycharm的作用

pycharm是一款专为python编程设计的ide,提供以下功能:智能代码补全,实时错误检测和快速修复;代码重构,版本控制集成,先进调试工具等等。想了解更多pycharm的相关内容,可以阅读本专题下面的文章。

2024.04.18

2410

10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
CentOS 官方文档
CentOS 官方文档

共0课时 | 0人学习

极客学院Java8新特性视频教程
极客学院Java8新特性视频教程

共17课时 | 4.1万人学习