上一篇走通了 llama.cpp 的最小链路:找仓库、挑量化档、下 GGUF、敲一长串参数起服务。链路本身不难,但每换一个模型就要重走一遍,模型文件散落各处,服务也全靠手动管理——这是引擎的视角,离"好用"还差一层壳。这一篇讲的就是那层壳:Ollama,大多数工程师接触本地大模型的第一站。
本文是《本地大模型部署实战》系列第 4 篇,从它与 llama.cpp 的关系与选型讲起,手把手完成安装、拉模型、对话,过一遍命令体系与 REST API,把 OpenAI 兼容端点直接接给现有代码,再用 Modelfile 定制专属模型,最后盘点上下文截断、内存占用这些高频坑。
1、Ollama 与 llama.cpp 的关系
上一篇说过,Ollama、LM Studio 这些工具的推理核心都是 llama.cpp。更准确地说,Ollama 是 2023 年开源的一个 Go 程序,它把 llama.cpp 的 C++ 引擎包进来,在上面补齐了引擎不管的事:模型分发与生命周期管理。ollama pull 从官方注册表下载模型(自动选好量化档),多个模型共享的层去重存储;首次请求时自动加载进显存,空闲 5 分钟自动卸载;服务进程常驻后台,同时暴露原生 REST API 和 OpenAI 兼容 API。
也就是说,上一篇五步的手工链路(找仓库、挑量化、下载、配参数、起服务),在这里被压缩成 pull 加 run 两条命令。代价是控制粒度变粗,两边怎么选,对照如下。
| 维度 | llama.cpp | Ollama |
|---|---|---|
| 获取模型 | 手动去 HuggingFace 挑仓库挑量化档 | pull 一条命令,注册表直供 |
| 参数控制 | 全部命令行可调,精确到层 | 常用项经 options 传入,细项受限 |
| GPU 卸载 | -ngl 精确控制卸载层数 |
自动检测,粗粒度 |
| 服务化 | llama-server 手动起停 |
常驻后台,按需加载、空闲卸载 |
| 适用场景 | 基准测试、极致调优、复现固定配置 | 日常开发、快速试用、给代码接本地模型 |
一句话判断:写代码、做产品、天天换模型试,用 Ollama;跑分对比、卡着显存极限做层卸载实验、要特殊编译选项,回 llama.cpp。两者不冲突——Ollama 底层就是上一篇那套引擎,量化档位、KV 缓存、上下文的账全部照旧成立。
2、安装与第一个模型
2.1、三平台安装
macOS 和 Windows 去官方下载页拿安装包:前者解压拖进 Applications,后者一路下一步 OllamaSetup.exe。装完进程自动常驻(菜单栏或系统托盘可见),监听 127.0.0.1:11434。Linux 用官方脚本一条命令完成。
# Linux:安装并自动配置 systemd 服务
curl -fsSL https://ollama.com/install.sh | sh
# 验证安装
ollama --version
脚本会把二进制装到 /usr/local/bin,注册 systemd 服务开机自启,无需手动 ollama serve。装好后唯一要记住的常识:服务默认只监听本机 11434 端口,别的机器要访问得改监听地址。
2.2、拉取与对话
第一个模型别贪大,8B 是多数开发机的甜区。上一篇已经认识 Qwen3-8B,这里继续用它,拉取命令如下。
ollama pull qwen3:8b
注册表会分层下载(模型本体加配置层),完成后输出如下。
pulling manifest
pulling 22f8f0c9153c... 100% ▕██████████▏ 5.2 GB
pulling 832dd42e6d5a... 100% ▕██████████▏ 7.7 KB
verifying sha256 digest
writing manifest
success
5.2 GB 正是上一篇算过的 8B Q4_K_M 体积——裸标签默认就是这个量化甜区,不用自己挑。接着执行 ollama run qwen3:8b 进入交互对话,会话摘录如下。
>>> 为什么本地推理普遍用量化模型
量化把权重从 16 bit 压到更低位宽,显存占用近似等比下降,
推理也更快。8B 模型 fp16 要 16 GB 显存,Q4_K_M 只要 5 GB 出头,
日常任务的质量损失几乎无感。
>>> /bye
run 发现模型没下载会自动先 pull;/bye 退出会话;会话内还能用 /set parameter num_ctx 8192 临时调参、/show info 看模型详情。到这里,"装好 Ollama 并跟模型说上话"就完成了——但交互终端只是入口,真正的价值在命令体系和 API。
3、命令速查
Ollama 的子命令不多,一表打尽,日常高频的是前五个。
| 命令 | 作用 | 示例 |
|---|---|---|
ollama pull |
下载模型到本地 | ollama pull qwen3:8b |
ollama run |
加载并进入交互(未下载自动拉) | ollama run qwen3:8b |
ollama list |
列出本地已有模型 | ollama list |
ollama ps |
查看当前驻留内存的模型 | ollama ps |
ollama show |
查看模型信息、参数、模板 | ollama show qwen3:8b |
ollama stop |
立即卸载驻留模型 | ollama stop qwen3:8b |
ollama rm |
删除本地模型 | ollama rm qwen3:8b |
ollama cp |
复制模型并重命名 | ollama cp qwen3:8b my-qwen |
ollama create |
从 Modelfile 构建自定义模型 | ollama create dba -f Modelfile |
ollama serve |
手动前台启动服务 | ollama serve |
两个行为值得注意。其一,模型加载后不会立刻释放,默认驻留 5 分钟(OLLAMA_KEEP_ALIVE 可调),期间再请求零冷启动;其二,ollama ps 是排查显存占用的第一现场,它列出的就是当前真金白银占着显存的模型。完整参数见官方 CLI 参考。
4、REST API 调用
服务监听 11434,原生 API 两个核心端点:/api/generate 走单轮 prompt,/api/chat 走多轮消息数组。先用 generate 试试。
curl http://localhost:11434/api/generate -d '{
"model": "qwen3:8b",
"prompt": "用一句话解释 KV 缓存",
"stream": false,
"options": {
"temperature": 0.7,
"num_ctx": 8192
}
}'
options 是结构化传参的入口,上一篇命令行里的 temperature、上下文长度等运行参数都从这里进。不传 stream 时默认 true,响应是一行一个 JSON 的流;调试阶段显式传 false 最直观,拿到单个 JSON 如下。
{"model":"qwen3:8b","created_at":"2026-10-25T20:30:00Z",
"response":"KV 缓存把注意力已算过的键值存下来,避免每个新 token
都重算全部历史,是长上下文推理的核心优化。","done":true,
"context":[...],"prompt_eval_count":14,"eval_count":42}
响应里 eval_count 是生成的 token 数,配合 prompt_eval_count 能粗算吞吐。多轮对话换 /api/chat,请求体与 OpenAI 风格的 messages 数组同构,system 消息也在这里传。
curl http://localhost:11434/api/chat -d '{
"model": "qwen3:8b",
"messages": [
{"role": "system", "content": "你是简洁的编程助手"},
{"role": "user", "content": "Python 怎么逐行读大文件"}
],
"stream": false
}'
返回结构与 generate 类似,正文包在 message.content 里,done 同样标记结束。Windows 用户建议在 Git Bash 里跑 curl,避开 cmd 的引号转义问题。更多端点(embeddings、版本查询等)见 API 文档。
5、OpenAI 兼容端点
真正让 Ollama 成为本地开发事实标准的,是它在同一端口上提供的 /v1 兼容层。Python 的 OpenAI 官方 SDK 只要换一个 base_url,其余代码原样运行。
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama", # 占位即可,本地不校验
)
resp = client.chat.completions.create(
model="qwen3:8b",
messages=[{"role": "user", "content": "一句话介绍 GGUF 格式"}],
)
print(resp.choices[0].message.content)
api_key 随便填个非空字符串,本地服务不校验。这意味着 Agent 系列文章里的代码、LangChain、各类 ChatBox 客户端,把 base_url 指到本地后一行业务逻辑都不用改,账单直接归零。兼容层支持流式、JSON mode、tools 函数调用、base64 图片输入;不支持 tool_choice、logprobs、n 和图片 URL,迁代码时注意。
两个实战技巧。其一,有些第三方工具写死了模型名,可以用 cp 做别名:ollama cp qwen3:8b gpt-4o-mini,让找 gpt-4o-mini 的请求落到本地模型上。其二,OpenAI 协议里没有上下文长度参数(max_tokens 只管输出上限),想扩上下文必须走 Modelfile 或原生 API 的 options,这正是下一节的主场。细节见兼容性文档。
6、Modelfile 与上下文
6.1、自定义角色模型
Modelfile 是 Ollama 的模型"配方文件",语法明显借鉴 Dockerfile:FROM 指定基座,其余指令声明覆盖项,ollama create 把它固化成一个新的本地模型。一个领域助手示例如下。
FROM qwen3:8b
PARAMETER temperature 0.3
PARAMETER num_ctx 8192
SYSTEM """
你是资深 MySQL DBA。回答只围绕数据库领域,
先给结论,再给一句依据;
与数据库无关的问题,礼貌拒答并说明原因。
"""
TEMPLATE """{{- range .Messages }}<|im_start|>{{ .Role }}
{{ .Content }}<|im_end|>
{{ end }}<|im_start|>assistant
"""
四类指令各司其职:FROM 继承基座的权重与默认配置;PARAMETER 覆盖运行参数(temperature 0.3 求稳定,num_ctx 8192 扩上下文);SYSTEM 固化系统提示词,等效于每次请求自动带上这条 system 消息;TEMPLATE 是对话模板,控制消息怎么拼成模型输入。多数时候不要手写 TEMPLATE——基座自带模板会自动继承,真要改,用 ollama show --modelfile qwen3:8b 导出官方模板照着改(指令全集见 Modelfile 文档),上面这段是简化示意。构建与验证如下。
ollama create dba-helper -f Modelfile
ollama run dba-helper "慢查询第一步查什么"
create 只记录配方(层引用加参数),几秒完成、不复制权重;dba-helper 从此出现在 ollama list 里,用法与任何官方模型无异。
6.2、上下文默认截断的坑
num_ctx 是 Ollama 新手的头号暗坑。它的默认值长期是 4096(更早版本是 2048),新版开始按显存动态决定——低显存机器上仍可能被砍得很小。问题在于截断是静默的:喂进去 2 万 token 的文档,模型只看到最后 4096 个,它不会报错,只会表现得"看不全、变笨了",你还会以为换的模型不行。
注意:长文档、长对话、Agent 的工具循环消息,都极容易超默认上下文。先显式设置
num_ctx,再怀疑模型能力。
设置有三条路:API 请求的 options.num_ctx(最灵活,按请求生效);交互会话里的 /set parameter num_ctx 8192(临时验证);Modelfile 的 PARAMETER num_ctx(固化到模型,OpenAI 兼容层调用的唯一途径)。记着上一篇的账:上下文翻倍,KV 缓存近似翻倍,别一上来就拉满。
7、模型库命名规则
官方模型库的命名是 名字:标签 结构,会读标签就不会下错模型。以 qwen3:8b 为例:冒号前的 qwen3 是模型系列,8b 是参数量规格。同系列还有 0.6b、4b、14b 等规格,数字对应上一篇算显存账的那套逻辑。
量化信息也编码在标签里。裸标签(如 qwen3:8b)默认给 Q4_K_M 量化,是体积与质量的甜区;想要其他档位就带量化后缀,如 qwen3:8b-q8_0(近无损存档)、:fp16(原版全精度),命名与 GGUF 档位体系一一对应,上一篇的 Q4_K_M/Q8_0 知识直接复用。此外库里的默认标签都是 instruct 对话版,上一篇"下了 base 版没有对话模板"的坑在官方库里天然免疫。
最后一层是用户命名空间:用户名/模型:标签(如 sam860/qwen3:8b-Q4_K_M)是社区用户发布的内容,官方模型库之外的有益补充,生产使用前建议核对发布者与下载量。
8、常见坑盘点
内存被吃满,机器发卡。模型加载后默认驻留 5 分钟,期间换用别的模型,旧的可能还没卸载,两个 8B 叠着就是 10 GB 起步。排查用 ollama ps 看驻留清单,ollama stop 模型名 立即释放;想限制同时驻留数,设 OLLAMA_MAX_LOADED_MODELS(默认 3 乘 GPU 数),低配机器设 1。
并发请求打爆显存。单个模型默认可并行处理多个请求(OLLAMA_NUM_PARALLEL,内存充足时为 4),但每个并行序列的 KV 缓存独立计费,并发一高显存翻着倍涨。跑 Agent 框架时尤其明显——多个智能体同时打一个端点。要么压低并发,要么拿显存换吞吐,二选一,再配合 OLLAMA_MAX_QUEUE 控制排队上限。
export OLLAMA_NUM_PARALLEL=2
export OLLAMA_MAX_LOADED_MODELS=1
ollama serve
休眠唤醒后服务假死。系统睡眠再唤醒,GPU 上下文可能已失效,表现为第一个请求超时或连接被拒,后续也恢复不了。这是平台层问题而非 Ollama 的 bug,Windows 加 NVIDIA 显卡上最常见。解法简单:ollama stop 全部模型或重启服务进程。把开发机设成不休眠,或服务交给 systemd 托管自动拉起,都能绕开。
再加上 6.2 的 num_ctx 静默截断,这四个坑覆盖了绝大多数"Ollama 怎么不工作了"。通用排查思路:先 ollama ps 看驻留,再看服务日志,最后查环境变量——大多数疑难杂症在前两步就现形了,更多细节见官方 FAQ。
9、总结与练习
本文把 llama.cpp 装进了"最好用的壳":Ollama 用注册表分发、自动加载卸载、双套 API 把五步手工链路压成两条命令,日常开发选它,极致控制回 llama.cpp;一张速查表十个命令管住全部生命周期;原生 API 用 options 结构化传参,/v1 兼容层让 OpenAI SDK 换个 base_url 就跑;Modelfile 以 FROM 加 PARAMETER 加 SYSTEM 固化角色与参数;模型标签里藏着参数量与量化档,4096 默认上下文的静默截断是第一坑。
留一个练习:用 6.1 的模板造一个自己的领域助手——比如 Git 提交信息生成器(system 写清 conventional commits 规范,temperature 压到 0.2)或 K8s 排障助手(system 塞进常用排查路径)。ollama create 之后,用第 5 节的 OpenAI SDK 代码调它,跑十次看输出稳定性。做完这一轮,你就拥有了可复现、可分发的定制模型——下一篇讲多模型并存与显存不足时的进阶方案。对于想立刻在本地跑通 Agent 的工程师,建议今天就把 pull、run、/v1 这三件事走一遍,半小时内就能让现有代码用上本地模型。

