核心架构
llama.cpp 仓库实现了一个用于 LLaMA 模型的 C++ 推理框架。其核心架构围绕 ggml 张量库进行数值计算,以及一组管理模型、上下文和推理过程的 C++ 类和函数。
关键组件
llama.cpp 架构的主要组件包括:
ggml张量库:所有数值运算的基础。- 模型加载与管理 (
llama_model):处理加载模型权重和参数。 - 上下文管理 (
llama_context):管理推理状态,包括 KV 缓存和计算图。 - 推理执行:执行实际的令牌生成。
1. ggml 张量库
目的与功能:
ggml 是一个专为机器学习推理设计的张量库。它为创建和操作多维数组(张量)以及定义计算图提供了基础构建模块。
ggml 的主要特性包括:
- 张量运算:一套全面的运算,如矩阵乘法、加法、激活函数等。(来源:ggml.hL8)
- 计算图:允许将复杂计算定义为一个操作图。然后可以高效地执行此图。(来源:ggml.hL20)
- 内存管理:
ggml使用上下文 (ggml_context) 来管理张量的内存。张量通常在预定义的内存缓冲区内分配。(来源:ggml.hL30-L38) - 量化支持:
ggml支持各种量化方案(例如 Q4_0、Q8_0)以减小模型大小并可能加速推理,相关函数通常位于ggml-quants.h中并在ggml.c内使用。(来源:ggml.cL11 引用ggml-quants.h) - 自动微分:虽然在
llama.cpp中主要用于推理,但ggml也具备自动微分的能力。(来源:ggml.hL10) - 后端系统 (
ggml_backend):ggml具有一个后端系统,允许将操作卸载到不同的硬件加速器,如 GPU(CUDA、Metal、OpenCL、SYCL、Vulkan)或专用硬件。(来源:ggml.cL7,ggml-backend.h) 在架构中的角色:ggml位于技术栈的最底层,提供核心计算能力。llama.cpp中的所有更高级别的组件(模型加载、上下文管理、推理)都依赖ggml进行张量运算和图执行。**
在架构中的角色: llama_model 组件是与特定 LLaMA 模型交互的入口点。它提供原始权重和参数,然后由 llama_context 用于执行推理。
2. 模型加载与管理 (llama_model)
目的与功能:
llama_model 结构(及相关函数)负责从 GGUF (GGML Universal File Format) 文件加载 LLaMA 模型权重和参数。
关键方面包括:
- 文件解析:读取 GGUF 文件格式,其中包含模型元数据、词汇表和张量数据。这主要由
llama_model_loader.cpp处理。(通过llama_load_model_from_file间接被llama.cpp使用) - 超参数加载:提取模型超参数,如词汇表大小、嵌入维度、层数等。(来源:llama.cppL100 -
model.load_hparams(ml)) - 词汇表加载:加载分词器词汇表。(来源:llama.cppL105 -
model.load_vocab(ml)) - 张量加载:将模型权重(张量)加载到内存中。这通常涉及内存映射(
mmap)以提高效率。(来源:llama.cppL115 -model.load_tensors(ml)) - 设备映射:根据
split_mode和main_gpu参数,将张量层分布到可用的计算设备(CPU、GPU)上。(来源:llama.cppL157-L180) 在架构中的角色:llama_model组件是与特定 LLaMA 模型交互的入口点。它提供原始权重和参数,然后由llama_context用于执行推理。
3. 上下文管理 (llama_context)
目的与功能:
llama_context 结构(及相关函数)封装了推理过程的状态。这包括 KV (Key-Value) 缓存、模型的计算图以及内存缓冲区。
关键方面包括:
- KV 缓存管理:存储先前令牌的注意力机制的键(Key)和值(Value),以加速后续令牌的生成。这对于高效的 Transformer 推理至关重要。(由
llama_context内部管理,KV 缓存的张量是上下文ggml_context_的一部分。) - 计算图构建:构建表示 LLaMA 模型前向传播的
ggml计算图。(在llama_new_context_with_model及后续评估期间完成)。 - 内存分配:使用
ggml为 KV 缓存、计算缓冲区和其他运行时数据分配内存。 - 批处理:通过
llama_batch处理用于推理的序列批次。(来源:llama.h 中llama_batch的定义,在llama_decode中使用)。 - 令牌评估:处理输入令牌并为下一个令牌生成 logits。
代码示例(创建上下文并执行推理 - 简化版):
在架构中的角色: llama_context 是推理的主力。它接收加载的 llama_model 并管理生成令牌所需的动态状态。单个模型可以存在多个上下文,从而允许并行推理会话(尽管线程安全需要用户应用程序仔细管理)。
4. 推理执行 (llama_decode、llama_sample_token 等)
目的与功能:
这指的是驱动实际令牌生成过程的一组函数。
典型推理循环中的关键步骤:
- 分词 (Tokenization):用户输入文本使用模型的词汇表(例如
llama_tokenize)转换为令牌序列。 - 批次准备 (Batch Preparation):将令牌准备到
llama_batch结构中,指定它们的位置、序列 ID 以及是否需要 logits。 - 解码 (
llama_decode):llama_context处理输入llama_batch的核心步骤。这包括:- 构建或更新
ggml计算图。 - 使用
ggml_graph_compute或后端特定函数执行该图。 - 更新 KV 缓存。
- 为批处理中
logits[i]为 true 的位置生成 logits。
- 构建或更新
- 采样 (
llama_sample_token、llama_sample_token_greedy等):根据llama_decode生成的 logits 选择下一个令牌。可以采用各种采样策略(贪婪、top-k、top-p、温度)。 - 反分词 (Detokenization):将采样的令牌 ID 转换回文本(例如
llama_token_to_piece)。 - 循环 (Loop):将新采样的令牌添加到序列中,重复此过程。
图表:推理循环
mermaid
在架构中的角色: 这些函数协调 llama_model、llama_context 和 ggml 之间的交互,以执行端到端的文本生成过程。
整体数据流和交互
mermaid
图表说明:
- GGUF 模型文件由
llama_load_model_from_file加载以创建llama_model实例。 (来源:llama.cppL131) llama_model用于初始化一个或多个llama_context实例。 (来源:llama.h -llama_new_context_with_model签名)- 输入文本被分词。
- 推理循环:
- 令牌被准备到
llama_batch中。 llama_decode使用llama_context处理批次。这涉及ggml进行图执行,并更新上下文中的 KV 缓存。 (来源:llama.h -llama_decode签名)- 从上下文中获取 Logits。
- 采样函数选择下一个令牌。
- 令牌被转换为文本,并成为下一次迭代输入的一部分。
- 令牌被准备到
- 循环继续,直到满足停止条件。
设置和使用
- 构建
llama.cpp:遵循仓库主 README.md 中的构建说明。这通常涉及 CMake。 - 获取模型文件:下载 GGUF 格式的 LLaMA 模型权重。
- 与您的应用程序集成:
- 在您的 C/C++ 项目中包含
llama.h。 - 链接已编译的
llama.cpp库。 - 如上述示例和仓库的
/examples目录中所示,使用 API 函数。
- 在您的 C/C++ 项目中包含
基本使用的关键 API 函数:
llama_backend_init()/llama_backend_free():初始化/反初始化 llama.cpp 后端(包括 ggml)。 (来源:llama.cppL50,llama.cppL66)llama_model_default_params()/llama_context_default_params():获取默认参数。llama_load_model_from_file():加载模型。llama_new_context_with_model():创建推理上下文。llama_tokenize():将文本转换为令牌。llama_batch_init()/llama_batch_free():管理令牌批次。llama_decode():处理令牌并生成 logits。llama_get_logits_ith():访问 logits。- 采样函数(例如
llama_sample_token_greedy、llama_sample_repetition_penalties等)。 llama_token_to_piece():将令牌 ID 转换为文本。llama_free()/llama_free_model():释放资源。
核心架构设计得既高效又灵活,允许从简单的命令行推断到更复杂的服务器应用程序等各种用例。ggml 的使用为数值计算提供了坚实的基础,而 llama.cpp 层则为与 LLaMA 模型交互提供了更高级别的 API。