告别Flask和Django!用Streamlit快速给你的ChatGLM3-6B做个Web聊天界面
用Streamlit为ChatGLM3-6B打造极简Web聊天界面的实战指南
当你在本地成功部署了ChatGLM3-6B这样的大语言模型后,下一步自然是想给它配上一个美观实用的Web界面。传统方案如Flask或Django虽然功能强大,但对于只想快速展示模型能力的开发者来说,学习曲线陡峭且开发效率低下。这就是为什么Streamlit正在成为LLM原型开发的首选工具——它让你用纯Python代码就能构建出功能完整的Web应用,无需任何前端经验。
1. 为什么Streamlit是LLM演示的理想选择
在机器学习领域,快速验证想法比构建完美产品更重要。Streamlit正是为这一需求而生,它解决了传统Web框架在LLM演示中的几个核心痛点:
- 零前端知识要求:所有界面元素通过Python函数调用生成
- 实时交互设计:内置状态管理,轻松处理聊天会话
- 流式输出支持:原生API完美适配LLM的token-by-token生成特性
- 极简部署:一行命令即可分享你的应用
# 比较三种框架的启动代码量
flask_startup = """
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return render_template('chat.html')
if __name__ == '__main__':
app.run()
"""
streamlit_startup = """
import streamlit as st
st.title('我的LLM聊天室')
"""
提示:Streamlit的另一个优势是丰富的社区组件,如
st-chat专门为对话场景优化,比通用组件更符合LLM交互需求
2. 环境准备与基础配置
开始前确保你的开发环境满足以下条件:
- Python 3.8-3.12(与ChatGLM3-6B要求一致)
- 已部署好的本地LLM服务(如通过OpenAI格式API暴露的ChatGLM3-6B)
- 干净的Python虚拟环境
安装核心依赖:
pip install streamlit streamlit-chat requests
验证安装:
streamlit hello
这个测试应用会展示Streamlit的所有核心功能,包括图表、交互组件和布局选项。关闭示例应用后,我们开始构建真正的LLM聊天界面。
3. 构建基础聊天框架
Streamlit采用声明式编程模型,界面布局与业务逻辑自然融合。创建一个新文件chatglm_demo.py:
import streamlit as st
from streamlit_chat import message # 专门为聊天优化的组件
st.set_page_config(page_title="ChatGLM3-6B演示", layout="wide")
st.title(" ChatGLM3-6B智能助手")
# 初始化对话历史
if "history" not in st.session_state:
st.session_state.history = []
st.session_state.history.append(("assistant", "您好!我是ChatGLM3-6B,有什么可以帮您?"))
# 渲染历史消息
for role, text in st.session_state.history:
message(text, is_user=(role == "user"), key=f"{role}_{len(text)}")
# 用户输入区域
user_input = st.text_input("请输入您的问题...", key="user_input")
此时运行streamlit run chatglm_demo.py,你会看到一个带有初始问候语和输入框的基础界面。但这还不能真正与LLM交互,接下来我们添加API集成。
4. 集成ChatGLM3-6B的API调用
假设你的本地模型服务运行在http://localhost:8000/v1/chat/completions,使用以下代码实现完整对话流程:
import requests
def query_llm(prompt, history):
"""调用本地LLM API"""
headers = {"Content-Type": "application/json"}
messages = [{"role": role, "content": content} for role, content in history]
messages.append({"role": "user", "content": prompt})
payload = {
"model": "chatglm3-6b",
"messages": messages,
"temperature": 0.7,
"stream": True # 启用流式输出
}
response = requests.post(
"http://localhost:8000/v1/chat/completions",
headers=headers,
json=payload,
stream=True
)
return response
if user_input:
# 添加用户消息到历史
st.session_state.history.append(("user", user_input))
# 清空输入框
st.session_state.user_input = ""
# 调用LLM并处理流式响应
with st.spinner("思考中..."):
response = query_llm(user_input, st.session_state.history)
# 创建占位符用于流式输出
response_placeholder = st.empty()
full_response = ""
for chunk in response.iter_lines():
if chunk:
decoded_chunk = chunk.decode("utf-8")
if decoded_chunk.startswith("data:"):
try:
data = json.loads(decoded_chunk[5:])
token = data["choices"][0]["delta"].get("content", "")
full_response += token
response_placeholder.markdown(full_response + "▌")
except:
pass
# 最终渲染完整响应
response_placeholder.markdown(full_response)
st.session_state.history.append(("assistant", full_response))
这段代码实现了几个关键功能:
- 通过
stream=True参数启用流式响应 - 使用
st.spinner显示等待状态 - 利用
st.empty()创建动态更新的响应区域 - 实时解析SSE(Server-Sent Events)格式的流数据
5. 高级功能扩展
基础聊天功能实现后,可以考虑添加这些增强体验的功能:
5.1 对话记忆管理
# 添加在侧边栏的记忆控制
with st.sidebar:
if st.button("清空对话历史"):
st.session_state.history = [("assistant", "对话已重置,有什么新问题吗?")]
# 记忆长度控制
memory_length = st.slider("保留的对话轮数", 1, 20, 10)
if len(st.session_state.history) > memory_length * 2:
st.session_state.history = st.session_state.history[-memory_length * 2:]
5.2 参数实时调整
# 模型参数控制
temperature = st.sidebar.slider("Temperature", 0.1, 1.0, 0.7, 0.1)
max_tokens = st.sidebar.number_input("Max Tokens", 50, 2000, 500)
# 修改query_llm函数中的payload
payload = {
# ...其他参数...
"temperature": temperature,
"max_tokens": max_tokens
}
5.3 多模态支持
如果模型支持图片理解,可以扩展输入方式:
uploaded_file = st.file_uploader("上传图片", type=["png", "jpg"])
if uploaded_file:
bytes_data = uploaded_file.getvalue()
st.image(bytes_data, caption="上传的图片", width=300)
# 将图片转为base64编码并加入prompt
prompt += f"\n[图片]{base64.b64encode(bytes_data).decode()}"
6. 性能优化与部署建议
当你的演示应用准备分享时,考虑这些优化措施:
性能优化表
| 优化方向 | 具体措施 | 预期效果 |
|---|---|---|
| 响应速度 | 使用st.cache_data缓存模型响应 |
减少重复计算 |
| 内存占用 | 限制历史对话长度 | 避免内存泄漏 |
| 并发处理 | 部署时增加worker数量 | 支持多用户 |
| 网络延迟 | 启用HTTP/2 | 提升流式响应速度 |
部署到生产环境的最简方案:
# 使用nohup后台运行
nohup streamlit run chatglm_demo.py --server.port 8501 &
# 或用更专业的进程管理
pip install gunicorn
gunicorn -w 4 -k uvicorn.workers.UvicornWorker chatglm_demo:app
对于需要公网访问的场景,可以考虑这些方案:
- 内网穿透工具:如frp/ngrok
- 云服务器部署:AWS Lightsail等轻量级方案
- 容器化打包:Docker镜像便于迁移
# 示例Dockerfile
FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8501
CMD ["streamlit", "run", "chatglm_demo.py"]
在实际项目中,我发现Streamlit的session_state在处理复杂状态时可能会遇到序列化问题。一个实用的技巧是使用st.rerun()强制刷新页面状态,或者将大对象存储在外部缓存如Redis中。
更多推荐



所有评论(0)