Gemini モデルチューニング API ガイド
モデルチューニング API は、Geminiベースのカスタムモデルを作成し、あなたのドメイン固有のデータに適応させる機能です。事前学習済みのGeminiモデルをあなたのデータで追加学習することで、特定のタスクに最適化されたモデルを構築できます。ここでモデルチューニングの基礎から実装、デプロイメントまで解説します。
モデルチューニングとは
モデルチューニング(またはファインチューニング)は、事前学習済みモデルをあなたのデータセットで追加学習させるプロセスです。この方法により、以下のような利点が得られます:
モデルチューニングの利点
- ドメイン特化性: 医療、法律、金融など特定分野の知識を学習
- カスタマイズ性: ブランドの声、トーン、形式に合わせた出力
- コスト効率性: 小規模な学習データで高い精度を実現
- 潜在性削減: 不適切な回答の頻度を減らす
チューニングデータセットの準備
モデルチューニングの成功は、高品質なトレーニングデータに依存します。
データセット要件
- 最小サイズ: 100個の例(推奨: 1,000個以上)
- 形式: JSONL(JSON Lines)形式
- バランス: 各カテゴリが適切に代表されていること
- 品質: クリーニングされた、正確なデータ
データセット準備例
// training_data.jsonl
{"messages": [{"role": "user", "content": "技術サポートチケット #123"}, {"role": "assistant", "content": "チケットを確認しました。どのようなサポートが必要ですか?"}]}
{"messages": [{"role": "user", "content": "API呼び出しでエラーが発生しています"}, {"role": "assistant", "content": "エラーログを確認してください。詳細を教えていただけますか?"}]}
{"messages": [{"role": "user", "content": "デプロイメント方法は?"}, {"role": "assistant", "content": "Cloud Functionsへのデプロイについてご説明します。"}]}Python でのデータセット準備
import json
from typing import List, Dict
class DatasetPreparer:
"""トレーニングデータセットの準備と検証"""
@staticmethod
def create_training_example(
user_input: str,
assistant_response: str
) -> Dict:
"""トレーニング例を作成"""
return {
"messages": [
{"role": "user", "content": user_input},
{"role": "assistant", "content": assistant_response}
]
}
@staticmethod
def validate_dataset(data: List[Dict]) -> tuple[bool, List[str]]:
"""データセットを検証"""
issues = []
if len(data) < 100:
issues.append(f"データセットが小さすぎます ({len(data)} 例)。最低100例推奨")
for i, example in enumerate(data):
if "messages" not in example:
issues.append(f"例 {i}: 'messages' キーが見つかりません")
elif len(example["messages"]) < 2:
issues.append(f"例 {i}: メッセージペアが不完全です")
for j, msg in enumerate(example.get("messages", [])):
if "role" not in msg or "content" not in msg:
issues.append(f"例 {i}、メッセージ {j}: 'role' または 'content' が欠落")
if not msg.get("content"):
issues.append(f"例 {i}、メッセージ {j}: コンテンツが空です")
return len(issues) == 0, issues
@staticmethod
def save_dataset(data: List[Dict], filepath: str) -> None:
"""データセットをJSONL形式で保存"""
with open(filepath, 'w', encoding='utf-8') as f:
for example in data:
f.write(json.dumps(example, ensure_ascii=False) + '\n')
@staticmethod
def load_dataset(filepath: str) -> List[Dict]:
"""JSONL ファイルからデータセットを読み込み"""
data = []
with open(filepath, 'r', encoding='utf-8') as f:
for line in f:
if line.strip():
data.append(json.loads(line))
return data
# 使用例
training_data = [
DatasetPreparer.create_training_example(
"Gemini APIについて教えてください",
"Gemini APIはGoogleが提供する最新のAI API で、テキスト、画像、音声を処理できます"
),
DatasetPreparer.create_training_example(
"プライシングはどうなっていますか?",
"Gemini API は従量課金制で、1百万トークンあたりの料金が設定されています"
),
]
# 検証
is_valid, issues = DatasetPreparer.validate_dataset(training_data)
if not is_valid:
for issue in issues:
print(f"警告: {issue}")
# 保存
DatasetPreparer.save_dataset(training_data, "training_data.jsonl")
print("データセットを保存しました")
# 予期される出力:
# データセットを保存しましたモデルチューニングの実行
チューニングジョブの作成
import anthropic
import time
def create_tuning_job(
training_data_path: str,
model: str = "gemini-1.5-pro",
epochs: int = 1,
learning_rate_multiplier: float = 1.0
) -> dict:
"""モデルチューニングジョブを作成"""
client = anthropic.Anthropic(api_key="YOUR_API_KEY")
# トレーニングデータをアップロード
with open(training_data_path, 'rb') as f:
response = client.beta.files.upload(
file=('training_data.jsonl', f, 'application/json'),
)
training_file_id = response.id
print(f"トレーニングファイルがアップロードされました: {training_file_id}")
# チューニングジョブを作成
job_response = client.beta.fine_tuning.jobs.create(
model=model,
training_file=training_file_id,
hyperparameters={
"batch_size": 32,
"learning_rate_multiplier": learning_rate_multiplier,
"n_epochs": epochs
}
)
return {
"job_id": job_response.id,
"status": job_response.status,
"training_file_id": training_file_id,
"model": model
}
# チューニングジョブを作成
job = create_tuning_job(
training_data_path="training_data.jsonl",
model="gemini-1.5-pro",
epochs=3,
learning_rate_multiplier=2.0
)
print(f"チューニングジョブを作成しました: {job['job_id']}")
print(f"ステータス: {job['status']}")チューニング進捗の監視
def monitor_tuning_job(job_id: str, poll_interval: int = 30) -> dict:
"""チューニングジョブの進捗を監視"""
client = anthropic.Anthropic(api_key="YOUR_API_KEY")
while True:
job = client.beta.fine_tuning.jobs.retrieve(job_id)
print(f"\nジョブID: {job.id}")
print(f"ステータス: {job.status}")
print(f"作成日時: {job.created_at}")
if hasattr(job, 'result') and job.result:
print(f"チューニング済みモデル: {job.result.fine_tuned_model}")
if job.status in ["succeeded", "failed", "cancelled"]:
return {
"job_id": job.id,
"status": job.status,
"model": job.result.fine_tuned_model if job.result else None
}
time.sleep(poll_interval)
# ジョブ進捗を監視
completed_job = monitor_tuning_job("job_abc123xyz")
print(f"\nチューニング完了: {completed_job['status']}")
if completed_job['model']:
print(f"チューニング済みモデル: {completed_job['model']}")チューニング済みモデルの使用
チューニング済みモデルでの推論
def use_tuned_model(
tuned_model_id: str,
user_prompt: str
) -> str:
"""チューニング済みモデルで推論を実行"""
client = anthropic.Anthropic(api_key="YOUR_API_KEY")
response = client.messages.create(
model=tuned_model_id,
max_tokens=1024,
messages=[
{
"role": "user",
"content": user_prompt
}
]
)
return response.content[0].text
# チューニング済みモデルを使用
custom_model_id = "ft_gemini-1.5-pro_20240314_abcdef123"
response = use_tuned_model(
custom_model_id,
"技術サポートについて説明してください"
)
print("チューニング済みモデルの応答:")
print(response)評価とメトリクス
パフォーマンス評価
from typing import List, Tuple
class TuningEvaluator:
"""チューニング済みモデルのパフォーマンス評価"""
@staticmethod
def evaluate_accuracy(
test_cases: List[Tuple[str, str]],
tuned_model_id: str
) -> dict:
"""精度を評価(ベースラインとの比較)"""
client = anthropic.Anthropic(api_key="YOUR_API_KEY")
correct_predictions = 0
baseline_correct = 0
for user_input, expected_output in test_cases:
# チューニング済みモデルでの推論
tuned_response = client.messages.create(
model=tuned_model_id,
max_tokens=512,
messages=[{"role": "user", "content": user_input}]
)
# ベースラインモデルでの推論
baseline_response = client.messages.create(
model="gemini-1.5-pro",
max_tokens=512,
messages=[{"role": "user", "content": user_input}]
)
tuned_text = tuned_response.content[0].text
baseline_text = baseline_response.content[0].text
# 簡易的な一致度チェック
if expected_output.lower() in tuned_text.lower():
correct_predictions += 1
if expected_output.lower() in baseline_text.lower():
baseline_correct += 1
total = len(test_cases)
return {
"tuned_accuracy": correct_predictions / total * 100,
"baseline_accuracy": baseline_correct / total * 100,
"improvement": (correct_predictions - baseline_correct) / total * 100,
"test_count": total
}
# 評価の実行
test_data = [
("Gemini API の最新バージョンは?", "Gemini 2.0"),
("料金モデルは?", "従量課金制"),
]
results = TuningEvaluator.evaluate_accuracy(
test_data,
"ft_gemini-1.5-pro_20240314_abcdef123"
)
print(f"チューニング済みモデル精度: {results['tuned_accuracy']:.1f}%")
print(f"ベースライン精度: {results['baseline_accuracy']:.1f}%")
print(f"改善度: {results['improvement']:.1f}%")ベストプラクティス
1. イテレーティブな改善
# 初期チューニング
initial_job = create_tuning_job("initial_training_data.jsonl", epochs=1)
# 結果を評価
eval_results = TuningEvaluator.evaluate_accuracy(test_data, completed_job['model'])
if eval_results['improvement'] < 5:
# さらにデータを追加
expanded_job = create_tuning_job("expanded_training_data.jsonl", epochs=2)2. データセットのバージョン管理
import datetime
def save_versioned_dataset(data: List[Dict], version: str) -> str:
"""バージョン付きでデータセットを保存"""
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
filepath = f"training_data_v{version}_{timestamp}.jsonl"
DatasetPreparer.save_dataset(data, filepath)
return filepath全体を振り返って
モデルチューニング API を使用することで、Geminiを特定のドメインやタスクに最適化されたカスタムモデルに変換できます。高品質なトレーニングデータ準備、段階的な改善、継続的な評価を通じて、強力で信頼性の高いAIシステムを構築してください。
詳細については、関数呼び出しガイド で、チューニング済みモデルでのツール統合方法を学ぶことをお勧めします。
個人開発の視点で — チューニングは「データの掃除」が9割
個人開発で複数のアプリと Dolice Labs を並行して保守している私自身の経験では、Gemini のチューニングで成果を分けるのは手法そのものより、学習データの前処理でした。重複・表記揺れ・ラベルのブレを残したまま回すと、ベースモデルより悪化することすらあります。
私はいつも、まず数十件の小さなデータセットで挙動を確かめ、評価が安定してから件数を増やすようにしています。最初から大量に投入すると、何が効いたのか切り分けられなくなるためです。地味ですが、この順番が結局いちばん早く着地します。
評価も、全体の正解率だけでなく「以前は通っていたのに悪化したケース」を必ず別途追うようにしています。平均が上がっても、特定の入力で退行していることがあるからです。チューニングは一度きりではなく、退行を見張りながら少しずつ寄せていく作業だと考えています。
また、チューニング済みモデルは「いつ作り直すか」も運用の一部です。私は対象ドメインの言い回しや前提が変わってきたと感じたら、定期的に新しいデータで作り直すようにしています。一度作って放置すると、現場とのズレが静かに広がっていくためです。私はモデルのバージョンと作成日を必ず記録し、いつの判断で作ったものかを後から追えるようにしています。