-
Notifications
You must be signed in to change notification settings - Fork 576
llamacpp_zh
以llama.cpp工具为例,介绍模型量化并在本地部署的详细步骤。Windows则可能需要cmake等编译工具的安装。本地快速部署体验推荐使用经过指令精调的Alpaca-2模型,有条件的推荐使用6-bit或者8-bit模型,效果更佳。 下面以中文Alpaca-2-7B模型为例介绍,运行前请确保:
- 系统应有
make
(MacOS/Linux自带)或cmake
(Windows需自行安装)编译工具 - 建议使用Python 3.10以上编译和运行该工具
- (可选)如果已下载旧版仓库,建议
git pull
拉取最新代码,并执行make clean
进行清理 - 拉取最新版llama.cpp仓库代码
$ git clone https://github.com/ggerganov/llama.cpp
- 对llama.cpp项目进行编译,生成
./main
(用于推理)和./quantize
(用于量化)二进制文件。
$ make
Windows/Linux用户如需启用GPU推理,则推荐与BLAS(或cuBLAS如果有GPU)一起编译,可以提高prompt处理速度。以下是和cuBLAS一起编译的命令,适用于NVIDIA相关GPU。参考:llama.cpp#blas-build
$ make LLAMA_CUBLAS=1
macOS用户无需额外操作,llama.cpp已对ARM NEON做优化,并且已自动启用BLAS。M系列芯片推荐使用Metal启用GPU推理,显著提升速度。只需将编译命令改为:LLAMA_METAL=1 make
,参考llama.cpp#metal-build
$ LLAMA_METAL=1 make
(💡 也可直接下载已量化好的gguf模型:gguf模型)
目前llama.cpp已支持.pth
文件以及huggingface格式.bin
的转换。将完整模型权重转换为GGML的FP16格式,生成文件路径为zh-models/7B/ggml-model-f16.gguf
。进一步对FP16模型进行4-bit量化,生成量化模型文件路径为zh-models/7B/ggml-model-q4_0.gguf
。不同量化方法的性能对比见本Wiki最后部分。
$ python convert.py zh-models/7B/
$ ./quantize ./zh-models/7B/ggml-model-f16.gguf ./zh-models/7B/ggml-model-q4_0.gguf q4_0
由于本项目推出的Alpaca-2使用了Llama-2-chat的指令模板,请首先将本项目的scripts/llama-cpp/chat.sh
拷贝至llama.cpp的根目录。chat.sh
文件的内容形如,内部嵌套了聊天模板和一些默认参数,可根据实际情况进行修改。最新版llama.cpp已在转换模型时考虑了长上下文训练时的参数,因此加载长上下文版模型时无需手动设置--rope-scale
参数。
- GPU推理:cuBLAS/Metal编译需要指定offload层数,在
./main
中指定例如-ngl 40
表示offload 40层模型参数到GPU
#!/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 \
--in-prefix-bos --in-prefix ' [INST] ' --in-suffix ' [/INST]' -p \
"[INST] <<SYS>>
$SYSTEM
<</SYS>>
$FIRST_INSTRUCTION [/INST]"
使用以下命令启动聊天。
$ chmod +x chat.sh
$ ./chat.sh zh-models/7B/ggml-model-q4_0.gguf '请列举5条文明乘车的建议'
在提示符 >
之后输入你的prompt,cmd/ctrl+c
中断输出,多行信息以\
作为行尾。如需查看帮助和参数说明,请执行./main -h
命令。下面介绍一些常用的参数:
-c 控制上下文的长度,值越大越能参考更长的对话历史(默认:512)
-f 指定prompt模板,alpaca模型请加载prompts/alpaca.txt
-n 控制回复生成的最大长度(默认:128)
-b 控制batch size(默认:512)
-t 控制线程数量(默认:8),可适当增加
--repeat_penalty 控制生成回复中对重复文本的惩罚力度
--temp 温度系数,值越低回复的随机性越小,反之越大
--top_p, top_k 控制解码采样的相关参数
更详细的官方说明请参考:https://github.com/ggerganov/llama.cpp/tree/master/examples/main
下表给出了不同量化方法的相关统计数据供参考。推理模型为Chinese-LLaMA-2-7B,测试设备为M1 Max芯片(8x性能核心,2x能效核心),分别汇报CPU速度(8线程)和GPU速度,单位为ms/tok。速度方面报告的是eval time
,即模型回复生成的速度。更多关于量化参数的介绍可参考llama.cpp量化统计表。
相关结论:
- 默认的量化方法为q4_0,虽然速度最快但损失也较大,推荐使用Q4_K作为替代
- 线程数
-t
与物理核心数一致时速度最快,超过之后速度反而变慢(M1 Max上从8改到10之后耗时变为3倍) - 机器资源够用且对速度要求不是那么苛刻的情况下可以使用q8_0或Q6_K,非常接近F16模型的效果
测试命令:
$ ./perplexity -m zh-models/7B/ggml-model-q4_0.gguf -f test.txt -c 4096 -ngl 999
F16 | Q2_K | Q3_K | Q4_0 | Q4_1 | Q4_K | Q5_0 | Q5_1 | Q5_K | Q6_K | Q8_0 | |
---|---|---|---|---|---|---|---|---|---|---|---|
PPL | 9.128 | 11.107 | 9.576 | 9.476 | 9.576 | 9.240 | 9.156 | 9.213 | 9.168 | 9.132 | 9.129 |
Size | 12.91G | 2.41G | 3.18G | 3.69G | 4.08G | 3.92G | 4.47G | 4.86G | 4.59G | 5.30G | 6.81G |
CPU Speed | 117 | 42 | 51 | 39 | 44 | 43 | 48 | 51 | 50 | 54 | 65 |
GPU Speed | 53 | 19 | 21 | 17 | 18 | 20 | x | x | 25 | 26 | x |
F16 | Q2_K | Q3_K | Q4_0 | Q4_1 | Q4_K | Q5_0 | Q5_1 | Q5_K | Q6_K | Q8_0 | |
---|---|---|---|---|---|---|---|---|---|---|---|
PPL | 8.810 | 12.804 | 9.738 | 9.371 | 9.549 | 8.952 | 8.988 | 8.924 | 8.858 | 8.820 | 8.811 |
Size | 24.69G | 5.26G | 6.02G | 7.01G | 7.77G | 7.48G | 8.52G | 9.28G | 8.76G | 10.13G | 13.05G |
CPU Speed | - | 75 | 90 | 76 | 80 | 80 | 91 | 99 | 92 | 104 | 125 |
GPU Speed | - | 31 | 37 | 30 | 32 | 36 | x | x | 47 | 51 | x |
llama.cpp还提供架设server的功能,用于API调用、架设简易demo等用途。
运行以下命令启动server,二进制文件./server
在llama.cpp根目录,服务默认监听127.0.0.1:8080
。这里指定模型路径、上下文窗口大小。如果需要使用GPU解码,也可指定-ngl
参数。
$ ./server -m ./zh-models/7B/ggml-model-q4_0.gguf -c 4096 -ngl 999
服务启动后,即可通过多种方式进行调用,例如利用curl
命令。以下是一个示例脚本(同时存放在scripts/llamacpp/server_curl_example.sh
),将Alpaca-2的模板进行包装并利用curl
命令进行API访问。
# server_curl_example.sh
SYSTEM_PROMPT='You are a helpful assistant. 你是一个乐于助人的助手。'
# SYSTEM_PROMPT='You are a helpful assistant. 你是一个乐于助人的助手。请你提供专业、有逻辑、内容真实、有价值的详细回复。' # Try this one, if you prefer longer response.
INSTRUCTION=$1
ALL_PROMPT="[INST] <<SYS>>\n$SYSTEM_PROMPT\n<</SYS>>\n\n$INSTRUCTION [/INST]"
CURL_DATA="{\"prompt\": \"$ALL_PROMPT\",\"n_predict\": 128}"
curl --request POST \
--url http://localhost:8080/completion \
--header "Content-Type: application/json" \
--data "$CURL_DATA"
例如,我们给出一个示例指令。
$ bash server_curl_example.sh '请列举5条文明乘车的建议'
稍后返回响应结果。
{
"content": " 以下是五个文明乘车的建议:1)注意礼貌待人,不要大声喧哗或使用不雅用语;2)保持车厢整洁卫生,丢弃垃圾时要及时处理;3)不影响他人休息和正常工作时间,避免在车厢内做剧烈运动、吃零食等有异味的行为;4)遵守乘车纪律,尊重公共交通工具的规则和制度;5)若遇到突发状况或紧急情况,请保持冷静并配合相关部门的工作。这些建议旨在提高公民道德水平和社会文明程度,共同营造一个和谐、舒适的乘坐环境。",
"generation_settings": {
"frequency_penalty": 0.0,
"ignore_eos": false,
"logit_bias": [],
"mirostat": 0,
"mirostat_eta": 0.10000000149011612,
"mirostat_tau": 5.0,
"model": "zh-alpaca2-models/7b/ggml-model-q6_k.gguf",
"n_ctx": 4096,
"n_keep": 0,
"n_predict": 128,
"n_probs": 0,
"penalize_nl": true,
"presence_penalty": 0.0,
"repeat_last_n": 64,
"repeat_penalty": 1.100000023841858,
"seed": 4294967295,
"stop": [],
"stream": false,
"temp": 0.800000011920929,
"tfs_z": 1.0,
"top_k": 40,
"top_p": 0.949999988079071,
"typical_p": 1.0
},
"model": "zh-alpaca2-models/7b/ggml-model-q6_k.gguf",
"prompt": " [INST] <<SYS>>\nYou are a helpful assistant. 你是一个乐于助人的助手。\n<</SYS>>\n\n请列举5条文明乘车的建议 [/INST]",
"stop": true,
"stopped_eos": true,
"stopped_limit": false,
"stopped_word": false,
"stopping_word": "",
"timings": {
"predicted_ms": 3386.748,
"predicted_n": 120,
"predicted_per_second": 35.432219934875576,
"predicted_per_token_ms": 28.2229,
"prompt_ms": 0.0,
"prompt_n": 120,
"prompt_per_second": null,
"prompt_per_token_ms": 0.0
},
"tokens_cached": 162,
"tokens_evaluated": 43,
"tokens_predicted": 120,
"truncated": false
}
更详细的使用教程请访问:https://github.com/ggerganov/llama.cpp/tree/master/examples/server