从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核心 | 336G | 4 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