◉GEMINI LABEN
●TTS — Gemini 3.8 Flash TTS と Flash-Lite TTS が GA(9/22)。声の複製に対応するのは Flash だけで、Lite に渡すと 400 が返ります●2.5 — 2.5 系モデルのアクセスは、過去に利用実績のあるユーザーに限定されました(9/18)。廃止ではなく、新規は 3.5 Flash-Lite か 3.8 Flash へ●9/30 — gemini-omni-flash-preview の提供終了まで残り2日、10/2 には gemini-2.5-flash-image も停止。後者の実務上の差し替え先は gemini-3.1-flash-image です●AUTH — 「Workspace の Enterprise アカウントだけ Gemini CLI の認証が通らない」という報告が続いています。個人アカウントとの切り分けが焦点●NEW — 3.8 Flash-Lite TTS への置き換えで、案内音声の声を選び直した記録●429 — 新規プロジェクトが Free tier 表示なのに limit: 0 で 429 が返る。最初の1時間で確かめる点を整理しています●TTS — Gemini 3.8 Flash TTS と Flash-Lite TTS が GA(9/22)。声の複製に対応するのは Flash だけで、Lite に渡すと 400 が返ります●2.5 — 2.5 系モデルのアクセスは、過去に利用実績のあるユーザーに限定されました(9/18)。廃止ではなく、新規は 3.5 Flash-Lite か 3.8 Flash へ●9/30 — gemini-omni-flash-preview の提供終了まで残り2日、10/2 には gemini-2.5-flash-image も停止。後者の実務上の差し替え先は gemini-3.1-flash-image です●AUTH — 「Workspace の Enterprise アカウントだけ Gemini CLI の認証が通らない」という報告が続いています。個人アカウントとの切り分けが焦点●NEW — 3.8 Flash-Lite TTS への置き換えで、案内音声の声を選び直した記録●429 — 新規プロジェクトが Free tier 表示なのに limit: 0 で 429 が返る。最初の1時間で確かめる点を整理しています
記事一覧/高度な活用
⬡ 高度な活用/2026-06-14上級

Gemini の構造化出力を本番で信用するために — スキーマ設計・二重検証・抑制つきリトライの実装メモ

Gemini の構造化出力は「パースできるJSON」は保証しても「正しい値」までは保証しません。@google/genai での新しいスキーマ設計、propertyOrdering の効き目、Zod による二重検証、MAX_TOKENS 切れの扱い、抑制つきリトライの実装をまとめました。

gemini115structured-output26json-schema2zod3production105

✦ プレミアム記事

請求書の自動仕分けを動かしていたとき、月に数件だけ「合計金額が明細の足し算と合わない」レコードが混ざることに気づきました。JSON のパースは通っていますし、スキーマのバリデーションも緑です。それでも値が間違っている。

構造化出力を本番に載せると、多くの人がここでつまずきます。responseMimeType: "application/json" を付ければ確かに毎回パース可能な JSON が返ります。けれど「パースできる」ことと「業務的に正しい」ことは別の話です。この境界を最初に引いておかないと、静かに壊れたデータが下流へ流れていきます。

ここでは @google/genai の現行スキーマ設計から、二層検証、失敗の見分け方、回収の実装まで、運用で実際に効いた順に整理します。2026 年 6 月時点で既定モデルは Gemini 3.5 Flash に上がり、Structured Outputs も GA になりました。挙動が安定した今こそ、設計を固め直す良い時期だと考えています。

「構造化出力=安全」が成り立たない理由

構造化出力が保証してくれるのは、おおむね次の三つです。出力が指定した JSON 型に従うこと、required のフィールドが欠けないこと、enum で列挙した値の範囲を外れないこと。これは大きな前進で、自由形式テキストを正規表現で剥がしていた頃に比べれば段違いに堅牢です。

一方で、保証してくれないものもはっきりしています。数値が業務的に妥当か(明細合計と総額が一致するか)、日付が実在するか(2026-02-30 を弾けるか)、複数フィールド間の整合性(payment_status: paid なのに paid_date が空でないか)。これらはスキーマの外側にあります。

つまり構造化出力は「形」を保証する層であって、「意味」を保証する層ではありません。本番パイプラインでは、この二つを別々のコードとして持つのが結局いちばん壊れにくい、というのが個人開発で数か月運用して出した結論です。本番運用では、形のエラーと意味のずれを同じ対処で握りつぶさないことが効きます。

スキーマ設計 — モデルに「形」を教える

まずは現行 SDK での最小構成です。旧 @google/generative-ai から @google/genai へ移ったことで、呼び出しは ai.models.generateContent に集約され、設定は config に入ります。

// structured-review.ts
import { GoogleGenAI, Type } from "@google/genai";
 
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
 
// description はモデルへの指示として効く。型名だけでなく「何を入れるか」を書く
const reviewSchema = {
  type: Type.OBJECT,
  properties: {
    productName: { type: Type.STRING, description: "レビュー対象の製品名" },
    rating: {
      type: Type.INTEGER,
      description: "1〜5 の整数。小数や範囲外は許容しない",
    },
    pros: {
      type: Type.ARRAY,
      items: { type: Type.STRING },
      description: "良い点。本文に根拠がある項目だけ",
    },
    cons: {
      type: Type.ARRAY,
      items: { type: Type.STRING },
      description: "改善点。本文に根拠がある項目だけ",
    },
    sentiment: {
      type: Type.STRING,
      enum: ["positive", "neutral", "negative"],
      description: "全体の論調",
    },
  },
  // propertyOrdering でモデルが生成する順序を固定する
  propertyOrdering: ["productName", "rating", "pros", "cons", "sentiment"],
  required: ["productName", "rating", "sentiment"],
};
 
export async function analyzeReview(reviewText: string) {
  const res = await ai.models.generateContent({
    model: "gemini-3.5-flash",
    contents: `次のレビューを分析してください:\n\n${reviewText}`,
    config: {
      responseMimeType: "application/json",
      responseSchema: reviewSchema,
    },
  });
  return JSON.parse(res.text);
}

ここで地味に効くのが三点あります。

description は飾りではなく、実質的な指示として読まれます。「1〜5 の整数」とだけ書くより「小数や範囲外は許容しない」と添えるほうが、境界値の暴れが目に見えて減りました。型の説明ではなく、現場のルールを書く場所だと捉えると質が上がります。

propertyOrdering は見落とされがちですが、生成順を固定すると出力の安定度が上がります。モデルは前のフィールドを文脈にして次を埋めるため、たとえば rating を pros/cons より先に置くと、評点と理由がちぐはぐになりにくくなります。逆に重要な判断フィールドを末尾に置くと、手前の冗長な配列に引きずられることがあります。

required は最小限にとどめます。すべてを必須にすると、モデルは埋められない欄を無理やり捏造します。「無ければ省略してよい」とスキーマで許すほうが、結果的にハルシネーションが減ります。

✦

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

この記事の続きを読む

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

この記事で得られること
✦responseSchema が保証する範囲と、ビジネス整合性検証を分離する二層設計の具体コード
✦propertyOrdering・enum・description を使ってモデルの出力品質を上げるスキーマの書き方
✦MAX_TOKENS による途中切れ・空応答を finish_reason で見分け、抑制つきリトライで回収する実装
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

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

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

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

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

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

関連記事

⬡ 高度な活用2026-08-25
AI 検索が広げたクエリを分母から外して、実質 CTR を出し直します
運営サイトの検索データで、表示回数上位5件のクリックが全て0でした。うち4件は人間が打つ語ではありません。分母を作り直す手順と、Gemini に判定を任せる境界の引き方をまとめます。
⬡ 高度な活用2026-08-24
日本の版画か中国の版画かを Gemini に当てさせない来歴ゲート
浮世絵の壁紙アプリに素材を入れる前の来歴チェックを、モデルに国を当てさせる形から、紙に写っている痕跡だけを列挙させる形へ組み替えた記録です。判断の表をこちら側に置き、証拠が足りない入力は保留へ回す配線を、動くコードと運用の判断基準まで含めてまとめました。
⬡ 高度な活用2026-06-27
Gemini の完了イベントは二度届きます — Webhook と照合ポーラーを「実質1回」にする冪等な受け口
Gemini の長時間オペレーションを Webhook で受けつつ照合ポーラーで二重化すると、同じ完了イベントが二度届き、公開や課金が二度走ります。冪等キーの取り方と claim→実行→確定の三相で「実質1回」にする受け口を実装します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます