Large Language Model,大语言模型。典型代表ChatGPT。
推理端:模型训练出来后,用于模型应用和部署的interface。
推理端实现了本地环境中部署大语言模型。可以实现LLM的基本功能,包括生成文本、自动摘要、语言翻译、代码生成、问答系统等。
Llamma.cpp是Llama推理端的C++实现库。github.com/ggerganov/l…
Llama(Large Language Model Meta AI)是Meta2023年2月发布的开源大语言模型。
论文:arxiv.org/pdf/2302.13…
Gemma.cpp是Gemma推理端的C++实现库。github.com/google/gemm…
Gemma是Google基于Gemini推出的开源LLM。blog.google/technology/…
论1b-212-215.above.com:2181
LLAMA.cpp用于在各种硬件平台上高效地运行大型语言模型(LLMs)。可以使大型语言模型能够在资源受限的环境中运行,例如在个人电脑、智能手机甚至树莓派等设备上。
Gemma.cpp用于在各种硬件平台上高效运行Gemma模型。
2. 工作流程
LLM推理端的工作流程大致相同,我们以Llama.cpp为例
Llama.cpp 工程目录
|-- example
| |-- main
| |-- main.cpp # 推理llama 2的主函数
|-- ggml-alloc.c #内存分配管理
|-- ggml-alloc.h
|-- llama.cpp # 整个llama 2的核心文件,包含所有重要interface
|-- llama.h
|-- ggml.c # 机器学习计算库.定义一些框架的基础数据结构和函数等
|-- ggml.h
|-- ggml-cuda.cu #cuda版本的llama2 中的kernel实现与调用
|-- ggml-cuda.h
|-- ggml-opencl.cpp #opencl版本的llama2 中的kernel实现与调用
|-- ggml-opencl.h
|-- ... #其他
Llama.cpp 的工作流程
步骤一:解析和设置参数
参数可以控制推理过程的行为。例如,可以设置批量大小来提高推理速度,或者设置温度来控制生成文本的多样性。
-
解析参数
gpt_params_parse()
。 -
可设置的用户参数:
- –model 模型地址
- –color 颜色区分生成和输入
- –interactive 启用交互模式
- –prompt 输入的提示词
- –file 提示词文件
步骤二:加载模型
加载模型是 LLAMA.cpp 工作流程的第一步。模型文件包含模型的参数和权重,是推理过程所必需的。
- 根据输入参数生成模型参数,
llama_model_params
- 使用
llama_load_model()
函数加载模型文件。
步骤三:创建 llama_context
llama_context
是整个llama.cpp 重要数据结构。存储了各种参数,模型,prompt,backend(cpu/gpu),推理的计算结果。
llama_new_context_with_model()
步骤四:处理输入的 prompt
将输入的文本数据转换为模型可以理解的格式。也就是文本转化为词向量。
-
Tokenization:
- 使用
llama_tokenize()
对输入文本进行分词(Tokenization),将文本拆分为token(词元)。 - 再输出为一个整数类型
token_id
。
- 使用
-
Embedding:
- 将分词后的文本转换为词嵌入向量(Embeddings),这通常涉及到查找预训练的词嵌入矩阵(词汇表)。词向量的长度为hidden_dim,是LLM模型训练后固定的。把每个词元
token_id
转化为一个向量。 - 对于某些模型,可能还需要进行位置编码(Positional Encoding)以保留序列中单词的顺序信息。
- 输出为(词元数 * hidden_dim)的矩阵。
- 将分词后的文本转换为词嵌入向量(Embeddings),这通常涉及到查找预训练的词嵌入矩阵(词汇表)。词向量的长度为hidden_dim,是LLM模型训练后固定的。把每个词元
步骤五:推理
这是LLAMA.cpp 工作流程的核心步骤。在这个步骤中,模型会根据输入数据生成预测结果。
推理包括两个部分逻辑
Prompt:将转化后的所有词向量进行Transformer-decode计算。
Generate:根据Prompt的结果和前一次生成的结果,进行Transformer-decode计算。最后返回预测结果
下面比较重要的函数
llama_decode()
开始推理llama_build_graph()
构建计算图llama_graph_compute()
根据计算图调用对应算子,开始计算。
计算的结果是一组概率数组,表示预测的结果,存放在llama_context
中。
步骤六:输出结果
对预测结果进行进一步处理。
- 根据需要对预测结果进行采样,获取到要输出的token_id。采样(sample)是从模型预测的概率分布中生成下一个词或标记的过程。
- 将token_id 转换回文本字符,
llama_token_to_piece()
。 - 输出结果给用户。
步骤七:释放资源
释放资源是 LLAMA.cpp 工作流程的最后一步。释放模型句柄可以回收内存和计算资源。
调用 llama_free_model()
等函数释放模型资源。
以下是一些 LLAMA.cpp 工作流程的示例代码:
//解析参数
gpt_params params;
gpt_params_parse(argc, argv, params);
// 加载模型
llama_model_t *model = llama_load_model("llama-2-7b-chat");
//创建llama_context
llama_context * ctx = llama_new_context_with_model(model, params);
// 处理输入prompt
const char *input = "This is an example input.";
vector<llama_token> *embd_input = llama_tokenize(ctx, input);
// 推理
llama_decode(ctx, embd_input);
// 输出结果
cllama_token id = llama_sampling_sample(llama_sampling_context, ctx);
string token_str = llama_token_to_piece(ctx, id)
printf("%s\n", token_str);
// 释放资源
llama_free(ctx);
llama_free_model(model);
3. 数学计算流程
3.1 模型架构
Llama的基础模型架构是Transformer,出自Attention Is All You Need。Transformer目前是大部分生成式人工智能的基础模型架构。
Llama相比基础Transformer,主要优化工作有下面几点:
- 使用RMSNorm作为标准函数
- 使用SwiGLU作为激活函数
- 使用RoPE作为位置编码函数
LLM的核心是Attention的计算。
Attention是计算每个token相对其他token的重要程度,结果是一组权重向量。
“算子”(Operator)通常指的是执行特定数学运算的函数或指令。类似于c/c++的operator关键字,
在机器学习中算子的对象是张量(Tensor)。
张量是用于数学计算的数据结构,它的基本构成是多维数组。
下面是Llama.cpp定义的算子
enum ggml_op {
GGML_OP_NONE = 0,
GGML_OP_DUP,
GGML_OP_ADD,
GGML_OP_ADD1,
GGML_OP_ACC,
GGML_OP_SUB,
GGML_OP_MUL,
GGML_OP_DIV,
GGML_OP_SQR,
GGML_OP_SQRT,
GGML_OP_LOG,
GGML_OP_SUM,
GGML_OP_SUM_ROWS,
GGML_OP_MEAN,
GGML_OP_ARGMAX,
GGML_OP_REPEAT,
GGML_OP_REPEAT_BACK,
GGML_OP_CONCAT,
GGML_OP_SILU_BACK,
GGML_OP_NORM, // normalize
GGML_OP_RMS_NORM,
GGML_OP_RMS_NORM_BACK,
GGML_OP_GROUP_NORM,
GGML_OP_MUL_MAT,
GGML_OP_MUL_MAT_ID,
GGML_OP_OUT_PROD,
GGML_OP_SCALE,
GGML_OP_SET,
GGML_OP_CPY,
GGML_OP_CONT,
GGML_OP_RESHAPE,
GGML_OP_VIEW,
GGML_OP_PERMUTE,
GGML_OP_TRANSPOSE,
GGML_OP_GET_ROWS,
GGML_OP_GET_ROWS_BACK,
GGML_OP_DIAG,
GGML_OP_DIAG_MASK_INF,
GGML_OP_DIAG_MASK_ZERO,
GGML_OP_SOFT_MAX,
GGML_OP_SOFT_MAX_BACK,
GGML_OP_ROPE,
GGML_OP_ROPE_BACK,
GGML_OP_ALIBI,
GGML_OP_CLAMP,
GGML_OP_CONV_TRANSPOSE_1D,
GGML_OP_IM2COL,
GGML_OP_CONV_TRANSPOSE_2D,
GGML_OP_POOL_1D,
GGML_OP_POOL_2D,
GGML_OP_UPSCALE, // nearest interpolate
GGML_OP_PAD,
GGML_OP_ARGSORT,
GGML_OP_LEAKY_RELU,
GGML_OP_FLASH_ATTN,
GGML_OP_FLASH_FF,
GGML_OP_FLASH_ATTN_BACK,
GGML_OP_WIN_PART,
GGML_OP_WIN_UNPART,
GGML_OP_GET_REL_POS,
GGML_OP_ADD_REL_POS,
GGML_OP_UNARY,
GGML_OP_MAP_UNARY,
GGML_OP_MAP_BINARY,
GGML_OP_MAP_CUSTOM1_F32,
GGML_OP_MAP_CUSTOM2_F32,
GGML_OP_MAP_CUSTOM3_F32,
GGML_OP_MAP_CUSTOM1,
GGML_OP_MAP_CUSTOM2,
GGML_OP_MAP_CUSTOM3,
GGML_OP_CROSS_ENTROPY_LOSS,
GGML_OP_CROSS_ENTROPY_LOSS_BACK,
GGML_OP_COUNT,
};
标记为红色的算子是计算Attention中会用到的。
3.2 Attention计算步骤和对应的算子
CUDA是LLM计算中最常采用的计算平台,我们以CUDA算子举例。
CUDA是NVIDIA推出的基于GPU的科学计算软件平台和代码模型,大范围用于机器学习领域的训练和推理的计算工作。它提供了一套API和工具,使得程序员可以编写能够在GPU上执行的并行程序。
Llama.cpp的所有CUDA核函数实现全部在ggml-cuda.cu
算法流程
把上面算法流程进行拆分
Q*K - MatMul - 矩阵乘法
CUDA算子:mul_mat_p021_f16_f32
static __global__ void mul_mat_p021_f16_f32(
const void * __restrict__ vx, const float * __restrict__ y, float * __restrict__ dst,
const int ncols_x, const int nrows_x, const int nchannels_x, const int nchannels_y)
{
}
除以sqrt(dk) - Scale - 缩放
CUDA算子: scale_f32
static __global__ void scale_f32(const float * x, float * dst, const float scale, const int k) {
const int i = blockDim.x*blockIdx.x + threadIdx.x;
if (i >= k) {
return;
}
dst[i] = scale * x[i];
}
Mask - Mask
CUDA算子:diag_mask_inf_f32
static __global__ void diag_mask_inf_f32(const float * x, float * dst, const int ncols, const int rows_per_channel, const int n_past) {
const int col = blockDim.y*blockIdx.y + threadIdx.y;
const int row = blockDim.x*blockIdx.x + threadIdx.x;
if (col >= ncols) {
return;
}
const int i = row*ncols + col;
//dst[i] = col > (n_past + row % rows_per_channel) ? -INFINITY : x[i];
//dst[i] = x[i] - (col > n_past + row % rows_per_channel) * INT_MAX; // equivalent within rounding error but slightly faster on GPU
dst[i] = x[i] - (col > n_past + row % rows_per_channel) * FLT_MAX;
}
softmax - SoftMax
CUDA算子:soft_max_f32
static __global__ void soft_max_f32(const float * x, const float * mask, const float * pos, float * dst, const int ncols_par, const int nrows_y, const float scale, const float max_bias, const float m0, const float m1, uint32_t n_head_log2)
{
}
- V - MatMul - 矩阵乘法
CUDA算子:mul_mat_vec_nc_f16_f32
static __global__ void mul_mat_vec_nc_f16_f32( // nc == non-contiguous
const void * __restrict__ vx, const float * __restrict__ y, float * __restrict__ dst, const int ncols_x, const int nrows_x,
const int row_stride_x, const int channel_stride_x, const int channel_x_divisor)
{
}
4. 工程优化
LLAMA.cpp使LLM能够在资源受限的环境中运行,例如在个人电脑、智能手机甚至树莓派等设备上。
已经对各种硬件环境进行了优化。
主要包括:
宏定义 | 计算优化项 |
GGML_USE_MPI | MPI并行计算优化 |
GGML_USE_METAL | METAL GPU计算优化 |
GGML_USE_CUBLAS | CUDA GPU计算优化 |
GGML_USE_VULKAN | VULKAN GPU计算优化 |
GGML_USE_SYCL | SYCL 并行计算优化 |
GGML_USE_KOMPUTE | KOMPUTE GPU计算优化 |
LLAMA_AVX,LLAMA_AVX2,LLAMA_AVX512 | CPU指令集优化 |
推理过程中llama_graph_compute()
等函数中调用不同平台优化算子。
static void ggml_compute_forward(struct ggml_compute_params * params, struct ggml_tensor * tensor) {
GGML_ASSERT(params);
if (tensor->op == GGML_OP_NONE) {
return;
}
#ifdef GGML_USE_CUBLAS
bool skip_cpu = ggml_cuda_compute_forward(params, tensor);//调用ggml-cuda.cu的CUDA算子
if (skip_cpu) {
return;
}
GGML_ASSERT(tensor->src[0] == NULL || tensor->src[0]->backend == GGML_BACKEND_TYPE_CPU);
GGML_ASSERT(tensor->src[1] == NULL || tensor->src[1]->backend == GGML_BACKEND_TYPE_CPU);
#elif defined(GGML_USE_VULKAN)
const bool skip_cpu = ggml_vk_compute_forward_cpu_assist(params, tensor);
#ifdef GGML_VULKAN_CHECK_RESULTS
if (skip_cpu) {
ggml_vk_check_results_1_cpu_assist(params, tensor);
}
#endif
if (skip_cpu) {
return;
}
GGML_ASSERT(tensor->src[0] == NULL || tensor->src[0]->backend == GGML_BACKEND_TYPE_CPU);
GGML_ASSERT(tensor->src[1] == NULL || tensor->src[1]->backend == GGML_BACKEND_TYPE_CPU);
#endif // GGML_USE_CUBLAS
#ifdef GGML_USE_SYCL
bool skip_cpu = ggml_sycl_compute_forward(params, tensor);
if (skip_cpu) {
return;
}
#endif // GGML_USE_SYCL
Gemma.cpp使用Hightway高性能cpp库进行针对CPU的计算优化。
算法优化 Lora - (Low-Rank Adaptation)优化和调整大型预训练语言模型的技术。能够减少计算资源和内存需求。
KVcache - 缓存下Attention计算中产生的Key和Value张量,减少计算量。
量化 - 量化通常涉及将浮点数(如32位的FP32)转换为低精度的表示,如8位的整数(INT8)或其他低精度格式。这种转换可以在不显著影响模型性能的情况下,显著降低模型的内存占用和计算需求。(这段由moonshot 生成)
Ps. 推理过程需要的显存
Llama 7B模型为例,使用FP16数据类型,每个FP16占2个字节。hidden_dim为4096,每个K和V 都要储存。一共32个Transformer Layer。
FP16 * hidden_dim * K,V * 32Layer * context_length = 2 * 4096 * 2 * 32 * context_length(取1024) = 512M
如果输入有1024个token就需要512M显存。
如何学习AI大模型?
我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;
第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;
第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;
第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;
第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;
第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;
第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。
👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;
• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;
• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;
• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。
1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集
👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓