如何为streamlit_chat添加滚动并固定输入框位置
解决Streamlit Chatbot对话区域独立滚动问题
问题背景
使用ChatGPT 3.5和Streamlit开发聊天机器人时,输入框初始放在页面底部,但随着对话消息增多,输入框会被挤到页面下方,需要实现类似ChatGPT的效果:对话消息区域独立滚动,输入框固定在底部不随页面滚动。
方案1:无需修改st-chat源码,用Streamlit容器+自定义CSS实现
这种方法不需要改动第三方组件源码,直接通过Streamlit的容器布局和自定义CSS就能实现需求。
修改后的完整代码
import openai import streamlit as st from streamlit_chat import message openai.api_key='API_KEY' def generate_response(prompt): completion=openai.Completion.create( engine='text-davinci-003', prompt=prompt, max_tokens=1024, n=1, stop=None, temperature=0.6, ) message_content=completion.choices[0].text return message_content st.title("ChatGPT3.5 BOT") # 自定义CSS:固定输入框在底部,设置对话容器的滚动样式 st.markdown(""" <style> /* 固定输入框区域在页面底部 */ .stTextInput { position: fixed; bottom: 3rem; left: 50%; transform: translateX(-50%); width: 80%; } /* 给对话容器设置最大高度和滚动 */ .chat-container { max-height: calc(100vh - 15rem); overflow-y: auto; padding-bottom: 5rem; } </style> """, unsafe_allow_html=True) if 'generated' not in st.session_state: st.session_state['generated'] = [] if 'past' not in st.session_state: st.session_state['past'] = [] def inputchange(): output=generate_response(st.session_state.input) # 追加对话到会话状态 st.session_state['past'].append(st.session_state.input) st.session_state['generated'].append(output) # 清空输入框 st.session_state.input = "" # 创建对话容器 chat_container = st.container() with chat_container: st.markdown('<div class="chat-container">', unsafe_allow_html=True) # 遍历对话消息(倒序展示) if st.session_state['generated']: for i in range(len(st.session_state['generated']) - 1, -1, -1): message(st.session_state['past'][i], is_user=True, key=str(i) + '_user') message(st.session_state['generated'][i], key=str(i), avatar_style="adventurer", seed=123) st.markdown('</div>', unsafe_allow_html=True) # 输入框 user_input = st.text_input("Input Message: ", "", key="input", on_change=inputchange)
代码说明
- 自定义CSS:
- 给输入框添加
position: fixed固定在页面底部,通过transform: translateX(-50%)居中 - 给对话容器设置
max-height: calc(100vh - 15rem),确保容器高度不超过视口,超出部分自动滚动 - 对话容器添加
padding-bottom避免最后一条消息被输入框遮挡
- 给输入框添加
- 容器布局:用
st.container()包裹所有对话消息,并套上自定义的滚动容器类 - 输入框清空:在
inputchange函数末尾清空输入框,提升交互体验
方案2:修改st-chat组件源码实现
如果希望直接修改streamlit_chat的组件样式,让其自带滚动功能,可以修改组件的前端代码:
- 找到
stChat.tsx文件中包裹所有消息的外层容器div - 给该容器添加样式属性:
<div style={{ maxHeight: 'calc(100vh - 12rem)', overflowY: 'auto', paddingBottom: '4rem' }}> {/* 原有的Message循环渲染代码 */} </div> - 修改后重新安装本地修改的
streamlit_chat包,即可让组件本身支持滚动
注意事项
- 修改源码后需要重新构建前端并重新安装包,适合需要深度定制组件的场景
- 若后续组件更新,修改会被覆盖,需要重新适配
内容的提问来源于stack exchange,提问作者MAC
相关产品推荐
相关产品推荐

