llama.cpp / Ollama / LM Studio:本地 LLM 推理栈的硬核拆解

28 阅读8分钟

本地跑大模型的人常问“到底装哪个”——但这个问题本身容易问错。更准确的分层是:llama.cpp 是推理引擎,Ollama 是 daemon+模型仓库+API,LM Studio 是桌面 GUI+本地服务。三者底层大量共用 GGUF 与 GGML/llama 运行时,差异主要在“包了多少层、暴露多少旋钮”。


1. 来源与定位

1.1 llama.cpp

由 Georgi Gerganov 于 2023 年发起,现归 ggml-org 组织维护,纯 C/C++、无 Python 运行时依赖。原始动机是在 MacBook 上跑 LLaMA,后来变成整个本地生态的“发动机”:GGUF 解析、量化、CPU/x86/ARM/Apple/GPU 后端、OpenAI 兼容 HTTP 服务全在这一层。

它的产品形态不是单个 app,而是一组二进制:llama-cli、llama-server、llama-quantize、llama-imatrix、llama-bench、convert_hf_to_gguf.py 等,上面再封装 libllama 的 C API。

1.2 Ollama

定位是“本地 LLM 的 Docker 化体验”:一条 ollama run qwen3 完成拉取、解包、起 daemon、开 API。它把 llama.cpp 包成常驻服务,自己再加一层模型 registry、Modelfile、版本 manifest、REST API(默认 127.0.0.1:11434)。

对开发者友好,对“要调每一个 cuda/Metal/线程/量化参数”的人不够细——这不是缺点,是抽象税。

1.3 LM Studio

桌面端本地 LLM GUI,闭源免费(个人/商用可装,企业版另算)。内置 llama.cpp 运行时,macOS 上可走 Metal、Windows/Linux 可走 CUDA/Vulkan,提供模型浏览器、GGUF 导入、GPU 层数/offload 滑块、上下文长度设置,以及 Developer 里的 OpenAI 兼容服务器(默认常提 localhost:1234/v1)。

它不重新实现张量引擎,价值在“不让用户碰命令行也能挑量化、看 token、起 API”。


2. 架构拆解

2.1 llama.cpp:GGML → libllama → 工具层

  • GGML 张量库:延迟建图、零分配倾向、后端抽象。CPU 走 AVX2/AVX512/AMX/NEON/RVV;GPU 走 CUDA、Metal、HIP/ROCm、Vulkan、SYCL 等。
  • GGUF 单文件容器:magic GGUF+version+KV 元数据+tensor info+对齐权重。元数据可放架构、tokenizer.ggml.*、chat template、rope、GQA 等;权重可按 block 量化。因为整体可 mmap,多进程可共享只读页,加载接近“映射即就绪”。
  • libllama:llama_tokenize → llama_decode → sampler(logits) → next token,sampler 支持 temperature/top_p/min_p/repeat/grammar;多模态走 libmtmd,投机解码支持 draft/EAGLE/ngram。
  • 服务层:llama-server 用轻量 C++ HTTP 实现,暴露 /v1/chat/completions、/v1/completions、/v1/embeddings,也支持 Anthropic 风格消息;内置连续批处理、slot、Prometheus 指标。

硬核点:GGUF 的“可扩展 KV”是它取代老 GGML 的关键。新架构只加新 key,老 loader 不认识就跳过,不破坏旧文件。

2.2 Ollama:registry + blob + llama backend

执行 ollama run xxx 实际链路:

  1. 解析模型名→向 registry(默认 registry.ollama.ai)拉 manifest;
  2. 按 manifest 下载 content-addressed blobs(权重 blob+模板/license/参数小 blob);
  3. 按 Modelfile/默认模板组装参数;
  4. 调用内置 llama.cpp 系后端加载 GGUF 权重;
  5. 起 ollama serve 监听 11434,提供 /api/chat、/api/generate、/api/embed 等。

模型存储:

  • macOS:~/.ollama/models/blobs(权重)+ manifests(名字→blob 映射)
  • Linux:通常 ~/.ollama/models/...,可通过 OLLAMA_MODELS 改根目录
  • Windows:C:\Users<you>.ollama\models...

Ollama 的“模型名”是逻辑名,磁盘上是 sha256 blob;聊天模板、system、temperature、num_ctx 可在 Modelfile 里固化,但原始 GGUF 自身若已带 template,很多情况会直接用文件内元数据。

2.3 LM Studio:GUI + 本地 runtime + OpenAI shim

  • 模型目录默认 ~/.lmstudio/models/<publisher>/<model>/xxx.gguf(也可在设置里改);
  • 加载时读 GGUF 元数据,自动识别架构、tokenizer、量化;GUI 上调 n-gpu-layers、context、batch、线程;
  • 聊天用内置 UI;服务用 Developer/Server 模式起 OpenAI 兼容 HTTP,典型 http://localhost:1234/v1/chat/completions;
  • CLI 侧有 lms 命令,可 lms import 本地 GGUF、lms server start 起服务。对 Ollama 模型可通过把 GGUF 放到 LM 模型目录或软链共享,不是再转格式。

3. 基本使用

3.1 llama.cpp:从编译到服务

编译(按硬件开后端):

git clone https://github.com/ggml-org/llama.cpp && cd llama.cpp
cmake -B build -DGGML_CUDA=ON      # NVIDIA
# macOS Metal 默认常开;AMD 用 -DGGML_HIP=ON;跨平台 GPU 用 -DGGML_VULKAN=ON
cmake --build build --config Release

交互/单次:

./build/bin/llama-cli -m model.Q4_K_M.gguf -p "解释 GGUF" -n 256 -ngl 35 -t 8
  • -ngl N:往 GPU 卸多少 transformer 层,N=999 表示尽量全卸;
  • -t N:CPU 线程;
  • -c N:context,0 用 GGUF 内默认值;
  • --mmap:内存映射加载,大文件省物理内存、多进程可共享。

起 OpenAI 兼容服务:

./build/bin/llama-server -m model.Q4_K_M.gguf -c 8192 --port 8080 -ngl 35
# 直接拉 HuggingFace GGUF:
./build/bin/llama-server -hf ggml-org/gemma-3-4b-it-GGUF:Q4_K_M -c 8192 --port 8080

-hf ns/repofile:QUANT 会自动按 quant 后缀选文件并缓存到 ~/.cache/llama.cpp。

量化(先有 F16 GGUF):

python convert_hf_to_gguf.py /path/to/hf --outfile model-f16.gguf --outtype f16
./build/bin/llama-quantize model-f16.gguf model.Q4_K_M.gguf Q4_K_M
# imatrix 校准(低比特更稳)
./build/bin/llama-imatrix -m model-f16.gguf -f calib.txt -o model.imatrix
./build/bin/llama-quantize --imatrix model.imatrix model-f16.gguf model.IQ4_XS.gguf IQ4_XS

常用档:Q8_0(近无损大文件)、Q6_K、Q5_K_M、Q4_K_M(通用性价比)、IQ4_XS(imatrix 后常比同体积 K-quant 更稳)、更低可 IQ3/QQ2 但质量波动大。

3.2 Ollama:拉模型与自定义 GGUF

默认库模型:

ollama pull qwen3:8b
ollama run qwen3:8b "用一句话解释 mmap"

自定义 GGUF(本地已下载 model.Q4_K_M.gguf):

# Modelfile
FROM ./model.Q4_K_M.gguf
PARAMETER num_ctx 8192
PARAMETER temperature 0.7
TEMPLATE """{{ if .System }}System: {{ .System }}\n{{ end }}User: {{ .Prompt }}\nAssistant:"""
ollama create mymodel -f Modelfile
ollama run mymodel "hello"

API:

curl http://localhost:11434/api/chat -d '{
  "model":"mymodel",
  "messages":[{"role":"user","content":"解释 GGUF"}],
  "stream":false}'

查看某个模型实际指向的权重 blob:

ollama show mymodel --modelfile   # FROM 行会给出 sha256 blob 路径

Ollama 没有官方 ollama export;导出就是把 blobs 里对应权重复制成 .gguf。

3.3 LM Studio:GUI 与服务器

  1. 模型浏览器搜/下载,或把 GGUF 放到 ~/.lmstudio/models/<pub>/<name>/x.gguf;
  2. Chat 标签加载,调 GPU layers、context、max tokens;
  3. Developer/Server 标签选模型→Start Server,默认 http://localhost:1234/v1;
  4. 客户端:
from openai import OpenAI
c = OpenAI(base_url="http://localhost:1234/v1", api_key="not-needed")
print(c.chat.completions.create(model="local-model",
    messages=[{"role":"user","content":"hello"}]).choices[0].message.content)

CLI 等价思路:

lms import /abs/path/model.Q4_K_M.gguf
lms server start --model model.Q4_K_M.gguf --port 1234

LM Studio 不负责“从 safetensors 训后转 GGUF”,自定义模型应先在 llama.cpp 转好再丢进来。


4. 互相转换与共享

这三家之间多数时候不是“格式互转”,而是“共享 GGUF+各写一层元数据”。

4.1 HuggingFace safetensors/PyTorch → llama GGUF → 量化

python convert_hf_to_gguf.py /hf/model --outfile m-f16.gguf --outtype f16
./build/bin/llama-quantize m-f16.gguf m-Q4_K_M.gguf Q4_K_M

产出 GGUF 后可同时给下面两家用。

4.2 GGUF → Ollama

写 Modelfile 指本地路径:

FROM /models/m-Q4_K_M.gguf
PARAMETER num_ctx 8192
ollama create ollama-m -f Modelfile
ollama run ollama-m "test"

同文件系统下 Ollama 可能硬链、跨文件系统会整文件复制;别假设一定不占空间。 若只想要 Ollama 库名又不想管文件,直接 ollama pull 官方/社区 GGUF 构建最省事。

4.3 Ollama → llama.cpp / LM Studio

找权重 blob:

ollama show some-model --modelfile | grep FROM
# 例如 FROM /home/u/.ollama/models/blobs/sha256-xxxx
cp /home/u/.ollama/models/blobs/sha256-xxxx /models/some-model.Q4_K_M.gguf

之后:

  • llama.cpp:./build/bin/llama-server -m /models/some-model.Q4_K_M.gguf ...
  • LM Studio:放到 ~/.lmstudio/models/...gguf 或直接用 lms import

注意:Ollama Modelfile 里的 system/temperature/num_ctx 不会写进 GGUF;从 blob 导出来后要在新工具重新传 template/参数,否则聊天行为会变。

4.4 GGUF → LM Studio / 与 Ollama 共存

  • 最省事:统一放一个 ~/models/gguf/ 目录,Ollama 用 Modelfile FROM /abs/xxx.gguf 注册,LM Studio 在设置里把这个目录加进模型路径或直接复制到 ~/.lmstudio/models 层级。
  • 不想复制:LM Studio 支持导入本地 GGUF;Ollama 与 LM 都读同一文件,但 Ollama 若 create 后内部用硬链,删 Ollama 模型可能影响原文件,跨盘则是副本——生产环境用复制最稳。

4.5 再量化 / 改档

GGUF 低比特回转 safetensors 是有损的;反过来 F16 GGUF 可自由重量:

./build/bin/llama-quantize m-f16.gguf m-Q5_K_M.gguf Q5_K_M
./build/bin/llama-quantize m-f16.gguf m-Q8_0.gguf Q8_0

Ollama/LM 拿到新 GGUF 重新注册/重新加载即可,没有“Ollama 专属格式”。


5. 选型与避坑

  • 要最大控制、基准测试、新架构首发、嵌入式/CPU/多GPU按层切分:直接用 llama.cpp。-ngl/--tensor-split/--split-mode/-t/llama-bench 全开放。

  • 要 agent/Open WebUI/IDE 插件、服务器常驻、一行拉模型:Ollama。代价是部分细参被抽象掉,新量化类型可能比上游 llama.cpp 晚一点。

  • 要不懂命令行也能挑 Q4_K_M/IQ4_XS、看 GPU 占用、起本地 OpenAI 服务:LM Studio。代价是闭源、app 体积大、极端调参不如源码构建灵活。

  • 并发多用户高吞吐不要只靠 Ollama/LM/裸 llama-server 小模型:那种场景看 vLLM/SGLang;本地单用户三者差异往往小于模型/量化/上下文选择的影响。

  • 常见坑:

    • Ollama 默认 num_ctx 可能偏小,长文档/RAG 显式设 8192/32768;
    • 从 Ollama blob 提出 GGUF 后少了 Modelfile 的 system/template,llama-server 要手动 --chat-template或用文件内模板;
    • 跨文件系统注册 GGUF 到 Ollama 会复制,不是零占用;
    • 低比特(≤Q3/IQ3)不做 imatrix 容易乱码,重要模型用 llama-imatrix 校准;
    • llama.cpp 版本太旧读新 GGUF quant/version 会报不支持,Ollama/LM 内置运行时也要跟着升级。