1. 为什么我把本地大模型的“裸引擎”当成默认首选
1.1 从“能用”到“可控”:本地推理解决了什么
最早我在本地跑模型,是为了解决三个很实际的问题:数据不出内网、按量计费的心慌、以及自由度。云端接口确实方便,但每次请求都有成本,而且你的 Prompt、文档、对话记录都要经过别人的服务。做技术的人都清楚,一旦涉及私有数据或者离线环境,云端方案基本等于没方案。于是本地推理成了刚需,llama.cpp 恰好是这条路上绕不开的那个名字。
我第一次接触 llama.cpp 的时候,它还没有今天这么“平易近人”。当时只有一个main可执行文件,要自己编译,要自己去下载权重,还要手工转换格式。相比之下,现在的开源生态已经友好很多,但 llama.cpp 的核心气质没变:它不给你封装精美的图形界面,不给模型做“一键安装”,它只提供原始的计算能力——加载 GGUF 模型、跑前向计算、把 token 一个个吐出来。这就是我标题里说的“裸引擎”。
1.2 llama.cpp 的定位:别叫它框架,它是引擎
很多人会把 llama.cpp 和 Ollama、LM Studio 这类工具混为一谈,这其实是两回事。Ollama 这类软件是做“层”的,它们在 llama.cpp 外面包了模型管理、API 服务、镜像下载这些功能,让你用得更舒服。而 llama.cpp 本身是“底”上的那台机器,它擅长的事情很单一:读入一个 GGUF 模型文件,充分利用你的 CPU、GPU、内存资源,把推理跑得尽可能快。
这就像改车:Ollama 是带真皮座椅和倒车影像的量产车,llama.cpp 是只给你发动机、底盘和方向盘的车架。量产车当然好开,但你要想搞清楚扭矩曲线、换挡逻辑、悬挂调校,必须回到车架上自己动手。我从“消费者”变成“动手党”之后,才真正理解这层区别:llama.cpp 没有默认策略,所有事情都要你显式地告诉它——用多少线程、放几层到显卡、上下文开多长、采样参数怎么设。麻烦,但是透明。
1.3 什么人适合直接上手 llama.cpp
我不会劝所有人都去用裸引擎。如果你只是想在本地找个人聊天,直接装一个带界面的工具,十分钟就能跑起来,犯不着折腾编译。但如果你是这几类人,llama.cpp 值得花时间:
- 你在做自动化脚本、代码库集成,需要把推理能力嵌进自己的程序里;
- 你需要精确控制运行参数,比如给 7B 模型压到 4-bit、把上下文撑到 32K;
- 你用的是老旧设备或特殊硬件(ARM 盒子、老显卡甚至没有显卡的服务器);
- 你想搞懂大模型推理到底吃了多少内存、算力瓶颈在哪,而不是黑盒式地“能用就行”。
这篇文章不会带你装完就跑,而是把 llama.cpp 和 GGUF 这两件事拆开:一个负责“跑”,一个负责“装”,搞懂它们的关系,后面调参、排错、优化就都有了根。
2. GGUF 是什么:一个为“塞进内存”而生的文件格式
2.1 GGML 到 GGUF:一次让社区统一起来的格式迭代
讲 GGUF 之前,得先讲讲它的前身 GGML。早期的 llama.cpp 用 GGML 格式存放量化后的模型,这个格式的问题很明显:它侧重于“能跑”,但缺少自我描述能力。一个 GGML 文件里的张量顺序、超参数含义,全靠读取方的代码写死,版本一变就容易对不上。结果就是社区里到处是“这个模型要用哪一天的 commit 才能加载”的帖子。
GGUF 是后来推出的替代格式,目标就一句话:让模型文件自己“交代清楚”自己。它把模型的架构类型、层数、词表大小、上下文长度、量化方式、甚至在转换时使用的原始来源信息都写进了文件头部的元数据区。加载器只要读元数据,就能确定该用哪一套代码路径来解析这个文件,而不是靠猜。现在开源社区里 GGUF 基本成了本地推理的事实标准,几乎没有哪个新的开源模型不提供 GGUF 版本。
2.2 单文件、元数据内嵌、内存映射:三个设计关键
GGUF 在设计上有三个点我觉得特别关键,理解了这三个点,你就理解了为什么它能活得这么好。
第一是“单文件”。一个模型就是一个人文件,从几 GB 到几十 GB,拷走、传给同事、部署到服务器,都只需要复制一个文件。这个设计在工程上的价值被严重低估:文件碎片没有,路径引用没有,版本管理简单,哈希校验也只需要算一个文件。我自己维护模型目录的习惯就是按“模型名-参数量-量化档位.gguf”命名,一个文件夹一个模型,干净得不像深度学习项目。
第二是“元数据内嵌”。GGUF 的头部就是你模型的“身份证”,里面包含了architecture、context_length、block_count、embedding_length、attention.head_count、rope.freq_base这一长串东西。这意味着加载器不必预先知道“这个模型是哪个系列的”,只要实现了对某种架构的支持,就能读懂。往后就算主程序版本升级,新格式扩展,旧文件也照样能打开。
第三是“内存映射”。这是 llama.cpp 启动快的最重要原因。现代操作系统加载大文件时,可以用mmap把文件直接映射进虚拟内存,程序访问文件里的数据就像访问内存数组一样,不需要主动把整个文件读进内存。模型文件被映射之后,实际只在 CPU 访问到对应页面时才发生磁盘读取,这个懒加载机制让你的冷启动时间大幅缩短。而且多个进程可以共享同一份映射页,单机部署多个实例时内存开销能省不少。
2.3 GGUF 和其它权重格式的本质差异
很多人会把 GGUF 和 PyTorch 的safetensors、ONNX、TensorFlow 的 SavedModel 搞混。它们确实都是“存放模型权重”的方式,但用途完全不同。safetensors 是针对训练和微调场景设计的,权重是 FP16 或 FP32 的原值,加载进 PyTorch 后你可以继续对它做反向传播。ONNX 则是一种计算图和权重的打包格式,目标是跨框架部署,但它对量化的定义比较“正统”,基本只支持对称、非对称等少数几种量化。
GGUF 的定位非常特殊:它天生就是为了推理而生,而且原生支持一堆“非常规”量化格式。你可以在同一个 GGUF 文件里用混合精度——不同层用不同的量化位宽。比如注意力层的 KV Cache 保持较高精度,而前面几层 FFN 用 4-bit,这种粒度是其它格式很少考虑的。换句话说,GGUF 不是从训练框架那边“顺带支持”的一种导出格式,而是一个专门为本地推理设计的容器,整个格式的每一个字段都在为“用更少的内存跑出可接受的质量”服务。
3. 从零跑通第一个本地模型:编译、下载与命令行推理
3.1 编译 llama.cpp 的两种方式
不管用哪个系统,编译 llama.cpp 都不难,难点只在你到底需要哪些后端。这里说的“后端”指计算加速方式:纯 CPU、CUDA(N 卡)、Metal(苹果)、Vulkan(通用 GPU)、SYCL(Intel)等。默认编译只带 CPU 后端,如果你有独立显卡但忘了开对应选项,你就会看到一个用不起来 GPU 的版本。
我推荐直接用 CMake 流程:
git clone https://github.com/ggml-org/llama.cpp cd llama.cpp cmake -B build -DGGML_CUDA=ON cmake --build build --config Release -j如果你的机器不是 N 卡,把GGML_CUDA换成GGML_METAL=ON(macOS)或者GGML_VULKAN=ON(跨平台通用 GPU)。没有 GPU 的机器不需要加任何选项,CPU 后端已经可以跑。编译完成后,可执行文件在build/bin/下面,新版本里最常见的是llama-cli(命令行交互)和llama-server(HTTP 服务)。老教程里的main和server是旧名字,对应关系要认清楚。
提示:不同版本的 llama.cpp 对 GGUF 的兼容性有差异。编译完成后先跑
llama-cli --version确认版本,再去下载对应时期的模型文件,能少踩很多莫名其妙的加载错误。
3.2 去哪里找 GGUF 模型:下载时的注意事项
现在主流开源模型都有人帮你转换好 GGUF,通常发布在模型托管网站的文件列表里。下载的时候要避开几个坑。
第一,认清参数量。同一个模型有 7B、13B、70B 等不同规模,下载前先看自己内存够不够。我的经验是:
- 7B 模型用 4-bit 量化,文件大约 4GB 出头,内存至少留 8GB;
- 13B 模型用 4-bit 量化,文件大约 7GB,内存至少留 12GB;
- 70B 模型即便 4-bit 也要 40GB 左右,普通人先别碰。
第二,认出“官方量化”和“社区量化”。同一系列模型可能有官方发布的 GGUF,也有社区第三方做的转换版。我优先选官方或标注来源清晰的版本,因为你不知道某个来路不明的转换版本到底改没改过采样参数、有没有夹带奇怪的模板前缀。
第三,看清楚文件分组。有些超大模型把权重拆成多个分卷 GGUF(文件名带-00001-of-00003这种后缀),下载时要全部拿全,然后放在同一个目录里加载。只下第一份就开始跑,你会得到“文件不完整”的报错。选文件时我一般直接挑单文件版本,省事。
3.3 第一次运行:最简命令和它的输出解读
假设你已经下载了一个 7B 模型的 GGUF 文件,我们就用最简单的命令跑一次:
./llama-cli -m /models/example-7b-q4_k_m.gguf -p "写一段关于本地推理的简介" -n 128-m指定模型路径,-p是输入提示词,-n是生成的最大 token 数。跑起来之后,你会看到一堆日志:加载时间、mmap 状态、模型参数量、上下文大小、计算设备信息,最后才是模型生成的正文。
第一次跑通的时候,建议仔细盯一下这行日志:
llm_load_tensors: offloading 0 repeating layers to GPU如果你的编译开了 GPU 后端但这里显示offloading 0,说明模型全在 CPU 上跑。对于 7B 的 4-bit 模型,CPU 跑大概每秒几个到十几个 token,能忍但不算快;加一行-ngl 999把尽可能多的层塞进 GPU,速度通常会翻几倍。关于-ngl怎么设,我在后面专门讲。
4. 量化与精度:Q4_K_M、Q5_K_M、Q8_0 到底怎么选
4.1 量化为什么是本地推理的命门
大模型权重默认是 FP16,也就是每个参数占 2 字节。一个 7B 模型光权重就要 14GB,绝大多数人没有这个条件。量化做的事情,就是把每个权重用更少的比特表示:4-bit 意味着平均每个参数只有 0.5 字节,7B 模型瞬间压到 4GB 左右,内存门槛一下子降到普通台式机也能承受的水平。
但量化不是没有代价。权重是模型的“记忆”,你用低精度去逼近这些记忆,肯定会有信息损失。好的量化算法会尽量把损失控制在“人感觉不出来”的范围内。GGUF 里那几十种量化档位,本质上就是在“模型质量”和“内存占用”之间提供一条连续的光谱,让你按需选取。
4.2 K 系列和 IQ 系列:量化家族的演进
GGUF 的量化名看着像密码,其实有规律。最初的q4_0、q4_1、q5_0、q8_0属于“老一代”量化,按固定大小的块做缩放和零点补偿,简单但效率一般。后来出现的 K 系列(q4_K_S、q4_K_M、q5_K_M等)做了一次重要升级:它把模型里的不同张量区分对待——注意力层、FFN 层、输出层用不同的位宽组合,后缀_S是“small”小体积版,_M是“medium”中间版,在体积和质量之间取得平衡。
再后来是 IQ 系列,比如IQ2_XS、IQ3_XXS、IQ4_XS,用上了“重要性矩阵”的概念。简单说,它会把“更重要”的权重量化得更细、“不重要”的权重压得更狠,所以能在更小的体积下保持不错的质量。代价是解码速度略慢一点,而且只适合推理,不太适合继续做微调。
我整理了一个简化对照表,方便新手选型:
| 量化档位 | 文件大小(7B 模型参考) | 质量 | 速度 | 适用场景 |
|---|---|---|---|---|
| q8_0 | 约 7.2GB | 接近原始 | 偏慢 | 显存/内存充裕,追求质量 |
| q6_K | 约 5.5GB | 很好 | 较快 | 视觉/感知类任务,写代码 |
| q5_K_M | 约 4.8GB | 很好 | 快 | 均衡之选,日常问答足够 |
| q4_K_M | 约 4.1GB | 良好 | 最快 | 内存吃紧,大多数场景首选 |
| q3_K_M | 约 3.3GB | 及格 | 快 | 内存极小时兜底 |
| IQ2_XS | 约 2.4GB | 一般 | 中等 | 极端场景,能跑就行 |
4.3 我的选型经验:按硬件和场景选量化档位
没有哪个量化是“绝对最好”的,只有“最适合你的硬件和任务”。我自己的经验有三条:
第一,内存不是只看文件大小。模型运行时,除了权重还要加载 KV Cache、临时计算图和一些额外缓冲。8GB 内存的机器跑一个 4.1GB 的 q4_K_M 模型,虽然文件能装下,但实际跑起来会频繁触发换页,速度慢到怀疑人生。所以我建议内存至少是文件大小的 1.5 倍到 2 倍。
第二,代码和数学任务优先上高精度。写代码、做数学推理这种对“精确性”敏感的任务,4-bit 和 8-bit 的差距会被放大。我实测过同一个模型在 q4_K_M 下写 Python 脚本,偶尔会出现变量名拼错、漏括号这类低级错误;换到 q6_K 之后明显改善。日常闲聊倒是无所谓,q4_K_M 完全够用。
第三,拿不准就选 q4_K_M 或者 q5_K_M。这两个档位是社区里验证最多的“万金油”。我在三四款不同规模的模型上试过,q4_K_M 的综合性价比最高,q5_K_M 在内存允许的情况下质量更好。新手不建议碰q2_K以下的反直觉档位——文件是小了,但模型会“变笨”到你怀疑是不是下载错了。
5. 性能调优:GPU 层数、KV Cache 与并发请求
5.1 计算图、线程与内存映射:性能的三个基础引擎
要调好性能,先得有正确的性能模型。llama.cpp 的推理计算可以粗略分成两个阶段:预填充阶段(处理 Prompt,并行度高)和逐 token 生成阶段(串行,每一步都依赖前一步)。前者吃矩阵乘法的吞吐量,后者吃内存带宽和延迟。CPU 上跑的时候,前者的关键是 BLAS 库和线程数,后者的关键是能否让权重常驻在最快的存储层级里。
线程数-t值得手动试,不要一味加满。我的经验是:物理核心数的一半到全部之间,找一个吞吐量峰值。CPU 推理时,超线程带来的提升很有限,线程开太多反而会因为调度开销拖慢速度。内存带宽也很关键,用双通道内存比单通道快不少,这块很少有人提,但实测对 CPU 推理影响很大。
内存映射(mmap)是 llama.cpp 默认开启的加速手段。它的意义在于:当模型权重第一次被访问时,OS 会按页读入内存,后续所有推理都直接在内存里完成。启动一个 4GB 模型只需要几秒,靠的就是 mmap。但有个前提——确保你的系统盘是 SSD。如果模型文件放在机械硬盘上,mmap 的懒加载反而会因为随机访问灾难性掉速。
5.2 n_gpu_layers 怎么设:GPU 显存和权重的博弈
-ngl(即--n-gpu-layers)决定把模型的前多少层放到 GPU 上计算。它不是越高越好,最终约束是显存容量。一个 7B 的 q4_K_M 模型,全部层上 GPU 大约需要 4-5GB 显存;13B 的 q4_K_M 需要 7-8GB。如果层数设太多导致显存溢出,llama.cpp 不会优雅提示,而是直接崩溃或者卡死。
我建议的设法是:先算“显存余量”,再逐步增加。比如你的显卡是 6GB 显存,系统已占用约 1GB,实际可用约 5GB,那 7B 的 q4_K_M 全部放上去是危险的,可以只放一部分层上去,比如-ngl 20,把剩下的层留给 CPU。这里的判断标准是:GPU 负责的层越多,越能掩盖 CPU 算力弱的短板;但如果显存快满了,宁可少放一点,也不要赌“刚好能塞下”。
正常情况下,日志里会有类似这样的信息:
llama_kv_cache_init: offloading 18 layers to GPU它说明 KV Cache 也有部分层被放到 GPU 上。KV Cache 本身就是显存大户,尤其在长上下文场景下,这部分的占用不能忽略。
5.3-c上下文长度与 KV Cache 占用计算
上下文长度是你给模型的“工作记忆上限”,设得越大,模型能记住的前文越多,但 KV Cache 占用按比例线性增长。计算公式不复杂:
KV Cache 大小 ≈ 2 × 层数 × 数量头数(KV) × 头维度 × 每元素字节 × 上下文长度举例:一个 7B 模型有约 28 层,GQA 的 KV 头数为 8,头维度 128,FP16 下每元素 2 字节。那么上下文长度 4096 时:
2 × 28 × 8 × 128 × 2 字节 = 约 114 KB/每个 token 114 KB × 4096 ≈ 470 MB也就是说,上下文从 4K 拉到 32K,KV Cache 就要吃掉约 3.7GB 内存。这就是为什么有些人把-c调到 65536 之后,模型直接跑不动了——不是模型太大,是“记忆”太占地方。新的 llama.cpp 版本支持 KV Cache 量化(比如-ctk q8_0),可以把这部分砍半,牺牲一点点质量换更大上下文,长文档场景很实用。
注意:
-c是“我们允许模型用多长上下文”,不是“模型本来能处理多长”。如果模型原始训练只支持 4K,你硬开到 16K,推理结果可能会变差。要先确认模型元数据里的context_length再调。
6. 实测数据:同模型在不同软硬件配置下的差距
6.1 测试环境与测法
光说不练没有说服力,我把自己手头几台机器的实测数据整理一下。测试统一使用同一个 7B 模型、同一个 q4_K_M 量化版本、相同 Prompt,生成 200 token,取平均速度。这里不写具体硬件品牌,只描述配置级别,因为结论主要看“相对差距”。
| 配置级别 | 大致硬件 | 运行模式 | 平均速度 |
|---|---|---|---|
| 入门级笔记本 | 无独显,双通道 DDR4 | CPU only | 8-12 token/s |
| 中端台式机 | 6核 CPU + 6GB 中端显卡 | GPU 混合 | 30-45 token/s |
| 工作站 | 16核 CPU + 24GB 高端显卡 | GPU 全层 | 60-80 token/s |
| 苹果统一内存设备 | 内存带宽较高 | Metal | 40-70 token/s |
这个数据只是量级参考,不同的 CPU 内存频率、显卡型号都会带来明显波动。但趋势很稳定:GPU 参与推理的收益远大于 CPU 单打独斗,而“全层上 GPU”和“部分层上 GPU”的差距主要看你 CPU 的补位能力。
6.2 CPU-only vs GPU 混合推理的 token/s 对比
CPU-only 跑 7B 模型,最核心的瓶颈是内存带宽。你每生成一个 token,理论上要把模型的所有权重从头到尾读一遍(因为每层都要计算),所以内存带宽越高,速度越快。我见过有人用低频低压内存跑 CPU 推理,只有 5 token/s,换一套高频双通道内存瞬间翻倍。这个经验可以帮你在预算有限时优先升级内存而不是 CPU。
GPU 混合推理的收益曲线不是线性的。把 28 层里的前 20 层放到 GPU、剩下 8 层留在 CPU,速度通常会比纯 CPU 快两三倍,瓶颈变成 CPU 与 GPU 之间的数据传输。而如果显存足够、全部层放 GPU,瓶颈才真正变成 GPU 自身的算力。所以我的建议是:只要你有多余显存,哪怕只能塞一半层,也比纯 CPU 强很多。
6.3 并发场景:llama-server 的实测表现
llama-server是更贴近生产的使用方式。启动之后,它提供一个 HTTP 接口,你可以在任意语言里用requests或者curl调用。这个模式下的性能调优多了一个维度:并发。
./llama-server -m /models/example-7b-q4_k_m.gguf -c 4096 -ngl 999 --port 8080llama.cpp 的调度策略是:多个请求共享同一个推理槽位,排队处理。它支持“多槽位”(--parallel N),本质上是把 KV Cache 切成 N 份同时服务 N 个请求。我实测 7B 模型在单槽位下并发两个请求,第二个请求会明显排队,单请求速度几乎不变但整体吞吐接近翻倍;--parallel 4时,吞吐量能到单槽位的 2-3 倍,但每个请求的延迟会多一些。
做服务端的时候还有个细节:预填充阶段(用户发来大段 Prompt)会占用较长时间,这时候其它请求都在排队。如果你要接真实项目,建议把--parallel设大一点,并且给客户端设置合理的超时时间。另外llama-server支持 OpenAI 兼容的接口路径,很多现成客户端可以直接把 base_url 指过来,迁移成本很低。
7. 那些年踩过的坑:从崩溃到幻觉的排查链路
7.1 模型文件加载失败的第一反应:校验和与文件完整性
“加载失败”是新手最常遇到的错误,表现形式五花八门:报magic mismatch、报file is too small、加载到一半进程退出。很多人第一反应是去查代码、调编译参数,其实八成是文件本身有问题。GGUF 文件在下载过程中损坏的概率不低,尤其是大文件、断点续传、网盘转存这些环节。
我现在的排查顺序是固定的。第一步看文件大小,跟发布页面上写的是否一致,差几 MB 就直接重下。第二步算哈希,主流下载页面都会给出文件的 SHA256 值,算一遍比什么调试都管用。第三步才轮到检查 llama.cpp 版本——因为老版本可能不支持新模型的某个架构字段,这时需要升级编译或者换一个转换时间匹配的 GGUF。
7.2 显存溢出不是报错,而是“卡死”和“OOM”
GPU 显存溢出时,llama.cpp 偶尔会输出CUDA error: out of memory,但更多时候是进程直接卡住不动,或者被系统杀掉。这个“驯服”难度在于,它发生在你说不清到底是哪一步炸的。我的建议是:启动参数里加上日志级别调整,运行时留意显存占用曲线,逐步降低-ngl和-c,直到稳定为止。
另外有个经常被忽略的点:显存和内存是两回事。当你-ngl设得不够时,剩余的层会放在系统内存里跑,这没问题;但当-ngl设过头、GPU 装不下时,系统内存不会来“兜底”,而是直接崩掉。严格来说,这不算 bug,是显存边界没有预留余量。所以我的习惯是先留出 1GB 显存余量再往上堆层数。
7.3 输出乱码与重复生成:采样参数的坑
模型生成质量差,很多人第一时间怪模型本身,其实采样参数的影响才是大头。--temp控制随机性,--top-p控制候选词的概率截断,--repeat-penalty控制重复惩罚。默认参数适合通用场景,但在特定任务上不调就是灾难。我见过最典型的情况是:模型一直在复读同一个句子,或者输出夹杂乱码式的符号——这往往是因为--repeat-penalty设得太低或者--temp开得过高。
还有个玄学点:对话模板。GGUF 元数据里通常带tokenizer.chat_template,新版本 llama.cpp 会自动套用正确的模板,但如果你用旧版或者手动覆盖了模板,模型就会输出前言不搭后语的“幻觉”。现象表现为回答和问题完全无关、角色反串、或者开头莫名其妙多个[INST]标签。排查时先确认日志里打印的模板信息是不是你预期的那个。
7.4 一个完整的排查思路:从日志到复现
遇到任何诡异问题,不要直接改参数碰运气,按下面的链路走一遍:
- 先跑官方最小的 demo 命令,比如只用
-p "hi" -n 16,排除掉 Prompt 和业务代码的干扰; - 看启动日志里的加载信息,确认模型架构、量化类型、设备分配都符合预期;
- 逐步加回你的业务参数,每加一个跑一次,找到让问题出现的那个“开关”;
- 如果问题只在特定 Prompt 下出现,减小
-n和上下文长度,看是否与生成长度有关; - 问题能复现之后,再决定是换量化、换上下文、换并发参数,还是直接换模型。
我一直强调“复现”这个词,因为绝大多数看似玄学的问题,只要你把参数一项项隔离,最后都会发现是某个字段的取值越界了。llama.cpp 最大的优点是所有参数都摆在明面上,没有任何隐藏的“自动优化”,这反而让排查变得非常直接——你看到什么,就是什么。
8. 我这一路用下来的最终体会
8.1 别急着上 70B,先把手头的 7B 用到极致
本地推理圈子里有个普遍心态:总想追求更大的模型、更长的上下文、更快的速度。我自己也经历过这个阶段,但回过头看,把一个小模型调教到“够用且稳定”,收获远大于盲目上大模型。7B 模型在 q4_K_M 量化下,普通电脑就能跑,配合好一点的 Prompt 和采样参数,写摘要、做分类、跑数据清洗,效果完全能打。先把手头资源榨干,再考虑升级硬件,是最务实的路径。
8.2 记录每次运行的参数组合
我给自己的要求是:每一次“跑出一个还不错的模型配置”,都要把完整的命令贴进笔记里,包括模型路径、量化档位、-ngl、-c、采样参数。这不是洁癖,是因为这些参数组合往往是“试了十几次才试出来”的,三个月后你再想复现,不可能凭记忆拼出来。我给每个模型建一份独立的说明文件,里面写好这个配置在哪台机器上测的、速度多少、质量如何、适合什么任务。这套笔记就是我自己的“调参手册”。
8.3 从“裸引擎”到“自己的栈”
最后说一句掏心窝的话。llama.cpp 看起来简陋,但它给了你一套从头到尾自己掌控的推理链路。当我把模型文件、推理进程、HTTP 接口、业务代码串成一个完整系统的时候,我对“大模型应用”的理解,已经和只会调用云接口的时候完全不一样了。裸引擎的每一个零件都看得见、摸得着,你可以换零件、改参数、甚至给它写补丁。这个自由度,才是它最大的价值。如果你刚开始接触本地推理,我建议从今天这篇文章里的最小命令开始,亲手把一个模型跑起来,再去探索更大的世界。