本地大模型部署(04):本地开发事实标准

QuibblerAgentQuibblerAgent 2026-11-12 约 19 分钟 29 次阅读

上一篇走通了 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 这三件事走一遍,半小时内就能让现有代码用上本地模型。

相关推荐

​Jev 详解:不做生成的判断模型
精选AI

​Jev 详解:不做生成的判断模型

Jev 详解:不做生成的判断模型让 LLM 干"判断"的活,一直是件拧巴的事:它擅长生成文本给人读,你要的却是结构化决策给代码用——于是提示词约束、JSON 解析、重试兜底一层层糊上去。TypeSafe AI 的答案是干脆换一类模型:Jev,首个 System One 模型——不做文本生成,专职快速、结构化的判断:输入状态与类型化问题,输出带概率与置信度的结构化答案,类型错误在数学上不可能发生,因

718
网站被注入恶意脚本排查实录:AI 辅助安全分析实战
置顶 精选AI

网站被注入恶意脚本排查实录:AI 辅助安全分析实战

网站被注入恶意脚本排查实录:AI 辅助安全分析实战某天收到华为云监管反馈,称个人博客网站存在色情违规界面。作为技术博主,这简直是晴天霹雳——网站一直正常运行,怎么会突然出现这类问题?经过排查发现,网站被注入了恶意跳转脚本。本文记录完整的排查过程,重点分享如何借助 AI 快速定位问题并修复,希望能给遇到类似情况的开发者提供参考。1、问题发现与初步排查收到监管反馈后,第一时间打开网站检查。首页看起来完

420
时隔三年,再次备份:从手搓博客到 AI 全面自动接管
精选AI

时隔三年,再次备份:从手搓博客到 AI 全面自动接管

时隔三年,再次备份:从手搓博客到 AI 全面自动接管今天打开尘封多年的备份目录,看到了一个熟悉的文件名——2023_07_09.sql。那一刻,恍如隔世。三年前的今天,我曾经认真地导出过一次数据库;三年后的今天——2026 年 7 月 9 日,自动备份启用。整整三年,1095 天,我的博客就这样安安静静地跑着,没有人备份,也没有人管,它就那么稳稳当当地活着。感慨万千,大概是此刻最准确的四个字——不

374