
前端交互增强ChatGLM3-6B支持Markdown输出渲染教程1. 引言从纯文本到富文本的体验升级如果你用过一些早期的AI对话模型可能会发现一个不大不小的痛点模型输出的内容尤其是代码块、列表、表格在界面上显示为一行行单调的纯文本。你需要费力地辨认哪里是代码的开头哪里是列表的结尾阅读体验大打折扣。现在基于ChatGLM3-6B和Streamlit构建的本地智能助手彻底解决了这个问题。它不仅能理解你的问题还能将回答以清晰、美观的Markdown格式渲染出来代码高亮、加粗标题、有序列表……一切都像你在专业文档里看到的那样。这篇文章我就带你一步步实现这个功能。你会发现给AI对话加上Markdown渲染并没有想象中那么复杂却能极大提升使用时的愉悦感和效率。我们不需要修改复杂的模型底层只需在前端交互上做一些聪明的“包装”。2. 核心原理Streamlit如何渲染Markdown在开始动手之前我们先花两分钟搞懂背后的原理。这样你不仅能照做还能举一反三。我们的系统基于Streamlit框架。Streamlit本身内置了一个非常强大的组件叫st.markdown()。顾名思义它就是用来渲染Markdown文本的。你给它一串符合Markdown语法的字符串它就能在网页上显示出格式化的内容。那么流程就清晰了用户提问你在前端输入问题。模型推理ChatGLM3-6B模型在本地处理你的问题生成回答。关键点来了我们需要引导模型在生成回答时主动使用Markdown语法。前端渲染Streamlit接收到模型生成的、包含Markdown语法的文本调用st.markdown()将其渲染成富文本。你看到结果一个结构清晰、代码高亮、排版美观的回答呈现在你面前。整个过程的核心在于第2步和第3步的衔接。模型得“知道”要用Markdown格式输出而前端得“知道”如何去渲染它。下面我们就从零开始构建这个流程。3. 环境准备与项目结构假设你已经按照基础教程在本地部署好了ChatGLM3-6B的Streamlit项目。如果你的项目目录看起来有点乱或者还不确定可以跟着我重新梳理一下。一个清晰的项目结构能让后续开发事半功倍。我建议的目录结构如下chatglm3-streamlit-md/ ├── app.py # Streamlit主应用文件 ├── model_loader.py # 模型加载与推理模块 ├── requirements.txt # Python依赖列表 ├── assets/ # 静态资源目录可选 │ └── ... └── README.md # 项目说明文档接下来确保你的Python环境安装了正确版本的库。在项目根目录下你的requirements.txt文件应该包含类似以下内容streamlit1.28.0 torch2.0.0 transformers4.40.2 sentencepiece accelerate为什么锁定transformers4.40.2这是项目介绍里提到的“黄金版本”。新版本的Tokenizer可能存在一些兼容性问题锁定这个版本可以确保ChatGLM3-6B-32k模型加载和推理的绝对稳定性避免出现奇怪的报错。在终端里进入项目目录运行以下命令安装依赖pip install -r requirements.txt如果一切顺利环境就准备好了。接下来我们进入核心的代码部分。4. 分步实现Markdown渲染功能我们将改造主要涉及两个文件model_loader.py(负责与模型对话) 和app.py(负责前端展示)。4.1 第一步改造模型对话函数引导模型使用Markdown首先打开model_loader.py文件。找到负责调用模型生成回复的函数它可能叫做get_model_response或chat。我们需要在给模型的“系统提示”或“用户提示”中明确要求它用Markdown格式回答。关键技巧在系统提示System Prompt中植入指令。系统提示是对话开始前给模型的“角色设定”和“行为规范”模型会严格遵守。我们在其中加入使用Markdown的指令。找到模型初始化的地方或者在每次对话前构建消息列表的地方。修改你的消息构建逻辑添加一个系统消息# 在 model_loader.py 中 def create_conversation_input(user_input, history): 构建模型输入的消息列表。 history: 之前的对话历史格式为 [(user1, assistant1), (user2, assistant2), ...] messages [] # 1. 加入系统提示要求模型使用Markdown system_message { role: system, content: 你是一个乐于助人的AI助手。请用清晰、结构化的Markdown格式来组织你的回答例如使用**加粗**表示重点用代码块包裹代码用列表来陈列项目。这能极大地提升回答的可读性。 } messages.append(system_message) # 2. 加入历史对话如果有 for human, assistant in history: messages.append({role: user, content: human}) messages.append({role: assistant, content: assistant}) # 注意历史中的助手回复也应保持Markdown格式 # 3. 加入当前用户问题 messages.append({role: user, content: user_input}) return messages这样模型在生成每一个新回复时都会收到“请使用Markdown格式”的指令从而更倾向于生成带有#,**, ,-等标记的文本。4.2 第二步改造前端渲染函数使用st.markdown接下来打开app.py文件。这里是Streamlit应用的入口。我们需要找到显示模型回复的地方。通常代码中会有一个循环或回调函数来处理用户输入并显示回复。将原来可能使用的st.write()或st.text()替换为st.markdown()。# 在 app.py 中 import streamlit as st # ... 之前的代码包括模型加载、会话状态初始化等 ... if st.button(发送) or user_input: if user_input: # 将用户输入添加到聊天历史并显示 st.session_state.messages.append({role: user, content: user_input}) with st.chat_message(user): st.markdown(user_input) # 用户消息也可以用markdown渲染如果包含格式的话 # 调用模型获取回复 with st.chat_message(assistant): with st.spinner(思考中...): # 这里调用你改造后的 model_loader 中的函数 full_response get_model_response(user_input, st.session_state.history) # 核心变化使用 st.markdown 渲染模型回复 st.markdown(full_response) # 将流式输出的每一段都渲染为Markdown # 如果是流式输出代码会稍有不同见下一节 # 将助手回复添加到会话历史 st.session_state.messages.append({role: assistant, content: full_response}) st.session_state.history.append((user_input, full_response))看主要改动就是一行st.markdown(full_response)。Streamlit会自动识别文本中的Markdown语法并将其渲染成漂亮的HTML。4.3 第三步实现流式输出的Markdown渲染进阶上面的代码适用于模型一次性生成完整回复。但如果你想要更酷的、像真人打字一样的“流式输出”体验并且希望流式输出的内容也能实时渲染Markdown就需要多做一些工作。Streamlit的st.markdown()支持一个神奇的参数unsafe_allow_htmlFalse默认。但当文本是逐段流入时直接更新同一个st.markdown组件可能会导致格式解析问题。一个更稳定、体验更好的方法是使用Streamlit的empty占位符和累加文本# 在 app.py 中处理流式输出的部分 with st.chat_message(assistant): message_placeholder st.empty() # 创建一个空的占位符 full_response # 假设 get_model_response_stream 是一个生成器逐词或逐句返回回复 for chunk in get_model_response_stream(user_input, st.session_state.history): full_response chunk # 每次收到新的片段都重新渲染整个到目前为止的回复文本 message_placeholder.markdown(full_response ▌) # “▌”是光标效果 # 流式输出结束后移除光标渲染最终完整文本 message_placeholder.markdown(full_response)这种方法能确保在流式输出过程中Markdown格式被逐步、正确地渲染出来。例如当模型输出一个以 python 开头的代码块时随着后续代码的流入整个代码块的高亮效果会逐渐呈现。5. 效果展示与使用技巧完成以上步骤后重启你的Streamlit应用 (streamlit run app.py)现在你可以尝试问一些能体现Markdown优势的问题了。试试这些问题“用Python写一个快速排序算法并给出步骤说明。”“列出云计算的主要优势并用表格对比IaaS, PaaS和SaaS。”“详细解释一下HTTP和HTTPS的区别分点说明。”你应该能看到模型的回复不再是平铺直叙的文字墙。代码有了语法高亮列表整齐排列加粗的重点一目了然。这不仅仅是“看起来好看”它显著降低了信息解析的难度让你能更快地抓住回复的核心。几个提升体验的小技巧自定义CSS可选如果你觉得Streamlit默认的Markdown样式不够好看可以在app.py开头注入自定义CSS来微调字体、代码块背景色等。st.markdown( style /* 让代码块有更明显的背景和圆角 */ .stCodeBlock { border-radius: 10px; border-left: 5px solid #4CAF50; } /style , unsafe_allow_htmlTrue)引导模型如果你的模型在某些时候还是输出了纯文本可以在对话中再次提醒它“请用Markdown格式回答。” 经过几次引导后它通常会更好地遵循指令。处理混合内容有时模型的回复可能混合了Markdown和未格式化的文本。st.markdown()组件很健壮它会尽力渲染所有它能识别的Markdown部分其余部分则作为普通文本显示这通常是可以接受的结果。6. 总结通过本教程我们完成了对本地ChatGLM3-6B智能助手的一次重要前端增强让AI的回答以渲染精美的Markdown格式呈现。回顾一下关键步骤引导模型通过在系统提示中明确指令让ChatGLM3-6B在生成文本时主动使用Markdown语法。前端渲染将Streamlit的显示组件从st.write()替换为st.markdown()从而激活富文本渲染能力。流式优化利用st.empty()占位符实现流式输出下的实时Markdown渲染获得更佳的交互体验。这个改进的成本很低只是对前后端交互逻辑的微调不涉及复杂的模型微调或训练但带来的体验提升是立竿见影的。它使得这个本地部署的AI助手不仅在性能上“零延迟、高稳定”在交互和呈现上也达到了主流云端AI产品的体验水准。现在你的本地AI助手已经具备了生产高质量、易阅读内容的能力。无论是用于代码评审、文档撰写还是知识问答它都能给你结构清晰、视觉友好的反馈。快去试试吧享受与一个“会排版”的AI对话的乐趣。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。