GEMINI LABEN
ROBOTICS — 8月31日に停止した ER 1.6 preview には後継があります。Gemini Robotics ER 2 が公開プレビュー中で、通常版とストリーミング版の2種類が提供されていますVIDEO — ER 2 の成功・失敗判定は静止画ではなく生の映像フィード上で動きます。こぼれ・滑り・位置ずれのような、実行の途中で起きる失敗を捉えられる設計ですDEADLINE — 次の期限は9月30日、gemini-omni-flash-preview の廃止です。移行先は8月27日に GA になった gemini-omni-1.1-flash で、残り4週間を切りましたAPIKEY — 残りの標準 API キーは、制限付きのものも含めて9月中に全面停止します。移行先は Google Cloud サービスアカウントに紐付く auth キー形式ですPRICE — Gemini 3.7 Flash の導入価格 $0.75/$3.75 per 1M は12月31日までです。2027年1月1日から $1.50/$7.50 になるため、年を跨ぐ見積もりは2本立てが要りますAUDIO — Gemini 3.5 Transcribe は85言語以上の言語検出、話者ダイアライゼーション、単語単位タイムスタンプ、最大1,000語のカスタム語彙バイアスに対応していますROBOTICS — 8月31日に停止した ER 1.6 preview には後継があります。Gemini Robotics ER 2 が公開プレビュー中で、通常版とストリーミング版の2種類が提供されていますVIDEO — ER 2 の成功・失敗判定は静止画ではなく生の映像フィード上で動きます。こぼれ・滑り・位置ずれのような、実行の途中で起きる失敗を捉えられる設計ですDEADLINE — 次の期限は9月30日、gemini-omni-flash-preview の廃止です。移行先は8月27日に GA になった gemini-omni-1.1-flash で、残り4週間を切りましたAPIKEY — 残りの標準 API キーは、制限付きのものも含めて9月中に全面停止します。移行先は Google Cloud サービスアカウントに紐付く auth キー形式ですPRICE — Gemini 3.7 Flash の導入価格 $0.75/$3.75 per 1M は12月31日までです。2027年1月1日から $1.50/$7.50 になるため、年を跨ぐ見積もりは2本立てが要りますAUDIO — Gemini 3.5 Transcribe は85言語以上の言語検出、話者ダイアライゼーション、単語単位タイムスタンプ、最大1,000語のカスタム語彙バイアスに対応しています
記事一覧/API / SDK
API / SDK/2026-04-26中級

Gemini API の logprobs で分類タスクの信頼度を測る — 動くコードと判断軸

Gemini API の logprobs で分類タスクの信頼度スコアを取り出し、閾値以下は人間レビューに回す設計パターンを Python の動くコードで解説します。レスポンス構造の読み解き、100件でのしきい値キャリブレーション、logprobs が頼れない場面も扱います。

gemini-api285logprobsclassification2信頼度スコアPython44プロンプトエンジニアリング10

Gemini にメール本文を「問い合わせ/苦情/その他」に振り分けてもらう、というシンプルな分類タスクを想像してみてください。返ってくるのは1語のラベルだけ。表面的には正しく見えても、モデル内部での確信度がどれくらいだったのかは分かりません。私が個人開発でこの種の分類を本番に組み込んだとき、いちばんのストレスはこの「自信のなさが見えない」ことでした。

responseLogprobs を有効化すると、その自信度が数字で手元に来ます。ここではGemini API で logprobs を取り出す具体的な手順と、得られた値を「人間レビューに回すべきか/自動処理してよいか」の判断にどう使うかを、動くコードとともに解説します。

logprobs が解決してくれる困りごと

Gemini が「問い合わせ」と返してきたとき、それは確率 0.99 で選ばれたのか、それとも 0.42 で苦情と僅差だったのか。前者と後者では、後段の処理を信じてよいかが大きく変わります。

logprobs は、モデルが各トークンを生成したときの対数確率(log probability)を返してくれる機能です。これを使えば次のような判断ができるようになります。

  • 信頼度が低い分類だけを人間のレビュー対象に回す(Active Learning 的な運用)
  • 同じ入力に対するプロンプトAとBを、出力ラベルの確信度で比較する
  • A/Bテスト中の「微妙に間違っている」ケースを定量的に検出する
  • LLM の推論コストを抑えながら、品質ゲートを通せた分だけ自動化する

実装上の負担は驚くほど小さいわりに、後段の運用設計に与える効果が大きい — これが logprobs を使い始めて最初に感じた印象です。

Gemini API で logprobs を有効にする

Python SDK(google-genai)での最小構成はこちらです。response_logprobs=True で対数確率の返却を有効化し、logprobs=N で「各位置で上位 N 個まで返す」を指定します(1〜5 の範囲)。

# pip install google-genai
from google import genai
from google.genai import types
import os
 
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
 
config = types.GenerateContentConfig(
    response_logprobs=True,    # ← logprobs の返却を有効化
    logprobs=3,                # ← 上位3候補までを返す
    max_output_tokens=4,       # 1〜2トークンで済む分類なので短く絞る
    temperature=0,             # 2.x 系では決定論寄りに。3.x 系では無視されます(後述)
)
 
resp = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=(
        "次のメールを {問い合わせ, 苦情, その他} のいずれか1語に分類してください。\n"
        "メール本文: 商品が届きません。注文番号は12345です。\n"
        "回答(1語のみ):"
    ),
    config=config,
)
 
print(resp.text)
print(resp.candidates[0].logprobs_result)

ポイントは3つあります。第1に temperature=0 にすること。確信度を「モデルがどれだけそのトークンを支持したか」として比較したいので、ランダム性は外しておきます。ただしこの指定が効くのは 2.x 系までです。3.x 系での扱いは後半で扱います。第2に max_output_tokens を絞ること。分類なら1〜2トークンで済むケースが多く、余計なトークンが返ってくるとノイズが増えます。第3に logprobs=3 ぐらいで十分なこと。10件返しても実務で使うのは上位2〜3件です。

レスポンスの構造を読み解く

logprobs_result には chosen_candidates(実際に採用されたトークン列)と top_candidates(各位置での上位候補)が入ります。Python から扱うときは、最初の意味のあるトークンだけを取り出すのが基本です。

import math
 
def label_confidence(resp):
    """採用ラベルの確率(0〜1)を返す。"""
    chosen = resp.candidates[0].logprobs_result.chosen_candidates
    if not chosen:
        return None, 0.0
    first = chosen[0]                  # 1トークン目を分類ラベルとみなす
    prob = math.exp(first.log_probability)
    return first.token, prob
 
label, p = label_confidence(resp)
print(f"label={label!r}  confidence={p:.3f}")
# 例: label='問い合わせ'  confidence=0.987

log_probability は自然対数なので、math.exp() で 0〜1 の確率に戻して使います。0.99 ならほぼ確信、0.5 を切るあたりから「他の候補と僅差」の領域です。

実践: 信頼度しきい値で「自動 / 人間レビュー」を分ける

これが個人的にいちばん効いた使い方です。閾値を1つ決めるだけで、自動処理できる分量が変わってきます。

def classify_with_gate(text: str, threshold: float = 0.85):
    """信頼度が閾値以上なら自動採用、未満ならレビューに回す。"""
    resp = client.models.generate_content(
        model="gemini-2.5-flash",
        contents=(
            "次のメールを {問い合わせ, 苦情, その他} のいずれか1語に分類してください。\n"
            f"メール本文: {text}\n回答(1語のみ):"
        ),
        config=config,
    )
    label, prob = label_confidence(resp)
 
    if label is None:
        return {"status": "ERROR", "reason": "empty response"}
 
    if prob >= threshold:
        return {"status": "AUTO",   "label": label, "confidence": prob}
    else:
        # 上位候補を一緒に渡しておくとレビュー画面が作りやすい
        top = resp.candidates[0].logprobs_result.top_candidates
        alternatives = [
            (c.token, math.exp(c.log_probability))
            for c in (top[0].candidates if top else [])
        ]
        return {
            "status": "REVIEW",
            "label": label,
            "confidence": prob,
            "alternatives": alternatives,
        }

実運用では threshold を最初から固定せず、過去 1〜2 週間の分類ログを元にキャリブレーションするのがおすすめです。「閾値 0.85 で自動採用率 78%、人間レビューでの修正率 4%」のように見える化できると、閾値の上げ下げが感覚論ではなく数値判断になります。

関連する設計のパターンは Gemini API の Pydantic で型安全に構造化出力を扱う や 本番で使う Gemini API のレートリミット設計 でも触れています。logprobs と組み合わせると、品質ゲートを通った分だけ自動化、という設計が自然に組み立てられます。

100件で閾値をキャリブレーションする

「閾値 0.85 にすればいいですか?」と聞かれることがありますが、答えはドメインによって違います。私が実際にやっているのは、過去ログから 100 件ぶんを抜き出して以下のようなテーブルを作ることです。

  • 正解ラベル: 過去に人間が確認した結果
  • モデルラベル: classify_with_gate の出力
  • confidence: その採用ラベルの確率

このペアを confidence 順にソートすると、「confidence 0.95 以上は誤りゼロ」「0.85〜0.94 は誤り 2%」「0.7〜0.84 は誤り 9%」のように、自分のデータでの誤り率が confidence ごとに見えてきます。許容できる誤り率(たとえば 2% 以下)に対応する confidence をそのまま閾値にすれば、感覚ではなく数値で運用が始められます。

逆にここで「どの閾値でも誤り率が高止まり」する場合、原因はだいたいプロンプトの曖昧さです。logprobs を上げる前に、まずプロンプトの定義(ラベルの境界、含めるべき例、出力形式)を見直してください。logprobs はプロンプトの足りないところを埋めてくれる魔法ではなく、ちゃんと設計されたプロンプトの上で初めて意味を持つ指標です。

落とし穴 — logprobs が当てにならない場面

logprobs は便利ですが、「いつでも信用できる確率」ではありません。私が実際にハマった3つを挙げておきます。

第1に、長文生成では役に立ちません。logprobs はトークンごとの確率なので、出力が10語以上になると「最初のトークンは自信があったけど後半は揺らいだ」といった状況を1つの数字で表現できません。logprobs を素直に使えるのは、出力が1〜数トークンに収まるタスクに限ると割り切るのが現実的です。

第2に、プロンプトが緩いと数値が貼り付きます。たとえば「カジュアルに分類してください」と書くと、モデルは余計な装飾語を生成しに行き、肝心のラベルが2トークン目以降にずれます。プロンプト末尾を 回答(1語のみ): のように強く制約しておくのが基本です。

第3に、temperature の効き方がモデル世代で分かれます。2.x 系では 0 以外にすると採用トークンが実行ごとに変わり、確率の意味が「サンプリング後の値」へずれます。閾値で運用するなら temperature=0 を置いてください。ところが 3.x 系では逆で、書いても届きません。ここは章を分けて扱います。

第4に、トークナイザの分割が直感と違うことがあります。「苦情」のような日本語ラベルは1トークンに収まらず複数のサブワードに分割される場合があり、その場合「最初の chosen トークン」はラベルの一部分でしかありません。回避策はシンプルで、ラベルがサブワードをまたぐ可能性があるなら最初の数トークンを連結して読む、もしくは出力を A/B/C のような1トークンに収まる記号に固定して凡例で対応づける、のどちらかにすると安定します。

3.x 系へ移す前に、temperature と logprobs を実測で確かめる

ここが今いちばん注意の要るところです。Gemini 3.7 Flash の移行チェックリストには、生成設定から temperaturetop_ptop_k を取り除くことが明記されています。3.6 Flash については「すでにこれらのパラメータをサポートしていない」とも書かれています(What's new in Gemini 3.7 Flash)。

厄介なのは外れ方です。Gemini 3.6 Flash のモデル解説によれば、temperature・top-K・top-P にカスタム値を設定しても、その値は無視されます。一方で frequency penalty と presence penalty は、同じ非対応でもエラーを返します。片方は音を立てて壊れ、もう片方は黙って通る、という非対称があるわけです。

この記事の閾値運用は temperature=0 を土台にしています。モデル ID を 3.x 系に差し替えたとき、リクエストは 200 で返り、(label, confidence) の CSV もこれまで通り出力されます。壊れた痕跡がどこにも残りません。私自身、設定キーが黙って無視される類の問題で半日を溶かしたことがあり、この形の非対応にはつい身構えます。だからこそ移行のタイミングで、自分の手で確かめておく価値があります。

設定3.x 系での扱い閾値運用への影響
temperature / top_p / top_k受理して無視(エラーなし)決定性の前提が黙って外れる。設定から削除する
frequency_penalty / presence_penaltyエラー移行時に必ず気づける
candidate_count3.x では非対応設定から削除する
response_logprobs / logprobsモデルによって差がある移行先ごとに実測で確認する

response_logprobs については、返る/返らないの報告がモデルごとに分かれています。仕様の記述を読んで判断するより、移行先のモデル ID へ1回投げてみるほうが早くて確実です。この記事の主題が「感覚ではなく数値で決める」ことなので、可否の判定も同じやり方で揃えます。

def probe_model(model_id: str, sample_text: str, runs: int = 8):
    """移行先モデルで logprobs が返るか / 出力が揺れるかを実測する。"""
    prompt = (
        "次のメールを {問い合わせ, 苦情, その他} のいずれか1語に分類してください。\n"
        f"メール本文: {sample_text}\n回答(1語のみ):"
    )
 
    # 1. logprobs がそもそも返ってくるか
    try:
        resp = client.models.generate_content(
            model=model_id,
            contents=prompt,
            config=types.GenerateContentConfig(
                response_logprobs=True, logprobs=3, max_output_tokens=4
            ),
        )
        has_logprobs = resp.candidates[0].logprobs_result is not None
    except Exception as e:
        return {
            "model": model_id,
            "logprobs": f"ERROR: {type(e).__name__}",
            "deterministic": None,
        }
 
    # 2. temperature=0 が届いているか(同一入力を複数回投げて出力の種類を数える)
    outputs = set()
    for _ in range(runs):
        r = client.models.generate_content(
            model=model_id,
            contents=prompt,
            config=types.GenerateContentConfig(temperature=0, max_output_tokens=4),
        )
        outputs.add((r.text or "").strip())
 
    return {
        "model": model_id,
        "logprobs": has_logprobs,
        "deterministic": len(outputs) == 1,
        "distinct_outputs": sorted(outputs),
    }

私はこの検査を、モデル ID を書き換えるコミットと同じブランチに入れるようにしています。deterministicFalse なら、temperature=0 は届いていません。ただし分類のように選択肢が少ないタスクでは、パラメータが無視されていても出力が偶然そろうことがあります。判定に使う入力は境界事例を選んでください。手元のログで confidence が 0.6〜0.8 に落ちた行が、そのまま良い検査用サンプルになります。自信のある入力で試すと、何も分からないまま合格します。

3.x 系で temperature が使えない前提に立つなら、決定性はシステム指示の側で担保することになります。出力形式とラベルの境界を言葉で書き切る、という地味な作業に戻ってくるわけですが、これは閾値がどこでも高止まりしたときの対処と同じ方向です。プロンプトの定義を締めることが、結局どちらにも効きます。

次の一歩

まずは手元の分類タスク 100 件ぶんで response_logprobs=True を回し、(label, confidence) のペアを CSV に書き出してみてください。ヒストグラムを描くと、自分のドメインで「ここから下は危ない」という閾値が驚くほどはっきり見えてきます。閾値が決まれば、後はそれを classify_with_gate のような関数に組み込むだけ。logprobs はモデルを差し替えなくても運用品質を一段引き上げられる、地味だけれど効果の大きい一手だと思っています。

ひとつだけ補足すると、confidence の絶対値はモデル間で直接比較できません。gemini-2.5-flash の 0.92 と gemini-2.5-pro の 0.92 は同じ意味ではないので、モデルを差し替えたときは同じ 100 件のセットで閾値を再キャリブレーションしてください。そして世代をまたぐ差し替えでは、その前に probe_model を通す順番になります。閾値を測り直す前に、そもそも同じ計測ができるかを見ておく、ということです。

シェア

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

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

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

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

関連記事

API / SDK2026-07-09
Gemini API のシステム指示とプロンプト設計 — 出力品質を劇的に上げる実践テクニック
Gemini API のシステム指示(system_instruction)とプロンプトエンジニアリングの実践的なテクニックを解説します。出力品質にダイレクトに効く設計パターンを、動作するコード例と共に紹介します。
API / SDK2026-06-12
Gemini の画像生成 preview モデルが 6月25日に停止します — GA 版への移行で確認したコード差分と検証手順
6月25日に停止する gemini-3.1-flash-image-preview / gemini-3-pro-image-preview から GA 版へ移行した作業記録です。モデルIDの確認手順、Python のコード差分、停止前にしかできない回帰チェック、切り替え順序まで実例で整理しました。
API / SDK2026-04-29
Gemini API で翻訳精度を最大化する temperature 設定 — 用途別ベストバリューと検証コード
Gemini API の翻訳で temperature をいくつにするか、用途別の早見表と検証コードで示します。値を決めた後に効いてくる、文字列タイプ別プロファイルのコード管理、逆翻訳ゲート、UI がはみ出さない表示幅バジェットまで実装込みでまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →