跟着这篇走完,你会在本机把 Qwen3 跑起来:先用命令行聊一轮,再用 HTTP 接口发起一次带上下文的多轮会话。整个过程 5 步,每步都有一条命令能验证自己做对了没有。文中出现的 localhost:11434 是 Ollama 的默认监听地址,模型固定用 qwen3:8b;如果你换了端口或换了 tag,把示例值替换掉即可。
前置条件
| 项 | 要求 | 说明 |
|---|---|---|
| Ollama | 0.34.4 或更高 | 本文按 0.34.4 写,它是 2026-09 的最新稳定版;0.40.0 仍是预发布版,不要用 |
| 磁盘 | 6 GB 以上空闲 | qwen3:8b 的权重文件 5.2 GB,另需一点空间放运行时文件 |
| 内存 | 8 GB 以上 | 8B 模型按默认 Q4_K_M 量化后约 5 GB 常驻,统一内存或显存都能兜住 |
| 网络 | 能访问 ollama.com | 只在首次拉模型时需要下载 5.2 GB,之后可以完全离线运行 |
装完或升级后先跑这条确认版本。
ollama --version
看到 ollama version is 0.34.4 就是对的。Windows 上有些版本只回显一行版本号字符串,内容一致即可;命令直接报 command not found 说明没装成功,回到第一步。版本低于 0.34 时 ollama ps 和 thinking 相关参数的行为会和本文不一致,建议先升级再往下走。
第一步:安装并启动 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 进程在不在,再看是不是被 OLLAMA_HOST 改到了别的地址。
第二步:拉取 qwen3:8b
Ollama 的模型不会随安装包一起下发,要单独 pull 到本地。qwen3 是仓库名,8b 是规格 tag,写全了才能避开歧义。
ollama pull qwen3:8b
下载 5.2 GB,速度取决于网络。qwen3 仓库里还有更小和更大的规格,按机器内存挑一档(完整 tag 列表见 qwen3 模型库页):
| tag | 下载体积 | 上下文 | 适合 |
|---|---|---|---|
qwen3:1.7b |
1.4 GB | 40K | 只验证链路,不追求效果 |
qwen3:4b |
2.5 GB | 256K | 8 GB 内存以下的机器 |
qwen3:8b |
5.2 GB | 40K | 本文用的档位,16 GB 内存机器跑得舒服 |
qwen3:14b |
9.3 GB | 40K | 32 GB 内存以上 |
验证模型是否真的落到本地。
ollama list
输出里出现一行 qwen3:8b、SIZE 列显示 5.2 GB,就算拉好了。列表里没有它,说明前面的 pull 中途失败,重跑一次 ollama pull qwen3:8b 会断点续传。
第三步:用命令行完成一次会话
ollama run 会拉起模型并进入交互提示符,这是最快确认「模型到底能不能答」的方式。
ollama run qwen3:8b
首次执行需要把权重加载进内存,会等几秒到几十秒。加载完出现 >>> 提示符,直接敲问题回车即可。Qwen3 默认开启 thinking,你会先看到一段推理过程,再看到正式回答。聊完输入 /bye 退出。
会话变长以后如果发现模型开始忘掉前面的内容,是默认上下文只有 4096 token 被塞满了。可以在会话里临时抬高。
>>> /set parameter num_ctx 8192
这个设置只对当前会话生效。想改所有会话的默认值,用环境变量起服务:OLLAMA_CONTEXT_LENGTH=8192 ollama serve。
验证。
在 >>> 下输入 用一句话解释什么是栈溢出,能看到先出一段 thinking 再给出答案;输入 /bye 能干净退出回到 shell,这一步就算成了。如果一直停在 pulling manifest,那是网络没通,不是模型问题。
第四步:用 REST API 发一次请求
Ollama 服务同时暴露了一套 HTTP 接口,端口就是刚才验证过的 11434。先发一条单轮请求确认接口通不通。
curl http://localhost:11434/api/chat -d '{
"model": "qwen3:8b",
"messages": [
{ "role": "user", "content": "用一句话说明 /api/chat 和 /api/generate 的区别" }
],
"stream": false
}'
stream 默认是 true,会把响应切成一行一个 JSON 分片推回来。这里显式写成 false,一次拿到完整 JSON,便于确认链路。想看流式效果就把它打开,同时给 curl 加上 -N 关掉输出缓冲。
curl -N http://localhost:11434/api/chat -d '{
"model": "qwen3:8b",
"messages": [{ "role": "user", "content": "从 1 数到 5" }],
"stream": true
}'
验证。
拿第一个请求的返回体,同时满足三条就算通了:"done": true、message.content 非空、eval_count 大于 0。eval_count 是这次实际生成的 token 数,它是 0 就说明模型没产出内容,通常是模型名写错或显存不够导致加载失败。total_duration 和 eval_duration 单位都是纳秒,顺手除一下能得到每秒 token 数。
第五步:把会话接下去
/api/chat 是无状态的,它不记得你上一次请求过什么。所谓多轮会话,就是每轮都把历史消息按顺序拼进 messages 再发一遍。下面这条把第一轮的问和答都带了进去。
curl http://localhost:11434/api/chat -d '{
"model": "qwen3:8b",
"messages": [
{ "role": "user", "content": "我叫阿禾,在做支付网关的限流。" },
{ "role": "assistant", "content": "<上一轮真实的回答原文>" },
{ "role": "user", "content": "我刚才说我在做什么?" }
],
"stream": false
}'
第二条 assistant 消息要填上一轮返回的 message.content 原文,不能自己编一句。这一段就是你以后写客户端时要维护的会话状态:一个按 role 和 content 累积的数组,越聊越长,直到撞上 num_ctx 上限再考虑截断或摘要。
验证。
返回的 message.content 里出现「支付网关」或「限流」,说明上下文真的被带进去了。如果答非所问,先检查 messages 数组里有没有漏掉 assistant 那一条——只塞 user 消息等于把上一轮的答案抹掉,模型自然接不上话。
核心概念
| 概念 | 是什么 | 类比 |
|---|---|---|
| Ollama | 把权重文件、运行参数和推理引擎(llama.cpp / MLX)打包成本地常驻服务的运行时 | 像本地的数据库服务,装好就有一个进程守在 11434 端口 |
| 模型 tag | 仓库名:规格 形式的模型标识,如 qwen3:8b、qwen3:4b |
像镜像 tag,同一个仓库下不同规格 |
| 量化 | 把权重压到 4 bit 左右再存,默认 Q4_K_M,体积能小到三分之一上下 | 像给图片降码率,体积大降、质量损失有限 |
| num_ctx | 一次请求能看到的 token 上限,默认 4096,超出的历史会被截掉 | 相当于工作台面积,放不下的材料只能推到地上 |
/api/chat |
无状态的对话接口,历史会话完全由调用方自己拼 | 和 HTTP 一样天然无状态,服务端不替你记 session |
常见问题
curl: (7) Failed to connect to localhost port 11434
现象:命令行 curl 或客户端都连不上 11434,报 Connection refused,不是超时。
原因:Ollama 服务没起来,或者只绑在别的地址上(容器里最常见,容器内的 localhost 不是宿主机)。
model "qwen3:9b" not found, try pulling it first
现象:请求发出去了,Ollama 回一句 model not found 并让你先 pull。
原因:服务是通的,只是本地库里没有这个名字——tag 写错、规格不存在,或者压根没拉过。
多轮对话到后面报 400,或者模型开始忘掉开头的内容
现象:前几轮正常,聊长了以后要么被服务端拒绝,要么回答里丢掉早先的设定。
原因:历史消息越堆越长,撞上了 num_ctx;默认 4096,条数没超但 token 早就爆了。
Java 客户端里模型名写错,抛的是 NullPointerException
现象:服务端明明只是「没这个模型」,客户端栈里却是 NPE,连模型名都不提。
原因:Ollama 对不存在的模型返回 404、响应体为空,客户端解析空响应体时炸在 HTTP 层。
