はじめに
昨年、VMware Private AI Reference Architecture が発表され、関連記事も少し見始めているのですが、どうしても GPU リソースを必要とするものが多く、個人的に、なかなか触りづらさを感じていました。
しかし、llama-cpp-python
を使えば、ノート PC のようなリソースが限られた環境でも、Python から簡単に LLaMA を動かすことができそうなので、今回はこれを試していきます。
また、この llama-cpp-python
を実行する Python 環境は、Rye を使って、構築していきます。
この Rye に関しては、Python でとある OSS を開発していた時にあれば、どんなに幸せだっただろうと思えるくらい、とても便利だったので、どんどん使っていきたいと思っています。
これだけでも要素が多いですが、LLaMA を動かしていく際に、せっかくなので日本語の学習済みモデル ELYZA-japanese-Llama で、日本語で対話してみたいと思います。
前提
今回は Ubuntu OS を利用しており、利用バージョンは、下記の通りです。
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.3 LTS"
また、長くなってしまうので、Rye は、公式ドキュメントに記載の方法でインストール済みとさせてください。
とはいえ、ガイドにあるコマンドを実行し、少しばかり対話による選択をするのみです。
手順
基本的には、llama-cpp-python
の GitHub のガイドに沿って、実行していきますが、実行していく上で、いくつか依存パッケージのインストール等が必要だったので、その辺りを補足してあります。
依存パッケージのインストール
llama-cpp-python
が、llama.cpp
という C/C++ のライブラリを Python から使えるようにしたもの (バインディング) である関係上、パッケージのインストール過程で、C/C++ のライブラリのビルドが発生します。
そのため、ビルドのためのパッケージ群を、事前にインストールしておく必要がありました。
sudo apt install build-essential libpython3-dev
Python プロジェクトの作成
Rye を使って、遊ぶための Python プロジェクトを作成します。
$ rye init test-llama-cpp-python
success: Initialized project in /home/yusukei/test-llama-cpp-python
Run `rye sync` to get started
注意
Rye で Python プロジェクトを作成する際、後でインストールする Python モジュールと同じ名前 (今回の場合は llama-cpp-python
) とは、異なる名前を指定してください。
はっきりと確認した訳ではないのですが、同じ名前にしてしまうと、Python モジュールをインストールする際 (具体的には rye sync
実行時) にエラーしてしまいました。
作成したプロジェクトのディレクトリに移動しておきます。
cd test-llama-cpp-python/
プロジェクトの情報を確認すると、下記のようになるはずです。
$ rye show
project: test-llama-cpp-python
path: /home/yusukei/test-llama-cpp-python
venv: /home/yusukei/test-llama-cpp-python/.venv
target python: 3.8
venv python: cpython@3.12.1
virtual: false
llama-cpp-python
のインストール
Rye のパッケージ管理を使って、llama-cpp-python
をインストールしていきます。
まず、llama-cpp-python
を依存パッケージに登録します。
$ rye add llama-cpp-python
Added llama-cpp-python>=0.2.38 as regular dependency
登録した依存パッケージの情報を元に、パッケージをインストールします。
前述の通り、C/C++ ライブラリのビルドが走るので、ちょっと時間がかかります。
$ rye sync
Initializing new virtualenv in /home/yusukei/test-llama-cpp-python/.venv
Python version: cpython@3.12.1
Generating production lockfile: /home/yusukei/test-llama-cpp-python/requirements.lock
Generating dev lockfile: /home/yusukei/test-llama-cpp-python/requirements-dev.lock
...
... (snip) ...
...
Successfully installed diskcache-5.6.3 jinja2-3.1.3 llama-cpp-python-0.2.38 markupsafe-2.1.5 numpy-1.26.3 test-llama-cpp-python-0.1.0 typing-extensions-4.9.0
Done!
学習済みモデルの用意
冒頭で記載した通り、せっかくなので日本語の学習済みモデル ELYZA-japanese-Llama を動かしていきたい思うのですが、llama-cpp-python
が gguf という形式のモデルを必要とするようなので、Hugging Face のサイトから、変換済みのモデルを利用しています。
今回は、お試しなので、一番ファイルサイズの小さい ELYZA-japanese-Llama-2-7b-fast-instruct-q2_K.gguf
を取得し、Python プロジェクト配下に models
というディレクトリを作成して、配置しました。
この時点で、プロジェクトの構造は、こんな感じになっているはずです。
.
├── README.md
├── models
│ └── ELYZA-japanese-Llama-2-7b-fast-instruct-q2_K.gguf <-- 追加
├── pyproject.toml
├── requirements-dev.lock
├── requirements.lock
└── src
└── test_llama_cpp_python
└── __init__.py
お試しスクリプトの用意
llama-cpp-python
の GitHub を見ながら、こんな感じのスクリプトを用意してみました。
プロンプトのテンプレ等が上手く扱えていない辺りは、勉強不足ですので、ご容赦ください...
from llama_cpp import Llama
llm = Llama(
model_path = "./models/ELYZA-japanese-Llama-2-7b-fast-instruct-q2_K.gguf",
#n_gpu_layers = 1,
)
output = llm("""
[INST] ギャグを言ってみてください。 [/INST]
""")
print(output['choices'][0]['text'])
実行環境に GPU が無かったので、試していませんが、コメントアウトしてある n_gpu_layers = 1
の部分をちゃんと指定すると、GPU リソースちゃんと使えるらしいです。
よって、この時点で、プロジェクトの構造は、こんな感じになっているはずです。
.
├── README.md
├── demo.py <-- 追加
├── models
│ └── ELYZA-japanese-Llama-2-7b-fast-instruct-q2_K.gguf
├── pyproject.toml
├── requirements-dev.lock
├── requirements.lock
└── src
└── test_llama_cpp_python
└── __init__.py
スクリプトの実行
毎回ちゃんと rye run python
と打つのが面倒なので、先に Python venv 環境へ入っておきます。
$ . .venv/bin/activate
(test-llama-cpp-python) $ # <-- venv 環境のプロンプト
参考
rye shell
という、いかにも便利そうなコマンドもあるのですが、Rye 0.21.0 時点では、「バグが多いコマンドだから、ちゃんと venv を有効化してね」と警告が出たので、ここでは venv を使っています。
では、いよいよスクリプトを実行して、さぞや面白い冗談を見てみましょう。
$ python demo.py
llama_model_loader: loaded meta data with 21 key-value pairs and 291 tensors from ./models/ELYZA-japanese-Llama-2-7b-fast-instruct-q2_K.gguf (version GGUF V3 (latest))
llama_model_loader: Dumping metadata keys/values. Note: KV overrides do not apply in this output.
llama_model_loader: - kv 0: general.architecture str = llama
llama_model_loader: - kv 1: general.name str = ELYZA-japanese-Llama-2-7b-fast-instruct
llama_model_loader: - kv 2: general.source.huggingface.repository str = elyza/ELYZA-japanese-Llama-2-7b-fast-...
llama_model_loader: - kv 3: llama.tensor_data_layout str = Meta AI original pth
...
...(略)...
...
llama_print_timings: load time = 3867.23 ms
llama_print_timings: sample time = 11.45 ms / 16 runs ( 0.72 ms per token, 1397.87 tokens per second)
llama_print_timings: prompt eval time = 3867.14 ms / 35 tokens ( 110.49 ms per token, 9.05 tokens per second)
llama_print_timings: eval time = 2171.19 ms / 15 runs ( 144.75 ms per token, 6.91 tokens per second)
llama_print_timings: total time = 6139.06 ms / 50 tokens
いや、私はAIですので笑うことはできません…。
...はい???
そういうギャグってことでしょうか...?? 分からん...
まとめ
今回は、「とりあえず動かした。以上」レベルで、最後が酷かったですが、まずは色々と遊ぶための入り口に立った感じでしょうか。
もう少し知識をつけて、もう少し知見を増やせたら、また関連記事を書きたいと思います。