m1 MacbookにLlama 2をインストールして使ってみる

2023.07.31

支給されているPC(m1 Macbook)を使ってローカルでLlama 2を動かしてみるまでの記録です。

AppleシリコンのMacでもLlama 2をつかえるようにするLlama.cppというプロジェクトがあるので、これを利用させてもらいました。

Llama.cppはLlamaをC/C++に移植したもので、Mac上で4ビット整数量子化を使ってLlama 2をローカルに実行できるようにしたものです

Llama 2のモデルはmetaのダウンロードリンクから取得しています。

準備

作業用のディレクトリを作成して行います。

$ mkdir llama2
$ cd llama2

Llama 2, Llama.cppのgithubレポジトリをcloneしておきます。

$ git clone https://github.com/facebookresearch/llama.git
$ git clone https://github.com/ggerganov/llama.cpp.git

モデルを保存するディレクトリも別途作っておきます。

$ mkdir models

モデルのダウンロードするためのリクエスト

モデルをダウンロードするためにリクエストを送ります。

Request Link: https://ai.meta.com/resources/models-and-libraries/llama-downloads/

リンク先に遷移すると、いくつかの入力を行ってLlama 2 Community Licenseに同意する必要があります。

これが完了すると後ほどメールが送られてきますので、そのメールにあるダウンロードリンクを控えておきます。

モデルのダウンロード

cloneしたllama.gitにあるdownload.shを使ってモデルを入手できます。

※ wget と md5sum が必要なので、インストールされていない場合はmacにインストールしておきます。

$ brew install wget
$ brew install md5sha1sum

では実際にインストールしてみます。

$ cd models
$ sh ../llama2/download.sh

download.shを実行すると

Enter the URL from email: というのが表示されるので、ここに先ほど控えたダウンロードリンクを入力してエンターキーを押します。

次に

Enter the list of models to download without spaces (7B,13B,70B,7B-chat,13B-chat,70B-chat), or press Enter for all: と表示されるので、ダウンロードしたいモデルを選択してエンターキーを押します。

今回は7Bにしてました。

70億パラメータのもので13.49 GBありますので、ダウンロードには時間がかかります。待ちましょう。

Llama.cppのビルド

cloneしたLlama.cppのプロジェクトを使うためにビルドを行います。

makeコマンドを実行します。

## CPUで計算させる場合
$ cd llama.cpp
$ make

## LLAMA_METAL=1 をつけると、計算をGPU上で実行させるようにできます。
$ LLAMA_METAL=1 make

様々なバイナリがビルドされます。

モデルの変換

Llama.cppで動作させるために、Llamaのモデルを変換します。

※ 変換にはpythonが必要です。

まず、必要なライブラリなどをインストールします。

$ cd llama.cpp
$ python3 -m pip install -r requirements.txt

そして、ダウンロードした7Bのモデルをggml FP16 フォーマットというものにコンバートします。

$ mkdir models/7B
$ python3 convert.py --outfile models/7B/ggml-model-f16.bin --outtype f16 ../llama2/models/llama-2-7b
Loading model file ../models/llama-2-7b/consolidated.00.pth
~~~
~~~
Wrote models/7B/ggml-model-f16.bin

$ ls models/7B/
ggml-model-f16.bin

※ ../llama2/models/llama-2-7b ですが、ここにはダウンロードしたモデルの場所を指定するようにします。

次は生成されたファイルを4-bitsに量子化します。

$ ./quantize ./models/7B/ggml-model-f16.bin ./models/7B/ggml-model-q4_0.bin q4_0
$ ls -la models/7B/
 13477814912  7 31 15:09 ggml-model-f16.bin
 3825517184  7 31 15:29 ggml-model-q4_0.bin

13.48GBから3.83GBまで小さくなりました。

このファイルが推論を行うために使用するファイルとなります。

なお、ggml形式に変換済みモデルを提供しているサイトもありましたので、コマンドを実行せず以下からDLするのも手ですね。

推論の実行

mainというプログラムファイルを使うことで実行できます。

examplesフォルダ に様々な実行例が書かれたコードがあるので、これを実行してみました、。

例) examples/chat.sh に書いてあるコマンド

$ ./main -m ./models/7B/ggml-model-q4_0.bin -c 512 -b 1024 -n 256 --keep 48 --repeat_penalty 1.0 --color -i -r "User:" -f ./prompts/chat-with-bob.txt
<<省略>>
 Transcript of a dialog, where the User interacts with an Assistant named Bob. Bob is helpful, kind, honest, good at writing, and never fails to answer the User's requests immediately and with precision.

User: Hello, Bob.
Bob: Hello. How may I help you today?
User: Please tell me the largest city in Europe.
Bob: Sure. The largest city in Europe is Moscow, the capital of Russia.
User:

promptsフォルダにはいくつかのサンプルがあって、これらを開始プロンプトとしてモデルに送信できます。

試しに、chat-with-bob.txt を使っています。

起動すると、入力待ち状態になります。

ここに質問を入力していくと、アシスタントのBobが質問の回答をしてくれるというものです。

遊んでみた例

User:How many of the numbers up to 20 are prime numbers?
Bob: 1, 2, 3, 5, 7, 11, 13, 17, 19 are prime numbers.
User:what is youtube?
Bob: YouTube is a website that hosts a collection of user-generated video content.
User:About Suneo
Bob: Suneo is a Japanese company that specializes in the production of digital music players.

日本語もある程度理解して返してくれるみたい。

User:スネ夫について教えて
Bob:スネ夫は日本の会社の一つである。 彼らはMP3プレーヤーを製造販売している。
User:ドラゴンボールの主人公は?
Bob: ドラゴンボールの主人公はゴジラです。
User:30までに素数はいくつある?
Bob: 素数は30まで20でしかない。
User:日本の首都は?
Bob: 日本の首都は東京です。

13bや70bのモデルを使うともっと精度がいい答えが返ってくるかもしれませんね。

参考:コマンド引数

$ ./main --help
usage: ./main [options]

options:
  -h, --help            show this help message and exit
  -i, --interactive     run in interactive mode
  --interactive-first   run in interactive mode and wait for input right away
  -ins, --instruct      run in instruction mode (use with Alpaca models)
  --multiline-input     allows you to write or paste multiple lines without ending each in '\'
  -r PROMPT, --reverse-prompt PROMPT
                        halt generation at PROMPT, return control in interactive mode
                        (can be specified more than once for multiple prompts).
  --color               colorise output to distinguish prompt and user input from generations
  -s SEED, --seed SEED  RNG seed (default: -1, use random seed for < 0)
  -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                    process prompt escapes sequences (\n, \r, \t, \', \", \\)
  --prompt-cache FNAME  file to cache prompt state for faster startup (default: none)
  --prompt-cache-all    if specified, saves user input and generations to cache as well.
                        not supported with --interactive or other interactive options
  --prompt-cache-ro     if specified, uses the prompt cache but does not update it.
  --random-prompt       start with a randomized prompt.
  --in-prefix-bos       prefix BOS to user inputs, preceding the `--in-prefix` string
  --in-prefix STRING    string to prefix user inputs with (default: empty)
  --in-suffix STRING    string to suffix after user inputs with (default: empty)
  -f FNAME, --file FNAME
                        prompt file to start generation.
  -n N, --n-predict N   number of tokens to predict (default: -1, -1 = infinity)
  -c N, --ctx-size N    size of the prompt context (default: 512)
  -b N, --batch-size N  batch size for prompt processing (default: 512)
  -gqa N, --gqa N       grouped-query attention factor (TEMP!!! use 8 for LLaMAv2 70B) (default: 1)
  -eps N, --rms-norm-eps N rms norm eps (TEMP!!! use 1e-5 for LLaMAv2) (default: 5.0e-06)
  --top-k N             top-k sampling (default: 40, 0 = disabled)
  --top-p N             top-p sampling (default: 0.9, 1.0 = disabled)
  --tfs N               tail free sampling, parameter z (default: 1.0, 1.0 = disabled)
  --typical N           locally typical sampling, parameter p (default: 1.0, 1.0 = disabled)
  --repeat-last-n N     last n tokens to consider for penalize (default: 64, 0 = disabled, -1 = ctx_size)
  --repeat-penalty N    penalize repeat sequence of tokens (default: 1.1, 1.0 = disabled)
  --presence-penalty N  repeat alpha presence penalty (default: 0.0, 0.0 = disabled)
  --frequency-penalty N repeat alpha frequency penalty (default: 0.0, 0.0 = disabled)
  --mirostat N          use Mirostat sampling.
                        Top K, Nucleus, Tail Free and Locally Typical samplers are ignored if used.
                        (default: 0, 0 = disabled, 1 = Mirostat, 2 = Mirostat 2.0)
  --mirostat-lr N       Mirostat learning rate, parameter eta (default: 0.1)
  --mirostat-ent N      Mirostat target entropy, parameter tau (default: 5.0)
  -l TOKEN_ID(+/-)BIAS, --logit-bias TOKEN_ID(+/-)BIAS
                        modifies the likelihood of token appearing in the completion,
                        i.e. `--logit-bias 15043+1` to increase likelihood of token ' Hello',
                        or `--logit-bias 15043-1` to decrease likelihood of token ' Hello'
  --grammar GRAMMAR     BNF-like grammar to constrain generations (see samples in grammars/ dir)
  --grammar-file FNAME  file to read grammar from
  --cfg-negative-prompt PROMPT
                        negative prompt to use for guidance. (default: empty)
  --cfg-scale N         strength of guidance (default: 1.000000, 1.0 = disable)
  --rope-freq-base N    RoPE base frequency (default: 10000.0)
  --rope-freq-scale N   RoPE frequency scaling factor (default: 1)
  --ignore-eos          ignore end of stream token and continue generating (implies --logit-bias 2-inf)
  --no-penalize-nl      do not penalize newline token
  --memory-f32          use f32 instead of f16 for memory key+value (default: disabled)
                        not recommended: doubles context memory required and no measurable increase in quality
  --temp N              temperature (default: 0.8)
  --perplexity          compute perplexity over each ctx window of the prompt
  --hellaswag           compute HellaSwag score over random tasks from datafile supplied with -f
  --hellaswag-tasks N   number of tasks to use when computing the HellaSwag score (default: 400)
  --keep N              number of tokens to keep from the initial prompt (default: 0, -1 = all)
  --chunks N            max number of chunks to process (default: -1, -1 = all)
  --mlock               force system to keep model in RAM rather than swapping or compressing
  --no-mmap             do not memory-map model (slower load but may reduce pageouts if not using mlock)
  --numa                attempt optimizations that help on some NUMA systems
                        if run without this previously, it is recommended to drop the system page cache before using this
                        see https://github.com/ggerganov/llama.cpp/issues/1437
  --mtest               compute maximum memory usage
  --export              export the computation graph to 'llama.ggml'
  --verbose-prompt      print prompt before generation
  --lora FNAME          apply LoRA adapter (implies --no-mmap)
  --lora-base FNAME     optional model to use as a base for the layers modified by the LoRA adapter
  -m FNAME, --model FNAME
                        model path (default: models/7B/ggml-model.bin)