到这里,全书 40 课讲完了。从"llama.cpp 是什么"出发,你一路走过了 ggml 的张量与计算图、llama 的模型加载与推理主循环、公共 API 与命令行工具、底层 CPU/CUDA 内核,再到投机解码、MoE、多模态、状态空间模型这些进阶机制,最后学会了怎么把一个 HuggingFace 模型转成 GGUF、怎么给这个项目提一个站得住的 PR。这套推理引擎,你已经从上到下走了一遍。
这最后一课不教任何新东西,而是给你一张速查地图:先用一条"学习路径"把九个部分怎么层层递进看清楚,再用一张概念依赖图把核心概念之间"谁建立在谁之上"画出来,最后给一份分类术语表——每个术语一句话定义、标好它在源码里的位置、再附上"点一下跳回讲它的那一课"的链接。往后你忘了某个概念,不必从头翻,来这里一查、一跳就回到现场。
怎么用它:当你在读代码或调试时撞见一个似曾相识的名词(ggml_cgraph?llama_batch?),先在术语表里扫一眼"它大概是什么、在哪定义",需要细看就顺着链接回到对应课。这一课本身很短,价值全在"查得快、跳得准"。 换句话说,前面的课教你"怎么从零理解",这一课帮你"以后怎么快速回忆"。
先看整体。这门课的九个部分不是随便排的,而是从外到内、再从内到外:先建立全局印象,再一层层钻进 ggml 和 llama 的内部,摸透了内部再回到工具、内核、进阶机制,最后落到实战与速查。每一部分都站在前一部分的肩膀上——所以哪一课要是觉得跳跃,往前回翻往往就接上了。 一个小提示:如果你是带着某个具体目的来的(比如"我只想搞懂量化"),完全可以直接跳到对应部分;但若想建立整体直觉,按顺序走一遍仍是最省力的路。
这张图也回答了一个常见疑问:"该按什么顺序读?"答案就是从左到右:每一部分都默认你已经消化了它左边的内容。当然,作为速查页,你也完全可以从任意一格跳进去——这正是下面那份术语表存在的意义。 这也是为什么前面每一课的开头,几乎都在用一两句话先接上前一课——课程的"层层递进",在这张地图上一眼就能看明白。
再往深一层看,这九个部分其实是三段式的:第一段(一到三部分)建立"它是什么"的整体印象,让你不至于一上来就淹没在细节里;第二段(四到七部分)一头扎进引擎内部,把张量、计算图、KV cache、采样、内核这些"机器零件"逐个拆开看清;第三段(八到九部分)再从内部走出来,落到"怎么用、怎么改、怎么查"。很多人学一个大项目卡住,往往是因为跳过第一段直接抠细节,或者抠完细节却没回到第三段去真正用它——这门课特意把这三段都给你铺齐了。
九个部分是时间上的顺序;但概念之间还有一层逻辑上的依赖——谁是地基、谁建在谁之上。下面这张图把最核心的几个概念按依赖关系摞了起来:最底下是 ggml_tensor(一切数据的基本单位),往上每一层都建立在下一层之上,最顶上才是你最熟悉的"一次 llama_decode"。 注意"依赖"和"调用顺序"不是一回事:运行时是自上而下地发起(decode 调 context、context 调 backend),但构建和理解却最好自下而上——先懂张量,才谈得上懂图、懂后端。
举个具体例子,把这张图"走"一遍:你在 llama-cli 里输入一句话,它先经 vocab 切成 token,装进一个 llama_batch,交给 llama_context 的 llama_decode;context 内部建起一张 ggml_cgraph(里面全是 ggml_tensor 节点),交给某个 ggml_backend 执行,算的过程中读写 KV cache;最后吐出 logits,sampler 从中挑出下一个 token。看——从输入到输出,恰好把图里每个盒子都点了一遍。这就是为什么说"读懂这张图,就读懂了一次推理的骨架"。
这张图真正的价值,是把"读源码时该往哪看"画了出来。比如你在调一个和 KV cache 有关的 bug,顺着图就知道该往 llama_context 里找(KV cache 归它持有),而不会跑去 ggml_tensor 那一层瞎转。每一根箭头,都是一条"出了问题该往哪一层追"的线索。
下面把全书最常打交道的术语按四类列出来。每条给三样东西:一句话定义(它是什么、管什么)、源码位置(想看真身去哪个文件)、跳转(点一下回到讲它的那一课)。不求全,只求"撞见时能立刻对上号"。 关于"源码位置"那一列:给的是单一最佳落脚点——不是说这个概念只在这一个文件里,而是"想从哪开始读最不会迷路"。比如 KV cache 的实现散在好几个文件,但从 llama-kv-cache.h 的类定义看起准没错。
为什么分成这四类?因为它们恰好对应你读源码时的四种"在哪一层":核心数据结构是 ggml 这台计算器的"数据与图";推理流程是 llama 把一次对话跑起来的那条主线;内核与后端是"同一张图怎么落到不同硬件上";进阶机制与工具则是标准流程之外的那些特殊玩法。撞见一个陌生符号时,先粗判它属于哪一类,往往就已经知道该去哪个目录找了。
| 术语 | 一句话定义 | 源码位置 | 跳转 |
|---|---|---|---|
| ggml_tensor | 张量:ggml 里数据的基本单位,带形状/类型/数据指针,也是计算图的节点 | ggml/include/ggml.h | L05 |
| ggml_cgraph | 计算图:把一串算子按依赖连成的 DAG,先建图、再统一执行 | ggml/src/ggml-impl.h | L09 / L10 |
| GGUF | llama.cpp 的模型文件格式:自描述的单文件,元数据 + 全部张量都在里面 | ggml/include/gguf.h | L13 |
| ggml_type | 张量的数据/量化类型(F16、Q4_K 等),决定每个权重怎么存、占多少字节 | ggml/include/ggml.h | L06 / L12 |
| 术语 | 一句话定义 | 源码位置 | 跳转 |
|---|---|---|---|
| llama_context | 一次推理会话:持有 KV cache、计算缓冲、采样状态等全部运行时状态 | src/llama-context.h | L17 |
| llama_batch | 一次 decode 喂进去的一批 token(或 embedding),附带位置和序列信息 | include/llama.h | L18 |
| KV cache | 缓存历史 token 的 K/V,让每步只算新 token;显存随序列线性增长 | src/llama-kv-cache.h | L19 |
| llama_vocab | 词表:token id 与文本互转,含特殊 token 与分词器(SentencePiece/BPE) | src/llama-vocab.h | L20 |
| llama_sampler | 采样器:从 logits 按策略(top-k/top-p/温度等)挑出下一个 token | src/llama-sampler.cpp | L21 |
| RoPE | 旋转位置编码:给 Q/K 注入位置信息的算子,相关超参写在模型元数据里 | ggml/include/ggml.h | L15 |
| 术语 | 一句话定义 | 源码位置 | 跳转 |
|---|---|---|---|
| ggml_backend | 后端抽象:一种执行计算图的设备实现(CPU/CUDA/Metal/Vulkan...) | ggml/include/ggml-backend.h | L31 / L33 |
| 算子 (op) | 计算图的基本运算(matmul、softmax、rope...),每个后端各实现一份 | ggml/include/ggml.h | L11 |
| CPU 后端 | 参考实现,是所有后端的 ground truth;带 SIMD 和多线程优化 | ggml/src/ggml-cpu | L31 |
| 后端调度 | 把一张图的算子分派到合适的后端、处理跨后端的数据搬运 | ggml/include/ggml-backend.h | L33 |
| 术语 | 一句话定义 | 源码位置 | 跳转 |
|---|---|---|---|
| build_moe_ffn | MoE:路由器给 token 选 top-k 专家、只算选中的专家再加权合并 | src/llama-graph.cpp | L35 |
| common_speculative | 投机解码:小模型猜一串、大模型一次并行验证,接受匹配前缀来提速 | common/speculative.h | L34 |
| mtmd | 多模态:clip + projector 把图像编成 embedding,和文本一起 decode | tools/mtmd/mtmd.h | L36 |
| ggml_ssm_scan | 状态空间模型:用固定大小的递推状态替代 KV cache,显存 O(1) | ggml/include/ggml.h | L37 |
| LoRA | 低秩适配器:不改原权重,挂一个小的低秩增量来做微调 | src/llama-adapter.h | L24 |
| convert_hf_to_gguf | 把 HF 模型转成 GGUF:认架构 -> 张量改名 -> 写盘的薄 CLI + conversion 包 | convert_hf_to_gguf.py | L38 |
用法很简单:把这一页加进收藏。当你读源码或调 bug 撞见一个名词,先来术语表扫一眼"是什么、在哪定义",需要深入就点链接回到那一课的现场;想理清几个概念的关系,就回头看那张依赖图。它不替代任何一课,只是让你不必为了一个名词把整门课重翻一遍——这正是"速查"二字的全部意义。 也别忘了浏览器自带的页内搜索(Ctrl/Cmd+F):在这一页直接搜一个英文符号名,往往比你回想"它在第几课"还快。也提醒一句:这二十来个词只是骨架,不是全部。书里还讲过不少同样重要、但更专门的概念——比如聊天模板(L22)、语法约束解码(L23)、llama-server 的连续批处理(L28)、量化工具与评测(L29/L30)。它们没进这张速查表,只是因为速查讲究"少而准";真要用到,顺着对应课的标题就能找回去。换句话说,这张表是一份最常用词的索引,而整门课才是完整的词典。 用熟了你会发现,查得越少、记得越牢——好的速查表,最终是为了让你不再需要它。
最后,收个尾。四十课走下来,你已经把 llama.cpp 从"一个能跑大模型的神奇程序",拆成了一台看得见每个零件、说得清每条数据流的机器:模型怎么加载、一个 token 怎么从 prompt 一路走到输出、KV cache 怎么省下重复计算、后端怎么把计算图算到 GPU 上、进阶架构怎么在标准 transformer 之外另辟蹊径、又怎么把这一切转换、编译、再贡献回去。读懂一个真实世界的大型 C++ 项目,从来不是靠一口气读完,而是靠一层层拆、一个个概念啃——而你,已经做到了。接下来,挑一个你真正好奇或在意的点,去读它的源码、去跑它、去改它。这门图解课到此结束,但你和 llama.cpp 的故事,才刚翻到"自己动手"那一页。
如果你问"那具体第一步做什么?"——这里有几个低门槛的入口:把 llama-cli 加上 -v 跑一遍,对着刷屏的日志,认一认前面学过的加载、建图、decode、采样各个阶段;或者挑一个最小的 test-* 用例,读懂它、再故意把它改坏,看测试怎么报错;又或者去仓库的 issue 列表里找一个标着 "good first issue" 的小问题练手。重要的从来不是第一步多大,而是真的迈出去——你手里已经有了这张地图,不会迷路。祝你玩得开心。
Here we are - all 40 lessons done. Starting from "what is llama.cpp", you have walked through ggml's tensors and compute graphs, llama's model loading and inference loop, the public API and command-line tools, the low-level CPU/CUDA kernels, on through advanced mechanisms like speculative decoding, MoE, multimodality, and state-space models, and finally how to convert a HuggingFace model to GGUF and how to open a PR this project will accept. You have been through this inference engine top to bottom.
This last lesson teaches nothing new; it hands you a quick-reference map: first a "learning path" making clear how the nine parts build up step by step, then a concept dependency map drawing "who builds on whom" among the core concepts, and finally a categorized glossary - each term a one-line definition, marked with where it lives in the source, plus a "click to jump back to the lesson that covers it" link. Forget a concept later and you need not page through from the start; come here, look it up, jump back to the scene.
How to use it: when reading code or debugging you hit a half-familiar term (ggml_cgraph? llama_batch?), first scan the glossary for "roughly what it is, where it is defined", and follow the link back to its lesson when you need detail. This lesson itself is short; its whole value is "look up fast, jump accurately". In other words, the earlier lessons teach "how to understand from scratch"; this one helps you "recall quickly later".
Start with the whole. The nine parts of this course are not in random order; they go from outside in, then inside out: first build a global picture, then drill layer by layer into ggml and llama internals, and once the internals are clear, come back out to tools, kernels, advanced mechanisms, and finally practice and quick reference. Each part stands on the shoulders of the one before - so if a lesson feels like a jump, paging back usually reconnects it. A small tip: if you came with a specific goal (say "I only want to get quantization"), feel free to jump straight to that part; but to build whole-picture intuition, going through in order is still the least-effort path.
This map also answers a common question: "in what order should I read?" The answer is left to right: each part assumes you have digested what is to its left. Of course, as a quick-reference page you can also jump into any cell - which is exactly what the glossary below is for. This is also why almost every earlier lesson opens by connecting back to the previous one in a sentence or two - the course's "building up step by step" is visible at a glance on this map.
Look one level deeper and the nine parts are really in three movements: movement one (parts 1-3) builds the "what is it" big picture, so you are not drowned in detail from the start; movement two (parts 4-7) dives into the engine, taking apart the "machine parts" - tensors, compute graph, KV cache, sampling, kernels - one by one; movement three (parts 8-9) comes back out of the internals, landing on "how to use it, change it, look it up". Many people stall on a big project because they skip movement one and dig straight into detail, or finish the detail but never return to movement three to actually use it - this course deliberately lays out all three for you.
The nine parts are an order in time; but among the concepts there is another layer of logical dependency - who is the foundation, who is built on whom. The map below stacks the most core concepts by dependency: at the very bottom is ggml_tensor (the basic unit of all data), each layer above builds on the one below, and only at the very top sits the "one llama_decode" you know best. Note that "dependency" and "call order" are not the same: at runtime things are initiated top-down (decode calls context, context calls the backend), but building and understanding are best done bottom-up - understand tensors before you can talk about graphs and backends.
For a concrete example, "walk" the map once: you type a sentence into llama-cli; it first goes through vocab into tokens, packed into a llama_batch, handed to llama_decode on the llama_context; inside, the context builds a ggml_cgraph (all ggml_tensor nodes), handed to some ggml_backend to execute, reading and writing the KV cache along the way; finally it emits logits and the sampler picks the next token. See - from input to output, that touched every box in the map exactly once. This is why "read this map and you have read the skeleton of one inference".
The real value of this map is that it draws "where to look when reading source". Say you are debugging something to do with the KV cache: follow the map and you know to look inside llama_context (which holds the KV cache), rather than wandering off into the ggml_tensor layer. Every arrow is a clue for "which layer to chase when something goes wrong".
Below are the terms you deal with most across the book, in four groups. Each entry gives three things: a one-line definition (what it is, what it handles), a source location (which file to read for the real thing), and a jump (click to return to the lesson that covers it). Not exhaustive - just enough to "recognize it the moment you bump into it". About the "source location" column: it gives a single best entry point - not that the concept lives in only that one file, but "where to start reading so you least get lost". The KV cache implementation, for instance, spreads across several files, but starting from the class definition in llama-kv-cache.h is never wrong.
Why these four groups? Because they line up with the four "which layer am I in" you face when reading source: core data structures are the "data and graph" of the ggml calculator; the inference flow is llama's main line that runs one conversation; kernels and backends is "how the same graph lands on different hardware"; and advanced mechanisms and tools are the special plays beyond the standard flow. When you hit an unfamiliar symbol, roughly judging which group it belongs to often already tells you which directory to look in.
| term | one-line definition | source location | jump |
|---|---|---|---|
| ggml_tensor | tensor: ggml's basic unit of data, with shape/type/data pointer; also a node of the compute graph | ggml/include/ggml.h | L05 |
| ggml_cgraph | compute graph: a DAG wiring ops by dependency; build the graph first, then execute it as a whole | ggml/src/ggml-impl.h | L09 / L10 |
| GGUF | llama.cpp's model file format: a self-describing single file holding both metadata and all tensors | ggml/include/gguf.h | L13 |
| ggml_type | a tensor's data/quant type (F16, Q4_K, ...), deciding how each weight is stored and how many bytes | ggml/include/ggml.h | L06 / L12 |
| term | one-line definition | source location | jump |
|---|---|---|---|
| llama_context | one inference session: holds the KV cache, compute buffers, sampling state - all runtime state | src/llama-context.h | L17 |
| llama_batch | the batch of tokens (or embeddings) fed into one decode, with position and sequence info | include/llama.h | L18 |
| KV cache | caches past tokens' K/V so each step computes only the new token; memory grows linearly with length | src/llama-kv-cache.h | L19 |
| llama_vocab | vocabulary: token ids to/from text, including special tokens and the tokenizer (SentencePiece/BPE) | src/llama-vocab.h | L20 |
| llama_sampler | sampler: picks the next token from logits by a strategy (top-k/top-p/temperature, ...) | src/llama-sampler.cpp | L21 |
| RoPE | rotary position encoding: an op injecting position into Q/K; its hyper-params live in model metadata | ggml/include/ggml.h | L15 |
| term | one-line definition | source location | jump |
|---|---|---|---|
| ggml_backend | backend abstraction: a device implementation that executes the compute graph (CPU/CUDA/Metal/Vulkan...) | ggml/include/ggml-backend.h | L31 / L33 |
| op (operator) | a basic graph operation (matmul, softmax, rope...); each backend implements its own version | ggml/include/ggml.h | L11 |
| CPU backend | the reference implementation, ground truth for all backends; with SIMD and multithreading | ggml/src/ggml-cpu | L31 |
| backend dispatch | assigns a graph's ops to suitable backends and handles cross-backend data movement | ggml/include/ggml-backend.h | L33 |
| term | one-line definition | source location | jump |
|---|---|---|---|
| build_moe_ffn | MoE: the router picks top-k experts per token, computes only the chosen ones, then weight-merges | src/llama-graph.cpp | L35 |
| common_speculative | speculative decoding: a small model guesses a run, the big model verifies in parallel, accept the prefix | common/speculative.h | L34 |
| mtmd | multimodal: clip + projector encode an image into embeddings, decoded together with text | tools/mtmd/mtmd.h | L36 |
| ggml_ssm_scan | state-space models: a fixed-size recurrent state replaces the KV cache, O(1) memory | ggml/include/ggml.h | L37 |
| LoRA | low-rank adapter: fine-tune by hanging a small low-rank delta on top, without changing original weights | src/llama-adapter.h | L24 |
| convert_hf_to_gguf | convert an HF model to GGUF: recognize arch -> rename tensors -> serialize; a thin CLI + conversion package | convert_hf_to_gguf.py | L38 |
Usage is simple: bookmark this page. When reading source or chasing a bug you hit a term, come to the glossary for "what it is, where it is defined", and click the link back to its lesson when you need depth; to untangle how a few concepts relate, look again at that dependency map. It replaces no lesson; it just spares you re-reading the whole course over one term - which is the entire point of "quick reference". And do not forget the browser's in-page search (Ctrl/Cmd+F): searching an English symbol name right on this page is often faster than recalling "which lesson was it in". One more reminder: these twenty-odd terms are only the skeleton, not everything. The book covers many equally important but more specialized concepts too - chat templates (L22), grammar-constrained decoding (L23), llama-server's continuous batching (L28), the quantize tool and evaluation (L29/L30). They are not in this quick table only because quick reference favors "few and precise"; when you actually need one, the lesson title leads you right back. In other words, this table is an index of the most-used terms, while the whole course is the full dictionary. As you grow used to it you will find the less you look up, the better you remember - the best quick reference, in the end, is one that frees you from needing it.
Finally, a closing word. Forty lessons in, you have taken llama.cpp from "a magical program that runs big models" and turned it into a machine whose every part is visible and whose every data flow you can articulate: how a model loads, how one token travels from prompt all the way to output, how the KV cache saves repeated work, how a backend runs the compute graph on a GPU, how advanced architectures find a path beyond the standard transformer, and how to convert, build, and contribute all of it back. Understanding a real-world large C++ project is never about reading it in one breath; it is about peeling it layer by layer and chewing one concept at a time - and you have done exactly that. Next, pick a point you are genuinely curious about or care about, and go read its source, run it, change it. This illustrated course ends here, but your story with llama.cpp has just turned to the page titled "do it yourself".
If you ask "so what is the actual first step?" - here are a few low-barrier entry points: run llama-cli with -v and, against the scrolling logs, spot the loading, graph-building, decode, and sampling stages you learned earlier; or pick the smallest test-* case, understand it, then deliberately break it and watch how the test reports; or go to the repo's issue list and find a small one labeled "good first issue" to practice on. What matters is never how big the first step is, but actually taking it - you already hold this map, you will not get lost. Have fun.