Twitterで、
これは衝撃!1.5Bで超高性能LLM!RWKV-5-World-v2
というのが流れて来たので、RWKVを試してみるのも良いなと思ってやってみました。
最初はPythonで試そうと思ったのですが、公式サイトにRWKV.cppというリンクがあったので、RWKV.cppの方で試してみました。
動かした環境はOrange Pi 5、つまりシングルボードコンピュータです。
ggmlについて
RWKVのことについては、元の清水氏のエントリや公式サイトの方を見て下さい。
RWKV.cppはllama.cppやwhisper.cppと同じように、ggmlを使ったものです。
ggmlは雑で不正確な説明をすれば、「PyTorchをcppで書いたようなもの」だと思えば、だいたい合ってます。もう少し正確なことを言えば、今時のAIで使われがちな演算をまとめたライブラリでcppで書かれています。cppなのでバイナリが得られます。単体で走るバイナリが作れるので、LLM等をエッジで動かす時に便利です。
いろんな事情から普通に出回っている「モデルファイル」がそのままは使えませんが、変換することで使える形式になります。また、量子化したモデルを作ることもできます。PyTorchを使った場合、Orange Pi 5では量子化されたモデルは使えない(演算が対応してないらしい)のですが、ggmlは量子化されたモデルでも使えるので、メモリの節約になります。演算速度が速くなったりはしませんし、量子化された演算とかだとCPUが対応していないので逆に遅くなる要素になったりしますが、メモリが節約されるのは速くなる方に働きます。いくつかOrange Pi 5で試した範囲では、速度そのものは有利でも不利でもない感じです。
ggmlはライブラリみたいなものですがlibxxxみたいな形式ではなくて、作ろうとするソフトのソースに取り込んで使うものっぽいです。llama.cppはファイルをコピーして持って来てますし、RWKV.cppはリポジトリの参照になっています。後者の方がわかりやすいですが、前者は本家ですからねぇ。どっちがどうということもないと思います。
ggmlを使って作られたものはいろいろあります。何が作られているかは、ggmlのREADME.mdを見て下さい。ここにRWKV.cppがあったので、「そのうち試そう」と思っていましたので、ちょうどいい機会でした。
動かす準備
RWKV.cppを動かすのはとても簡単です。
元々ggmlが「他のライブラリに依存しない」のが売りなこともあって(外部のBLASとかを使うこともできます)、とりあえず試してみるという範囲であれば依存関係がどうこうということに悩む必要はありません。また、現状の範囲であれば、Orange Pi 5で動かす限りではBLASとか使う意味はありません(速くならない)。
そして、手順がstep by stepでREADME.mdに書かれています。そこから抜粋します。
まずはclone
$ git clone --recursive https://github.com/saharNooby/rwkv.cpp.git
$ cd rwkv.cpp
取って来たらbuildします。Linuxの場合だと、
$ cmake .
$ cmake --build . --config Release
cmakeを使うっぽいですね。llama.cppだとMakefileもあるのですが、RWKV.cppにはありません。
待っているとbuildが終わります。やることはそれだけです。
外部のライブラリを使う場合にはそれなりの手間が必要だと思いますが、その辺は御自分で。まぁやったところでOrange Pi 5(RK3588)では意味がありませんが。
モデルの用意
まずはモデルを取って来ます。
$ wget https://huggingface.co/BlinkDL/rwkv-5-world/resolve/main/RWKV-5-World-1B5-v2-20231025-ctx4096.pth
とりあえず、1.5Bを取ります。
これをggmlの形式に変換します。
$ python python/convert_pytorch_to_ggml.py RWKV-5-World-1B5-v2-20231025-ctx4096.pth RWKV-5-World-1B5-v2-20231025-ctx4096.bin FP16
convert_pytorch_to_ggml.pyはPyTorchに依存してるらしいので、あらかじめ入れておいて下さい。
しばらくすると、変換されます。
上の例ではモデルファイルをcurrentに置いてしまってますが、邪魔になると思うので適当にディテクトリ掘って置くと良いでしょう。これはggml使うもの全般に言えますね。
ファイル名はこのエントリ執筆時のものなので、実際にやる時は実際のファイルやURLにして下さい。
走らせてみる
とりあえず、README.mdにあるテキスト生成のコマンドラインを入れてみます。
Llama.cppの時はバイナリをそのまま起動していましたが、ここではPythonで書かれたラッパ経由で起動しているようです。ラッパと言っても本当にラッパでしかなくて、実質何もしてないに等しいんですけどね。裸のバイナリはコマンドパラメータがいろいろあってわかりにくいので、こういったやり方の方がいろいろ楽だと思います。
$ python python/generate_completions.py Downloads/RWKV-5-World-1B5-v2-20231025-ctx4096.bin
System info: AVX=0 AVX2=0 AVX512=0 FMA=0 NEON=1 ARM_FMA=1 F16C=0 FP16_VA=1 WASM_SIMD=0 BLAS=0 SSE3=0 VSX=0
Loading RWKV model
Loading World v20230424 tokenizer
105 tokens in prompt
--- Generation 0 ---
# rwkv.cpp
This is a port of [BlinkDL/RWKV-LM](https://github.com/BlinkDL/RWKV-LM) to [ggerganov/ggml](https://github.com/ggerganov/ggml).
Besides the usual **FP32**, it supports **FP16**, **quantized INT4, INT5 and INT8** inference. This project is **focused on CPU**, but cuBLAS is also supported.[
This project is still under development. The current implementation is a bit messy, and it's not yet stable.
## Build
### CPU
```bash
# build for CPU
make -j$(nproc)
```
### GPU
```bash
# build for GPU
make -j$(nproc) -Dgpu=1
```
## Test
### CPU
```bash
# test for CPU
./run_test.sh
```
### GPU
]
Took 20.342 sec, 203 ms per token
--- Generation 1 ---
# rwkv.cpp
This is a port of [BlinkDL/RWKV-LM](https://github.com/BlinkDL/RWKV-LM) to [ggerganov/ggml](https://github.com/ggerganov/ggml).
Besides the usual **FP32**, it supports **FP16**, **quantized INT4, INT5 and INT8** inference. This project is **focused on CPU**, but cuBLAS is also supported.[
## Install
```bash
git clone https://github.com/gerganov/rwkv.git
cd rwkv
make
```
## Usage
### CPU
```
./rwkv.sh
```
### GPU
```
./rwkv.sh -gpu
```
### Windows
```
.\rwkv.exe
```
## Changelog
Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.
]
Took 20.366 sec, 203 ms per token
--- Generation 2 ---
# rwkv.cpp
This is a port of [BlinkDL/RWKV-LM](https://github.com/BlinkDL/RWKV-LM) to [ggerganov/ggml](https://github.com/ggerganov/ggml).
Besides the usual **FP32**, it supports **FP16**, **quantized INT4, INT5 and INT8** inference. This project is **focused on CPU**, but cuBLAS is also supported.[
## Requirements
- cuDNN 7.0 or higher
- cuBLAS 10.0 or higher
- cuDNN 7.0 or higher
- cuBLAS 10.0 or higher
- cuDNN 7.0 or higher
- cuBLAS 10.0 or higher
- cuDNN 7.0 or higher
- cuBLAS 10.0 or higher
- cuDNN 7.0 or higher
- cuBLAS 10]
Took 20.355 sec, 203 ms per token
なんてのが出て来ました。いきなり何の話だ? と思いましたが、python/generate_completions.py
を見ると、ソースの中にプロンプトがありました。
prompt: str = """# rwkv.cpp
This is a port of [BlinkDL/RWKV-LM](https://github.com/BlinkDL/RWKV-LM) to [ggerganov/ggml](https://github.com/ggerganov/ggml).
Besides the usual **FP32**, it supports **FP16**, **quantized INT4, INT5 and INT8** inference. This project is **focused on CPU**, but cuBLAS is also supported."""
自己説明を出すようになっているようです。面白いですね。
チャットもできるようなので試してみます。
$ python python/chat_with_bot.py Downloads/RWKV-5-World-1B5-v2-20231025-ctx4096.bin
System info: AVX=0 AVX2=0 AVX512=0 FMA=0 NEON=1 ARM_FMA=1 F16C=0 FP16_VA=1 WASM_SIMD=0 BLAS=0 SSE3=0 VSX=0
Loading RWKV model
Loading World v20230424 tokenizer
Processing 178 prompt tokens, may take a while
Processed in 13 s, 76 ms per token
Chat initialized! Your name is User. Write something and press Enter. Use \n to add line breaks to your message.
> User:
何か入れてみましょう。
> User: おはようございます。今日は寒いね。暑いのと寒いのと、どっちが好き?
> Bot: 私は、夏と冬のどちらが好きかわからないので、どちらでもいいです。ただ、私は冬の時期に家にいるときは、寒い時間が気持ちが良いです。
なんか普通に会話ができるっぽいです。続けてみます。
> User: 今日は何をして過ごしたい?
> Bot: 今日は、ゆっくりと過ごしたい。また、何か新しいことを学ぶこともいいですね。
なんかちゃんと会話してます。
速度は感覚的にはYouTubeにありがちの「ゆっくり解説」でしゃべっているくらいの感じです。結構なリアルタイム性があります。
3Bを試す
ふと思って3Bの方で動かしてみました。
モデルの準備は同じ感じで、チャットだけ
$ python python/chat_with_bot.py RWKV-5-World-3B-v2-20231113-ctx4096.bin
System info: AVX=0 AVX2=0 AVX512=0 FMA=0 NEON=1 ARM_FMA=1 F16C=0 FP16_VA=1 WASM_SIMD=0 BLAS=0 SSE3=0 VSX=0
Loading RWKV model
Loading World v20230424 tokenizer
Processing 178 prompt tokens, may take a while
Processed in 25 s, 141 ms per token
Chat initialized! Your name is User. Write something and press Enter. Use \n to add line breaks to your message.
> User:
なんか起動しちゃいましたよ。サイズの分だけ起動は遅いですが、単にそれだけです。
> User: おはようございます。今日は寒いね。暑いのと寒いのと、どっちが好き?
> Bot: こんにちは。寒い日が多いですね。それでも、暑い日も楽しめますよ。どちらが好きですか?
> User: 寒い方が好きだな。今日は何をして過ごしたい?
> Bot: 寒い日には、温かいお茶やコーヒーなどのお茶を飲みながら、読書や映画鑑賞などを楽しむことができます。また、温かいお茶やコーヒーを飲みながら、家族や友人と過ごすことも楽しいですよ。
こいつはこいつで会話が成立してますね。
いろいろ走らせていると、上の例みたいに「質問で質問を返す」ようなことをすることがあります。きっとジョジョは学習セットに入っていないのでしょうw
ちなみに、どちらの例もソースをいじらずに動かしているので、言語がEnglishになっているままです(python/chat_with_bot.py
の中に言語設定があります)。日本語入れるとちゃんと理解してくれるっぽいですね。
1.5Bの倍くらいの処理時間がかかっているようです。会話の感じそのものは違いがわからないので、普通の会話では1.5Bで良いのかも知れません。
(Bing Image Creatorで雑に生成した絵)
まとめ
難しい会話とかしたわけではないですが、結構会話は成立してて楽しいです。
個人的には、「凄く物知りで頭のいいLLM」が欲しければChatGPTを使えばいいと思っているので、この程度に普通に会話ができるのであれば「うちの子」としては十分だなと思います。追加学習についてもあるようですし(そのうち試します)。
1.5Bで十分会話ができるというのはなかなか凄いですし、Orange Pi 5で結構な速度で会話が出来ているのも凄いなと思います。「おしゃべり箱」が実現できそうですね。