はじめに
前回、Gemma 2 2B をローカルで動かすところまでの構築メモを書きましたが、今回はその続きとして 日本語に特化した instruction-tuned モデル google/gemma-2-2b-jpn-it を試してみました。
前回は英語ベースの gemma-2-2b(素のベースモデル)を使ったため、生成結果が同じ文を繰り返すという挙動が見られました。今回はその改善版として、
-
日本語に特化した
jpn-itバリアント - 指示追従(instruction-tuned) 済みなので、チャット的な応答が期待できる
- ローカルキャッシュから読み込む ため、2回目以降は再ダウンロード不要
という 3 点を確認することが目的です。
同じく GPUなし・CPUのみ・RAM 8GB の低スペック環境での動作確認メモです。
検証環境
前回と同じ環境です。
| 項目 | スペック |
|---|---|
| OS | Windows 11 |
| CPU | GPUは使わずCPUのみで実行 |
| GPU | なし(今回も意図的に不使用) |
| メモリ | 8GB |
| Python | venv による仮想環境 |
| モデル |
google/gemma-2-2b-jpn-it(ローカルキャッシュ済み) |
動作確認スクリプト
今回実行したコードは以下のとおりです。
test_jpn_it.py
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
model_name = "google/gemma-2-2b-jpn-it"
print("トークナイザーを読み込み中...")
tokenizer = AutoTokenizer.from_pretrained(model_name, local_files_only=True)
print("モデルを読み込み中...")
model = AutoModelForCausalLM.from_pretrained(
model_name,
dtype=torch.bfloat16,
device_map="cpu",
local_files_only=True,
)
print("読み込み完了!簡単な生成テストをします。")
inputs = tokenizer("品川駅から東京まで最短で何分で行ける?", return_tensors="pt")
outputs = model.generate(**inputs, max_new_tokens=128)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
前回のコードとの主な違いは以下の 3 点です。
| 変更点 | 前回(gemma-2-2b) |
今回(gemma-2-2b-jpn-it) |
|---|---|---|
| モデル名 | google/gemma-2-2b |
google/gemma-2-2b-jpn-it |
| ダウンロード挙動 | 初回に自動ダウンロード | 初回ダウンロード済み前提。local_files_only=True でキャッシュのみ参照 |
dtype 引数名 |
torch_dtype= |
dtype=(新仕様) |
| プロンプト | 天気の話題(日本語補完テスト) | 路線情報の質問(指示応答テスト) |
ポイント解説
local_files_only=True とは
モデルを一度ダウンロードすると、ファイルはローカルキャッシュ(C:\Users\(ユーザー名)\.cache\huggingface\hub)に保存されます。local_files_only=True を指定することで、2回目以降は Hugging Face へのネットワークアクセスを一切行わず、キャッシュから直接読み込むようになります。
⚠️ このフラグはキャッシュが存在することが前提です。初回は
local_files_only=Trueを外した状態でダウンロードを完了させてから使う必要があります。gemma-2-2b-jpn-itも初回は同様にダウンロードが発生します。
tokenizer = AutoTokenizer.from_pretrained(model_name, local_files_only=True)
model = AutoModelForCausalLM.from_pretrained(
model_name,
local_files_only=True,
...
)
オフライン環境での実行や、ネットワーク遅延の排除に便利です。モデルをキャッシュしていない状態でこのフラグを立てると OSError が出るので注意してください。
dtype= vs torch_dtype=
前回の記事でも触れましたが、transformers の仕様変更により torch_dtype 引数は非推奨になりつつあり、dtype が推奨表記になっています。今回のコードは最初から dtype=torch.bfloat16 で書いています。動作への影響はありませんが、新規コードでは dtype= を使っておくと良いでしょう。
# 旧(非推奨・警告が出る場合あり)
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.bfloat16)
# 新(推奨)
model = AutoModelForCausalLM.from_pretrained(model_name, dtype=torch.bfloat16)
gemma-2-2b-jpn-it とは
jpn-it は Japanese Instruction-Tuned の略で、Google が日本語に特化して instruction-tuning を施したモデルです。
-
ベースモデル(
gemma-2-2b):次のトークンを予測するだけの素の言語モデル。指示に従うよりも文章を「続ける」動作をする -
指示チューニング済み(
gemma-2-2b-jpn-it):「質問→回答」「指示→実行」のような対話形式の応答ができるよう追加学習されている
前回起きた「生成結果が同じ文の繰り返し」は、ベースモデルの仕様上の挙動でした。-it モデルを使うことで、より自然な応答が期待できます。
実行結果
(venv) $ python test_jpn_it.py
トークナイザーを読み込み中...
モデルを読み込み中...
読み込み完了!簡単な生成テストをします。
品川駅から東京まで最短で何分で行ける?
品川駅から東京駅までは、JR山手線または京浜東北線で約6分です。
前回のベースモデルで見られた「同じ文の繰り返し」が解消され、質問に対して端的な回答が返ってきました。instruction-tuned モデルの効果が確認できた形です。
なお、CPU のみの実行なので読み込み完了までに 1〜2 分程度かかります(モデルウェイトの展開時間)。生成自体も数十秒〜数分かかることがあります。
メモ
-
local_files_only=Trueにより、実行時のネットワーク通信はゼロ。モデルを一度キャッシュしてしまえば完全オフラインで動く。 -
gemma-2-2b-jpn-itはgemma-2-2bとほぼ同じサイズのため、メモリ使用量は前回同様 約 4〜5 GB(bfloat16指定時)に収まる。RAM 8GB でも動作可能。 -
max_new_tokens=128は生成する最大トークン数の上限。長い回答が必要な場合はここを増やせばよいが、CPU では生成速度が落ちるのでトレードオフを意識する。 - 今回のプロンプトはシンプルなテキスト形式だが、
gemma-2-2b-jpn-itはチャットテンプレート(apply_chat_template)を使ったフォーマットで入力するとより安定した応答が得られる。
注意点メモ
| 事象 | 原因 | 対処 |
|---|---|---|
OSError: We couldn't connect to 'huggingface.co' |
local_files_only=True なのにキャッシュにモデルが存在しない |
一度 local_files_only を外してダウンロードしてからフラグを有効化する |
torch_dtype is deprecated 警告 |
transformers の仕様変更 |
dtype=torch.bfloat16 に書き換える |
| 読み込み・生成が遅い | CPU のみでの実行のため | GPU 環境なら device_map="cuda" に変更すると大幅に高速化できる |
| 回答が日本語にならない場合 | プロンプトの形式が指示チューニングの期待フォーマットと合っていない |
tokenizer.apply_chat_template() を使って入力を整形する |
次回 TODO
動作確認ができたので、次のステップは以下を予定しています。
-
apply_chat_templateを使ったチャット形式の入力に切り替えて、より安定した応答を確認する - LoRA を使ったファインチューニングで、特定タスク向けに調整する
- 将来的なマルチエージェント構成への組み込みを検討する