◉GEMINI LABEN
●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — deep-research-pro-preview-12-2025 は 10/23 に停止、残り6日。移行先は deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●MCP — ツール結果が 8.5万トークンに膨らんだ事例を、ADK で 310 トークンに包んで抑えた報告が出ています●FLASH — gemini-3.7-flash と 3.5-flash は新しい Flash モデルに自動で回されます(10/08)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — deep-research-pro-preview-12-2025 は 10/23 に停止、残り6日。移行先は deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●MCP — ツール結果が 8.5万トークンに膨らんだ事例を、ADK で 310 トークンに包んで抑えた報告が出ています●FLASH — gemini-3.7-flash と 3.5-flash は新しい Flash モデルに自動で回されます(10/08)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…
記事一覧/高度な活用
⬡ 高度な活用/2026-04-25上級

Gemini API で『自己批判するエージェント』を実装する — Reflection × Critic × Refiner で本番品質を継続的に上げる実装

Gemini 3 Pro と 3.5 Flash-Lite を組み合わせて自己批判するエージェントを構築する設計と本番運用ノウハウ。Reflection / Critic-Refiner パターンの実装、コスト上限、過剰修正の防ぎ方まで踏み込んで解説します。

gemini119gemini-3-pro4reflectionagent9production105self-improving

✦ プレミアム記事

Gemini API を本番で運用していて、ワンショットの応答品質が頭打ちになる瞬間に出会ったことはないでしょうか。プロンプトを丁寧にチューニングし、temperature を下げ、Few-shot まで揃えました。それでも 10% 前後の応答が事実誤認・指示違反・形式崩れで落ちてきます。私自身、自分のアプリで顧客向けのメール下書き機能を作ったとき、まさにこの壁に突き当たりました。

その壁を越えるための実用的なパターンが Reflection と Critic-Refiner です。要するに「LLM に自分の出力を批判させてから書き直させる」という発想で、論文レベルでも実装レベルでも長年検証されてきた枠組みなのですが、本番で使おうとすると「無限ループ」「コストが3倍」「過剰修正で逆に劣化」といった具体的な落とし穴が現れます。

ここでは Gemini 3 Pro と 3.5 Flash-Lite を組み合わせて自己批判するエージェントを実装する手順を、私が実際にプロダクトに組み込んだ経験を踏まえて段階的に解説します。動くコードは3つ用意しました。コピーして温度感を確かめ、自分のユースケースに合わせて調整していただければと思います。

ワンショット推論の限界に最初にぶつかる場所

LLM のワンショット応答(プロンプトを1回投げて1回返ってくる方式)は、9割のタスクで十分な品質を出します。問題は、残り1割で落ちてくる応答が「無視できないコスト」を発生させるユースケースです。

たとえば次のようなケースです。

  • 顧客向けの文書を生成するアプリで、たまに相手の名前を間違える、指示にあった必須項目を抜かす
  • コードレビューエージェントで、明らかな脆弱性は指摘するのに、依存関係の壊れる変更を見落とす
  • 商品説明文の生成で、「絶対に書かないでください」と指示した競合ブランド名がたまに混入する

ワンショットでこれらを全て潰そうとすると、プロンプトが肥大化して逆に品質が落ちる現象が起きます。Gemini 2.5 Pro でも 3.1 Pro でも、プロンプトに 30 個以上の制約を詰め込むと、一部の制約だけが守られなくなる挙動を私は何度も観測してきました。

ここで考え方を切り替えます。「全ての制約をワンショットで満たす」のではなく、「生成 → 自己レビュー → 修正」という工程に分割するアプローチです。これが Reflection の出発点になります。

Reflection パターン — まず最小構成で試す

仕組み

Reflection の基本形は次の3ステップです。

  1. ユーザーの要求 → モデル A が初稿を生成
  2. 初稿 → モデル A(同じモデル)が「指示違反・事実誤認・形式崩れ」を指摘するレビューを生成
  3. 初稿 + レビュー → モデル A が修正稿を生成

シンプルですが、この3ステップを通すだけで品質が体感で2割ほど上がります。重要なのは、レビューの中身を構造化出力で受け取り、修正ステップが何を直すべきかを明示的に渡すことです。曖昧なフィードバックを渡すと、修正ステップで本来直す必要のなかった部分まで書き直してしまいます。

コード — Gemini 3 Pro 単体での Reflection ループ

何をするコードか: 任意のタスクと制約リストを受け取り、初稿生成 → レビュー → 修正稿生成の3段で品質を引き上げて返します。

# requirements: google-genai>=0.5.0, pydantic>=2.0
import os
from google import genai
from google.genai import types
from pydantic import BaseModel
from typing import List
 
client = genai.Client(api_key=os.environ["YOUR_GEMINI_API_KEY"])
MODEL = "gemini-3-pro"
 
class Issue(BaseModel):
    """レビューが検出した個別の問題"""
    category: str  # 例: "指示違反" / "事実誤認" / "形式崩れ" / "禁止語混入"
    snippet: str   # 問題のある箇所(最大80文字)
    suggestion: str  # どう直すべきか
 
class Review(BaseModel):
    issues: List[Issue]
    needs_revision: bool
 
def generate_first_draft(task: str, constraints: List[str]) -> str:
    """初稿を生成する。"""
    prompt = (
        f"次の要件を満たす本文を書いてください。\n\n要件:\n{task}\n\n"
        f"制約:\n" + "\n".join(f"- {c}" for c in constraints)
    )
    resp = client.models.generate_content(
        model=MODEL,
        contents=prompt,
    )
    return resp.text
 
def review_draft(draft: str, constraints: List[str]) -> Review:
    """初稿をレビューし、構造化された Issue リストを返す。"""
    prompt = (
        "次の本文を、以下の制約に照らしてレビューしてください。\n"
        "本物の問題のみを issues に列挙し、軽微な好みの違いは無視してください。\n"
        "問題が0件なら needs_revision を false にしてください。\n\n"
        f"制約:\n" + "\n".join(f"- {c}" for c in constraints) +
        f"\n\n本文:\n{draft}"
    )
    try:
        resp = client.models.generate_content(
            model=MODEL,
            contents=prompt,
            config=types.GenerateContentConfig(
                # 決定性は response_schema と指示の明示で担保する(サンプリング設定は非推奨)
                response_mime_type="application/json",
                response_schema=Review,
            ),
        )
        return Review.model_validate_json(resp.text)
    except Exception as e:
        # JSON パース失敗時は「修正不要」として安全側に倒す
        print(f"[review_draft] fallback: {e}")
        return Review(issues=[], needs_revision=False)
 
def revise_draft(draft: str, review: Review) -> str:
    """レビュー結果を踏まえて修正稿を生成する。"""
    issues_text = "\n".join(
        f"- [{i.category}] {i.snippet} → {i.suggestion}" for i in review.issues
    )
    prompt = (
        "次の本文の、指摘されている箇所のみを最小限修正してください。\n"
        "指摘されていない箇所は変更しないでください。\n\n"
        f"修正点:\n{issues_text}\n\n元の本文:\n{draft}"
    )
    resp = client.models.generate_content(
        model=MODEL,
        contents=prompt,
    )
    return resp.text
 
def reflect_once(task: str, constraints: List[str]) -> str:
    """1回の Reflection ループを実行して最終本文を返す。"""
    draft = generate_first_draft(task, constraints)
    review = review_draft(draft, constraints)
    if not review.needs_revision:
        return draft
    return revise_draft(draft, review)
 
# 期待出力: 初稿よりも制約をより厳密に守った本文が返る
if __name__ == "__main__":
    final = reflect_once(
        task="新サービスの招待メール本文を200文字以内で書いてください。",
        constraints=[
            "200文字以内に厳密に収める",
            "宛先名は廣川さま とする",
            "競合の Acme Corp という単語を絶対に書かない",
            "敬体で統一する",
        ],
    )
    print(final)

なぜこう書くか: レビューを Pydantic で受け取り、修正ステップに渡す指示を「issues に列挙された問題だけ直してください」と明示的に絞っています。これを「全体的に直してください」と曖昧にすると、修正ステップが本来直す必要のなかった文章まで書き換える「過剰修正」が頻発します。曖昧さを許さない構造化が Reflection の安全装置になります。

✦

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

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦ワンショット推論で品質が頭打ちになっていた人が、Reflection ループと Critic-Refiner の使い分けを今日手に入れられる
✦Gemini 3 Pro と 3.5 Flash-Lite を組み合わせて、品質を上げつつコストを 1.5〜2 倍以内に抑える設計と監視メトリクスを習得できる
✦自己批判ループの暴走(無限ループ・過剰修正・Critic 偏向)を防ぐガード設計と、本番で効果が落ちた兆候を検知する運用ノウハウを身につけられる
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

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

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

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

関連記事

⬡ 高度な活用2026-04-27
Gemini Computer Use の自己修復アーキテクチャ — 失敗するブラウザ自動化を本番で安定稼働させる設計パターン
Gemini Computer Use のブラウザ自動化を本番で運用すると、要素消失・モーダル割り込み・ネットワーク遅延で頻繁に失敗します。失敗を「自己修復」させる回復戦略を、検出・分類・リトライ・人間介入のレイヤーに分けて、Pythonの動くコードで設計します。
⬡ 高度な活用2026-04-24
Gemini API のシャドウトラフィックで新モデル移行を安全に進める — 出力差分を本番で測る実装パターン
Gemini のモデル移行を「デプロイしてみないと分からない」から卒業するためのシャドウトラフィック設計。本番入力をコピーして新モデルに流し、出力差分を定量評価してから段階的にカットオーバーする実装パターンを、Python と Cloud Tasks のコード付きで解説します。
◈ API / SDK2026-05-11
Gemini 3 Pro × Firebase Cloud Messaging で個人アプリのプッシュ通知をパーソナライズ配信する本番運用ガイド
個人開発のアプリでプッシュ通知の開封率が頭打ちになっている方へ。Gemini 3 Pro でユーザーの最終操作・課金状態・好みに応じた文面を生成し、Firebase Cloud Messaging で配信する本番設計を、実装コード・コスト試算・落とし穴まで含めて整理しました。