Supershipの名畑です。サイコミで連載されていた「リプライズ 2周目のピアニスト」が完結。毎週楽しみに読んでいました。楽しみが一つ減ってしまったのは少し残念。
はじめに
Metaがリリースした大規模言語モデルLlama 2(ラマ2)が話題です。
詳しくはここでは触れませんので興味のある方は
- Meta、新たな大規模言語モデル「Llama 2」 商用利用可でGPT-3.5に匹敵 - Impress Watch
- Metaが商用可能な大規模言語モデル「Llama 2」を無料公開、MicrosoftやQualcommと協力してスマホやPCへの最適化も - GIGAZINE
このあたりを読んでいただくとして、今回はこのLlama 2をAppleシリコンのMacBookでダウンロードして簡単な会話をするまでを試したので、その手順を記録に残します。
私の環境
MacBook Pro(Apple M2 Proチップ)です。OSはmacOS 13 Venturaです。
Pythonのバージョンは3.10.12です。
$ python --version
Python 3.10.12
また、Llamaはモデルをダウンロードする際のチェックでmd5sumが呼ばれるのですが、MacOSはデフォルトだとmd5しかないと思います。
ですのでmd5sumをインストールしておきました。
$ brew install md5sha1sum
Running `brew update --auto-update`...
以下略
一応バージョンを確認しておきます。
$ md5sum --version
Microbrew md5sum/sha1sum/ripemd160sum 0.9.5 (Wed Dec 6 12:48:56 EST 2006)
Compiled Nov 19 2022 at 04:26:05
Written by Bulent Yilmaz
Copyright (C) 2004,2006 Microbrew Software
Llama 2のモデルのダウンロード
まずはLlama 2のモデルをダウンロードします。
そのためにはユーザー登録が必要です。
Request access to the next version of Llamaを訪れて氏名などの情報を入力して規約をよく読んで同意すると、メールが届きます。
届いたメールの本文に下記のようにダウンロード用のURLが記載されています。これを後ほど使います。このURLは24時間のみ有効らしいので、気をつけてください。
Visit the Llama repository in GitHub and follow the instructions in the README to run the download.sh script.
When asked for your unique custom URL, please insert the
following:
【ここにダウンロード用のURLが記載されています】
Select which model weights to download
好きな場所にLlamaのリポジトリをcloneします。
$ git clone https://github.com/facebookresearch/llama.git
落とし終わったならその中のdownload.shを叩きます。
$ cd llama
$ chmod 755 download.sh
$ ./download.sh
すると
Enter the URL from email:
と表示されるので先ほどのメールのURLをコピペしてEnterを押します。
次に
Enter the list of models to download without spaces (7B,13B,70B,7B-chat,13B-chat,70B-chat), or press Enter for all:
ダウンロードするモデルを聞かれます。7、13、70はそれぞれパラメータ数が違います。-chatがついているものは対話形式に最適化されているようです。
今回はまずは試してみるためということで、オーソドックスに7Bと打ってEnterを押します。それでも容量が13.5G近くありますので、時間がかかります。
略
./llama-2-7b/checklist.chk 100%[=============================================================>] 100 --.-KB/s 時間 0s
2023-07-21 01:28:41 (10.6 MB/s) - `./llama-2-7b/checklist.chk' へ保存完了 [100/100]
Checking checksums
consolidated.00.pth: OK
params.json: OK
ダウンロードが完了するとllama-2-7bというフォルダの中にモデルが格納されています。
llama.cppのビルド
LlamaをMacBookなどで使えるようにするllama.cppというプロジェクトがあります。
まずは好きな場所にllama.cppのリポジトリをcloneします。
$ git clone https://github.com/ggerganov/llama.cpp
次に、llama.cppのフォルダに、先ほどダウンロードしたモデル類を移動します。元の場所のままでもできるのですが、移動した方がpathの指定がわかりやすいので移動させました。
具体的な手順は下記です。
- llama直下のtokenizer_checklist.chkとtokenizer.modelをllama.cpp/modelsに移動する。
- llama.cpp/modelsに7Bというフォルダを作り、その配下にllama/llama-2-7b配下のファイルをすべて移動する。
用意するフォルダ名は7Bでなくてもいいのですが、llama.cppの公式サンプルコードに合わせました。
結果として下記のファイル構成になりました。
$ cd llama.cpp
$ ls ./models
7B ggml-vocab.bin tokenizer.model tokenizer_checklist.chk
$ ls ./models/7B
checklist.chk consolidated.00.pth params.json
次にllama.cpp直下でmakeを叩いてbuildします。
$ make
I llama.cpp build info:
I UNAME_S: Darwin
I UNAME_P: arm
略
c++ --shared -I. -I./examples -O3 -std=c++11 -fPIC -DNDEBUG -Wall -Wextra -Wpedantic -Wcast-qual -Wno-unused-function -Wno-multichar -pthread -DGGML_USE_K_QUANTS examples/embd-input/embd-input-lib.cpp ggml.o llama.o common.o k_quants.o -o libembdinput.so -framework Accelerate
c++ -I. -I./examples -O3 -std=c++11 -fPIC -DNDEBUG -Wall -Wextra -Wpedantic -Wcast-qual -Wno-unused-function -Wno-multichar -pthread -DGGML_USE_K_QUANTS examples/embd-input/embd-input-test.cpp ggml.o llama.o common.o k_quants.o -o embd-input-test -framework Accelerate -L. -lembdinput
モデルの変換
次にPrepare Data & Runに従ってモデルの変換を行なっていきます。変換済みのモデルもネット上にはあるのですが、公式か不明なので使用を避けました。
まずPythonのライブラリ類をインストールします。
$ python -m pip install -r requirements.txt
Collecting numpy==1.24
Downloading numpy-1.24.0-cp310-cp310-macosx_11_0_arm64.whl (13.8 MB)
以下略
次にモデルをRWKV(pth)からGGML(bin)に変換します。
ファイル形式についてはここでは触れないので、初耳で興味のある方は下記あたりをご参照ください。
- 従来の大規模言語モデルの制約だった「入力量の限界」を取り払った「RWKV」は一体どんな言語モデルなのか? - GIGAZINE
- ggml.ai、GPUなしでチャットAIを動作させるライブラリ「GGML」開発中 Raspberry Pi上で音声認識モデルを実行可能:開発プロセスはオープンで、誰でも参加できる - @IT
- ggerganov/ggml: Tensor library for machine learning
変換にはconvert.pyというファイルを使います。引数はモデルファイルまでのpathです。
$ python convert.py ./models/7B/consolidated.00.pth
Loading model file models/7B/consolidated.00.pth
Loading vocab file models/tokenizer.model
params: n_vocab:32000 n_embd:4096 n_mult:256 n_head:32 n_layer:32
略
UnquantizedDataType(name='F32')
Wrote models/7B/ggml-model-f32.bin
ggml-model-f32.binというbin形式のファイルが生成されました。
次に、生成されたggml-model-f32.binを4-bitsに変換します。quantizeを呼びます。
$ ./quantize ./models/7B/ggml-model-f32.bin ./models/7B/ggml-model-q4_0.bin q4_0
main: build = xxx (xxxxxxx)
main: quantizing './models/7B/ggml-model-f32.bin' to './models/7B/ggml-model-q4_0.bin' as Q4_0
llama.cpp: loading model from ./models/7B/ggml-model-f32.bin
llama.cpp: saving model to ./models/7B/ggml-model-q4_0.bin
略
main: quantize time = 11449.52 ms
main: total time = 11449.52 ms
ggml-model-q4_0.binというファイルが生成されました。
これで環境の準備は完了です。
サンプルの実行
では実際にLlama 2をllama.cpp経由で呼び出してみましょう。
llama.cpp/examplesの中にサンプルコードがいくつかあるので、今回はこの中のchat.shを使うこととします。
参考までにchat.shのコードは下記です。
#!/bin/bash
#
# Temporary script - will be removed in the future
#
cd `dirname $0`
cd ..
# Important:
#
# "--keep 48" is based on the contents of prompts/chat-with-bob.txt
#
./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
非常に短いコードです。
mainを呼び出し、その際にモデルなどの各種パラメータが渡されます。パラメータについて詳しくはmainのREADMEをご覧ください。
chat.shに書かれたモデルのpathは必要に応じて各自の環境に合わせてください。
プロンプトとしてprompts/chat-with-bob.txtが渡されています。
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:
つまりはchat.shを実行するとBobとの会話が始まるようです。
chat.shを実際に呼んでみます。
$ ./examples/chat.sh
略
== Running in interactive mode. ==
- Press Ctrl+C to interject at any time.
- Press Return to return control to LLaMa.
- To return control without starting a new line, end your input with '/'.
- If you want to submit another line, end your input with '\'.
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:
ここまではプロンプト通りですね。
会話を続けてみます。各行においてUserの後ろが私の入力した内容です。
User:Where are you from now?
Bob: I'm from Toronto, Canada.
User:Thank you
Bob: You're welcome.
無事に動いていそうです。
ちなみに一つずつのレスポンスは私の環境ではだいたい即座に返ってきました。数秒かかる時もたまにはあります。
Ctrl+Cで終了します。
日本語でも会話をしてみた
prompts/chat-with-bob.txtの内容を下記のように変えてみました。「good at Japanese writing」としています。
Transcript of a dialog, where the User interacts with an Assistant named Bob. Bob is helpful, kind, honest, good at Japanese writing, and never fails to answer the User's requests immediately and with precision.
User: こんにちは、ボブ
Bob: こんにちは。今日はいかがいたしましたか?
User:
その上でchat.shを呼び出し、会話してみた結果は下記です。いい感じですね。新しい名前を記憶していることから、会話の履歴が活かされていることがわかります。
User: こんにちは、ボブ
Bob: こんにちは。今日はいかがいたしましたか?
User:日本の首都はどこですか?
Bob: 東京です。
User:日本で最北端の都道府県はどこですか?
Bob: 北海道です。
User:あなたの名前は実はボブではなくトムです
Bob: すいません。名前はトムです
User:あなたの名前は何ですか?
Bob: 名前はトムです。
最後に
できることがかなり幅広そうです。
次回はPythonからの呼び出しを実装してみる予定です。
宣伝
SupershipのQiita Organizationを合わせてご覧いただけますと嬉しいです。他のメンバーの記事も多数あります。
Supershipではプロダクト開発やサービス開発に関わる方を絶賛募集しております。
興味がある方はSupership株式会社 採用サイトよりご確認ください。