目的
特別な環境構築なしで、Google Colaboratory (Colab) のGPUリソースを使って、実際に動作する中小規模(7Bクラス)の高性能LLM(cyberagent/calm2-7b)の推論プロセスを体験します。
このハンズオンの目的のポイントは、次の2点です。
-
環境の違いの理解: 通常のWebサービスや専用アプリで利用するLLMは、クラウドサーバー上の巨大なモデルを利用しており、ユーザーはモデルの制御権限を持ちません。これに対し、今回は自分のColab環境のGPUメモリにモデルの重み(知識)を直接ロードし、推論処理を占有的に実行している点が大きく異なります。
-
振る舞いの制御: ロードしたLLMの生成パラメータ(例:temperature, top_k, top_p, repetition_penalty)を直接変更し、応答の確率的・創造的な振る舞いがどのように変化するかを観察・比較します。この体験を通じて、LLMが単語の確率に基づいて文章を生成している仕組み(確率機械としての側面)を理解します。
使用するモデルの説明
cyberagent/calm2-7b は、CyberAgent社が開発した日本語特化の中小規模LLM(約70億パラメータ)です。日本語の文体や会話表現を中心に学習しており、自然な日本語生成や説明文の出力に強みがあります。一方で、巨大モデル(例:GPT-4やClaudeなど)ほどの知識量・論理推論力はありませんが、Google Colab のGPU環境でも動作可能なサイズであり、「自分で制御できるLLM体験」 に最適なモデルです。このモデルを使うことで、確率的なテキスト生成の仕組み(temperature, top_k, top_p, repetition_penaltyなど)を安全かつ手軽に理解・実験できます。
補足: CALM2-7Bは日本語能力が高いですが、パラメータを適切に制御しないと、応答が単調になったり、不正確になることがあります。今回は、その制御の体験に焦点を当てます。
| 分類 | パラメータ数の目安 | 代表モデル例 | 備考 |
|---|---|---|---|
| 小型 LLM | 〜1B(10億)未満 | GPT-2 Small, TinyLlama, Phi-2 | 軽量・高速、性能は限定的 |
| 中小規模 LLM | 1B〜7B程度 | CALM2-7B, Llama-2-7B, Mistral-7B | 消費資源と性能のバランスが良い。Colabなどでも動作可能 |
| 中規模 LLM | 13B〜34B程度 | Llama-2-13B, Mixtral-8×7B | 高性能だが、GPUメモリ(>24GB)が必要 |
| 大規模 LLM | 65B〜100B超 | GPT-3 (175B), Claude 3 Opus, Gemini 1.5 Pro | クラウド専用。個人環境で動かしている人は少ない |
事前準備
Google アカウント:Colabを利用するために必須です。
Colabノートブック:新しいノートブックを用意します。
ランタイムの変更:メニューの「ランタイム」>「ランタイムのタイプを変更」で、ハードウェア アクセラレータを「T4 GPU」に設定し、保存します。
ハンズオン ステップ 1: 基本LLMのロードと実行
1.1 必要なライブラリのインストール
以下のコードセルを実行し、モデルのロードと推論に必要なライブラリをインストールします。
# LLMの実行に必要なライブラリをインストール
!pip install transformers accelerate bitsandbytes
1.2 モデルのロード
モデルをメモリ効率の良い4bit量子化でロードします。CALM2-7Bは比較的大きいため、ロードに数分かかります。Colab無料枠では、初回ロードに5〜10分ほどかかる場合があります。
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
# 使用するモデル名 (CyberAgent開発の高性能日本語LLM)
model_name = "cyberagent/calm2-7b"
# トークナイザー(文章を数値に変換)とモデルのロード
# 4bit量子化(メモリを節約する技術)を利用してロードします。
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
load_in_4bit=True, # 4bit量子化を有効化
torch_dtype=torch.float16,
device_map="auto"
)
model.eval() # モデルを評価モードに設定
print(f"モデル {model_name} のロードが完了しました。")
cyberagent/calm2-7b の特性
cyberagent/calm2-7b の特性 CALM2-7Bは、rinna/3.6bよりもパラメータ数が倍以上多く、より複雑な指示の理解や論理推論、一般的な知識再生に優れています。応答の安定性も高いですが、パラメータ設定を誤ると、やはり単調な回答(ループ)や文脈の逸脱が発生します。
プログラミングコードの生成、複雑な数値計算、長文の構成・要約、最新情報に関する事実確認など比較的難しい質問は避けて、以下のような比較的やさしい質問を選んでテストすることをお勧めします。
| カテゴリ | 質問例 |
|---|---|
| 日常会話・雑談系 | 「猫と犬、どちらが好き?理由も教えて。」、「朝ごはんにおすすめのメニューを教えて。」 |
| 基礎的な知識・説明系 | 「日本の四季の特徴を簡単に説明してください。」、「電気はどのようにして作られますか?」 |
| 文章生成・言い換え | 「『今日はとても暑いです』を別の言い方にして。」、「短い挨拶文を書いてください。」 |
| 創作・感想・想像 | 「未来の東京はどんな町だと思いますか?」、「桜を見たときの気持ちを短く書いてください。」 |
1.3 テキスト生成(動作確認)
安定版 attention_maskの適用と、CALM2-7Bの特性に合わせた安定パラメータを使用します。
# 1行だけコメントアウト#を外して、試してください。
prompt = "猫と犬、どちらが好き?理由も教えて"
# prompt = "朝ごはんにおすすめのメニューを教えて。"
# prompt = "日本の四季の特徴を簡単に説明してください。"
# prompt = "電気はどのようにして作られますか?"
# prompt = "未来の東京はどんな町だと思いますか?"
# prompt = "桜を見たときの気持ちを短く書いてください。"
# prompt = "『今日はとても暑いです』を別の言い方にして。"
# トークナイザーを使って、input_ids と attention_mask の両方を生成します
inputs = tokenizer(
prompt,
return_tensors="pt"
).to(model.device)
input_ids = inputs["input_ids"]
attention_mask = inputs["attention_mask"]
with torch.no_grad():
output = model.generate(
input_ids,
attention_mask=attention_mask,
max_length = 150,
# ★★★ 応答の安定化のための設定 ★★★
do_sample=True, # 確率的なサンプリングを有効化 default値True
temperature=0.8, # 安定性と創造性のバランスが取れた標準値 default値0.8
top_k=50, # 確率の高い50単語から選択 default値50
top_p=0.9, # 核サンプリング(より柔軟な単語選択) default値0.9
repetition_penalty=1.1, # 繰り返しを抑制するためのペナルティ default値1.1
pad_token_id=tokenizer.eos_token_id
)
generated_text = tokenizer.decode(output[0], skip_special_tokens=True)
print("--- 基本応答 ---")
# 応答からプロンプトを切り離して表示
cleaned_response = generated_text.replace(prompt, "").strip()
print(cleaned_response)
ハンズオン ステップ 2: 生成パラメータの変化を観察する実験
2.1 応答生成関数の定義
生成結果を比較しやすくするため、6種の比較する設定パターンを定義して、出力します。
# 1行だけコメントアウト#を外して、試してください。
prompt = "猫と犬、どちらが好き?理由も教えて"
# prompt = "朝ごはんにおすすめのメニューを教えて。"
# prompt = "日本の四季の特徴を簡単に説明してください。"
# prompt = "電気はどのようにして作られますか?"
# prompt = "未来の東京はどんな町だと思いますか?"
# prompt = "桜を見たときの気持ちを短く書いてください。"
# prompt = "『今日はとても暑いです』を別の言い方にして。"
# 比較する設定パターンを定義
experiments = [
{"label": "① 低温度・安定出力", "temperature": 0.3, "top_k": 50, "top_p": 0.9, "repetition_penalty": 1.1},
{"label": "② 通常・バランス型", "temperature": 0.8, "top_k": 50, "top_p": 0.9, "repetition_penalty": 1.1},
{"label": "③ 高温度・創造的", "temperature": 1.3, "top_k": 50, "top_p": 0.9, "repetition_penalty": 1.0},
{"label": "④ top_k 制限緩和", "temperature": 0.8, "top_k": 200, "top_p": 0.9, "repetition_penalty": 1.1},
{"label": "⑤ top_p 狭める", "temperature": 0.8, "top_k": 50, "top_p": 0.5, "repetition_penalty": 1.1},
{"label": "⑥ repetition_penalty 強", "temperature": 0.8, "top_k": 50, "top_p": 0.9, "repetition_penalty": 1.5},
]
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
input_ids = inputs["input_ids"]
attention_mask = inputs["attention_mask"]
# 各設定で生成を実行
for exp in experiments:
print("="*60)
print(f"{exp['label']}")
print(f"設定: temperature={exp['temperature']}, top_k={exp['top_k']}, top_p={exp['top_p']}, repetition_penalty={exp['repetition_penalty']}")
print("-"*60)
with torch.no_grad():
output = model.generate(
input_ids,
attention_mask=attention_mask,
max_length=200,
do_sample=True,
temperature=exp["temperature"],
top_k=exp["top_k"],
top_p=exp["top_p"],
repetition_penalty=exp["repetition_penalty"],
pad_token_id=tokenizer.eos_token_id
)
generated_text = tokenizer.decode(output[0], skip_special_tokens=True)
cleaned_response = generated_text.replace(prompt, "").strip()
print(cleaned_response)
print("\n")
パラメータの説明
| パラメータ名 | 概要 | 主な影響 |
|---|---|---|
| temperature | 単語選択のランダム性を調整 | 低いほど「堅実・安定」、高いほど「創造的・多様」 |
| top_k | 確率の高い上位 k 単語だけから選択 | 小さいほど「保守的」、大きいほど「自由」 |
| top_p | 上位確率の合計が p になるまでの単語群から選択(核サンプリング) | 小さいほど「限定的」、大きいほど「柔軟」 |
| repetition_penalty | 同じ語句の繰り返しを抑える | 値を大きくするとループ防止に効果的だが、文脈が不自然になることも |
temperature と top_k / top_p は、創造性と一貫性のトレードオフを調整するツマミです。
3.4 結論と振り返り
このハンズオンを通じて、以下の重要な点を理解できます。
-
LLMの動作原理: LLMは、次にくる単語の確率を計算し、それに基づいて文章を生成する、一種の確率機械であることを理解した。
-
制御の体験: 通常のサービスでは触れられない do_sample、temperature, top_k, top_p, repetition_penalty のような生成パラメータを直接操作することで、LLMの応答の堅実さと創造性のバランスをプログラマー(またはユーザー)が細かく制御できることを実感した。
-
環境と主体性: クラウドサービスではなく、自分のColab GPU環境にモデルをロードして実行することで、パラメータ制御の結果が自分の環境で確認できるという、LLMを動かす上での主体的な体験の重要性を確認できた。
参考
CyberAgent LLM : https://huggingface.co/cyberagent