GEMINI LABEN
MODEL — Gemini 3.5 FlashがGA(正式版)となり、gemini-flash-latestの実体になりましたAGENT — Managed AgentsがGemini APIで公開プレビュー入り。分離されたGoogleホストのLinuxサンドボックスで自律エージェントを動かせますSEARCH — File Searchがマルチモーダル検索に対応し、gemini-embedding-2で画像も直接埋め込み・検索できますWEBHOOK — Batch APIや長時間処理向けにイベント駆動のWebhookが追加され、ポーリングを置き換えられますEMBED — gemini-embedding-2がGAとなり、埋め込みの本番利用が安定しましたDEPRECATION — 一部の画像生成モデルが8月17日に提供終了となるため、移行の準備が必要ですMODEL — Gemini 3.5 FlashがGA(正式版)となり、gemini-flash-latestの実体になりましたAGENT — Managed AgentsがGemini APIで公開プレビュー入り。分離されたGoogleホストのLinuxサンドボックスで自律エージェントを動かせますSEARCH — File Searchがマルチモーダル検索に対応し、gemini-embedding-2で画像も直接埋め込み・検索できますWEBHOOK — Batch APIや長時間処理向けにイベント駆動のWebhookが追加され、ポーリングを置き換えられますEMBED — gemini-embedding-2がGAとなり、埋め込みの本番利用が安定しましたDEPRECATION — 一部の画像生成モデルが8月17日に提供終了となるため、移行の準備が必要です
記事一覧/API / SDK
API / SDK/2026-07-04上級

Gemini API の英語出力に日本語が『たまに』混ざるとき — 混入率を計測して段階的に締める運用メモ

英語出力を指示したGemini APIが、100回に数回だけ日本語を混ぜてくる——この『たまに』を止められない本当の理由と、混入率をSLOとして計測し、段階的リカバリで本番品質まで締める運用パターンを実装コード付きで整理します。

gemini-api264python96multilingual4observability11production101

プレミアム記事

英語サマリーを返すだけの単純な処理を書いたつもりが、100 本流すと 3 本ほど、末尾の一文だけ日本語が顔を出す。ローカルで 20 回試したときは一度も再現せず、本番で数日回してから読者の指摘で気づく——個人開発で多言語のコンテンツ生成を Gemini API に任せていて、私自身が一番手を焼いたのはこの「たまに混ざる」でした。

厄介なのは、これがバグらしいバグに見えないことです。例外は飛ばず、JSON も壊れず、大半の出力は完璧な英語。だからこそ、テストでは捕まらず、監視にも引っかからないまま本番をすり抜けます。ここでは「英語で出力させても日本語が混ざる」現象を、止める前にまず計測するという順番で扱います。混入を連続量として観測できるようにしてから、System Instructions・Few-shot・スキーマ検証・段階的リカバリを、それぞれの効き目を測りながら重ねていきます。

なぜ「たまに」なのか — 二値ではなく確率で起きている

英語を指示しても日本語が混ざる直接の原因は、Gemini が大量の多言語コーパスで学習されており、長い日本語入力に注意(attention)が強く引かれることにあります。プロンプト末尾に短く Answer in English と添えても、入力本文が長いほど指示の相対的な強度は下がります。加えて、固有名詞や引用のように「そのまま保持したほうが正確だ」とモデルが判断した箇所は、指示を強めない限り原語で残ります。

ここで見落としやすいのが、この現象が決定論的ではないという点です。同じ入力でも、温度やサンプリングの揺らぎによって、混ざる回もあれば混ざらない回もあります。つまり本質は「混入するか否か」という二値ではなく、「1,000 出力あたり何回混ざるか」という確率です。私の翻訳パイプラインの実測では、入力が 2,000 トークンを超えるあたりから Gemini 2.0 Flash で混入が目立ち始め、2.5 Pro でも 3.1 Pro でも完全にゼロにはなりませんでした。「モデルを上げれば直る」という発想を捨てるべき理由がここにあります。相手が確率なら、対策も「計測して閾値まで下げる」という形にせざるを得ません。

まず混入を計測する — 二値の検出器と混入率

対策を積む前に、出力を数えられる状態にします。ひらがな・カタカナ・漢字の Unicode 範囲を検出する軽量な関数を用意し、混入した「文字数の割合」まで返すようにしておくと、後で閾値を引けます。

import re
from dataclasses import dataclass
 
JP_RANGE = re.compile(r"[぀-ヿ一-鿿]")
 
@dataclass
class LangCheck:
    contaminated: bool      # 日本語が1文字でも混入したか
    jp_chars: int           # 日本語文字数
    total_chars: int        # 全文字数
    ratio: float            # 混入率(0.0-1.0)
    sample: str             # 最初に見つかった混入箇所の周辺
 
def check_english_output(text: str) -> LangCheck:
    matches = list(JP_RANGE.finditer(text))
    total = len(text) or 1
    sample = ""
    if matches:
        i = matches[0].start()
        sample = text[max(0, i - 20): i + 20]
    return LangCheck(
        contaminated=bool(matches),
        jp_chars=len(matches),
        total_chars=total,
        ratio=len(matches) / total,
        sample=sample,
    )

ratio を持たせるのが要点です。末尾に一文だけ日本語が残る軽症と、丸ごと日本語で返ってくる重症を、同じ「混入」で括ってしまうと後段の判断を誤ります。sample に混入箇所の周辺を残しておくと、ログを見ただけで「固有名詞が残っただけか、指示自体が無視されたのか」を切り分けられます。

そのうえで、本番の各呼び出しにこの検査を通し、混入率を時系列で残します。私は 1 リクエストごとに 1 行のログを出し、日次で「混入したリクエストの割合(contamination rate)」を集計しています。これを一種の SLO として扱い、たとえば「0.5% 未満」を維持目標に置くと、対策の効果を体感ではなく数字で語れるようになります。

import json, time
 
def log_lang_metric(request_id: str, model: str, in_tokens: int, chk: LangCheck):
    print(json.dumps({
        "ts": time.time(),
        "request_id": request_id,
        "model": model,
        "in_tokens": in_tokens,
        "contaminated": chk.contaminated,
        "jp_ratio": round(chk.ratio, 4),
        "sample": chk.sample,
    }, ensure_ascii=False))

in_tokens を必ず一緒に残すのがコツです。後で集計すると、混入は入力長と強く相関しているのが見えてきます。相関が見えれば、「長い入力だけ対策を厚くする」という費用対効果の高い打ち手に進めます。

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

この記事の続きを読む

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

この記事で得られること
出力言語の混入を『0か1か』ではなく混入率という連続量として計測する検出器とログ設計
System Instructions・Few-shot・response_schema それぞれが『どの条件で効いてどこで破れるか』の実測比較
盲目的な再試行ではなく、違反箇所を引用して締める段階的リカバリの実装と人手エスカレーションの線引き
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

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

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

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

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

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

関連記事

API / SDK2026-04-23
Gemini API × Langfuse — LLM オブザーバビリティの本番実装ガイド
Gemini API を本番運用するチーム向けに、Langfuse を使った LLM オブザーバビリティの実装を体系的に解説します。トレース設計、コスト可視化、プロダクショントレースでの LLM-as-Judge 評価、PII マスキング、サンプリングまで動作コード付きで網羅します。
API / SDK2026-03-30
Gemini API 本番環境のオブザーバビリティ — ログ・監視・コスト追跡の実践パターン
Gemini APIを本番運用する際に不可欠なオブザーバビリティ基盤を構築する方法を解説。構造化ログ、トークン使用量の追跡、レイテンシ監視、コスト最適化ダッシュボードまで、実装コード付きで網羅します。
API / SDK2026-07-02
Gemma 4 ローカル推論と Gemini API の使い分けで月額¥32,000を¥9,000台にした — ハイブリッドルーターの本番設計
月額¥32,000のGemini APIコストを¥9,000台まで下げたハイブリッド推論構成の記録です。ルーティング設計・Python実装・本番の落とし穴に加え、2026年7月のGemma 4 API提供開始を踏まえた構成見直しの指針もまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →