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-04-30中級

Gemini API の maxOutputTokens と stopSequences で出力を精密制御する

Gemini API の maxOutputTokens と stopSequences を組み合わせて、応答長を狙い通りにコントロールする方法を実装パターンとともに解説します。途中で切れる、長すぎる、JSON が壊れる、を一気に解決します。

gemini-api279max-output-tokensstop-sequencespython103production105

「思っていたより長い応答が返ってきて Cloud Run の上限を超えた」「JSON が途中で切れて壊れた」「箇条書きで止めたかったのに余計な解説まで生成された」— Gemini API を本番で動かしていると、出力長まわりの細かい問題が地味に効いてきます。私自身、最初にぶつかったのは「同じプロンプトでも応答長が日によって倍くらい違う」という現象でした。原因は思考トークン(thinking)と出力トークンを混同していたことだったのですが、当時は気付くまで半日溶かしてしまいました。

ここでは maxOutputTokensstopSequences という二つのパラメータを使い分けて、出力長を精密にコントロールする方法を整理します。両方とも公式ドキュメントには簡潔な説明しかありませんが、実際に組み合わせると挙動の理解が必要になる場面が多いので、本番で詰まりやすいポイントまで含めて解説していきます。

maxOutputTokens は「最大値」であって「希望値」ではありません

まず誤解しやすい点ですが、maxOutputTokens応答に含まれる出力トークン数の上限を指定するものであり、「だいたいこれくらいの長さで返してほしい」という希望ではありません。Gemini はこの上限に到達した時点で生成を強制終了するため、運悪く文末記号の前で切れると応答が中途半端になります。

# Python SDK 例
from google import genai
from google.genai import types
 
client = genai.Client()
 
response = client.models.generate_content(
    model="gemini-2.5-pro",
    contents="次の議事録を300文字程度で要約してください。\n---\n(議事録本文)",
    config=types.GenerateContentConfig(
        max_output_tokens=400,  # 出力の上限。300文字目安なら少し余裕を持たせる
        temperature=0.3,
    ),
)
print(response.text)
print("finish_reason:", response.candidates[0].finish_reason)

ここで重要なのは finish_reason を必ず確認することです。STOP であれば自然終了、MAX_TOKENS であれば上限切り捨てなので、後者なら設定値を見直します。本番運用では MAX_TOKENS の発生率をログに残して監視すると、コスト最適化と品質改善の両方に役立ちます。

「文字数」ではなく「トークン数」で考える

日本語の場合、おおむね 1 文字 = 1〜2 トークンと見ておくと感覚が合います。300 文字で要約させたいなら、max_output_tokens は 400〜500 くらいに設定するのが安全です。英語なら 1 単語が 1.3 トークン程度なので、500 ワードなら 700 程度。厳密に測るなら client.models.count_tokens() を併用してください。

# 想定プロンプトでのトークン消費を事前計測
count = client.models.count_tokens(
    model="gemini-2.5-pro",
    contents="次の議事録を300文字程度で要約してください。",
)
print(f"input_tokens: {count.total_tokens}")
# → 入力トークン数が把握できれば、合計コストの見積もりも正確になる

Gemini 2.5 / 3 系では thinking トークンが別枠です

ここが一番ハマりやすいポイントです。Gemini 2.5 Pro や Gemini 3 系では、応答前に内部で思考(thinking)トークンを消費しますが、これは maxOutputTokens含まれない枠で課金されます。つまり「出力上限を 500 にしたのに、課金トークンは 3,000 を超えていた」ということが普通に起こります。コスト感を見積もる際は thinking 側の予算も合わせて考える必要があり、詳しくは Gemini 2.5 thinking budget の最適化ガイド で解説しています。

stopSequences は「ここで終わって」と教えるためのもの

stopSequences は、生成中にこの文字列が出現したら即座に応答を終わらせる、という指示です。最大 5 つまで指定でき、配列で渡します。

response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="次の3つの単語で英作文を作ってください: cat, river, morning\n出力は1文だけにしてください。",
    config=types.GenerateContentConfig(
        stop_sequences=["\n\n", "###", "解説:"],
        max_output_tokens=200,
        temperature=0.7,
    ),
)
print(response.text)

この例では「2 行空き」「###」「解説:」のいずれかが現れた瞬間に止まります。Gemini は親切心から「以下、解説します」と続けがちなのですが、それを stopSequences で抑え込めるのです。

出力に含まれない、という重要な仕様

stopSequences に指定した文字列自体は応答テキストに含まれません。たとえば stop_sequences=["</answer>"] と設定して <answer>...</answer> のような構造を生成させた場合、終端タグは応答に含まれない点に注意してください。後段でパースする際に「終端タグがあるはず」と仮定したコードを書くとバグります。私は実際にこれで後処理が壊れたことがあります。

JSON モードと組み合わせるときの注意

response_mime_type="application/json" で構造化出力を取らせる場合、stopSequences} のような JSON 構文の一部を入れてしまうと中身が空のオブジェクトで止まります。構造化出力を扱うなら stopSequences ではなく Pydantic スキーマの responseSchema を使うほうが安全です。

実践パターン:両者を組み合わせて出力を狙い通りに整える

ここからが本題です。実運用では両者を組み合わせて、安全弁と意図表現の二重構成にするのが効果的です。

パターン 1: 短文要約をきっちり止める

def summarize_strict(text: str, max_chars: int = 200) -> dict:
    """指定文字数±20%で要約を返す。超過時は finish_reason で警告を返す。"""
    response = client.models.generate_content(
        model="gemini-2.5-flash",
        contents=f"次の文章を{max_chars}文字以内で要約してください。要約のみを返し、前置きは不要です。\n---\n{text}",
        config=types.GenerateContentConfig(
            max_output_tokens=int(max_chars * 1.5),  # 安全マージン
            stop_sequences=["\n\n要約", "\n\n以上", "###"],
            temperature=0.2,
        ),
    )
    finish = response.candidates[0].finish_reason.name
    return {
        "text": response.text.strip(),
        "truncated": finish == "MAX_TOKENS",
        "finish_reason": finish,
    }
 
result = summarize_strict("(長い記事本文)", max_chars=200)
if result["truncated"]:
    print("⚠️ 上限到達。プロンプトの指示文字数を見直してください。")
print(result["text"])

パターン 2: 構造化された短い回答を抽出する

「カテゴリ: ◯◯」のような決まった形式の出力を取るときは、出力末尾を stopSequences で切るとパースが楽になります。

PROMPT = """次の問い合わせを以下の形式で分類してください。
形式:
カテゴリ: <技術|請求|営業|その他>
理由: <30文字以内>
---
問い合わせ: {query}"""
 
def classify(query: str) -> dict:
    response = client.models.generate_content(
        model="gemini-2.5-flash",
        contents=PROMPT.format(query=query),
        config=types.GenerateContentConfig(
            max_output_tokens=80,
            stop_sequences=["\n---", "\n\n"],
            temperature=0.0,
        ),
    )
    out = response.text
    cat = out.split("カテゴリ:")[-1].split("\n")[0].strip()
    reason = out.split("理由:")[-1].strip() if "理由:" in out else ""
    return {"category": cat, "reason": reason}
 
print(classify("ログインできません"))
# → {'category': '技術', 'reason': 'ログイン関連の不具合'}

このように stopSequences をパース起点として活用すると、後段の処理が安定します。期待通りに止まらないケースでは、まずプロンプトで「フォーマット以外の出力をしないでください」と明示し、それでも止まらない場合に stopSequences を追加するのが順序として安全です。

パターン 3: チームで共有する SDK ラッパーには防御的なデフォルトを置く

SDK の薄いラッパーをチーム内向けに作る場合、最悪のケースを書く呼び出し元が暴走しないように防御的なデフォルトを設定しておきます。

DEFAULTS = {
    "max_output_tokens": 1024,
    "temperature": 0.4,
    "stop_sequences": [],
}
 
def call_gemini(prompt: str, **overrides) -> dict:
    cfg = {**DEFAULTS, **overrides}
    response = client.models.generate_content(
        model=cfg.pop("model", "gemini-2.5-flash"),
        contents=prompt,
        config=types.GenerateContentConfig(**cfg),
    )
    return {
        "text": response.text,
        "finish_reason": response.candidates[0].finish_reason.name,
        "input_tokens": response.usage_metadata.prompt_token_count,
        "output_tokens": response.usage_metadata.candidates_token_count,
        "thinking_tokens": getattr(response.usage_metadata, "thoughts_token_count", 0),
    }

usage_metadata をテキストと一緒に返すことで、呼び出し元が個別に計測コードを足さなくてもコスト追跡ができます。Gemini 2.5/3 系の thinking トークン数も忘れずに含めておくと、後で分析するときに迷子になりません。

ハマりやすい落とし穴

実装中によくある失敗を 3 つだけ挙げておきます。

  • ストリーミングと併用したときの体感差: ストリーミングでは stopSequences ヒット時に即座にストリームが終了するため、UI 側で「途中で文末が来た」演出が必要になります。詳しい制御は ストリーミング応答のチャンク制御 を参照してください。
  • 長過ぎる入力で出力枠が圧迫される: モデルの総コンテキスト上限は入力+出力+thinking の合計です。100 万トークン入力したら出力余地は実質ゼロになります。長文要約では入力を分割するか、Flash 系で先行要約してから Pro に渡す二段構えが有効です。
  • finish_reason の取りこぼし: 失敗時に MAX_TOKENS を握りつぶしてしまうと「なぜか応答が短い日がある」というバグになります。応答が短く感じたらまず finish_reason を確認するのが鉄則です。途中切れの根本対策は 応答が途中で切れる問題のトラブルシューティング にまとめてあります。

全体を振り返って — 次にやってみてほしいこと

maxOutputTokens は安全弁、stopSequences は意図表現、と役割を分けて考えると整理しやすいです。本日の記事を試すなら、まず手元のもっとも使用頻度が高い API 呼び出しに finish_reason のロギングを足してみてください。1 週間ほど運用ログを眺めるだけで、MAX_TOKENS で切れているリクエストの割合が見えます。そこを起点に上限値を調整していくと、コストと品質のバランスが一気に取りやすくなります。

LLM API を本番に載せ続ける開発者として、本書の「指示の粒度」と「出力の予測可能性」の章は何度か読み返しています。

シェア

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

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

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

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

関連記事

API / SDK2026-07-04
Gemini API の英語出力に日本語が『たまに』混ざるとき — 混入率を計測して段階的に締める運用メモ
英語出力を指示したGemini APIが、100回に数回だけ日本語を混ぜてくる——この『たまに』を止められない本当の理由と、混入率をSLOとして計測し、段階的リカバリで本番品質まで締める運用パターンを実装コード付きで整理します。
API / SDK2026-07-02
Gemma 4 ローカル推論と Gemini API の使い分けで月額¥32,000を¥9,000台にした — ハイブリッドルーターの本番設計
月額¥32,000のGemini APIコストを¥9,000台まで下げたハイブリッド推論構成の記録です。ルーティング設計・Python実装・本番の落とし穴に加え、2026年7月のGemma 4 API提供開始を踏まえた構成見直しの指針もまとめました。
API / SDK2026-06-25
プレビュー画像モデル停止の朝に学んだこと — Gemini 画像モデル GA 移行と廃止に強いパイプライン設計
gemini-3.1-flash-image-preview と gemini-3-pro-image-preview の停止を機に、GA 版への移行手順と、廃止日に振り回されない画像生成パイプラインの設計をコード付きで整理します。動画から画像を生成するサムネイル自動化も扱います。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →