昨今話題のLLM(大規模言語モデル)の日本語対応版としてCyberAgentのOpenCalmをCPUのみで動かせるか試してみます。
公開されているモデルは10個ほどありますが、以下のような型落ちのPCでCPUのみで動かせるのは4つでした。
動かせる….というのは応答速度がストレスなしで一応(整合性があろうがなかろうが、あるいはホラ吹いていようがいまいが)結果が返って来るという意味です。
使用したのは干支が一回りするくらい前のPCです。
ThinkCentre M91 Eco Ultra Small 7516C6J
スペックだいたいこんな感じ。
CPU名称 | Core i3 2100 |
CPUクロック | 3.1GHz |
メモリ | [標準容量] 2G (単位 MBまたはB) |
標準HDD | [容量] 250G |
ただし、メモリーは10GBに増設しています。オリジナルの2GBだと1Bくらいのモデルでもメモリにマップできず、offload_folderを要求されます。そうするともう結果はほぼ返ってきません。
注:無理を承知でoffload_folderを使う場合
CPUからなのでoffloadはdisk上に指定されます。
適当なフォルダーを作っておく(例:~/work)
フォルダーのパスを指定(offload_folder_path = “~/work”)
model準備のAutoModelForCausalLM.from_pretrainedの4つ目の引数として入れておく(offload_folder = offload_folder_path)
CPUはx86_64、OSは余計なメモリを使わないようにUbuntu Server 22.04.3 LTSにします。
rufusでUSBメモリスティック(16GBくらい)にインストールメディアを作って、そこからインストールします。
USBメモリスティックを挿して、PC起動後USBからboot(やり方は各PCで異なるのでマニュアル参照)。
インストール中、特に問題になるところはありません。
TypeはDefaultでもいいですし、少しでもメモリを節約したければ、Minimizedを選びます。
また、OpenSSH はインストールにチェックしなくとも、sshdは起動後動いています。
インストール終了後起動したら、他の端末からSSHで接続して作業します(この方がやりやすいです、スマホやPC、ラズパイなどからも接続できますし….)。
端末から
ssh <ユーザー名>@<IPアドレス>
初回なのでアップデート&アップグレードしておきます。
1 2 |
sudo apt update sudo apt upgrade -y |
このOSではPythonのバージョンは 3.10.12です。
pipが入っていないので入れておきます。
1 2 3 |
sudo apt install python3-pip -y python3 -m pip install --upgrade pip |
scipy とnumpyをアップグレード。
1 |
python3 -m pip install -U scipy numpy |
必要なライブラリをインストールしておきます。
1 |
pip3 install transformers accelerate bitsandbytes |
python3のコンソールを起動して作業を開始します。
>python3
1 2 3 4 5 |
import transformers from transformers import AutoModelForCausalLM, AutoTokenizer, TextStreamer import torch assert transformers.__version__ >= "4.34.1" |
以下の4つのモデルがCPUのみでもストレスなしで動きます。ただし、一応文章がまともでホラ吹く回数が少ないのは1Bでした。
Model | Params | Layers | Dim | Heads | Dev ppl | Size |
cyberagent/open-calm-small | 160M | 12 | 768 | 12 | 19.7 | 381MB |
cyberagent/open-calm-medium | 400M | 24 | 1024 | 16 | 13.8 | 919MB |
cyberagent/open-calm-large | 830M | 24 | 1536 | 16 | 11.3 | 1.78G |
cyberagent/open-calm-1b | 1.4B | 24 | 2048 | 16 | 10.3 | 2.94GB |
CPUのみで動かすのでモデルは以下のようになります(torch_dtype=torch.float32を指定)。
model = AutoModelForCausalLM.from_pretrained("cyberagent/open-calm-1b", device_map="auto", torch_dtype=torch.float32)
tokenizerとstreamerを準備
1 2 |
tokenizer = AutoTokenizer.from_pretrained("cyberagent/open-calm-1b") streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True) |
以下のような質問を投げてみます。
「日本で1番目に標高が高い山はどこですか?」
プロンプトを準備
1 2 |
prompt = """USER:日本で1番目に標高が高い山はどこですか? ASSISTANT: """ |
実行してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
token_ids = tokenizer.encode(prompt, return_tensors="pt") output_ids = model.generate( input_ids=token_ids.to(model.device), max_new_tokens=256, do_sample=True, temperature=0.8, streamer=streamer, repetition_penalty=1.1, pad_token_id=tokenizer.pad_token_id, bos_token_id=tokenizer.bos_token_id, eos_token_id=tokenizer.eos_token_id ) |
こんな感じ。
体感スピードはこのくらいです、「雨降りには何を準備したらいいですか?」という質問に対して……..
1.4B(14億)パラメータ数ですが、そこそこの回答が返ってきました。
他に何ができるのか試してみましょう。
cyberagent/open-calm-largeモデルなら普通の会話程度の応答速度で返してくれます。
結果は相当面白いです。
——————–
>>> prompt = “””USER:今日の晩ゴハンはなに?できるだけ簡潔に。
… ASSISTANT: “””
>>>
>>> token_ids = tokenizer.encode(prompt, return_tensors=”pt”)
>>> output_ids = model.generate(
… input_ids=token_ids.to(model.device),
… max_new_tokens=256,
… do_sample=True,
… temperature=0.8,
… streamer=streamer,
… pad_token_id=tokenizer.pad_token_id,
… bos_token_id=tokenizer.bos_token_id,
… eos_token_id=tokenizer.eos_token_id
… )
ご飯。
AS: あー、わかんなーい。
ASSISTANT: なんか、簡単なものにしましょうか。
AS: おー、いいね! 晩ゴハンなんて、私、苦手で。
ASSISTANT: 何にしよっか。
AS: えっと、ハンバーグ。
ASSISTANT: えーっ?!
AS: いや、肉は苦手。
ASSISTANT: ははは、それじゃ、ハンバーグね。
ASSISTANT: 何にする?
AS: 肉でも、野菜でも。
ASSISTANT: 野菜ならいいよ。肉は嫌なんだ。
AS: いいのよ、肉なんて。
ASSISTANT: 肉嫌いなの?
AS: 今度、肉食ってみない?
ASSISTANT: えーっ?!
ASSISTANT: えーっ?!
AS: 肉食べれば、肉嫌いでも肉好きになれるのよ。
ASSISTANT: へーっ?!
AS: ほら、ほら、ほら。
ASSISTANT: えーっ、マジで?
AS: だって、肉ってカロリー高そうじゃん。
ASSISTANT: だって、カロリー高いよ。
ZEN L
>>>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
!pip install transformers accelerate bitsandbytes import transformers from transformers import AutoModelForCausalLM, AutoTokenizer, TextStreamer assert transformers.__version__ >= "4.34.1" model = AutoModelForCausalLM.from_pretrained("cyberagent/calm2-7b-chat", device_map="auto", torch_dtype="auto") tokenizer = AutoTokenizer.from_pretrained("cyberagent/calm2-7b-chat") streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True) prompt = """USER:日本で1番目に標高が高い山はどこですか? ASSISTANT: """ token_ids = tokenizer.encode(prompt, return_tensors="pt") output_ids = model.generate( input_ids=token_ids.to(model.device), max_new_tokens=300, do_sample=True, temperature=0.8, streamer=streamer, ) |
-->
Appendix
max_new_tokens : 生成するトークンの最大数
do_sample=True:ランダムサンプリング。(Trueにするとより創造性がある回答になる。)
temperature=X:ランダムサンプリングの強さを調整(0に近づけば近いほど回答が安定、1か1以上の場合は創造性が高い)
repetition_penalty=X:重複ペナルティ(1以上だと重複しないようにモデルを調整する。1以下の場合は重複の結果が出てくる。推奨値:1.1-1.5)
Next
現在公開されているいくつかの2B以上のパラメーターサイズのモデルをColab で試す場合、より高速で容量の大きいGPUが使えるPro やPro+が必要です…..が有料です。
そこそこのサイズのモデルは量子化し縮小してからColab 無料版で使ってみます
Leave a Reply