简介:DeepSeek在Linux系统下的手动部署步骤与注意事项是一份面向深度学习开发者、运维工程师及AI部署初学者的PDF技术笔记。内容围绕环境准备、虚拟环境创建、代码库克隆、依赖安装、配置与运行等核心环节展开,详细说明了Ubuntu 20.04及以上系统、CPU/内存/存储/显卡要求,以及CUDA与cuDNN的安装和路径配置,并针对依赖包冲突、GPU未检测、内存不足、文件权限等典型问题给出排错思路。资料共1个PDF文件,包体仅215KB,轻量易读,适合作为部署操作的随身参考。目前已有794人学习下载,实用性受到关注。读者可据此按步骤完成DeepSeek在Linux上的手动部署,同时获得环境配置细节与常见故障的应对方法,减少摸索时间。
1. 先别急着装环境:DeepSeek 在 Linux 上手动部署前要算清的三笔账
在一台只有 16GB 显存的 Linux 服务器上,想手动部署 DeepSeek 的 7B 蒸馏版,很多人第一反应是装好驱动、pip install 一把梭,结果不是 CUDA 版本报错就是加载权重时 OOM,最后连错误日志都没看懂就放弃了。手动部署真正的门槛不在模型本身,而在环境匹配:GPU 驱动、CUDA 运行时、PyTorch 编译版本、推理框架四者必须对齐,任何一环断链,报错信息都长得像黑匣子。这篇文章按我平时给内部环境做部署的路子,从显存评估、环境准备、权重下载、框架选型一路写到 systemd 守护,把每一步的参数和坑位摆出来。适合手里有一台 Linux 显卡机器、想脱离一键脚本自己掌控部署过程的从业者,读完就能照着搭出一套能跑通、能守住的 DeepSeek 推理环境。
2. 部署环境准备:显存评估、CUDA 匹配与 Python 虚拟环境搭建
2.1 先算显存账:7B 模型在 FP16、INT8、INT4 下各占多少
决定能不能跑 DeepSeek,先看显存,这个结论几乎不需要争论。手动部署时最常见的翻车点,是把“模型权重大小”当成“运行内存占用量”。以 7B 蒸馏版为例,权重参数约 70 亿个,FP16 精度下每个参数占 2 字节,裸权重就是 14GB 左右。但这只是权重的占用,推理过程中还有 KV Cache、激活值和中间张量,实际峰值占用通常是裸权重的 1.3 到 1.5 倍。所以 16GB 显存跑 7B FP16 属于极限操作,加载能成功,生成长文本时极容易 OOM。
常见估算是这样的:显存需求 ≈ 参数量 × 精度字节数 × 1.3。把几个常用精度摆在一起看,选型就清楚了。
| 精度 | 单参数字节 | 7B 模型裸权重 | 建议显存(含推理开销) |
|---|---|---|---|
| FP16 / BF16 | 2 字节 | 约 14GB | 24GB 起 |
| INT8 | 1 字节 | 约 7GB | 12GB 起 |
| INT4 / GPTQ | 0.5 字节 | 约 3.5GB | 8GB 起 |
注意这张表里“建议显存”不是“能加载的显存”,是“跑长文本不翻车的显存”。我一般会在推荐值上再多留 2GB 余量,给 KV Cache 和并发请求用。INT4 量化后模型质量会有轻微下降,但 8GB 显卡也能跑起 7B,这是边缘设备上的常见做法。
动手前先确认显卡实际显存,命令很简单:
nvidia-smi看右上角的显存总量,以及驱动版本和 CUDA 版本号。这里有个关键认知:nvidia-smi显示的 CUDA 版本是驱动支持的最高版本,不是系统里装的 CUDA 工具包版本。PyTorch 装的是自己的 CUDA 运行时,只要驱动支持的最高版本不低于 PyTorch 需要的版本就能跑。很多人在这里被误导,以为要装一个和驱动 CUDA 版本完全一致的 CUDA Toolkit,其实手动部署推理服务根本不需要单独装 CUDA Toolkit。
2.2 用 conda 隔离 Python 环境并安装匹配 CUDA 的 PyTorch
DeepSeek 的推理依赖 PyTorch,而 PyTorch 和 CUDA 的版本匹配是手动部署的第一道坎。我见过太多人图省事,直接在系统 Python 里 pip install,最后把环境搞成一团乱麻。常见的做法是先用 conda 建一个独立环境,把 Python 版本锁定在 3.10 或 3.11,再按目标 CUDA 版本安装 PyTorch。
conda create -n deepseek python=3.10 -y conda activate deepseek pip install torch --index-url https://download.pytorch.org/whl/cu121先解释这三条命令在干什么。第一条创建名为 deepseek 的虚拟环境,Python 锁定 3.10,隔离系统自带的 Python,避免依赖冲突。第二条激活环境,后续所有安装都落在这个环境里。第三条指定从 PyTorch 官方源安装 CUDA 12.1 编译版本的 torch,--index-url参数是告诉 pip 去哪个源找包,这个参数在手动部署里非常关键,不指定的话默认源可能装到 CPU 版本,模型加载时直接报 CUDA 不可用。
装完验证一下 PyTorch 是否真的拿到了 GPU:
import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.device_count())这三行分别输出 PyTorch 版本、CUDA 是否可用、GPU 数量。如果torch.cuda.is_available()返回 False,别急着往下走,回 2.1 节重新核对驱动版本和 PyTorch 编译版本的匹配关系。这里多说一句:驱动版本如果太老,即使 PyTorch 装的是 CUDA 12.1 的轮子,运行也会报 no kernel image 错误,这是后续避坑章会细说的经典翻车现场。
3. 模型权重下载:国内平台的命令行拉取与完整性校验
3.1 用 modelscope 命令行把 DeepSeek 权重拉回本地
环境就绪后,下一步是把模型权重下载到本地。DeepSeek 权重在很多平台都有分发,手动部署时我一般优先选国内可直接访问的平台,下载速度有保障,断点续传也更省心。前面建好的 conda 环境里直接装对应命令行工具:
conda activate deepseek pip install modelscope modelscope download --model deepseek-ai/DeepSeek-R1-Distill-Qwen-7B --local_dir ./models/deepseek-7b这条命令会把整个仓库的权重文件拉到当前目录下的./models/deepseek-7b文件夹里。--model参数接受完整的模型标识,--local_dir指定本地存放路径,不加这个参数的话默认会存到缓存目录,手动部署时不建议用默认路径,因为后面写服务脚本时要引用固定路径,缓存目录一换就找不到权重了。
下载过程中如果断网或中断,modelscope 支持断点续传,重新执行同一条命令会接着下载未完成的部分,不用删掉重来。这是手动部署时很实用的特性,动辄几十 GB 的权重文件一次性下完的概率并不高。
下载完成后先看一眼目录结构,确认文件齐了:
ls -lh ./models/deepseek-7b正常会看到一系列.safetensors权重文件、一个config.json、tokenizer.json和分词器相关文件。config.json里的model_type和architectures字段决定了后面用什么加载方式,值得打开看一眼。
3.2 磁盘余量与 sha256 校验:下载完别急着加载
权重下载完直接加载是手动部署里最常见的急性子操作。几十 GB 的文件在传输过程中有可能因网络波动或磁盘写入异常产生截断,而截断后的文件在加载时才报错,错误信息还不直观。我一般会在加载前做两件事:查磁盘余量、算文件完整性。
du -sh ./models/deepseek-7b df -h /home sha256sum ./models/deepseek-7b/*.safetensorsdu统计整个权重目录的实际占用,df看目标磁盘分区的剩余空间。推理时除了权重本身,还要写日志、存临时文件,磁盘至少留出权重体积的 1.5 倍余量才从容。sha256sum对每个权重文件算校验值,算完后的输出和模型发布页面上给的官方校验值逐条比对,能对上说明文件完整。
这一步看起来繁琐,但能挡住一类特别隐蔽的故障:文件大小对、加载报错却指向维度不匹配,排了半天才发现是下载截断。手动部署没有一键脚本兜底,完整性校验是成本最低的防线。
4. 推理框架选型:Transformers、vLLM、Ollama 该怎么选
4.1 三类框架的适用边界:从单卡试跑到高并发服务
权重就位后,选择哪套推理框架直接决定部署形态。常见的做法是三类框架里选一个:Transformers、vLLM、Ollama。先说结论:单机调试、需要灵活改生成参数时选 Transformers;面向多用户高并发、需要 OpenAI 兼容接口时选 vLLM;追求快速验证、不想写代码时选 Ollama。
| 框架 | 显存效率 | 并发能力 | 调试灵活性 | 适用场景 |
|---|---|---|---|---|
| Transformers | 中等 | 低,单请求串行 | 高,可改任意生成参数 | 功能验证、参数调优 |
| vLLM | 高,PagedAttention 复用 KV Cache | 高,支持并发批处理 | 中,参数通过启动项控制 | 对外提供服务、生产部署 |
| Ollama | 中 | 中 | 低,封装较黑盒 | 个人快速试用、CPU 机器 |
Ollama 在手动部署这个话题下其实是个“反手动”选项,它帮你把环境、版本、依赖全包了,出了问题排查空间很小。标题里强调的是手动部署,所以重点落在 Transformers 和 vLLM 上:前者帮你理解模型加载和生成的每个环节,后者帮你把服务真正跑起来扛住流量。
4.2 用 Transformers 手写最小推理脚本:保住调试主动权
Transformers 是理解 DeepSeek 运行机制的最佳入口。在 conda 环境里补装依赖后,写一个最小脚本就能完成加载和生成:
pip install transformers accelerateaccelerate 是配合 device_map 做多卡或显存自动切分的库,手动部署时强烈建议装上,后面会看到它的作用。
import torch from transformers import AutoModelForCausalLM, AutoTokenizer model_name = "./models/deepseek-7b" tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForCausalLM.from_pretrained( model_name, torch_dtype=torch.float16, device_map="auto", max_memory={0: "14GiB"}, ) messages = [{"role": "user", "content": "用一句话介绍你自己"}] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, return_tensors="pt" ).to(model.device) outputs = model.generate( inputs, max_new_tokens=256, do_sample=True, temperature=0.7, top_p=0.9, ) print(tokenizer.decode(outputs[0], skip_special_tokens=True))这段脚本是手动部署的最小闭环。torch_dtype=torch.float16把权重以半精度加载,显存占用减半;device_map="auto"让 accelerate 自动分配显存;max_memory={0: "14GiB"}限制单卡最大使用量,防止加载时把显存撑爆。apply_chat_template是现在主流对话模型的标准用法,模板会处理好对话格式,不要自己手工拼 prompt。max_new_tokens控制生成长度,do_sample配合temperature和top_p控制随机性。
这个脚本最大的价值不在性能,而在可调试性。生成结果不对时可以单独调 temperature、top_p、repetition_penalty,每一处改动都能立刻看到效果。确认生成效果满意后,再考虑换 vLLM 提升并发。
4.3 用 vLLM 启动 OpenAI 兼容服务:并发参数怎么设
Transformers 脚本跑通后,对外提供服务就得换 vLLM。vLLM 用 PagedAttention 管理 KV Cache,显存利用率比 Transformers 高不少,更重要的是它自带 OpenAI 兼容的 HTTP 接口,客户端接入成本低。
pip install vllm vllm serve ./models/deepseek-7b \ --tensor-parallel-size 1 \ --max-model-len 4096 \ --gpu-memory-utilization 0.9 \ --port 8000vllm serve启动一个 HTTP 服务,--tensor-parallel-size 1表示单卡推理,多卡时改成卡数,模型会自动切分。--max-model-len 4096是上下文窗口上限,这里我强调一下:这个值不是越大越好,它直接决定 KV Cache 预留多少显存,设太大单卡会 OOM,设太小长对话会被截断。--gpu-memory-utilization 0.9表示允许模型最多占用 90% 显存,留出 10% 给 CUDA context 和碎片,这是生产环境的常用做法,不要设成 1.0。
启动后用 curl 验证接口:
curl http://127.0.0.1:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{"model":"./models/deepseek-7b","messages":[{"role":"user","content":"你好"}],"max_tokens":64}'返回的 JSON 里包含生成的文本和 token 统计,说明服务已经正常工作了。model字段传的是启动时的模型路径,这个细节容易踩坑,后面避坑章会展开说。
5. 部署避坑手册:5 个 Linux 下跑 DeepSeek 的典型翻车现场
5.1 CUDA error: no kernel image is available 是驱动和 PyTorch 打架
现象:加载模型时直接报RuntimeError: CUDA error: no kernel image is available for execution on the device。第一反应通常是显卡坏了,其实绝大多数情况是驱动支持的 CUDA 版本低于 PyTorch 编译用的 CUDA 版本。原因:PyTorch 的 CUDA 轮子里包含的是特定计算能力的 kernel,驱动太老时这些 kernel 无法在当前 GPU 上启动。解决:先nvidia-smi看驱动支持的最高 CUDA 版本,再回头选用匹配的 PyTorch 轮子,或者升级 GPU 驱动。不要试图用 CUDA Toolkit 版本去替代驱动,推理部署不需要独立 Toolkit。
5.2 OOM 不等于显存不够:device_map 与 max_memory 没设置
现象:CUDA out of memory报错出现在模型加载阶段。很多人会误判为“这卡跑不动这个模型”,直接放弃或者去买新卡。原因:from_pretrained默认把模型全部加载到单张显卡,如果没设置device_map和max_memory,16GB 显存加载 14GB 权重加上中间张量,必然溢出。解决:按 4.2 节的写法,显式指定device_map="auto"和max_memory={0: "14GiB"},剩余空间留给 KV Cache。多卡机器还可以用max_memory={0: "10GiB", 1: "10GiB"}把模型拆到多张卡上。
5.3 进程被系统杀掉:SWAP 和 OOM Killer 的关系
现象:服务跑着跑着进程突然消失,nvidia-smi显示 GPU 空闲,日志也断了。查系统日志才发现是 OOM Killer 干掉了进程。原因:vLLM 或 Transformers 在生成长文本时需要额外内存,宿主机内存不足时 Linux 的 OOM Killer 会挑选占用高的进程直接杀掉,GPU 进程往往是首选。解决:部署前用free -h检查内存,不够就调整 SWAP 或用systemd的MemoryMax限制进程内存。这个坑在多人共用服务器时尤其频繁,别人跑的任务吃光了内存,你的推理进程就跟着遭殃。
5.4 下载中断导致权重不完整:加载时报错看不出是文件问题
现象:加载权重时报safetensors文件读取异常,或者报维度不匹配、键缺失,指向模型文件本身。原因:权重文件下载中断后没有自动续传,文件不完整但体积看起来差不多,加载时才会暴露。解决:按第 3 章的流程,用sha256sum比对官方校验值,确认完整再加载。如果发现是下载不完整,重跑下载命令续传即可。这个错最容易迷惑人的地方在于报错信息里根本不提“文件不完整”,排查半天环境才发现是下载问题。
5.5 vLLM 请求超时:max-model-len 和并发数设置偏大
现象:vLLM 启动正常,单请求也正常,一旦并发上来就大量超时。原因:--max-model-len设得过大,KV Cache 预留过多显存,导致实际能并发处理的请求数大幅下降;--gpu-memory-utilization设太满,没有给调度留余量,请求排队时间过长。解决:把--max-model-len从 8192 降到 4096 或 2048,--gpu-memory-utilization从 0.95 降到 0.9。这类参数没有绝对标准,需要结合业务的实际输入长度和并发数做压测调整,一次部署到位是玄学,逐步调才是常态。
6. 部署完成后的守护与验证:systemd 托管服务 + 一条 curl 探活
服务跑起来了,接下来要做的是让它能在服务器重启后自己恢复。手动部署的完整度看两点:进程有没有人看着、挂了能不能自动拉起。vLLM 这类长驻服务,我一般用 systemd 托管。先写一个 service 文件:
[Unit] Description=DeepSeek vLLM Service After=network-online.target [Service] User=deploy WorkingDirectory=/home/deploy ExecStart=/home/deploy/miniconda3/envs/deepseek/bin/vllm serve ./models/deepseek-7b --tensor-parallel-size 1 --max-model-len 4096 --gpu-memory-utilization 0.9 --port 8000 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target注意ExecStart里用的是 conda 环境里的 vllm 绝对路径,不要写vllm裸命令,否则 systemd 的 PATH 环境里找不到这个命令。Restart=on-failure是核心配置,进程异常退出时 5 秒后自动拉起,比手动nohup可靠得多。写完执行:
sudo cp deepseek.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now deepseek sudo journalctl -u deepseek -fenable --now同时完成开机自启和立即启动,journalctl实时看日志。之后每次调试重启服务,用sudo systemctl restart deepseek就好,不用再手动找进程号。
最后留一个探活习惯:每天定时用 curl 检查接口并记录响应耗时,接口无响应时及时看日志定位。我之前吃过亏,服务没挂但显存泄漏导致响应越来越慢,因为没有探活机制,直到用户投诉才发现。经历过这次之后,我把探活脚本加进了定时任务,再也没犯过同样的错。部署 DeepSeek 不是跑通就算完,能守住的部署才值得投入。希望帮到你。
本文还有配套的精品资源,点击获取