StackTraces
DeepSeek-R1从零跑通

从零跑通 DeepSeek-R1 + Ollama:5 步,外加 4 个容易卡住的地方

@debug_master2026-09-30

跟着这篇走完,本机就能把 DeepSeek-R1 跑起来。先用命令行跟它聊一轮热热手,再调 /api/chat 发请求,让响应里 message.thinking(推理思考过程)和 message.content(最终回答)分两个字段给你。

整个流程 5 步,每步结尾都附一条 curl 或 ollama 命令验证你这步有没有走对。localhost:11434 是 Ollama 的默认监听端口,模型本文固定用 deepseek-r1:8b(即 5.2 GB 的 Q4_K_M 蒸馏版,基座是 Qwen3-8B,和 deepseek-r1:latest 指向同一份权重)。

如果你换了端口,或者改用 1.5b / 14b / 32b / 70b 这些 tag,把示例值替换掉就行,整套命令照样能跑。还没装过 Ollama 的,先去从零跑通 Ollama + Qwen3 本地对话把服务拉起来再回来。

DeepSeek-R1:从零跑通的 5 个步骤

前置条件

项 要求 说明
Ollama 0.34.4 或更高 0.40.0 仍是预发布版,不要用
磁盘 6 GB 以上空闲 deepseek-r1:8b 是 DeepSeek-R1-0528-Qwen3-8B 蒸馏版,Q4_K_M 量化 5.2 GB
内存 16 GB 以上(8b 推理)/ 32 GB+(14b)/ 64 GB+(32b)/ 96 GB+(70b) 8B 加载后常驻约 5 GB;大模型按 tag 推
网络 能访问 ollama.com 首次拉模型需下载 5.2 GB,之后可完全离线

先跑这条确认版本。

ollama --version

看到 ollama version is 0.34.4 就满足条件。命令报 command not found 说明 Ollama 没装成功,先解决再往下走。

第一步:安装并启动 Ollama

macOS 和 Linux 用同一条安装脚本,Windows 用 PowerShell。不想跑脚本的话,去官方下载页拿各平台的图形安装包。

# macOS / Linux
curl -fsSL https://ollama.com/install.sh | sh
# Windows(PowerShell)
irm https://ollama.com/install.ps1 | iex

装完之后 macOS 和 Windows 上 Ollama 会常驻菜单栏并自动拉起服务,Linux 上安装脚本会注册 systemd 服务并立即启动。这一步不用你手动跑 ollama serve,除非你跑在 Docker 或纯命令行环境里,那才需要自己起进程。

验证服务在监听默认端口。

curl http://localhost:11434/api/version

返回 {"version":"0.34.4"} 说明服务在跑,可以进入下一步。返回 curl: (7) Failed to connect to localhost port 11434 是服务没起 / OLLAMA_HOST 被改到别的地址 / 容器内 localhost 指自己,看 常见问题 第 1 项。

第二步:拉 deepseek-r1:8b

Ollama 的模型不会随安装包一起下发,要单独 pull 到本地。deepseek-r1 是仓库名,8b 是规格 tag,写全了才能避开歧义。

ollama pull deepseek-r1:8b

下载 5.2 GB,速度看网络。deepseek-r1 是仓库名,8b 是规格 tag——写全了才能避开歧义。

这里的 8b 实际是 DeepSeek-R1-0528-Qwen3-8B(arch=qwen3、parameters=8.19B、Q4_K_M 量化、128K 上下文),跟 deepseek-r1:latest 指向同一份 blob。

deepseek-r1 仓库下还有更小和更大的规格,按机器内存挑一档:

tag 磁盘 上下文 适合
deepseek-r1:1.5b 1.1 GB 128K 只验证链路
deepseek-r1:8b 5.2 GB 128K 本文用
deepseek-r1:14b 9.0 GB 128K 32 GB 内存
deepseek-r1:32b 20 GB 128K 64 GB 内存
deepseek-r1:70b 43 GB 128K 96 GB+ 内存

验证模型是否真的落到本地。

ollama list

输出里出现一行 deepseek-r1:8b、SIZE 列显示 5.2 GB,就算拉好了。列表里没它,说明前面的 pull 中途失败。报 Error: pull model manifest: file does not exist 一般是 tag 写错或大小写错(比如 deepseek-r1:8B),看 常见问题 第 2 项。

第三步:用命令行完成一次 thinking 会话

ollama run 会拉起模型并进入交互提示符,这是最快确认「模型到底能不能答」的方式。

ollama run deepseek-r1:8b

首次执行要把权重加载进内存,会等几秒到几十秒——第一次跑这种规模模型基本都有这一步等加载的耐心挑战,别误以为进程卡死了。加载完出现 >>> 提示符,直接敲问题回车即可。

DeepSeek-R1 跟一般聊天模型不一样:会先输出 thinking(推理过程),再输出 content(正式回答)。CLI 默认就开着 thinking,不用额外开关。

在 >>> 下输入:

>>> 用一句话解释什么是栈溢出
>>> /bye

能看到先出一段 thinking 再给最终答案;/bye 干净退出回到 shell,这一步就算成了。如果进程被 kill 或报 Error: model requires more system memory,多半是上一个模型还在 keep-alive 缓存里没释放,看 常见问题 第 3 项。

第四步:用 REST API 发一次带 thinking 的请求

Ollama 服务同时暴露了一套 HTTP 接口,端口就是刚才验证过的 11434。先发一条单轮请求确认接口通,同时验证 think 参数能让响应里出现 message.thinking 字段。

curl http://localhost:11434/api/chat -d '{
  "model": "deepseek-r1:8b",
  "messages": [
    { "role": "user", "content": "用一句话说明 /api/chat 的 stream 和 think 参数区别" }
  ],
  "think": true,
  "stream": false
}'

think: true 显式开启思考输出(默认值其实就是 true,写出来主要为了明确);stream: false 一次性拿完整 JSON,便于对照字段。

注意一个容易踩的点:Ollama 响应里用 message.thinking 装思考过程,用 message.content 装最终回答——这跟 DeepSeek 云 API 的 message.reasoning_content 不是同一个字段,把云 SDK 搬过来直接读 reasoning_content 会拿到 undefined。

返回体同时满足四条就算通了:"done": true、message.thinking 非空、message.content 非空、eval_count > 0。

eval_count 是这次实际生成的 token 数——它为 0 就说明模型啥都没吐出来,多半是模型名写错或者显存不够加载失败。

message.thinking 是空或字段缺失,那基本是按 DeepSeek 云 SDK 在 message.reasoning_content 取值、拿到 undefined 的问题了,看 常见问题 第 4 项。

第五步(可选进阶):流式看 thinking 实时回流

把 stream 打开,给 curl 加 -N 关掉输出缓冲,让 /api/chat 一边生成一边返回。

curl -N http://localhost:11434/api/chat -d '{
  "model": "deepseek-r1:8b",
  "messages": [
    { "role": "user", "content": "从 1 数到 5" }
  ],
  "think": true,
  "stream": true
}'

流式响应里 message.thinking 增量分片出现在 message.content 之前——这是肉眼能看到“思考过程一个字一个字地往外冒”的唯一方式。done: true 只在最后一行出现,前面每一行都是中间分片。

关掉 thinking 有几种写法,按你的场景挑:

  • 请求体里把 think 改成 false,或者干脆不写——简单粗暴。
  • 会话内 /set notthink,CLI 默认开启 thinking,临时切到 notthink。
  • CLI 启动时加 --hidethinking,适合脚本里想隐藏思考过程、但仍允许模型内部推理的场景。

核心概念

这张架构图就是整条调用链路的走向——从左到右走一遍,一次带 thinking 的请求的完整路径就看清楚了。

DeepSeek-R1 调用链路架构图

概念 是什么 类比
Ollama 把权重文件、运行参数和推理引擎(llama.cpp / MLX)打包成本地常驻服务的运行时 像本地的数据库服务,装好就有一个进程守在 11434 端口
DeepSeek-R1 / 蒸馏版 DeepSeek-R1 本身是 671B MoE 推理模型;Ollama 上常见的是蒸馏版(1.5b/8b/14b/32b/70b),默认 8b 即 DeepSeek-R1-0528-Qwen3-8B(Q4_K_M 量化,5.2 GB,128K 上下文) 像 GitHub 仓库里的 release tag,同一个仓库下不同规格,挑机器够得动的那个
thinking 字段 /api/chat 响应里 message.thinking 装推理思考过程,message.content 装最终回答;通过请求体 "think": true/false 或 CLI 的 /set think//set nothink 切换 像 LLM 的 inner monologue / 草稿区,思考在前面、答案在后面
num_ctx 一次请求能看到的 token 上限,Ollama 默认 4096,超出历史会被截断;DeepSeek-R1 蒸馏版模型上限 128K,671b 主模型 160K 像工作台面积,放得下的材料在工作台上用,放不下的就推到地上
keep_alive 模型在内存里停留的时间,默认 5m(5 分钟);超出后自动卸载,下一次请求触发重新加载 像酒店退房时间,超过时间房间就释放,下一个客人来再重新办入住

常见问题

curl: (7) Failed to connect to localhost port 11434

现象:命令行 curl 或客户端连不上 11434,报 Connection refused,不是超时。

原因:Ollama 服务没起来;或者只绑在别的地址上(容器里最常见,容器内的 localhost 不是宿主机);或者被 HTTP_PROXY/HTTPS_PROXY/NO_PROXY 没设 localhost/127.0.0.1 劫持。

相关文章:本地起 Ollama 后 curl 11434 报 Connection refused

Error: pull model manifest: file does not exist(或 model "deepseek-r1:8B" not found, try pulling it first)

现象:ollama pull deepseek-r1:8b 直接报 file does not exist,没下任何东西;或者 /api/chat 调用时回 model not found。

原因:tag 是 exact string;常见错例 deepseek-r1:8B(大写)、deepseek-r1:8b-v2(不存在的量化档)、OLLAMA_HOST 指向了别的机器。

相关文章:ollama pull deepseek-r1:8B 报 pull model manifest: file does not exist

CUDA error: out of memory(或进程被 kill / Linux dmesg 报 oom-kill)

现象:拉完后第一次推理直接被 kill;Linux 上 dmesg 报 OOM;有时换更小 tag 反而没事。

原因:模型超过 VRAM/RAM;num_ctx=4096 默认推高 KV cache;上一个模型还在 keep-alive(默认 5 分钟)缓存里没释放。

相关文章:ollama run deepseek-r1:14b 报 out of memory

响应里 message.thinking 字段缺失,或按 message.reasoning_content 取值拿到 undefined

现象:调 /api/chat 返回 JSON 里 message.content 正常但没有 message.thinking;或者按云 SDK 写法在 message.reasoning_content 取值,拿到 undefined/null。

原因:Ollama API 字段名是 message.thinking,不是 DeepSeek 云 API 的 message.reasoning_content;且需要请求体显式 "think": true(不传则按模型 thinking.default,多数情况下仍是 true,但写出来最稳)。

相关文章:把 DeepSeek 云 API 代码接到 Ollama 后 reasoning_content 字段是空

下一步

打开 / 关闭 thinking

CLI 里是 /set think 与 /set nothink 切换,REST 请求里靠 "think": true/false 控制,写脚本如果只想让模型默默想、不想让人看见,就用 --hidethinking。客户端拿到响应后,按 message.thinking 是否非空来决定 UI 折叠,免得 thinking 在终端里一直刷屏。

把 DeepSeek 云 API 代码接到 Ollama 后 reasoning_content 字段是空

拉到更大量级(deepseek-r1:32b / 70b)

量级一上去,体积就从 20 GB 跳到 43 GB;上下文还是 128K,但 OOM 风险会被 keep_alive + num_ctx + 多模型并发一起放大。跑之前先把上一个模型卸干净,别让它占着内存不放手。

ollama run deepseek-r1:14b 报 out of memory

把 Ollama 接到应用框架

本地能跑 DeepSeek-R1 不算完,把 Ollama 接进 Spring AI 或 LangChain4j 才是大多数项目的终点。这步最容易出问题的地方是 starter 依赖、ChatClient / ChatLanguageModel 装配、模型名拼写——starter 没加就直接报 No qualifying bean of type ChatModel。

Spring AI 报 No qualifying bean of type ChatModel

卡在哪一步了?

从零跑通的过程中撞到报错?把命令和输出记下来,帮助下一个刚起步的人。

贡献一条解法