DeepSeek-Coder-V2-Lite-Instruct WebDemo 部署实战:基于 Streamlit 搭建代码模型聊天界面(self-llm 教程)
【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调(全参数/Lora)、部署国内外开源大模型(LLM)/多模态大模型(MLLM)教程项目地址: https://gitcode.com/datawhalechina/self-llm
本文是《开源大模型食用指南》(self-llm)中 DeepSeek-Coder-V2 系列教程的第三篇,围绕 03-DeepSeek-Coder-V2-Lite-Instruct WebDemo 部署.md 展开,手把手讲解如何在 Linux 环境(AutoDL 实例)下使用 ModelScope 下载deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct权重,并基于 Transformers + Streamlit 构建一个可交互的网页聊天 Demo。读完本文,你将掌握从环境配置、模型下载、应用代码编写到 Web 服务启动与端口访问的完整链路,获得一套可直接复制运行的本地代码模型聊天界面。
一、方案概览:WebDemo 在本系列中的定位
在 models/DeepSeek-Coder-V2 目录下,仓库为DeepSeek-Coder-V2-Lite-Instruct提供了四份递进式教程:
| 教程 | 核心内容 |
|---|---|
| 01 FastApi 部署调用 | 基于 FastAPI + Uvicorn 提供 HTTP API 服务,供程序化调用 |
| 02 接入 LangChain | 自定义LLM类,把本地模型接入 LangChain 框架 |
| 03 WebDemo 部署(本文) | 基于Streamlit搭建可视化聊天网页,适合人工交互体验 |
| 04 Lora 微调 | 使用 LoRA 对模型做指令微调(需 4×3090 显卡) |
三份部署类教程共享同一套技术底座:相同的环境版本、相同的 ModelScope 下载脚本、相同的apply_chat_template + model.generate + batch_decode推理管线,区别仅在于对外暴露的交互形态。本文聚焦 WebDemo 形态,其余两种形态会在文末做对照说明,方便你在 API 服务与可视化界面之间按需切换。
二、环境准备与依赖安装
2.1 基础环境版本
本文所基于的推荐环境如下(与仓库内其他三份 DeepSeek-Coder-V2 教程保持一致):
---------------- ubuntu 22.04 python 3.12 cuda 12.1 pytorch 2.3.0 ----------------教程默认学习者已安装好以上 Pytorch(cuda) 环境,如未安装请自行安装。
考虑到部分同学配置环境可能遇到困难,仓库维护者在 AutoDL 平台准备了DeepSeek-Coder-V2-Lite-Instruct的现成环境镜像,可直接基于该镜像创建实例,省去手动装环境的环节。
2.2 pip 换源与依赖安装
国内网络环境下,先更换 pypi 源加速下载,再安装依赖包:
# 更换 pypi 源加速库的安装 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple # 升级pip python -m pip install --upgrade pip pip install modelscope==1.16.1 pip install langchain==0.2.3 pip install streamlit==1.37.0 pip install transformers==4.43.2 pip install accelerate==0.32.1各依赖在本文中的作用:
| 依赖包 | 版本 | 用途 |
|---|---|---|
modelscope | 1.16.1 | 从 ModelScope 下载模型权重(snapshot_download) |
transformers | 4.43.2 | 加载分词器与因果语言模型、执行对话生成 |
accelerate | 0.32.1 | 配合device_map="auto"实现多卡/自动设备分配 |
streamlit | 1.37.0 | 构建网页聊天界面,提供侧边栏、聊天组件与会话状态 |
langchain | 0.2.3 | 本教程安装以保持与系列教程一致,LangChain 接入见 02 教程 |
三、使用 ModelScope 下载模型
3.1 下载脚本
在/root/autodl-tmp路径下新建download.py文件,粘贴以下内容并保存:
import torch from modelscope import snapshot_download, AutoModel, AutoTokenizer import os model_dir = snapshot_download('deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct', cache_dir='/root/autodl-tmp', revision='master')三个关键参数:
- 第一个参数(模型 ID):
deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct,即 ModelScope 上的模型仓库名称; cache_dir:模型下载保存路径,这里设为/root/autodl-tmp(AutoDL 实例的数据盘目录,注意根据你的实际磁盘路径修改);revision:模型仓库分支版本,master代表主分支,即最新版本。
运行下载:
python /root/autodl-tmp/download.py该模型权重较大(约 40 GB),下载大概需要 20 分钟,请耐心等待。终端出现如下图所示的下载进度与完成信息即表示下载成功:
3.2 下载后的目录结构
下载完成后,模型权重会按cache_dir/模型ID/的组织方式落盘,即/root/autodl-tmp/deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct。后续chatBot.py中的model_name_or_path正是指向这个路径,这也是 AutoDL 文件目录(/autodl-tmp/下出现deepseek-ai文件夹与chatBot.py、download.py)的原因。关于模型下载的更多通用方案(Hugging Face、ModelScope 等不同来源的切换),可参考 模型下载通用指南。
四、编写 Streamlit 聊天应用 chatBot.py
在/root/autodl-tmp路径下新建chatBot.py,粘贴以下代码并保存(原教程代码带有详细注释):
# 导入所需的库 from transformers import AutoTokenizer, AutoModelForCausalLM, GenerationConfig import torch import streamlit as st # 在侧边栏中创建一个标题和一个链接 with st.sidebar: st.markdown("## DeepSeek-Coder-V2-Lite-Instruct") "[开源大模型食用指南 self-llm](https://link.gitcode.com/i/7f10f946b24d5c8ddd61abdd2556ea2a)" # 创建一个滑块,用于选择最大长度,范围在0到1024之间,默认值为512 max_length = st.slider("max_length", 0, 1024, 512, step=1) # 创建一个标题和一个副标题 st.title("💬 DeepSeek-Coder-V2-Lite-Instruct") st.caption("🚀 A streamlit chatbot powered by Self-LLM") # 定义模型路径 model_name_or_path = '/root/autodl-tmp/deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct' # 定义一个函数,用于获取模型和tokenizer @st.cache_resource def get_model(): # 从预训练的模型中获取tokenizer tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, use_fast=False, trust_remote_code=True) # 从预训练的模型中获取模型,并设置模型参数 model = AutoModelForCausalLM.from_pretrained(model_name_or_path, torch_dtype=torch.bfloat16, device_map="auto", trust_remote_code=True) return tokenizer, model # 加载 DeepSeek-Coder-V2-Lite-Instruct 的model和tokenizer tokenizer, model = get_model() # 如果session_state中没有"messages",则创建一个包含默认消息的列表 if "messages" not in st.session_state: st.session_state["messages"] = [{"role": "assistant", "content": "有什么可以帮您的?"}] # 遍历session_state中的所有消息,并显示在聊天界面上 for msg in st.session_state.messages: st.chat_message(msg["role"]).write(msg["content"]) # 如果用户在聊天输入框中输入了内容,则执行以下操作 if prompt := st.chat_input(): # 将用户的输入添加到session_state中的messages列表中 st.session_state.messages.append({"role": "user", "content": prompt}) # 在聊天界面上显示用户的输入 st.chat_message("user").write(prompt) # 构建输入 input_ids = tokenizer.apply_chat_template(st.session_state.messages,tokenize=False,add_generation_prompt=True) model_inputs = tokenizer([input_ids], return_tensors="pt").to('cuda') generated_ids = model.generate(model_inputs.input_ids, max_new_tokens=512) generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] # 将模型的输出添加到session_state中的messages列表中 st.session_state.messages.append({"role": "assistant", "content": response}) # 在聊天界面上显示模型的输出 st.chat_message("assistant").write(response) # print(st.session_state)两点提示:原教程代码的侧边栏标题写为 "Index-1.9B-chat LLM"、链接指向项目主页,这是早期模板遗留,不影响功能;本文已按仓库内相对路径调整链接,读者如遇到此差异可放心,以模型实际加载路径为准。
4.1 模型加载部分:注意三个关键参数
get_model()被@st.cache_resource装饰,Streamlit 会缓存函数返回值,保证每次页面交互(rerun)不会重复加载 40 GB 权重,这是 WebDemo 能流畅响应的关键设计。
加载参数值得展开说明:
use_fast=False:使用非 fast 版本的分词器。DeepSeek-Coder-V2 系列的分词器带有自定义实现,配合trust_remote_code=True从模型仓库加载远程代码,可保证 tokenizer 行为与训练时完全一致;torch_dtype=torch.bfloat16:以 bfloat16 半精度加载权重,在精度损失可控的前提下显著降低显存占用(40 GB 的原始权重以 bf16 加载后约为其一半的显存规模),这与系列教程中 FastApi 部署 的加载方式完全一致;device_map="auto":由 accelerate 自动把模型各层分配到可用的 GPU 上,单卡、多卡实例均可直接运行,无需手动指定设备。
4.2 对话生成部分:与 API 部署共用的推理管线
页面主体逻辑是标准的 Streamlit 聊天组件流:
st.session_state:保存messages消息列表,初始注入一条 assistant 欢迎语"有什么可以帮您的?",保证每次 rerun 后历史对话不丢失;- 历史消息渲染:
st.chat_message(msg["role"]).write(msg["content"])按角色(user/assistant)渲染气泡; - 输入处理:
st.chat_input()捕获用户输入,追加进消息列表并立即展示; - 推理生成:
input_ids = tokenizer.apply_chat_template(st.session_state.messages,tokenize=False,add_generation_prompt=True) model_inputs = tokenizer([input_ids], return_tensors="pt").to('cuda') generated_ids = model.generate(model_inputs.input_ids, max_new_tokens=512) generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]这段管线的每一步都有明确职责:
apply_chat_template(..., tokenize=False, add_generation_prompt=True):把多轮messages按 DeepSeek-Coder-V2 官方的 chat 模板组织成模型输入文本,add_generation_prompt=True在末尾追加生成提示符,是 Instruct 模型正确对话的关键一步;tokenizer([input_ids], return_tensors="pt").to('cuda'):文本转 token id 张量并送入 GPU;model.generate(..., max_new_tokens=512):自回归解码生成新 token,max_new_tokens限制单次回复的最大新增 token 数;- 切片
output_ids[len(input_ids):]:从完整输出中剥离输入部分,只保留模型新生成的内容; batch_decode(..., skip_special_tokens=True):token id 解码回文本并去除特殊 token。
细节说明:侧边栏的
max_length滑块在本示例代码中仅用于演示 Streamlit 组件用法,实际生成长度仍由max_new_tokens=512控制;如需滑块生效,可将max_new_tokens与滑块值绑定。侧边栏底部还放置了项目 README 入口链接,方便随时回顾教程。
五、启动 WebDemo 并通过 AutoDL 自定义服务访问
5.1 启动 Streamlit 服务
在终端运行以下命令启动服务:
streamlit run /root/autodl-tmp/chatBot.py --server.address 127.0.0.1 --server.port 6006 --server.enableCORS false三个启动参数的含义:
| 参数 | 作用 |
|---|---|
--server.address 127.0.0.1 | 绑定本机回环地址,仅在实例内部监听 |
--server.port 6006 | 指定服务端口为 6006(与系列教程约定一致,便于统一端口映射) |
--server.enableCORS false | 关闭跨域校验,方便 AutoDL 自定义服务反向代理访问 |
5.2 通过 AutoDL 自定义服务入口访问
服务启动后,在 AutoDL 实例控制台点击「自定义服务」入口:
系统会弹出确认提示:需要先在实例中以 6006 端口启动服务,再通过该入口访问。确认后即可打开聊天页面,运行效果如下:
本地部署场景:如果你是在自己的 Linux 机器(非 AutoDL)上运行,则直接在浏览器访问http://127.0.0.1:6006即可看到同一聊天界面。AutoDL 上更通用的端口映射思路(将实例 6006 端口映射到本地localhost:6006)可参考 AutoDL 开放端口。
六、从 WebDemo 延伸:同一推理管线的三种对外形态
WebDemo 只是交互形态之一。对照同目录另外两份部署教程,可以发现它们共享完全相同的模型加载与推理核心:
- FastApi 部署:把上述
apply_chat_template + generate管线封装进POST /端点,通过curl -X POST "http://127.0.0.1:6006" -d '{"prompt": "你好", "history": []}'或 Pythonrequests发起调用,返回 JSON 格式的response/status/time字段,并在每次请求后调用torch_gc()清理 GPU 缓存,适合被上层应用程序化调用; - LangChain 接入:从
langchain.llms.base.LLM继承自定义DeepSeek_Coder_LLM类,重写构造函数(加载模型)与_call函数(执行生成),并在生成时额外配置top_k=5、top_p=0.8、temperature=0.3、repetition_penalty=1.1、do_sample=True等采样参数,从而以统一接口接入 LangChain 生态。
三者的选择逻辑很简单:想要人工可视化体验模型能力,用本文的 Streamlit WebDemo;想要把模型能力接入自己的服务/应用,用 FastApi;想要构建 LangChain 应用(知识库、Agent 等),用自定义 LLM 类。此外,如果希望进一步对模型做领域微调(指令微调),可继续学习 04-DeepSeek-Coder-V2-Lite-Instruct Lora 微调,其中会使用仓库根目录 dataset 下的数据构建指令集。
七、常见问题排查
基于本文代码与运行环境,整理以下排查思路供参考(均可在本地快速验证):
- 模型加载失败/报错:优先检查
model_name_or_path是否为/root/autodl-tmp/deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct实际下载路径,确认trust_remote_code=True未被误删——DeepSeek-Coder-V2 依赖仓库内自定义代码; - 显存不足:确认加载时使用了
torch_dtype=torch.bfloat16与device_map="auto";40 GB 的 bf16 权重建议使用显存充裕的实例,多卡环境会自动分流; - 端口访问不通:AutoDL 场景下务必通过「自定义服务」入口访问,且服务必须以 6006 端口启动;本地场景直接访问
http://127.0.0.1:6006; - 端口被占用:修改
--server.port为其他端口,同时保持 AutoDL 自定义服务入口的端口一致; - 下载中断/缓慢:ModelScope 下载自带重试机制,可重新执行
download.py断点续传,无需删除已下载文件。
结语
至此,你已完整走通DeepSeek-Coder-V2-Lite-Instruct的 WebDemo 部署链路:环境与依赖 → ModelScope 权重下载 → Streamlit 聊天应用编写 → 服务启动与 AutoDL 访问。这份 WebDemo 同时可以作为学习 Streamlit + Transformers 交互式 LLM 应用的标准模板——把model_name_or_path换成其他模型,即可快速迁移到 self-llm 仓库中 Qwen、GLM 等系列的同类 WebDemo(如 Qwen2.5 WebDemo)。下一步建议结合 FastApi 部署 将模型封装为服务,再经由 LangChain 接入 构建更完整的应用。
【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调(全参数/Lora)、部署国内外开源大模型(LLM)/多模态大模型(MLLM)教程项目地址: https://gitcode.com/datawhalechina/self-llm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考