news 2026/9/12 2:56:12

使用 Streamlit 部署 BlueLM-7B-Chat WebDemo:self-llm 中文大模型对话界面的完整实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 Streamlit 部署 BlueLM-7B-Chat WebDemo:self-llm 中文大模型对话界面的完整实战指南

使用 Streamlit 部署 BlueLM-7B-Chat WebDemo:self-llm 中文大模型对话界面的完整实战指南

【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调(全参数/Lora)、部署国内外开源大模型(LLM)/多模态大模型(MLLM)教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm

本篇指南以 models/BlueLM/03-BlueLM-7B-Chat WebDemo 部署.md 为核心脉络,系统讲解如何基于 AutoDL 云服务器将 vivo 开源的 BlueLM-7B-Chat 大模型部署为带流式输出的 Streamlit 聊天 WebDemo。读完本文,你将掌握完整的云端环境搭建、模型下载、对话模板构造、流式生成封装以及端口映射访问的实操能力,并可结合仓库中的 FastApi、LangChain 部署方案横向理解 BlueLM 的接入方式。

BlueLM-7B-Chat 模型与对话格式概览

BlueLM-7B 是 vivo AI 全球研究院自主研发的大规模预训练语言模型,参数规模为 70 亿。根据仓库文档记载,该模型在 C-Eval 和 CMMLU 中文评测上均取得领先结果,对比同尺寸开源模型具有较强的竞争力(截至文档记录的 11 月 1 号)。本次发布共包含 7B 模型的 Base 基座版与 Chat 对齐版两个系列,其中 Chat 系列又细分如下模型版本:

基座模型(Base)对齐模型(Chat)
BlueLM-7B-BaseBlueLM-7B-Chat
BlueLM-7B-Base-32KBlueLM-7B-Chat-32K
BlueLM-7B-Chat-4bits

其中-32K后缀表示支持 32K 上下文长度的版本,-4bits为量化版本。本教程使用的是BlueLM-7B-Chat标准版本。

与多数模型使用<|im_start|><|user|>等特殊 token 标记角色的做法不同,BlueLM 的对话模板极为简洁,仅有[|Human|](用户)与[|AI|](模型)两个角色标识,模板形态如下:

[|Human|]:你的问题[|AI|]:

这一格式在仓库的 FastApi 部署、LangChain 接入 与 LoRA 微调 文档中保持一致,是理解 BlueLM 一切应用方式的关键约定,后文 WebDemo 的提示词构造同样基于此格式。

环境准备:租用 GPU 机器与安装依赖

租用 AutoDL 显卡机器

本教程在 AutoDL 平台中租赁一张3090 等 24G 显存的显卡机器。在创建实例时,镜像选择如下组合(CUDA 版本在 11.3 以上均可):

PyTorch --> 1.11.0 --> 3.8(ubuntu20.04) --> 11.3

租用完成后,打开服务器的 JupyterLab(也可以使用 VSCode SSH 远程连接服务器),并在其中打开终端开始环境配置、模型下载和运行 Demo。

pip 换源加速并安装依赖包

为加速依赖安装,先升级 pip 并配置清华镜像源,然后安装本 Demo 所需的全部依赖:

# 升级pip python -m pip install --upgrade pip # 设置pip镜像源 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple # 安装软件依赖 pip install modelscope==1.11.0 pip install transformers==4.37.0 pip install streamlit==1.24.0 pip install sentencepiece==0.1.99 pip install accelerate==0.24.1 pip install transformers_stream_generator==0.0.4

各依赖在本次部署中的职责如下:

依赖包版本作用
modelscope1.11.0从 ModelScope 魔搭社区下载模型权重
transformers4.37.0加载模型与分词器、执行推理生成
streamlit1.24.0构建 Web 聊天界面的核心框架
sentencepiece0.1.99分词器依赖的文本切分库(BlueLM 基于 SentencePiece 训练分词器)
accelerate0.24.1支持device_map="auto"自动设备映射加载
transformers_stream_generator0.0.4流式生成时的相关依赖

其中pip config set global.index-url属于环境通用配置,仓库 General-Setting/01-pip、conda换源.md 中还有更完整的换源说明可供参考。

模型下载:使用 ModelScope API 拉取权重

使用 ModelScope API 将BlueLM-7B-Chat模型下载到/root/autodl-tmp(AutoDL 的数据盘目录,容量更大)。在/root/autodl-tmp下创建model_download.py文件,内容如下:

from modelscope import snapshot_download model_dir = snapshot_download("vivo-ai/BlueLM-7B-Chat", cache_dir='/root/autodl-tmp', revision="master")

运行后模型会被下载到/root/autodl-tmp/vivo-ai/BlueLM-7B-Chat目录(vivo-ai为模型仓库命名空间,cache_dir指定缓存根目录,revision="master"指定下载主分支版本)。仓库 General-Setting/03-模型下载.md 中对该步骤有更详细的说明,下载完成后的路径即为后文代码中的模型加载路径。

编写 chatBot.py:Streamlit WebDemo 代码全解析

/root/autodl-tmp路径下新建chatBot.py文件,完整代码如下(对原文档中的模型路径笔误做了修正,其余逻辑与原文一致):

# 导入所需的库 from transformers import AutoTokenizer, AutoModelForCausalLM, GenerationConfig, TextStreamer import torch import streamlit as st # 在侧边栏中创建一个标题和一个链接 with st.sidebar: st.markdown("## BlueLM-7B-Chat") "[开源大模型食用指南 self-llm](https://link.gitcode.com/i/554b59465d658921c269846c0f574915)" # 创建一个滑块,用于选择最大长度,范围在0到1024之间,默认值为512 max_length = st.slider("max_length", 0, 1024, 512, step=1) # 创建一个标题和一个副标题 st.title("💬 BlueLM Chatbot") st.caption("🚀 A streamlit chatbot powered by Self-LLM") # 定义模型路径 mode_name_or_path = '/root/autodl-tmp/vivo-ai/BlueLM-7B-Chat' # 定义一个函数,用于获取模型和tokenizer @st.cache_resource def get_model(): # 从预训练的模型中获取tokenizer tokenizer = AutoTokenizer.from_pretrained(mode_name_or_path, trust_remote_code=True) # 从预训练的模型中获取模型,并设置模型参数 model = AutoModelForCausalLM.from_pretrained(mode_name_or_path, trust_remote_code=True, torch_dtype=torch.bfloat16, device_map="auto") # 从预训练的模型中获取生成配置 model.generation_config = GenerationConfig.from_pretrained(mode_name_or_path) # 设置生成配置的pad_token_id为生成配置的eos_token_id model.generation_config.pad_token_id = model.generation_config.eos_token_id # 设置模型为评估模式 model.eval() return tokenizer, model # 加载BlueLM的model和tokenizer tokenizer, model = get_model() def build_prompt(messages, prompt): """ 构建会话提示信息。 参数: messages - 包含会话历史的元组列表,每个元组是(用户查询,AI响应)。 prompt - 当前用户输入的文本。 返回值: res - 构建好的包含会话历史和当前用户提示的字符串。 """ res = "" # 遍历历史消息,构建会话历史字符串 for query, response in messages: res += f"[|Human|]:{query}[|AI|]:{response}</s>" # 添加当前用户提示 res += f"[|Human|]:{prompt}[|AI|]:" return res class BlueLMStreamer(TextStreamer): """ BlueLM流式处理类,用于处理模型的输入输出流。 参数: tokenizer - 用于分词和反分词的tokenizer实例。 """ def __init__(self, tokenizer: "AutoTokenizer"): self.tokenizer = tokenizer self.tokenIds = [] self.prompt = "" self.response = "" self.first = True def put(self, value): """ 添加token id到流中。 参数: value - 要添加的token id。 """ if self.first: self.first = False return self.tokenIds.append(value.item()) # 将token ids解码为文本 text = tokenizer.decode(self.tokenIds, skip_special_tokens=True) def end(self): """ 结束流处理,将当前流中的文本作为响应,并重置流状态。 """ self.first = True # 将token ids解码为文本 text = tokenizer.decode(self.tokenIds, skip_special_tokens=True) self.response = text self.tokenIds = [] # 初始化session状态,如果messages不存在则初始化为空,并添加欢迎信息 if "messages" not in st.session_state: st.session_state.messages = [] st.session_state.messages.append(("", "你好,有什么可以帮助你吗?")) # 遍历并显示历史消息 for msg in st.session_state.messages: st.chat_message("assistant").write(msg[1]) # 处理用户输入 if prompt_text := st.chat_input(): prompt_text = prompt_text.strip() st.chat_message("user").write(prompt_text) messages = st.session_state.messages # 使用BlueLMStreamer处理流式模型输入 streamer = BlueLMStreamer(tokenizer=tokenizer) # 构建当前会话的提示信息 prompt = build_prompt(messages=messages, prompt=prompt_text) # 将提示信息编码为模型输入 inputs_tensor = tokenizer(prompt, return_tensors="pt") inputs_tensor = inputs_tensor.to("cuda:0") input_ids = inputs_tensor["input_ids"] # 通过模型生成响应 outputs = model.generate(input_ids=input_ids, max_new_tokens=max_length, streamer=streamer) # 将模型的响应显示给用户 st.chat_message("assistant").write(streamer.response) # 更新会话历史 st.session_state.messages.append((prompt_text, streamer.response))

下面按功能模块拆解这段代码的关键设计。

侧边栏参数控制

with st.sidebar: st.markdown("## BlueLM-7B-Chat") max_length = st.slider("max_length", 0, 1024, 512, step=1)

侧边栏通过st.slider暴露了max_length(生成的最大新 token 数)滑杆,范围 0~1024,默认 512,运行时可实时调整,无需重启服务。

模型加载与缓存

@st.cache_resource def get_model(): tokenizer = AutoTokenizer.from_pretrained(mode_name_or_path, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained(mode_name_or_path, trust_remote_code=True, torch_dtype=torch.bfloat16, device_map="auto") model.generation_config = GenerationConfig.from_pretrained(mode_name_or_path) model.generation_config.pad_token_id = model.generation_config.eos_token_id model.eval() return tokenizer, model
  • trust_remote_code=True:BlueLM 模型的代码定义托管在模型仓库中,需开启远程代码信任才能加载其自定义的 modeling 文件;
  • torch_dtype=torch.bfloat16:以 BF16 精度加载权重,兼顾显存占用与数值稳定性(仓库 FastApi 部署文档中同样使用torch_dtype=torch.bfloat16,api.py 实现 与之一致);
  • device_map="auto":借助 accelerate 自动将模型分布到可用设备(多卡场景下自动分片);
  • pad_token_id显式设置为eos_token_id:由于生成时输入只有一个样本,padding 与结束符共用同一 token id,可避免生成过程中的 pad 告警与异常;
  • @st.cache_resource:Streamlit 的资源级缓存,保证页面每次交互重跑脚本时不会重复加载 7B 模型,而是复用已加载的模型与分词器实例。

build_prompt:多轮对话模板构造

def build_prompt(messages, prompt): res = "" for query, response in messages: res += f"[|Human|]:{query}[|AI|]:{response}</s>" res += f"[|Human|]:{prompt}[|AI|]:" return res

该函数将历史消息(messages中的(query, response)元组)拼接为 BlueLM 官方对话格式,历史轮次之间以</s>(结束符)分隔,最后拼接当前用户输入并以[|AI|]:收尾,等待模型续写。这与 FastApi 部署 中messages = f"[|Human|]:{prompt}[|AI|]:"的构造方式同源,也印证了该模板是 BlueLM 全系列接入方案统一遵守的约定。

BlueLMStreamer:基于 TextStreamer 的流式输出封装

class BlueLMStreamer(TextStreamer): def __init__(self, tokenizer: "AutoTokenizer"): self.tokenizer = tokenizer self.tokenIds = [] self.prompt = "" self.response = "" self.first = True def put(self, value): if self.first: self.first = False return self.tokenIds.append(value.item()) text = tokenizer.decode(self.tokenIds, skip_special_tokens=True) def end(self): self.first = True text = tokenizer.decode(self.tokenIds, skip_special_tokens=True) self.response = text self.tokenIds = []

BlueLMStreamer继承自 transformers 的TextStreamer,通过重写put(每生成一个新 token 时被调用)与end(生成结束时被调用)来捕获生成过程:

  • put中通过self.first标志跳过首个 token(通常为序列开始符或首 token,避免输出污染),随后将新 token id 追加到self.tokenIds并实时解码;
  • end中把累积的全部 token ids 解码为完整文本并存入self.response,同时重置流状态,供主程序在生成结束后一次性写入聊天界面。

从代码结构看,这里的流式实现是"边生成边累积 token、结束时统一取结果"的简化策略,put内每次都对整个累积序列做解码。在交互体验上,由于主程序最终是通过streamer.response一次性写入消息,当前版本的逐 token 推送效果有限,你可以基于put中的解码文本结合st.chat_message的增量写入进一步改造,实现真正的逐字流式渲染。

会话状态管理与交互渲染

if "messages" not in st.session_state: st.session_state.messages = [] st.session_state.messages.append(("", "你好,有什么可以帮助你吗?")) for msg in st.session_state.messages: st.chat_message("assistant").write(msg[1])

st.session_state.messages保存整个会话历史,首次进入时写入一条欢迎语;每次页面重跑都会遍历历史并以"助手"气泡渲染(欢迎语、历史回复均以 assistant 身份展示)。

用户输入处理部分则完成「写入用户气泡 → 构造提示词 → tokenizer 编码并转移到cuda:0model.generate生成(传入max_new_tokens=max_lengthstreamer)→ 展示助手回复 → 追加会话历史」的完整闭环:

if prompt_text := st.chat_input(): prompt_text = prompt_text.strip() st.chat_message("user").write(prompt_text) messages = st.session_state.messages streamer = BlueLMStreamer(tokenizer=tokenizer) prompt = build_prompt(messages=messages, prompt=prompt_text) inputs_tensor = tokenizer(prompt, return_tensors="pt") inputs_tensor = inputs_tensor.to("cuda:0") input_ids = inputs_tensor["input_ids"] outputs = model.generate(input_ids=input_ids, max_new_tokens=max_length, streamer=streamer) st.chat_message("assistant").write(streamer.response) st.session_state.messages.append((prompt_text, streamer.response))

注意,max_length滑杆值在此处作为max_new_tokens传入(而不是max_length),意味着它限制的是新增生成的 token 数量而非包含输入在内的总长度,这与滑杆名称的直觉略有差异,是原文档代码中一处值得留意的语义细节。

启动 WebDemo 服务并访问

在终端中运行以下命令启动 Streamlit 服务:

streamlit run /root/autodl-tmp/chatBot.py --server.address 127.0.0.1 --server.port 6006
  • --server.address 127.0.0.1:仅监听本机回环地址,避免服务直接暴露到公网;
  • --server.port 6006:指定端口,与 AutoDL 自定义服务端口约定保持一致。

由于服务运行在云服务器上,需要按照 AutoDL 平台的指示将6006端口映射到本地(AutoDL 的"自定义服务"功能会给出对应的本地访问地址与 SSH 端口转发命令,具体操作参见仓库 General-Setting/02-AutoDL开放端口.md)。完成端口映射后,在浏览器打开http://localhost:6006/即可看到聊天界面:

从运行截图可以看到,左侧边栏展示模型名称与max_length滑杆(默认 512),右侧为聊天主区域,用户输入问题后模型会基于[|Human|]:...[|AI|]:模板返回对应回复,并支持多轮上下文对话。

与仓库其他部署方案的横向关联

本 WebDemo 是 BlueLM-7B-Chat 在 models/BlueLM 目录下的三种接入方式之一,与仓库中另外两份文档形成完整的部署矩阵,值得对照阅读:

  • FastApi 部署:提供/POST 接口,通过curl或 Pythonrequests调用,适合作为后端 API 服务,模型加载方式(torch_dtype=torch.bfloat16device_map="auto"pad_token_id=eos_token_id)与 WebDemo 完全一致;
  • LangChain 接入:自定义BlueLM(LLM)子类重写_call,内部同样以f"[|Human|]:{prompt}[|AI|]:"构造输入,将模型无缝接入 LangChain 生态;
  • LoRA 微调:微调数据的目标格式即"[|Human|]:... [|AI|]:"形态,说明对话模板贯穿"微调—部署—应用"全链路,微调后的模型可直接套用本 WebDemo 的提示词构造方式。

如果你的目标是快速验证模型能力,本教程的 WebDemo 最为直观;若需要面向业务系统提供服务,建议结合 FastApi 方案;若需构建 Agent 应用,则参考 LangChain 方案。

常见问题与排查建议

  1. 模型路径报错(FileNotFoundError / OSError):原文档中模型路径写作/root/autodl-tvivo-ai/BlueLM-7B-Chat,对照 ModelScope 下载目录的命名规则(cache_dir/命名空间/模型名)可确认正确路径应为/root/autodl-tmp/vivo-ai/BlueLM-7B-Chat,即上文代码中采用的路径。建议在终端先执行ls /root/autodl-tmp/vivo-ai/BlueLM-7B-Chat确认权重完整存在。
  2. 显存不足(CUDA out of memory):BlueLM-7B 以 BF16 加载约需 14GB 显存,24G 显存机器完全够用;若在更低显存的机器上运行,可考虑换用 BlueLM-7B-Chat-4bits 量化版本。
  3. 生成异常或出现重复 pad 内容:检查model.generation_config.pad_token_id是否已按文档设置为eos_token_id
  4. 端口无法访问:确认--server.address 127.0.0.1 --server.port 6006参数与 AutoDL 自定义服务的端口映射一致,详见 AutoDL 开放端口。

至此,你已经完成了 BlueLM-7B-Chat 从云端环境准备、模型下载、Streamlit 界面编写到端口映射访问的全流程部署,并理解了其[|Human|]:...[|AI|]:对话模板在仓库多个部署方案中的统一约定,可以在此基础上进一步扩展多轮记忆、角色设定或接入 LangChain 构建更复杂的应用。

【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调(全参数/Lora)、部署国内外开源大模型(LLM)/多模态大模型(MLLM)教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 2:55:49

Speckit技术文档工具:从安装到API文档实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 2:55:34

具身智能系统中的TVA与World跨模态交互机制研究

前沿技术探索&#xff1a;TVA智能体&#xff08;简称TVA&#xff09;TVA智能体&#xff08;亦称“AI智能体视觉”或“TVA视觉智能体”&#xff09;是依托Transformer架构与“因式智能体”理论构建的通用视觉技术体系。它有机融合深度强化学习&#xff08;DRL&#xff09;、卷积…

作者头像 李华
网站建设 2026/9/12 2:55:26

基于ThinkPHP+Vue的家电商城售后管理系统开发实践

毕业设计选了这个题目的人&#xff0c;我建议你先想清楚一个问题&#xff1a;你到底是在“做项目”&#xff0c;还是在“交差”。这话不太好听&#xff0c;但确实是很多学生做类似选题时的真实状态。thinkphpvue家用电器家电销售商城售后服务管理系统&#xff0c;这个标题拆开看…

作者头像 李华
网站建设 2026/9/12 2:54:42

深入理解JavaScript Promise:从原理到实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 2:54:08

MPU6050实时曲线显示:从串口解析到姿态解算的完整实践

简介&#xff1a;一套基于STM32ZET6与MPU6050的六轴传感器实时数据监测项目&#xff0c;专为希望深入掌握嵌入式传感器采集、I2C通信、姿态解算与上位机开发的工程师和爱好者设计&#xff0c;适合中高级单片机学习者直接参考或二次开发。资源包共94个文件&#xff0c;以H/C源码…

作者头像 李华
网站建设 2026/9/12 2:52:51

Windows 10环境变量配置与管理全指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华