1299 字
4 分钟
本地跑vl模型用什么?llama.cpp vs Ollama?
2026-05-10
2026-05-20

起因#

2026-05-26 更新: 现在已经完全切到 llama.cpp,Ollama 已删除
下面这篇是当初折腾时写的记录,结论已过时——最终本地赢了

之前一直用 Ollama 跑 qwen3-vl 模型做视觉识别,AI 助手看图、截图描述都靠它
表现中规中矩,但有两个点让我动了「要不本地跑试试」的念头

一是 Ollama 的 API 有一定 overhead,尤其在做连续的视觉对话时,感觉推理之间多了些不透明的环节

二是手上有张 3060 12GB,平时 ComfyUI 生图的时候显存吃满,但空闲时五六 GB 就在那闲着,想利用起来

于是决定:自己搭一个纯 llama.cpp 的后端,看看能不能比 Ollama 更快、更可控

第一步:编译 llama.cpp#

要做对得起显卡的推理,得先编译带 CUDA 支持的 llama.cpp

git clone https://github.com/ggml-ai/llama.cpp
cd llama.cpp
cmake -B build -DGGML_CUDA=ON
cmake --build build --config Release -j$(nproc)

过程很顺利,Ryzen 9700X 编译这东西就是洒洒水,几分钟搞定

选模型:第一次踩坑#

模型选的是 haervwe/qwen3-vl-4b-heretic——一个做了一次「删除」的版本,去掉了一些限制,能更自由地描述图片内容

下载下来发现一个奇怪的事情:llama.cpp 加载 GGUF 时提示 unknown architecture,完全跑不了

细查发现,这个模型的 GGUF 包含了 Ollama 私有的 blob 格式数据,在 GGUF 文件里嵌入了一段额外的张量,只有 Ollama 自己能解析
这不是标准的 GGUF,而是一种被称作「Ollama GGUF」的特殊变体
你下载的 GGUF 文件里可能藏了一段 .ollama_blob,llama.cpp 看到直接 say no

那行,换一个

改下 Huihui/Qwen3-VL-4B-Instruct-abliterated-GGUF,同样是做了限制移除的版本(abliterated 就是「删除」的意思),而且走的是纯标准 GGUF,llama.cpp、llama-server 随便加载:

wget -c https://huggingface.co/noctrex/Huihui-Qwen3-VL-4B-Instruct-abliterated-GGUF/resolve/main/ggml-model-Q4_K_M.gguf
wget -c https://huggingface.co/noctrex/Huihui-Qwen3-VL-4B-Instruct-abliterated-GGUF/resolve/main/mmproj-model-F16.gguf

2.4GB 的模型 + 800MB 的视觉投影器,一共 3.2GB,3060 表示没压力

跑起来#

llama-server 启动参数:

./llama-server \
--model Huihui-Qwen3-VL-4B-Instruct-abliterated-Q4_K_M.gguf \
--mmproj mmproj-model-F16.gguf \
--host 0.0.0.0 --port 8083 \
--n-gpu-layers 99 \
--parallel 1 \
--ctx-size 8192 \
--cache-type-k q8_0 --cache-type-v q8_0

首测结果不错:

  • prompt 处理:~2.7s
  • 生成速度:~85 tok/s
  • 显存占用:~4.8 GB(含基础系统占用约 1GB)

Q4_K_M 量化对 4B 级别模型来说几乎不影响质量,4.8GB 显存也让 3060 还剩一大截给其他服务

让它更优雅:on-demand relay#

但问题是,我不想让模型常驻显存占着位置——ComfyUI 有时候需要那几 GB

于是写了个 vl-relay.py 守护进程,它做的事很简单:

  1. 启动时模型不加载,零显存占用
  2. 收到第一条视觉请求时,自动拉起 llama-server
  3. 连续 5 分钟没有请求,自动 kill 进程、释放显存
  4. 对外暴露一个 OpenAI 兼容 API,AI 助手不需要改任何配置就能直接用

整个流程对上层完全透明,API 调法和 Ollama 一模一样

# 核心逻辑示意
class VLCoordinator:
def handle_request(self, prompt, image):
self.start_server_if_needed()
self.last_active = time.time()
result = self.forward_to_llama(prompt, image)
return result
def check_idle(self):
while True:
if time.time() - self.last_active > 300: # 5分钟
self.stop_server()
break

这套机制开源了:

GT001well
/
qwen3-vl-ondemand
Waiting for api.github.com...
00K
0K
0K
Waiting...

和 Ollama 正面刚#

TIP

测试变量多,仅供参考

既然本地搭好了,那和 Ollama 比一下,用同一张截图做视觉描述

测试 1:优化版本地(q8_0 KV, 8K ctx)#

项目本地(优化)Ollama
总耗时7.0s10.0s
显存~5.8 GB~4 GB
描述质量可以,偏列表化自然语言式描述

本地快了 30%,但是描述风格偏结构化,不如 Ollama 流畅

测试 2:全尺寸本地(f16 KV, 32K ctx)#

调大 ctx-size、恢复 f16 KV 缓存

项目本地(全尺寸)
总耗时6.6s
显存~6.3 GB
描述质量和 Ollama 基本一致

快了更多,描述质量也追上了,但显存飙到了 6.3GB

再往上调到 262K ctx + f16 KV 直接 OOM——12GB 的 3060 就这么多,想上大上下文只能认命

好消息是,8K ctx + q8_0 KV 带来的质量损失极小——看图根本不需要大上下文,q8_0 KV 对视觉 token 也没有可见劣化
优化版 5.8GB 和全尺寸 6.3GB 的描述结果放在一起,人眼分不出区别

最后选了谁#

当初写这篇的时候结论是「还是继续用 Ollama」
但现在回头看,最终还是彻底回到了 llama.cpp,Ollama 已经删了

理由说起来也简单:

  • Ollama 的 overhead 虽然不大但也不是零 — 纯 llama.cpp 的 --sleep-idle-seconds 机制比 relay 优雅得多,自动休眠自动唤醒,不需要额外写守护进程
  • 模型管理 — 自己管 GGUF 文件反而比被 Ollama 的模型目录管着更灵活,想换就去 hf-mirror 下个 GGUF,不需要走 Ollama 的 pull
  • 去审查版模型 — Ollama 官方没有 abliterated 版本,想用只能自己下 GGUF 从自定义路径加载,那还不如直接上 llama.cpp

所以绕了一圈,跟上一篇文章说的一样——返璞归真了

不过这次折腾也不是白费,折腾过程中搭出来的 on-demand relay 机制 后来启发了我用 --sleep-idle-seconds 代替常驻,反而让最终方案更简洁

环境信息#

系统: Arch Linux
内核: 7.0.3-zen
CPU: AMD Ryzen 7 9700X 8-Core
GPU: NVIDIA RTX 3060 12GB (驱动 595.71, CUDA 13.2)
|模型: Huihui-Qwen3-VL-4B-Instruct-abliterated (Q4_K_M)
|llama.cpp: 编译版(已不依赖 Ollama)
开源仓库:
GT001well
/
qwen3-vl-ondemand
Waiting for api.github.com...
00K
0K
0K
Waiting...
ggml-ai
/
llama.cpp
Waiting for api.github.com...
00K
0K
0K
Waiting...
分享

如果这篇文章对你有帮助,欢迎分享给更多人!

本地跑vl模型用什么?llama.cpp vs Ollama?
https://text.lilystar.cn/posts/local-vs-ollama-vl/
作者
Lily
发布于
2026-05-10
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录