ChatGLM3-6B Streamlit定制教程:主题换肤+历史导出+快捷指令配置

1. 为什么需要一个“会打扮、记得住、懂 shortcuts”的本地对话助手?

你有没有试过这样的场景:
刚部署好 ChatGLM3-6B,打开 Streamlit 页面,界面灰扑扑的,像十年前的后台系统;
聊到一半想回看昨天写的代码提示词,却发现历史记录只存在内存里,刷新就清空;
每次问“帮我写个 Python 脚本读取 CSV”,都要打一整段——而其实你早就想好了固定模板。

这不是模型不够强,而是交互体验没跟上能力
ChatGLM3-6B-32k 本身已足够强大:32k 上下文、本地推理、RTX 4090D 上秒级响应。但真正让它从“能用”变成“爱用”,靠的是三层轻量却关键的定制——
主题换肤:让界面符合你的审美和工作环境(深色模式护眼、浅色模式适配文档写作)
历史导出:把每一次有价值的对话存成 Markdown 或 JSON,随时复用、归档、分享
快捷指令:输入 /code 自动补全编程模板,/doc 插入标准文档结构,/clear 一键重置上下文

本教程不讲模型训练、不调参数、不碰 CUDA 编译——只聚焦三件事:改界面、存记录、设快捷键。所有操作均基于原生 Streamlit 实现,无需额外前端框架,5 分钟内可完成全部定制。


2. 环境准备与最小可运行基础版

在动手定制前,先确认你已拥有一个稳定运行的 ChatGLM3-6B-32k + Streamlit 基础环境。以下命令适用于 Linux/macOS(Windows 用户请确保已安装 WSL2):

# 创建独立环境(推荐)
conda create -n glm3-streamlit python=3.10
conda activate glm3-streamlit

# 安装核心依赖(严格锁定版本,避坑关键!)
pip install torch==2.3.1+cu121 --index-url https://download.pytorch.org/whl/cu121
pip install transformers==4.40.2 accelerate sentencepiece tiktoken
pip install streamlit==1.33.0  # 避免 1.34+ 的 sidebar 渲染 bug

注意transformers==4.40.2 是本项目稳定基石。新版 4.41+AutoTokenizer.from_pretrained() 对 ChatGLM3 的 chatglm3 tokenizer 支持异常,会导致 ValueError: Unrecognized configuration class 报错。务必锁定此版本。

接着,新建 app.py,写入最简可用版本(仅含模型加载与基础聊天框):

# app.py —— 最小可运行骨架
import streamlit as st
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

@st.cache_resource
def load_model():
    tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm3-6b-32k", trust_remote_code=True)
    model = AutoModelForCausalLM.from_pretrained(
        "THUDM/chatglm3-6b-32k",
        trust_remote_code=True,
        device_map="auto",
        torch_dtype=torch.float16
    )
    return tokenizer, model

st.title(" ChatGLM3-6B 本地助手")
st.caption("基于 32k 上下文的私有化智能对话系统")

tokenizer, model = load_model()

if "messages" not in st.session_state:
    st.session_state.messages = []

for msg in st.session_state.messages:
    st.chat_message(msg["role"]).write(msg["content"])

if prompt := st.chat_input("请输入问题..."):
    st.session_state.messages.append({"role": "user", "content": prompt})
    st.chat_message("user").write(prompt)

    with st.chat_message("assistant"):
        message_placeholder = st.empty()
        full_response = ""
        for response in model.stream_chat(tokenizer, prompt, st.session_state.messages[:-1]):
            full_response += response[0] + " "
            message_placeholder.markdown(full_response + "▌")
        message_placeholder.markdown(full_response)
        st.session_state.messages.append({"role": "assistant", "content": full_response})

运行命令:

streamlit run app.py --server.port=8501

此时你将看到一个干净但朴素的对话界面——这就是我们定制的起点。


3. 主题换肤:三步实现深色/浅色自由切换

Streamlit 默认主题单调,且不支持运行时切换。但我们可以通过 st.set_page_config() + CSS 注入 + 会话状态控制,实现真正的“换肤自由”。

3.1 配置页面元信息与初始主题

app.py 开头添加:

# 在 import 之后、st.title 之前插入
st.set_page_config(
    page_title="ChatGLM3-6B 助手",
    page_icon="🧠",
    layout="centered",
    initial_sidebar_state="expanded"
)

# 初始化主题状态(默认深色)
if "theme" not in st.session_state:
    st.session_state.theme = "dark"

3.2 构建主题切换控件与 CSS 注入

st.title(...) 后添加侧边栏主题开关:

# 在 st.title(...) 下方插入
with st.sidebar:
    st.header(" 主题设置")
    theme_option = st.radio(
        "选择界面风格",
        ["深色模式", "浅色模式"],
        index=0 if st.session_state.theme == "dark" else 1,
        key="theme_radio"
    )
    if theme_option == "深色模式":
        st.session_state.theme = "dark"
    else:
        st.session_state.theme = "light"

# 根据主题注入 CSS(放在 st.sidebar 之后,确保生效)
if st.session_state.theme == "dark":
    st.markdown("""
    <style>
    .stApp { background-color: #0e1117; color: #e0e0e0; }
    .stChatMessage { background-color: #1a1d27; border-radius: 8px; padding: 12px; }
    .stChatMessage.user { background-color: #2b303f; }
    .stChatMessage.assistant { background-color: #1e2330; }
    .stTextInput > div > div > input { background-color: #2b303f; color: #e0e0e0; }
    </style>
    """, unsafe_allow_html=True)
else:
    st.markdown("""
    <style>
    .stApp { background-color: #f8f9fa; color: #212529; }
    .stChatMessage { background-color: #ffffff; border-radius: 8px; padding: 12px; box-shadow: 0 1px 2px rgba(0,0,0,0.05); }
    .stChatMessage.user { background-color: #e9ecef; }
    .stChatMessage.assistant { background-color: #f1f3f5; }
    .stTextInput > div > div > input { background-color: #ffffff; color: #212529; }
    </style>
    """, unsafe_allow_html=True)

效果验证:刷新页面后,侧边栏可实时切换深/浅色;所有文字、输入框、消息气泡自动适配,无闪烁、无错位。

3.3 进阶:保存用户偏好至本地

希望下次打开仍保持上次选择?只需一行代码写入浏览器 localStorage(需配合 streamlit-js-eval):

pip install streamlit-js-eval

app.py 中添加:

from streamlit_js_eval import get_geolocation, get_window_size, set_cookie, get_cookie

# 在 theme_option 逻辑后添加
if theme_option == "深色模式":
    st.session_state.theme = "dark"
    set_cookie("glm3_theme", "dark")
else:
    st.session_state.theme = "light"
    set_cookie("glm3_theme", "light")

# 页面加载时读取 cookie(放在 st.set_page_config 之后)
saved_theme = get_cookie("glm3_theme")
if saved_theme:
    st.session_state.theme = saved_theme

4. 历史导出:一键保存为 Markdown / JSON

默认 Streamlit 不提供历史导出功能。我们通过 st.download_button + 内存序列化,实现零依赖导出。

4.1 构建导出按钮与格式选择

st.chat_input(...) 上方添加:

# 在 st.chat_input 前插入
with st.sidebar:
    st.divider()
    st.header(" 对话历史")
    
    if st.session_state.messages:
        col1, col2 = st.columns(2)
        with col1:
            # 导出为 Markdown
            md_content = "# ChatGLM3-6B 对话记录\n\n"
            for msg in st.session_state.messages:
                role = "👤 用户" if msg["role"] == "user" else " 助手"
                md_content += f"### {role}\n{msg['content']}\n\n"
            
            st.download_button(
                label="💾 导出为 Markdown",
                data=md_content,
                file_name=f"chat_history_{int(time.time())}.md",
                mime="text/markdown"
            )
        
        with col2:
            # 导出为 JSON
            import json, time
            json_content = json.dumps(st.session_state.messages, ensure_ascii=False, indent=2)
            st.download_button(
                label="📦 导出为 JSON",
                data=json_content,
                file_name=f"chat_history_{int(time.time())}.json",
                mime="application/json"
            )
    else:
        st.info("暂无对话记录,开始聊天后即可导出")

注意:需在文件顶部 import timeimport json

4.2 增强体验:自动命名 + 时间戳 + 清空按钮

在导出区域下方追加:

    st.divider()
    st.caption(" 小技巧:导出文件名含时间戳,避免覆盖")
    
    if st.button("🗑 清空当前对话", type="secondary", use_container_width=True):
        st.session_state.messages = []
        st.rerun()

效果:点击即生成带时间戳的 .md.json 文件,双击即可用 Typora / VS Code 打开;清空按钮即时重置,不刷新页面。


5. 快捷指令配置:让常用操作“一句话触发”

快捷指令本质是对用户输入做前缀匹配 + 模板填充。我们支持 /code/doc/clear 三类高频指令,全部在 if prompt := st.chat_input(...) 内部处理。

5.1 定义指令映射表与执行逻辑

if prompt := st.chat_input(...) 判断块内,替换原有逻辑:

if prompt := st.chat_input("请输入问题..."):
    # 检查是否为快捷指令
    if prompt.strip().startswith("/"):
        cmd = prompt.strip().split()[0].lower()
        
        if cmd == "/clear":
            st.session_state.messages = []
            st.toast(" 对话已清空", icon="🧹")
            st.rerun()
            
        elif cmd == "/code":
            template = """请根据以下要求,生成一个完整、可运行的 Python 脚本:
- 功能:[在此描述具体需求]
- 输入:[说明输入格式或示例]
- 输出:[说明期望输出格式或示例]
- 要求:使用标准库,不依赖第三方包;添加详细注释;包含 if __name__ == "__main__": 块"""
            st.session_state.messages.append({"role": "user", "content": template})
            st.chat_message("user").write(template)
            
        elif cmd == "/doc":
            template = """请为以下主题撰写一份专业、结构清晰的技术文档:
- 主题:[在此填写主题名称]
- 目标读者:[如:初级开发者 / 产品经理 / 运维工程师]
- 要求:包含「背景」「核心概念」「使用步骤」「注意事项」四部分;语言简洁准确;避免模糊表述"""
            st.session_state.messages.append({"role": "user", "content": template})
            st.chat_message("user").write(template)
            
        else:
            st.session_state.messages.append({"role": "user", "content": prompt})
            st.chat_message("user").write(prompt)
            
    else:
        st.session_state.messages.append({"role": "user", "content": prompt})
        st.chat_message("user").write(prompt)

5.2 添加指令说明面板(提升新手友好度)

在侧边栏 st.header(" 对话历史") 上方插入:

with st.sidebar:
    st.header("⚡ 快捷指令")
    st.markdown("""
    - `/code` → 插入编程脚本模板  
    - `/doc` → 插入技术文档结构  
    - `/clear` → 清空当前对话  
    *指令区分大小写,输入后直接回车即可*
    """)

效果:输入 /code 后,自动填充标准化编程提示词;输入 /clear 即刻清空,无需手动删消息;所有指令响应毫秒级,无延迟感。


6. 总结:你的本地助手,现在真正属于你了

回顾这三步定制,我们没有改动模型一比特权重,也没有重写推理逻辑——
而是用 Streamlit 原生能力,完成了三个关键跃迁:

  • 从“能看”到“愿看”:主题换肤不是炫技,是降低视觉疲劳、适配不同工作场景(写代码用深色护眼,写文档用浅色提神);
  • 从“临时聊”到“可沉淀”:历史导出让每一次对话都成为知识资产,Markdown 便于阅读归档,JSON 便于程序解析再利用;
  • 从“逐字输”到“一键启”:快捷指令把重复劳动压缩成 /xxx 三个字符,把经验固化为可复用的提示词模板。

更重要的是,所有定制均满足“零外部依赖”原则:
🔹 不引入 React/Vue 前端框架
🔹 不依赖数据库或后端 API
🔹 不修改 transformersstreamlit 源码
🔹 全部代码可直接复制进 app.py,5 分钟内生效

你现在拥有的,不再是一个“跑起来的 demo”,而是一个真正贴合你工作流的私人 AI 助手——它知道你的偏好,记得你的习惯,理解你的意图。

下一步?试试把 /code 模板换成你团队的内部开发规范,或把导出路径指向公司 NAS;甚至用 st.file_uploader 接入本地 PDF,让 ChatGLM3 直接分析你的技术文档。能力已在手,边界由你定。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐