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日に停止される予定です
記事一覧/API / SDK
API / SDK/2026-05-19中級

Gemini API の seed を指定しても出力が毎回変わる原因と対処

Gemini API の generationConfig に seed を指定したのに、同じプロンプトで毎回異なる結果が返ってくる現象の原因と、現実的な対処方針を整理しました。

Gemini API191generationConfigseed2再現性2トラブルシューティング30

2014年から個人開発で運営している壁紙アプリでは、Gemini 2.5 Flash に画像と短いプロンプトを渡して自動的にカテゴリラベルを付けるパイプラインを使っています。新しい素材を投入するたびにバッチ処理で分類し直すのですが、同じ画像と同じプロンプトを渡し直しても、たまにラベルが揺れる現象に長らく悩まされていました。App Store のレビューで「カテゴリが昨日と違う気がする」と書かれてしまうのを避けたいので、回帰テストを書きたい。そこで generationConfig.seed を固定したのですが、それでもラベルが安定しません。同じ問題に当たっている方が周りに何人かいたので、原因の切り分けと、実運用で「再現性に近い状態」を確保するために私が落ち着いた構成を書き残します。

現象を最小コードで再現する

まず、何が起きているかを確認できる短いコードを置きます。Python 用 google-genai SDK 1.x 系を前提にしています。

from google import genai
from google.genai import types
 
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
 
config = types.GenerateContentConfig(
    temperature=0,
    seed=42,
    max_output_tokens=64,
)
 
for i in range(5):
    res = client.models.generate_content(
        model="gemini-2.5-flash",
        contents="日本の四季を一行で表現してください。",
        config=config,
    )
    print(i, res.text.strip())

temperature=0seed=42 を両方指定しているので、直感的には 5 回とも同じ文字列が返ってきそうですが、実際には微妙に違う表現がときどき混ざります。seed を消したときと比べると揺れ幅は小さくなりますが、ゼロにはなりません。

なぜ seed だけでは決定論にならないのか

混乱の原因は、seed の役割が「結果を完全に決定する乱数の種」ではなく、「サンプリングの乱数生成器の初期値」にすぎないところにあります。サンプリング以外の経路で揺らぎが入る限り、出力は完全には固定されません。

実運用で実際に効いてくる揺らぎの源は、主に三つあります。

第一に、モデル側のバージョンが裏で更新されることです。gemini-2.5-flash のようなエイリアスは内部的に最新の安定ビルドにルーティングされ、明示的なリリース通知なしに振る舞いが変わる場合があります。日付付きの gemini-2.5-flash-001 のような固定タグを使わない限り、seed の効果は「同じモデル重みの上でのみ」維持されます。

第二に、サーバー側のバッチング・並列化に起因する浮動小数点演算の非結合性です。マルチ GPU 上でテンソルを足し合わせる順序がリクエストごとに異なると、最終ロジットがビット単位で同じにならず、temperature=0 相当の argmax でも稀にトークンが変わります。これは Gemini に限らず、現代の大規模推論バックエンド全般に共通する問題です。

第三に、temperature を 0 にしても、サーバー側で top_ptop_k のような他のサンプリング設定がデフォルト値で残っている場合があります。thinking を伴うモデルでは、内部的な思考ステップの長さによって最終応答が分岐することもあり、seed だけでは制御しきれません。

私の壁紙アプリのパイプラインでは、500 枚程度の検証セットに対して同じ設定で 3 周分類を回してみたところ、seed 未指定では 4〜6 パーセントのラベルが揺れていたのに対し、seed=42 を指定すると 1〜2 パーセント程度まで下がりました。完全に止まったわけではありませんが、効いていないわけでもない、という肌感覚は数字とよく一致します。

まず確認する三つの設定

実際に「seed が効いていない」と感じたとき、私は次の三点を必ず確認するようにしました。

config = types.GenerateContentConfig(
    # 1. モデルは日付付きの固定タグにする
    # (Vertex AI の場合は "gemini-2.5-flash-001" 等)
    temperature=0,
    top_p=1,
    top_k=1,
    seed=42,
    max_output_tokens=64,
    # 2. 思考を必要としないタスクなら thinking_budget=0 にする
    thinking_config=types.ThinkingConfig(thinking_budget=0),
)

ポイントは、temperature=0 だけに頼らず、top_k=1 を併用してサンプリング空間そのものを 1 トークンに絞ること、そして思考が結果を変える余地のあるモデルでは thinking_budget=0 を明示することです。これだけでも、私の壁紙分類パイプラインでの揺らぎは体感で 1〜2 割程度まで下がりました。

それでも完全にゼロにはなりません。サーバー側の並列化由来の浮動小数点の揺らぎは、クライアント側からは制御できないからです。

「ほぼ決定論」を運用で確保するパターン

完璧な再現性が API レベルで得られない以上、設計レベルで「揺らいでも壊れない」形に逃がすのが現実的です。私のパイプラインで採用している構成は次の三層です。

1. 入力ハッシュ + レスポンスキャッシュ

同じ入力に対する応答は、最初の一回だけ Gemini に投げ、結果を (モデル, プロンプトハッシュ, パラメータハッシュ) をキーにして KV または SQLite に保存しています。これで「同じ入力で違う結果が返る」現象自体が二度目以降は起きません。

import hashlib
import json
 
def cache_key(model: str, prompt: str, config: dict) -> str:
    payload = json.dumps({"m": model, "p": prompt, "c": config}, sort_keys=True, ensure_ascii=False)
    return hashlib.sha256(payload.encode("utf-8")).hexdigest()

開発者によっては「キャッシュは決定論ではない」と感じるかもしれませんが、本番の挙動を一意に固定する手段としてはもっとも堅牢でした。

2. 構造化出力で許容範囲を縮める

response_mime_type="application/json"response_schema を併用して、出力空間そのものを狭めるのも効果が大きいです。文字列の言い回しの揺らぎは enum や bool のフィールドに変換することで吸収できます。

config = types.GenerateContentConfig(
    temperature=0,
    top_k=1,
    seed=42,
    response_mime_type="application/json",
    response_schema={
        "type": "object",
        "properties": {
            "category": {
                "type": "string",
                "enum": ["nature", "abstract", "geometric", "cute", "minimal"],
            },
            "is_dark_theme": {"type": "boolean"},
        },
        "required": ["category", "is_dark_theme"],
    },
)

私の壁紙分類では、自由記述から enum に切り替えただけで、回帰テストの不安定率が大きく下がりました。

3. 数回呼んで多数決を取る

どうしても揺らぎが残るユースケースでは、3 回呼んで多数決、あるいは整合性が取れたものだけ採用する、という後段ロジックを入れています。コストは増えますが、gemini-2.5-flash クラスのモデルなら 1 件あたりの差額は無視できる水準ですし、誤分類で別のラベルに飛んでしまったときの修正コストよりずっと小さくなります。

厳密な再現性が必須な場面ではどうするか

法的な監査ログや、A/B テストの厳密な対照群のように「完全に同じ出力」が必要な場面では、API 呼び出し時点の応答そのものをアーティファクトとして保存し、再現が必要なときはモデルではなく保存されたレスポンスを参照する設計に倒すべきだと考えています。Gemini API の seed は「同じハードウェア、同じバッチ、同じビルド」での再現を補助するための機能であって、長期にわたる厳密な再現を保証するものではない、と捉えるのが安全です。

実装パイプラインを設計するときに「seed があるからテストは緑になるはず」と前提を置くと、半年後にモデルが更新されたタイミングでテストが赤くなり、原因切り分けにかなりの時間を持っていかれます。私自身、回帰テストを「期待文字列の完全一致」から「JSON スキーマの構造一致+カテゴリ一致」に書き換えた経験があり、設計を変えたほうが結局は楽でした。

次のアクション

もし今 seed を真面目に効かせたい場面が手元にあれば、まずモデル名を日付付きタグに固定し、top_k=1thinking_budget=0 を併用したうえで、それでも残る揺らぎはキャッシュと構造化出力で吸収する、という順番で試してみてください。私の壁紙アプリでは、この三段構えに切り替えてから、回帰テストが赤くなる頻度が体感で月に数回から年に数回に落ち着きました。同じ課題に取り組んでいる方の参考になれば幸いです。

シェア

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

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

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

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

関連記事

API / SDK2026-06-22
Gemini API × Google Cloud 本番エラーを層で切り分ける診断手順
Gemini APIをGoogle Cloud本番環境で運用する際のエラーを体系的に診断。IAM権限・Vertex AI vs AI Studio・VPC・クォータ管理・サービスアカウント設定まで、実装コード付きで完全解説します。
API / SDK2026-06-21
Gemini API モデル非推奨・移行エラーの対処法
Gemini API でモデルが非推奨になった時の移行手順と、移行時に発生するエラーの対処法を詳しく解説します。
API / SDK2026-06-03
Gemini Live API の応答音声が速回しに聞こえる — サンプルレート取り違えの直し方
Gemini Live API の応答音声が甲高く速回しに聞こえる、あるいはノイズ混じりになる症状は、ほとんどが 24kHz の出力を別のサンプルレートで再生していることが原因です。ブラウザと iOS の両方で、取り違えを直す具体的なコードを記録します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →