wjohn1483.github.io
  • Posts
  • Archive
  • Audio to Scene
  • Give Feedback
  • About

如何使用CPU跑LLM

 
  • Tool
  • Machine-Learning
  • Natural-Language-Processing
  • Sep 11, 2023

Large Language Model(LLM)的風潮席捲全球,大家都在努力嘗試使用LLM來建造各式各樣的應用,但LLM本身所需要的計算量很大,沒有足夠的資源是跑不起來的,好在網路上有很多大神們在嘗試只使用少量的把LLM給跑起來,這篇文章介紹一下如何使用CPU的資源就將Llama2跑起來。

GGML

現在把LLM跑在資源相較匱乏的電腦上的方法主要都是透過quantization來減少模型的計算量,在訓練模型的時候,模型通常都是使用32 bits的浮點數來去儲存參數,倘若我們把浮點數下調一些,用16 bits或是4bits來儲存的話,雖說計算的精準度會下降,但模型在inference的計算量就可以減少很多。

其中quantization最常使用的是ggml這個工具,ggml是個用C寫成的套件,它可以幫助你把手上的模型做quantization,而且支援目前大多數的開源LLM模型,支援的模型們可以去它的github上面看。

llama.cpp

llama.cpp是一個基於ggml的工具,讓你可以很輕易地把你手上建構在llama上的模型做quantization,像是Llama、Alpaca、Vicuna、Llama2等都可以透過llama.cpp來把模型變得更小、計算得更快,底下會講一下如何使用llama.cpp來讓Llama2跑在CPU上。

Llama2

Llama2是Meta基於Llama訓練出來的有條件可商用模型,如果想要取得Llama2的模型,可以直接去Meta的官網上面填寫資料,之後根據寄來的email上的指示就能將模型的參數們下載回來了。

-> % ls llama-2-13b-chat
checklist.chk  consolidated.00.pth  consolidated.01.pth  params.json  tokenizer.model

Compile llama.cpp

在quantize模型之前,我們需要先編譯一下我們的工具llama.cpp,編譯的方法可以參考github上的README.md,如果是Linux的話應該只需要將repository clone下來以後執行make就可以了。

git clone https://github.com/ggerganov/llama.cpp.git
cd llama.cpp
pip3 install -r requirements.txt
make

Quantization

接下來就可以著手來做quantization了,詳細的步驟也可以參考官方的README.md,首先我們需要將模型的參數做成16 bits的gguf檔,在過去被稱為ggml,也就是套件的名稱,但後來ggml的格式又做了一些修改,變成了gguf,獲得了更好的可擴充性。

python3 ./convert.py ~/llama-2-13b-chat/

這時在原本模型儲存的路徑下應該會多出一個ggml-model-f16.gguf檔,這時其實就可以使用這個比較小的模型檔來在CPU上面做inference了,不過我們還可以進一步的做quantization,來讓執行時間變得更短。

./quantize ~/llama-2-13b-chat/ggml-model-f16.gguf ~/llama-2-13b-chat/ggml-model-f16.gguf.q4_0.bin q4_0

在上面的指令裡面,我們給了3個參數,分別是剛剛做好的gguf檔,再來是做完quantization後想輸出的路徑,最後是quantization的方法,quantization的方法在README.md上面有列表來告訴我們有哪些選項,以及其效果如何。

在Hugging Face上也已經有別人quantized好的模型了,如果想直接拿現成的也可以從上面下載下來。

Inference

在quantize好自己想要的大小的模型以後,接下來就是使用這個模型來執行看看prompt了。

./main -m ~/llama-2-13b-chat/ggml-model-f16.gguf.q4_0.bin -n -1 -e -t 8 -p "YOUR PROMPT HERE"

關於main更多的參數可以透過./main -h來查看,這邊列一下上面指令option所代表的意思。

  -m FNAME, --model FNAME
                        model path (default: models/7B/ggml-model-f16.gguf)
  -n N, --n-predict N   number of tokens to predict (default: -1, -1 = infinity, -2 = until context filled)
  -t N, --threads N     number of threads to use during computation (default: 4)
  -p PROMPT, --prompt PROMPT
                        prompt to start generation with (default: empty)
  -e, --escape          process prompt escapes sequences (\n, \r, \t, \', \", \\)

如果我們想要透過python使用這個quantized好的模型,我們可以使用llama-cpp-python,能過直接透過pip來安裝。

pip install llama-cpp-python

接著就能使用類似下面的程式碼來使用了,更多的使用方法可以參考其github repository。

from llama_cpp import Llama
llm = Llama(model_path="./llama-2-13b-chat/ggml-model-f16.gguf.q4_0.bin")
output = llm("YOUR PROMPT HERE", max_tokens=128, echo=True)
print(output)

值得一提的是,它所回傳的會是一個類似底下的dict object,需要自己再parse一下。

{
  "id": "cmpl-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "object": "text_completion",
  "created": 1679561337,
  "model": "./models/7B/ggml-model.bin",
  "choices": [
    {
      "text": "Q: Name the planets in the solar system? A: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune and Pluto.",
      "index": 0,
      "logprobs": None,
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 14,
    "completion_tokens": 28,
    "total_tokens": 42
  }
}

GPU Acceleration

如果你希望能把已經quantized好的模型,加速跑得更快的話,可以考慮在pip install llama-cpp-python的時候,多加一些參數,讓它可以使用各種BLAS backend來加速,如果你安裝的是cuBLAS,還可以使用GPU的資源來加速,詳細的介紹可以參考README.md,下面放上使用cuBLAS的安裝指令。

export LLAMA_CUBLAS=1
CMAKE_ARGS="-DLLAMA_CUBLAS=on" FORCE_CMAKE=1 pip install --upgrade --force-reinstall llama-cpp-python --no-cache-dir

這時我們在使用llama-cpp-python的時候,就能於讀取模型的地方多加n_gpu_layers的參數把部分的模型放到GPU上面執行。

from llama_cpp import Llama
llm = Llama(model_path="./llama-2-13b-chat/ggml-model-f16.gguf", verbose=True, n_gpu_layers=43)
output = llm("YOUR PROMPT HERE", max_tokens=128, echo=False, temperature=0.8)
print(output)

不同的模型、不同quantized的參數產生的模型所需要的GPU記憶體都不同,需要試著跑看看才知道GPU能不能吃的下來,而模型總共有多少layer可以在llama-cpp-python寫出來的log裡面看到,像是llama2總共有43層,n_gpu_layers設定超過43跟設43是一樣的效果。

GPTQ

上面所使用的quantization方法主要是調整模型參數的bit數,來達到減少運算量的目標,但這樣直接減少bit的數目會對精準度有一些影響,所以就有人在研究怎麼在quantize某一個特定的參數時,適時地調整還沒有被quantize的其他參數,讓整體的loss與quantize前的不要差異太大,其中衍生出了很多方法及其演進(OBD→OBS→OBQ→GPTQ),詳細的介紹和背後的原理推薦看QLoRA、GPTQ:模型量化概述這篇文章的介紹。

在HuggingFace上,有人使用了GPTQ的技術對Llama2做quantization,並將算出來的模型參數放上去了,如果對上面使用llama.cpp做出來的模型不滿意,且有個不錯的GPU,可以試試看用GPTQ quantize的Llama2。

參考資料

  • GPTQ: 模型量化,穷鬼救星
  • QLoRA、GPTQ:模型量化概述
PREVIOUSParameter-Efficient Fine-Tuning
NEXTnginx Reverse Proxy
Search