GEMINI LABEN
NANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定ですNANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定です
記事一覧/高度な活用
高度な活用/2026-03-14上級

Gemini モデルチューニング API ガイド — カスタムモデルを作成する

Gemini APIのモデルチューニング機能を活用して、独自のカスタムモデルを構築・展開する方法

Gemini API191モデルチューニングファインチューニング4カスタムモデル

Gemini モデルチューニング API ガイド

モデルチューニング API は、Geminiベースのカスタムモデルを作成し、あなたのドメイン固有のデータに適応させる機能です。事前学習済みのGeminiモデルをあなたのデータで追加学習することで、特定のタスクに最適化されたモデルを構築できます。ここでモデルチューニングの基礎から実装、デプロイメントまで解説します。

モデルチューニングとは

モデルチューニング(またはファインチューニング)は、事前学習済みモデルをあなたのデータセットで追加学習させるプロセスです。この方法により、以下のような利点が得られます:

モデルチューニングの利点

  1. ドメイン特化性: 医療、法律、金融など特定分野の知識を学習
  2. カスタマイズ性: ブランドの声、トーン、形式に合わせた出力
  3. コスト効率性: 小規模な学習データで高い精度を実現
  4. 潜在性削減: 不適切な回答の頻度を減らす

チューニングデータセットの準備

モデルチューニングの成功は、高品質なトレーニングデータに依存します。

データセット要件

  • 最小サイズ: 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 のチューニングで成果を分けるのは手法そのものより、学習データの前処理でした。重複・表記揺れ・ラベルのブレを残したまま回すと、ベースモデルより悪化することすらあります。

私はいつも、まず数十件の小さなデータセットで挙動を確かめ、評価が安定してから件数を増やすようにしています。最初から大量に投入すると、何が効いたのか切り分けられなくなるためです。地味ですが、この順番が結局いちばん早く着地します。

評価も、全体の正解率だけでなく「以前は通っていたのに悪化したケース」を必ず別途追うようにしています。平均が上がっても、特定の入力で退行していることがあるからです。チューニングは一度きりではなく、退行を見張りながら少しずつ寄せていく作業だと考えています。

また、チューニング済みモデルは「いつ作り直すか」も運用の一部です。私は対象ドメインの言い回しや前提が変わってきたと感じたら、定期的に新しいデータで作り直すようにしています。一度作って放置すると、現場とのズレが静かに広がっていくためです。私はモデルのバージョンと作成日を必ず記録し、いつの判断で作ったものかを後から追えるようにしています。

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

高度な活用2026-04-11
Gemma4 API活用法:Gemini APIとのハイブリッド開発でコストを最適化する
Gemma4 APIとGemini APIを組み合わせた高度な開発パターンを解説。Vertex AI上でのデプロイ、ファインチューニング、RAGパイプライン構築の実践的なコードを網羅します。
高度な活用2026-07-17
日本語で引いた検索に、対訳の英語記事が出てこない — 埋め込みが内容より先に言語を見ている件
gemini-embedding-2 で日英の対訳ペアを埋め込むと、同じ内容なのに最近傍になりません。言語そのものが類似度を押し上げているためです。対訳ペアを正解として再現率を測り、言語重心を引く方法と翻訳ブリッジを比べた記録をまとめます。
高度な活用2026-07-15
分類ラベルの近ミスはリトライで直らない — 閉じた語彙を正規化する層を挟んだ実測ノート
responseSchema の enum を外したラベルをリトライで直そうとすると同じ近ミスが返ります。壁紙アプリの30分類バッチで外れ方の分布を測り、別名表と埋め込み最近傍で正規化する受け入れ層を挟んだ実装と実測値をまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →