27. OpenAIでGPTモデルをファインチューニング!マネージド型の簡単な方法を体験
前回まで、Llama 3.2 1Bモデルでベースラインパフォーマンスを測定しました。でも、「もっと強力なモデルならどうなるの?」って気になりますよね。
今回は、同じSAMSum要約タスクでGPT-4o-miniのようなフロンティアモデル(最先端の高性能モデル)を使った場合に何が起こるか見ていきます。まず何もしない状態、次にファインチューニング後です。
これにより、同じデータセットでのオープンウェイトモデルとフロンティアモデルの明確な比較が得られ、マネージドファインチューニングが強力なベースモデルをどれだけ改善できるかがわかります。
しかも、必要な場合にフロンティアモデルをファインチューニングする方法も学べるんです!
これは、オープンウェイトモデルを使った実践的なファインチューニングに戻る前の、ちょっとした寄り道だと考えてください。でも、この寄り道が実はとても価値があるんですよ。
なぜこの小休止が必要なの?
ファインチューニングといえば、ノートブック、GPU、カスタムトレーニングループを思い浮かべますよね。次にやることはまさにそれです。
でもその前に、「すべての作業を代行してもらった場合に何が起こるか」を見ておくと役立つんです。
OpenAIやGoogleのような企業は、マネージドファインチューニングサービスを提供しています。データをアップロードし、ベースモデルを指定すれば、残りはすべて彼らが処理します。インフラ、最適化、スケーリング、チェックポイント作成、すべてです!
迅速で信頼性がありますが、トレードオフもあります:
- モデル内部への制御や可視性が少ない:何が起こっているか詳しく見えません
- トークンあたりのコストが高い:お金がかかります
- 中間チェックポイントへのアクセスがない:途中経過が見えません
このレッスンでは、Colabでのセルフホスト型ファインチューニングに戻る前に、トレードオフを理解するために一度だけこのワークフローを見ていきます。
比較する2つのワークフロー
OpenAI APIの仕組みを理解したところで、作業を2つの明確なワークフローに分けます:
Workflow 1:ベースモデルの評価
GPT-4o-miniをファインチューニングせずに評価します。「素の状態でどれくらいできるの?」を確認するんです。
Workflow 2:マネージドファインチューニング
OpenAIのホストAPIを使ってGPT-4o-miniをファインチューニングし、まったく同じパイプラインを使って再評価します。
この分離により一貫性が保たれます。同じデータセット、プロンプト、ROUGE計算を両方のワークフローで再利用し、モデルとそのトレーニングソースのみを変更します。
これで、フェアな比較ができるんですね!
Workflow 1:フロンティアモデルの評価(GPT-4o-miniベースライン)
まずベースライン評価ワークフローから始めましょう。
メカニクスの理解:一度に1つの例
OpenAIのAPIを使用する場合、タスクを説明するチャットメッセージのリストを送信します。各SAMSum対話はモデルの「会話」となり、モデルはその要約で応答します。
from datasets import load_dataset
from openai import OpenAI
client = OpenAI()
dataset = load_dataset("knkarthick/samsum")
val_data = dataset["validation"].shuffle(seed=42).select(range(200))
def build_user_prompt(dialog: str):
prompt = (
"You are a helpful assistant who writes concise, factual summaries of conversations. "
"Summarize the following conversation in one clear sentence. "
"If it can be shorter, make it as brief as possible.\n"
f"## Dialog: {dialog}\n"
"## Summary:\n"
)
return prompt
sample = {
"dialogue": (
"Jane: Hey, are we still on for lunch?\n"
"John: Yes, but let's move it to 1 PM instead of noon.\n"
"Jane: Works for me."
)
}
messages = [{"role": "user", "content": build_user_prompt(sample["dialogue"])}]
response = client.chat.completions.create(model="gpt-4o-mini", messages=messages, temperature=0)
print(response.choices[0].message.content)
出力:
Jane and John agreed to reschedule lunch from noon to 1 PM.
シンプルで明快ですね!これは、数百のサンプルにスケールする同じメカニズムです。すべての予測を生成し、リファレンス要約に対してROUGEスコアを計算します。
ベースライン評価の実装
前のレッスンで使った同じヘルパー関数を再利用できます:
load_and_prepare_dataset(cfg):SAMSumデータのロードとサンプリングcompute_rouge(predictions, samples):要約品質の評価build_messages_for_sample(sample, task_instruction):OpenAIプロンプトの構造化
そして2つの関数を追加します:
generate_openai_predictions():すべてのサンプルに対してスレッド化されたAPI推論を実行evaluate_openai_model():評価ワークフローをラップ(生成 + スコアリング + 保存)
def evaluate_openai_model(model_name: str, cfg: dict, limit: int = None, max_workers: int = 5):
"""Run evaluation on an OpenAI model (base or fine-tuned)."""
print(f"\n🚀 Evaluating OpenAI model: {model_name}")
_, val_data, _ = load_and_prepare_dataset(cfg)
if limit:
val_data = val_data.select(range(limit))
preds = generate_openai_predictions(model_name, val_data, cfg["task_instruction"], len(val_data), max_workers, 0.1)
scores = compute_rouge(preds, val_data)
print("\nROUGE Summary:")
print(f"ROUGE-1: {scores['rouge1']:.2%}, ROUGE-2: {scores['rouge2']:.2%}, ROUGE-L: {scores['rougeL']:.2%}")
return scores, preds
ベースライン結果
ベースGPT-4o-miniは、ファインチューニングなしですでにオープンウェイトのLlama 3.2 1Bベースラインを上回ります。フロンティアモデルの事前トレーニングの利点が見えますね!
Workflow 2:OpenAIのマネージドAPIでGPTモデルをファインチューニング
ベースモデルの評価方法を見たところで、2番目のワークフローに移りましょう。OpenAIのホストインフラを使って同じモデルをファインチューニングします。
このワークフローは、Llama 3.2でローカルに行ったことと同じですが、OpenAIがGPUリソース、トレーニングループ、チェックポイントを処理してくれる点が異なります。
再利用するもの
以下を再利用します:
- 同じ評価関数(evaluate_openai_model)
- 同じ指示プロンプトとROUGEメトリクス
ここで必要な新しいロジックは:
- データセットをOpenAI JSONL形式に変換
- APIにアップロード
- ファインチューニングジョブを起動・監視
- 結果として得られたファインチューニング済みモデルを評価
Step 1:データの準備とアップロード
OpenAIのファインチューニングAPIは、JSONL形式のデータを期待します。各レコードはユーザーとアシスタントのメッセージを含むチャット例です。
from openai import OpenAI
import json
client = OpenAI()
def build_user_prompt(dialogue):
return (
"You are a helpful assistant who writes concise, factual summaries of conversations. "
"Summarize the following conversation into a single sentence.\n"
f"## Dialog:\n{dialogue}\n"
"## Summary:\n"
)
# Convert dataset to JSONL format
def convert_to_jsonl(dataset, out_path):
with open(out_path, "w") as f:
for sample in dataset:
record = {
"messages": [
{"role": "user", "content": build_user_prompt(sample["dialogue"])},
{"role": "assistant", "content": sample["summary"]}
]
}
f.write(json.dumps(record) + "\n")
print(f"✅ Saved: {out_path}")
convert_to_jsonl(train_data, "samsum_train.jsonl")
convert_to_jsonl(val_data, "samsum_val.jsonl")
次に両方のファイルをOpenAIにアップロードします:
train_file = client.files.create(file=open("samsum_train.jsonl", "rb"), purpose="fine-tune")
val_file = client.files.create(file=open("samsum_val.jsonl", "rb"), purpose="fine-tune")
print("Training file ID:", train_file.id)
print("Validation file ID:", val_file.id)
Step 2:ファインチューニングジョブの作成
次に、ベースモデルとしてgpt-4o-miniを使ってファインチューニングジョブを作成します:
job = client.fine_tuning.jobs.create(
model="gpt-4o-mini",
training_file=train_file.id,
validation_file=val_file.id,
suffix="samsum-ft",
hyperparameters={"n_epochs": 1, "learning_rate_multiplier": 1, "batch_size": 8}
)
print("✅ Fine-tuning job created:", job.id)
ジョブは完全にOpenAIのインフラ上で実行されます。GPUやColabのセットアップは不要です!
OpenAIダッシュボードから直接進捗を監視でき、損失と精度の曲線がリアルタイムで更新されます。便利ですよね。
Step 3:トレーニング進捗の監視
ノートブックまたはターミナルから以下を使って進捗を確認できます:
import time
while True:
status = client.fine_tuning.jobs.retrieve(job.id)
print(f"🕒 {status.status} | Trained tokens: {status.trained_tokens or 0}")
if status.status in ("succeeded", "failed", "cancelled"):
break
time.sleep(30)
完了すると、レスポンスにはファインチューニング済みモデルIDが含まれます。例えば:
ft:gpt-4o-mini-2024-11-07:ready-tensor-inc:samsum-ft
Step 4:ファインチューニング済みモデルの評価
最後に、Workflow 1と同じヘルパー関数を使ってファインチューニング済みモデルを評価します:
tuned_model_id = "ft:gpt-4o-mini-2024-11-07:ready-tensor-inc:samsum-ft"
scores, preds = evaluate_openai_model(tuned_model_id, cfg, limit=200)
結果:
ROUGE Summary:
ROUGE-1: 55.72%, ROUGE-2: 32.80%, ROUGE-L: 47.77%
素晴らしい改善ですね!
これまでの結果
SAMSum要約ベンチマーク(検証セット200サンプル)での結果を比較してみましょう:
| モデル | ROUGE-1 | ROUGE-2 | ROUGE-L |
|---|---|---|---|
| Llama 3.2 1B(ベース) | 約30-35% | 約15-20% | 約25-30% |
| GPT-4o-mini(ベース) | 約50% | 約28% | 約43% |
| GPT-4o-mini(FT後) | 55.72% | 32.80% | 47.77% |
比較すると明確な進歩が見られます:
- Llama 3.2 1Bモデルは妥当な性能を示しますが、小さなサイズによる制限があります
- ベースGPT-4o-miniは、ファインチューニングなしですでに強力な要約品質を示します
- ファインチューニング済みGPT-4o-miniは、すべてのROUGEメトリクスで大幅に改善し、ROUGE-Lで47.77%近くを達成!
これらの結果は、モデルの規模とファインチューニングアプローチが要約性能にどのように影響するかを示しています。次のレッスンでセルフホスト型ファインチューニングに移る前の明確なベンチマークになりますね。
次のステップ
マネージドファインチューニングが最初から最後までどのように機能するかを見ました。高速でシンプル、完全にホストされています。
これは迅速な改善を得る効率的な方法ですが、トレードオフもあります:
- 透明性の制限:内部で何が起こっているか見えません
- 高コスト:トークンあたりの料金が発生します
- 制御が少ない:舞台裏で何が起こっているかを調整できません
次は、より実践的なアプローチを取ります!
次のレッスンでは、LoRAを使ってLlama 3.2 1Bを自分でファインチューニングし、プロセスのすべての部分を管理します。データの準備、アダプターの設定からトレーニング、監視、結果の評価まで、すべてです。
そこで、ファインチューニングはブラックボックスではなく、真のエンジニアリングになります。
さあ、構築しましょう!

コメント