从0开始微调LLama2系列 (2) - 运行一下llama2

676 阅读5分钟

从0开始微调LLama2系列 (2) - 运行一下llama2

前言

上一期给大家带来如何下载模型参数。在完成模型参数下载之后,我们可以尝试运行一下模型看看效果。

本文基于Chinese-LLaMA-Alpaca-2项目

在GPU上运行

克隆好了Chinese-LLaMA-Alpaca-2 项目之后,基于GPU的部署非常简单。我们以中文Alpaca-2模型为例,下载完成以后的模型参数(Hugging Face 格式)如下:

简单说明一下各个文件的作用

文件名称示例说明
config.json{
"architectures": [
"LlamaForCausalLM"
],
"hidden_size": 4096,
...
"vocab_size": 55296
}
hugging face Transformer的配置文件 文档路径在
huggingface.co/docs/transf…
generation_config.json{
"_from_model_config": true,
"bos_token_id": 1,
"eos_token_id": 2,
"pad_token_id": 0,
"transformers_version": "4.31.0"
}
这个主要是为了generation方法提供参数
huggingface.co/docs/transf…
pytorch_model.bin.index.json{
"metadata": {
"total_size": 13858521088
},
"weight_map": {
...
}

}
包含一些元数据以及一个参数名映射表,包含权重指示信息
pytorch_model-*.bin标准的Pytorch state dicts,它们各自包含模型的一部分
special_tokens_map.json{
...
"pad_token": "",
"unk_token": {
"content": "",
"lstrip": false,
"normalized": true,
"rstrip": false,
"single_word": false
}
}
映射文件,里面包含 unknown token 等特殊字符的映射关系;
tokenizer_config.json{
"add_bos_token": true,
...
"unk_token": {
"__type": "AddedToken",
"content": "",
"lstrip": false,
"normalized": true,
"rstrip": false,
"single_word": false
},
"use_fast": false
}
分词器配置文件,存储构建分词器需要的参数
tokenizer.model标记器(Tokenizer):将文本转换为模型可以处理的数据。模型只能处理数字,因此标记器(Tokenizer)需要将我们的文本输入转换为数字数据。

模型推理 Chinese-LLaMA-Alpaca-2 提供了一些使用脚本,可以很方便的体验模型推理的过程 教程

 python scripts/inference/inference_hf.py \
    --base_model /root/alpaca \
    --with_prompt \
    --interactive

在CPU上运行

在CPU上推理可以借助开源项目llama.cpp进行,该项目作者是Georgi Gerganov,是Vim/C/C++的狂热爱好者,目前位于保加利亚(B站十年老粉丝狂喜),该项目是老哥一晚上coding出来的,太猛了。

该项目支持了

  • 纯C/C++实现,无依赖
  • 优先支持Apple硅芯片 - 通过ARM NEON、Accelerate和Metal框架进行优化
  • 为x86架构支持AVX、AVX2和AVX512
  • 混合F16 / F32精度
  • 支持4位、5位和8位整数量化
  • 在BLAS中支持OpenBLAS/Apple BLAS/ARM Performance Lib/ATLAS/BLIS/Intel MKL/NVHPC/ACML/SCSL/SGIMATH等更多
  • 支持cuBLAS和CLBlast

让我们直接看看怎么用 教程

  • 克隆项目并编译

添加图片注释,不超过 140 字(可选)

  • 将已有的模型文件转换为gglm格式

  • 可选:量化并裁减模型大小

  • 读取并执行
#!/bin/bash 
# temporary script to chat with Chinese Alpaca-2 model 
# usage: ./chat.sh alpaca2-ggml-model-path your-first-instruction 

SYSTEM='You are a helpful assistant. 你是一个乐于助人的助手。' 
FIRST_INSTRUCTION=$2 
./main -m $1 \ --color -i -c 4096 -t 8 --temp 0.5 --top_k 40 --top_p 0.9 --repeat_penalty 1.1 -eps 1e-5 \ --in-prefix-bos --in-prefix ' [INST] ' --in-suffix ' [/INST]' -p \ "[INST] <<SYS>> $SYSTEM <</SYS>> $FIRST_INSTRUCTION [/INST]"

一些讨论

非标准的推理速度对比

我的设备环境如下:

CPU内存GPU
Intel(R) Xeon(R) Platinum 8260 CPU @ 2.40GHz
84核心
336G4 x T4

GPU推理速度 计算推理速度比较粗暴,用生成一次回答所产生总token数除以所花费的时间

import time 
import torch 
# 加载模型和tokenizer 
# ... (你的模型和tokenizer加载代码) 
# 准备数据 input_data = "请问中国的首都是" 
# 示例输入 
# 开始计时 start_time = time.time() # 进行N次生成以获得更稳定的计时结果 N = 100 all_tokens_generated = 0 for _ in range(N): with torch.no_grad(): generation_output = model.generate( input_ids=tokenizer(input_data, return_tensors="pt")["input_ids"].to(device), # ... (你的其他参数) ) all_tokens_generated += generation_output.shape[1] # 添加生成的token数 # 结束计时 end_time = time.time() # 计算平均每次生成的token数 average_tokens_per_generation = all_tokens_generated / N # 计算总体tokens/秒 total_time = end_time - start_time tokens_per_second = average_tokens_per_generation / (total_time / N) print(f"Tokens per second: {tokens_per_second}")
import time
import torch

# 加载模型和tokenizer
# ... (你的模型和tokenizer加载代码)

# 准备数据
input_data = "请问中国的首都是"  # 示例输入

# 开始计时
start_time = time.time()

# 进行N次生成以获得更稳定的计时结果
N = 100
all_tokens_generated = 0
for _ in range(N):
    with torch.no_grad():
        generation_output = model.generate(
            input_ids=tokenizer(input_data, return_tensors="pt")["input_ids"].to(device),
            # ... (你的其他参数)
        )
    all_tokens_generated += generation_output.shape[1]  # 添加生成的token数

# 结束计时
end_time = time.time()

# 计算平均每次生成的token数
average_tokens_per_generation = all_tokens_generated / N

# 计算总体tokens/秒
total_time = end_time - start_time
tokens_per_second = average_tokens_per_generation / (total_time / N)
print(f"Tokens per second: {tokens_per_second}")

得到的结果如下:

Input:中国的首都在哪
generation的size是torch.Size([1, 54])
总共token数量54, 花费时间为1.3875749111175537, 为平均每秒生成tokens数38.916817800134744
Response:  中国的首都是北京,位于华北平原中部、北京市中心城区。

需要注意的是这并不一定准确,随着输出token长度增加,速度会减慢。

CPU推理速度

llama.cpp 自带测量token输出速度,测试下来速度如下,稍微比GPU (hugging face transformer)慢一点

 [INST] <<SYS>>
You are a customer service representative in the automotive industry. 你是一个汽车行业的客服。
<</SYS>>

中国的首都在哪 [/INST] 中国的首都是北京,位于华北平原中部,是中国政治、文化和经济中心之一。
 [INST]

llama_print_timings:        load time =  1426.19 ms
llama_print_timings:      sample time =    20.37 ms /    21 runs   (    0.97 ms per token,  1030.78 tokens per second)
llama_print_timings: prompt eval time =  1336.76 ms /    43 tokens (   31.09 ms per token,    32.17 tokens per second)
llama_print_timings:        eval time =  8450.20 ms /    20 runs   (  422.51 ms per token,     2.37 tokens per second)
llama_print_timings:       total time = 36573.28 ms