ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

DeepSeek-R1本地部署:Ollama/LM Studio/Jan显存避坑

DeepSeek-R1本地部署:Ollama/LM Studio/Jan显存避坑

简介:这份Word文档面向希望在个人电脑或团队环境中私有化运行大模型的技术人员,系统梳理了DeepSeek开源模型的本地部署路径,解决从硬件选型到服务验证的落地难题。正文先给出最低与推荐配置的对照,包括CPU需支持AVX2指令集、16GB内存起步,推荐使用RTX 3090及以上显卡并配32GB内存,同时说明操作系统、Python与CUDA版本的匹配要求;随后以Ollama、LM Studio、Jan三款工具为主线,拆解安装、拉取模型、加载与启动服务的指令差异,并比较各自的优缺点与适用场景,方便读者按硬件条件取舍。最后一部分覆盖部署成功后的接口测试与调用示例,包括用Python客户端访问本地服务端口,帮助读者把模型接入自己的项目。压缩包内为单份docx,约20KB,篇幅紧凑、以命令行示例为主,便于对照操作。目前已有1436人学习,适合具备一定编程基础、希望低成本获取AI能力并做二次开发的读者。

1. 显存告急的那晚:DeepSeek 本地部署先算清的一笔账

前几天帮一个做 NLP 的朋友处理一次安装失败,他把 DeepSeek 本地部署想得太轻:模型拉下来了,ollama serve也亮着,可一问问题风扇起飞、终端卡成幻灯片,十几秒后进程被系统直接回收。他以为是模型文件坏了,卸了重装三遍,实际原因是 14B 的量化权重塞进了一台 16GB 内存的机器。这类安装失败在本地部署里太常见了——工具本身装上只要十分钟,难的是量化等级、内存、显存之间那笔账算不明白。

这篇笔记记的是我在 Linux 和 Windows 上把 DeepSeek-R1 装进本机的完整过程:三款工具(Ollama、LM Studio、Jan)分别怎么装、模型规格怎么挑、服务端口和常驻参数怎么配、跑不通时该看哪个日志。适合手上有独立显卡或大内存机器、想在自己机器上跑一个能离线问答的开发者;只想点两下就用、不打算碰命令行的,直接读第 4 章的图形化那两节也够。

2. 环境与版本选型:16GB 内存到 RTX 3090 之间的那道坎

装之前先把环境列清楚,比装完再返工省事得多。本地跑大模型这件事,卡人的从来不是安装包,而是「我这台机器到底能跑到哪个规格」。同一份权重,7B 和 14B 在体验上是两个东西,在资源占用上也是两个东西,选错了要么跑不动,要么跑得动但慢到没法用。

2.1 三档硬件对照:最低配置、推荐配置和中间的灰区

原始资料给的是一条底线加一条推荐线:最低配置要求 CPU 支持 AVX2 指令集、16GB 内存、30GB 存储;推荐配置是 NVIDIA GPU(RTX 3090 或更高)、32GB 内存、50GB 存储。这两条线之间其实还有一大片灰区,绝大多数人的机器都落在灰区里,所以我把实际能跑起来的档位拆成三档:

档位CPU / 指令集内存可用存储显卡实际能跑什么
底线档支持 AVX2 的四核以上16GB30GB 起无独显或显存小于 8GB7B 量化版,纯 CPU 推理,一问等十几秒
灰区档六核以上32GB50GB8GB~16GB 显存7B 全量、14B 量化版可尝试
推荐档六核以上32GB 以上50GB 以上RTX 3090 级别,24GB 显存14B 舒服,32B 量化版能跑但慢

存储这一栏最容易被低估。30GB 只是底线,模型文件本身加上解压缓存、再加上你后面想多拉几个规格做对比,50GB 很快就满了。我一般会把模型目录单独挂一块盘,系统盘只留工具本体,后面第 3 章会讲怎么改。

AVX2 这条指令集要单独确认,因为它不是「慢一点」的问题,而是某些量化推理内核直接崩给你看。老一点的服务器 CPU、部分低功耗型号都可能缺这条,装完才发现就只能换机器了。

# 确认 CPU 是否支持 AVX2,能打印出 avx2 才继续往下走 grep -o 'avx2' /proc/cpuinfo | head -n 1 # 看内存总量和当前的可用磁盘,模型缓存和解压都要算进去 free -h df -h ~ # 有独显的话,右上角会显示驱动支持的最高 CUDA 版本 nvidia-smi | head -n 12

grep -o只输出匹配到的片段,比整行输出干净;如果没有输出,说明这颗 CPU 不支持 AVX2,别急着往下装,先去查主板和 CPU 型号。df -h ~看的是家目录所在分区,Ollama 默认把模型放在家目录下,这一栏才是真正决定你内存够不够的地方。

2.2 软件底座:Python 3.8+、CUDA 11.7+ 与 PyTorch 的对齐

软件侧的要求看着简单:操作系统 Linux/Windows(推荐 Ubuntu 20.04+)、Python 3.8+、CUDA 11.7+,且 CUDA 需要和 PyTorch 版本匹配。真正出事的地方在最后半句——很多人nvcc --version显示 12.x 就以为万事大吉,结果装了个编译时针对 11.8 的轮子,torch.cuda.is_available()返回 False。

这里有个判断顺序:nvidia-smi右上角的 CUDA Version 是驱动能支持的上限,nvcc --version是本地工具链的版本,PyTorch 轮子要的是它自己编译时用的那个版本。三者不一定要完全相等,但轮子的版本必须小于等于驱动上限。

# 1. 先看驱动上限,这是硬约束 nvidia-smi # 2. 装 PyTorch 时显式指定轮子来源,别让 pip 自己猜 python3 -m pip install torch --index-url https://download.pytorch.org/whl/cu121 # 3. 装完立刻验证,False 就说明版本没对齐,别等跑模型时才发现 python3 -c "import torch; print(torch.__version__, torch.cuda.is_available())"

--index-url参数的作用是把包源钉死在 PyTorch 官方轮子库上,因为默认源里的torch通常是 CPU-only 版本,装完体积小、跑起来慢十倍,还找不到报错原因。第三步那句验证必须跑,返回True才说明显卡真的被接管了。

如果你只用 Ollama 或 LM Studio 这类封装好的工具,其实可以不碰 Python 和 CUDA,它们自带推理后端。但只要你打算自己写脚本调模型、或者用 transformers 直接加载权重,这层底座就必须对齐,否则后面排查会很痛苦——错误信息往往是「CUDA out of memory」,实际却是「根本没识别到 GPU」,方向完全跑偏。

注意:Python 3.8 是底线不是推荐值。3.8 已经比较老,部分新版本依赖包不再提供对应轮子,实际装机时用 3.10 或 3.11 会省很多事,但不要超过工具文档标注的支持上限。

2.3 三款部署工具的适用边界:Ollama、LM Studio、Jan 怎么选

三款工具都能把 DeepSeek 跑起来,但定位差别不小,选错工具会让本来十分钟的事拖成两小时。

工具上手成本模型格式默认端口适合谁
Ollama命令行,几条命令自带仓库拉取11434要接自己代码、要常驻服务、Linux 服务器
LM Studio图形界面,点选为主GGUF / MLX1234想要可视化对话、边调参数边看效果
Jan图形界面,依赖较多GGUF1337需要处理图像加文本的多模态场景

Ollama 的优势是命令行友好、跨 macOS/Linux/Windows、装完就是一条服务;代价是对内存和存储有实际要求,模型一大就顶不住。LM Studio 界面直观、适合刚上手,但要手动去下载和加载模型,模型放哪、上下文开多大全得自己选。Jan 支持多模态模型,图像加文本一起处理是它的长项,代价是要额外装一些依赖项,装不全会卡在加载阶段。

我的习惯是:机器上只留一个主力工具。想接代码就用 Ollama,把它当本地推理服务用;只想聊天和试提示词就用 LM Studio。两个都装、都开服务,很容易在第 5 章那个端口占用的坑里打转。

3. 用 Ollama 装 DeepSeek-R1:从拉模型到 11434 端口跑通

Ollama 这条线是我在 Linux 上最常用的,因为它装完即是服务,脚本和前端都能直接连。整个过程分四步:装工具、拉模型、把服务配成常驻、最后用接口验证一次。

3.1 安装 Ollama 并确认版本号

三个平台的装法不一样。macOS 和 Windows 从官网下载对应安装包,双击走完就行;Linux 上更省事,官方脚本会把二进制装好、顺手注册成 systemd 服务。

# Linux 一键安装,脚本执行完 ollama 已经在跑 curl -fsSL https://ollama.com/install.sh | sh # 验证:能打印版本号才算装好,例如 ollama version is 0.5.6 ollama --version # 看清楚二进制装到哪个路径了,后面排查 PATH 问题要用 which ollama

-fsSL四个参数合起来的意思是:失败不输出错误页、静默模式、出错也返回非零、跟随重定向。少写一个f,脚本下载失败时你会得到一堆 HTML 而不是报错。ollama --version输出的是版本号,如果报「command not found」,八成是/usr/local/bin不在 PATH 里,用which确认路径后手动加一下。

Windows 上装完记得重开一个终端,环境变量是安装时写进去的,老终端读不到。这是新手最常卡住的一步,现象是「明明装完了却提示命令不存在」。

3.2 拉取 deepseek-r1:7b、14b、32b 的资源换算

模型不是越大越好,是越大越吃资源。拉之前先看自己的内存和显存,再决定规格。

# 不带 tag 会拉默认那一版,体积最大,先别急着这么干 ollama pull deepseek-r1 # 按配置挑规格:7b 对中等配置友好,14b 起要更宽的显存 ollama pull deepseek-r1:7b ollama pull deepseek-r1:14b # 拉完核对清单,确认名字和体积对得上 ollama list

deepseek-r1后面那个:7b是 tag,决定参数规模。7B 模型适合中等配置的电脑,14B 或 32B 需要更高的硬件支持,这是原始资料里给的分档,实际体验也基本吻合:7B 在 16GB 内存的机器上能跑,回答质量够日常问答和代码补全;14B 明显更稳,但内存要往 32GB 走;32B 不是不能跑,是跑起来之后你得接受每秒几个 token 的速度。

体积上大概有个数量级概念:7B 的量化权重在 4~5GB 量级,14B 接近 10GB,32B 到 20GB 上下,具体数字随量化等级浮动,不同 tag 差别不小。所以ollama list里那一列 SIZE 要认真看,它直接决定你的磁盘和内存预算。

拉取过程中断是常事,网络抖动、磁盘写满都会中断。重新执行同一条ollama pull会断点续传,不用删了重来。判断依据是进度条会从上次的百分比接着走,而不是从 0 开始。

3.3 ollama serve 常驻与三个必须改的环境变量

装完之后 Ollama 通常已经在后台跑了,但你要接自己的服务、或者想让同网段的其他机器连进来,就得改成可控的常驻方式。

# 前台跑,方便盯日志;关掉这个终端服务就没了 ollama serve # 需要对外监听时,先设置这两个变量再启动 export OLLAMA_HOST=0.0.0.0:11434 # 默认只监听 127.0.0.1,改成全网卡 export OLLAMA_MODELS=/data/ollama/models # 模型目录挪到大盘,别塞系统盘 export OLLAMA_KEEP_ALIVE=30m # 模型在显存里驻留多久 ollama serve

OLLAMA_HOST是最常被忽略的一个:默认只监听本机回环地址,所以你在另一台机器上访问 11434 永远连不上,而本机测试一切正常。改成0.0.0.0:11434之后才对外可达。OLLAMA_MODELS建议在第一次拉模型之前就改,改晚了还得把已有模型搬过去。OLLAMA_KEEP_ALIVE控制模型加载后在显存里待多久,默认值偏短,反复调用时会反复加载卸载,体感非常卡;调到 30m 之后连续对话明显顺畅。

Linux 上更稳的做法是写 systemd 覆盖配置,这样重启机器也不丢参数:

# /etc/systemd/system/ollama.service.d/override.conf [Service] Environment="OLLAMA_HOST=0.0.0.0:11434" Environment="OLLAMA_MODELS=/data/ollama/models" Environment="OLLAMA_KEEP_ALIVE=30m" Environment="OLLAMA_NUM_PARALLEL=2"
# 改完必须 daemon-reload,否则新配置不会生效 sudo systemctl daemon-reload sudo systemctl restart ollama systemctl status ollama --no-pager

OLLAMA_NUM_PARALLEL=2是并发数,设成 2 表示同时处理两个请求。这个值不是越大越好,每路并发都要占一份上下文显存,显存不够时调大反而更容易 OOM。daemon-reload这步漏掉是经典翻车点:配置文件改得漂漂亮亮,systemctl restart也执行了,参数就是不生效,其实是 systemd 还拿着旧单元文件。

3.4 用 OpenAI 兼容接口做第一次调用

服务起来之后,最省事的验证方式不是浏览器,而是直接用代码打通,因为代码能跑通就说明接口层没问题了。

from openai import OpenAI client = OpenAI( base_url="http://localhost:11434/v1", # Ollama 提供的 OpenAI 兼容层 api_key="ollama", # 本地无鉴权,占位字符串即可 ) resp = client.chat.completions.create( model="deepseek-r1:7b", # 必须和 ollama list 里的名字一致 messages=[{"role": "user", "content": "用三句话解释什么是模型量化"}], temperature=0.7, # 0.2 偏稳,0.8 以上发散 max_tokens=512, ) print(resp.choices[0].message.content)

base_url末尾的/v1不能少,少了会 404,而且报错信息不直观。api_key在本地部署里没有实际意义,但 SDK 会校验这个字段非空,所以随便填一个。model字段必须和ollama list输出完全一致,写成deepseek-r1而实际拉的是deepseek-r1:7b,有的版本能自动补全,有的直接报模型不存在。

temperature是最值得调的参数:做结构化抽取、代码生成这类要求稳定的任务,压到 0.2 左右;写文案、头脑风暴就往 0.8 走。max_tokens建议第一次设小一点,先确认链路通,再逐步放大。

注意:R1 系列会把推理过程单独放在reasoning_content字段里,正文在content里。如果你的客户端只读content,会看到答案「没有推理过程」,这不是模型没思考,是字段没取对。

4. 图形化两条路:LM Studio 的 GGUF/MLX 与 Jan 的多模态

不想碰命令行的人走这两条线,界面点选为主,但格式选择和端口配置这两处该懂还得懂,不然会卡在「下载完了却加载不了」。

4.1 LM Studio:GGUF 与 MLX 怎么选、1234 端口怎么开

安装很简单,去官网找适配系统的版本下载安装即可。真正需要判断的是模型格式:Windows 或 Linux 系统选 GGUF 格式,Apple 处理器的 MacBook 选 MLX 格式。这两个格式不通用,下错了在 Local Models 里根本加载不出来,而界面不会明确告诉你「格式不对」,只会加载到一半失败。

流程是:打开 LM Studio,切到 Discover 标签页,搜索「DeepSeek R1」,按系统选格式,下载。下载完成后回到 Local Models 找到它,点 Load 加载。然后进 Developer 标签页,开启 Start Server,等 http://localhost:1234 可访问,模型就起来了。

加载这一步有两个参数值得手动改:

参数默认建议说明
Context Length偏小4096~8192太小会莫名截断对话,太大吃显存
GPU Offload自动尽量拉满显存够就全卸载到显卡,速度差几倍
量化等级按推荐Q4_K_M 优先体积和质量的平衡点,先跑通再换更高

上下文长度是新手最容易忽略的:设成 2048 之后,聊到第三轮模型就开始「忘事」,看起来像模型笨,其实是超长被截断了。GPU Offload 那栏如果显存不够,界面会给你一个部分卸载的方案,能跑但慢,加显存才是根治。

# 服务起来后先探一下模型列表,有返回说明 1234 端口通了 curl -s http://localhost:1234/v1/models | head -c 400

head -c 400限制输出前 400 字节,是因为完整模型列表可能很长,先看头一段能判断格式对不对。返回 JSON 里data数组非空就说明服务正常。

4.2 Jan:从模型仓库拉 GGUF、1337 端口与依赖补装

Jan 的安装同样是官网下载对应系统版本。它的特点是模型来源更开放:去模型仓库搜索「unsloth gguf deepseek r1」,找到后点「使用此模型」,选择 Jan,模型会自动在 Jan 里打开并开始下载。这条链路比手动下载文件再导入省事得多。

下载完成后选中模型点 Load 加载,Jan 会自动在 http://localhost:1337 启动服务。它也提供 OpenAI 兼容风格的接口,接法和 Ollama 基本一致,只换 base_url。

# Jan 的本地服务探活,1337 是它的默认端口 curl -s http://localhost:1337/v1/models

Jan 这条线最常见的卡点是依赖项。它支持多模态,图像加文本的场景要额外装运行时组件,装不全的时候表现为「模型加载成功但一传图片就报错」。这类错误在日志里写得比较含糊,我的处理顺序是先只跑纯文本,确认文本链路通了,再单独装多模态那部分依赖,把问题范围缩到最小。

4.3 三款工具的端口、模型目录与接口差异

三套跑起来之后,最容易搞混的是端口和模型目录。我踩过一次:Ollama 和 LM Studio 同时开着,脚本里 base_url 写的是 1234,结果连到了 LM Studio 上,模型名对不上,报了个莫名其妙的错。

对比项OllamaLM StudioJan
默认端口1143412341337
接口风格OpenAI 兼容/v1OpenAI 兼容/v1OpenAI 兼容/v1
模型格式自带仓库格式GGUF / MLXGGUF
模型存放OLLAMA_MODELS指定设置里的模型目录应用数据目录
常驻方式systemd 服务界面开关界面开关
命令行友好度高低低

记住一句话就够了:11434 是 Ollama,1234 是 LM Studio,1337 是 Jan。写脚本前先用curl探一下对应端口,确认连的是你以为的那一个。三个服务同时开着不会互相冲突(端口不同),但显存会互相抢,机器上同时加载两个 7B 模型,大概率两个都变慢。

5. 避坑与排查:五个最容易把人劝退的现场

下面这几条都是我在真机上撞过的,按「现象 → 原因 → 解决」记,方便你对照。

5.1 拉模型卡在 99% 不动,或者中途 connection reset

现象:ollama pull跑到 98%、99% 就停住,进度条十几分钟不动;或者直接报连接重置退出。

原因:模型文件是分片下载的,最后一小段经常是校验和合并阶段,磁盘 IO 慢的时候看起来像卡死;连接重置多半是网络抖动,或者磁盘剩余空间不够写入临时文件。

解决:先df -h看目标分区剩余空间,模型体积的两倍是安全线;空间够就 Ctrl+C 中断后重跑同一条命令,Ollama 会断点续传。连续失败三次以上,把OLLAMA_MODELS换到另一块盘再试,排除磁盘问题。

5.2 模型加载到一半进程消失,日志里是 killed

现象:ollama run或接口调用后没反应,过一会儿进程直接没了;dmesg里能看到 oom-killer 的记录。

原因:内存不够。模型加载时要把权重读进内存再往显存搬,这个瞬间的内存峰值远高于模型文件本身。16GB 内存硬上 14B,基本必挂。

解决:降规格到 7B,或者把OLLAMA_NUM_PARALLEL调到 1 减少并发占用,再不行就加内存。判断方法很简单:

# 看系统有没有触发 OOM kill,有记录就说明是内存问题而不是模型问题 dmesg -T | grep -i "killed process" | tail -n 5 free -h

-T让时间戳可读,tail -n 5只看最近五条。这条命令能把「模型坏了」和「内存不够」区分开,省下重装的三小时。

5.3 11434 连不上,但本机 curl 正常

现象:本机curl http://localhost:11434有返回,同一网段另一台机器访问就超时。

原因:OLLAMA_HOST还是默认的127.0.0.1,只监听回环地址。另外防火墙没放行也会这样。

解决:按 3.3 节改成0.0.0.0:11434,重启服务,然后确认监听状态:

# 看 11434 到底监听在哪个地址上,127.0.0.1 就说明没改成功 ss -lntp | grep 11434

输出里应该是0.0.0.0:11434或*:11434。仍然是127.0.0.1:11434,就回去检查环境变量是不是写在了错误的 service 单元里,或者daemon-reload漏了。

5.4 端口被占用,服务起不来

现象:启动时报address already in use,或者界面显示服务已启动但请求全失败。

原因:上一个实例没退干净,或者 LM Studio 和别的本地工具抢了同一个端口。图形化工具关窗口不等于关服务,后台进程还在。

解决:先定位占用进程再决定杀谁:

# 查 1234 / 1337 / 11434 三个端口分别被谁占了 ss -lntp | grep -E ':(1234|1337|11434)'

-E是扩展正则,三个端口一次查完。确认 PID 后kill掉,或者干脆换端口——Ollama 改OLLAMA_HOST,LM Studio 和 Jan 在设置里改。我一般不改端口,直接把不用的那个工具的服务关掉,端口换来换去最后自己都记不清。

5.5 回答反复输出思考过程、答到一半截断、或者出现乱码

现象:回复里全是「让我想想」「首先我们需要」,真正的答案迟迟不出现;或者答到一半硬停;偶尔还夹着乱码字符。

原因:三个不同的问题。反复输出思考过程是 R1 的特性,推理内容在reasoning_content字段,前端把它当正文渲染了;答到一半停住是max_tokens或上下文长度设小了;乱码多半是流式输出解码没处理好,或者终端编码不是 UTF-8。

解决:先分清是哪个。取字段时同时读content和reasoning_content,只展示后者之外的部分;max_tokens往上调一档,Ollama 默认上下文也建议显式设大;乱码先换curl验证是不是前端问题。

# 分开取两个字段,避免推理过程混进正文 msg = resp.choices[0].message reasoning = getattr(msg, "reasoning_content", None) # R1 特有,可能为空 answer = msg.content print("思考:", (reasoning or "")[:200]) print("回答:", answer)

getattr加默认值是为了兼容非 R1 模型,那些模型没有这个字段,直接取属性会抛异常。这样写一份代码能同时跑 R1 和其他模型。

6. 装完怎么验证:三层自检和一次端到端跑通

装完不等于跑通,跑通不等于能长期用。我给自己定的验证分三层,从下往上,每层不过就不往上走。

6.1 三层自检:进程、接口、生成质量

层级验证命令期望结果不过说明什么
进程层systemctl status ollama --no-pageractive (running)服务没起来,看 journalctl
端口层ss -lntp | grep 11434监听在预期地址环境变量没生效
接口层curl -s localhost:11434/v1/models返回模型名列表模型没拉成功或名字不对
生成层一句 20 字的提问10 秒内有完整回复资源不够或参数设错

进程层和端口层是秒级判断,接口层能确认模型真的被注册了,生成层才是最终验收。很多人跳过前三层直接问问题,一旦失败就分不清是服务没起、模型没拉、还是资源不够。

# 一次跑完前三层,输出对得上再进第四层 systemctl is-active ollama ss -lntp | grep 11434 curl -s http://localhost:11434/v1/models | python3 -m json.tool | head -n 20

python3 -m json.tool把返回的压缩 JSON 格式化,模型名一眼能看清;head -n 20防止列表太长刷屏。三步全过,再发一句提问,计时看多久出第一个字。

6.2 端到端压一次:并发和长文本才是真考验

单次问答通过只是热身。真正暴露问题的是连续调用和长上下文,我一般会跑一个短压测:

import time from openai import OpenAI client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama") start = time.time() # 连发三次,观察第二次之后是否明显变快(模型已驻留显存) for i in range(3): t0 = time.time() r = client.chat.completions.create( model="deepseek-r1:7b", messages=[{"role": "user", "content": f"第{i+1}次:简述量化的作用,50字以内"}], max_tokens=256, ) print(f"第{i+1}次耗时 {time.time()-t0:.2f}s,长度 {len(r.choices[0].message.content)}") print(f"总耗时 {time.time()-start:.2f}s")

判断标准:第一次可能慢(要加载模型),第二次、第三次应该明显变快,这说明OLLAMA_KEEP_ALIVE设对了,模型没被反复卸载。如果三次耗时一样慢,回去把驻留时间调长;如果第二次直接报错,那是显存不够,并发时被挤爆了。

再补一个长文本测试:丢一段两千字左右的中文进去让它摘要。这一步能验证上下文长度是不是真开到了你以为的值——很多「模型变笨」的反馈,最后都是上下文被默认值截断了。

从那以后我每次装完新机器,都会把这四层验证强制走一遍,哪怕只是换个模型 tag。因为最容易出问题的不是第一次装,是第三次懒得验证的时候。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进