GEMINI LABEN
STUDIO — Android と iOS 向けに予定されていた AI Studio の単体アプリは中止され、アプリ構築機能が Gemini アプリへ直接組み込まれます。画像生成・動画生成・テキスト分析・コード支援も同じ場所に集まりますBENCH — Gemini 3.7 Flash は長期タスクのコーディング指標 DeepSWE で 49.0 パーセントから 65.3 パーセントへ上がり、同時にトークン単価は半分になりましたREACH — 3.7 Flash は Gemini API に加え、Android Studio、Google Antigravity、Gemini Enterprise Agent Platform、Gemini アプリの Spark から使えますAPI — サンプリング系の temperature・top_p・top_k が非推奨になりました。これらで出力の揺れを抑えていた実装は、再現性の担保をどこで取るか決め直す時期ですROBOTICS — gemini-robotics-er-1.6-preview は8月31日に停止します。残り9日です。後継は er-2-preview と er-2-streaming-preview で、テキスト・画像・動画・音声を入力に取りますASSISTANT — Android の Google アシスタントを Gemini へ置き換える作業は9月4日から始まります。残り13日です。App Actions や音声ショートカットを使うアプリは挙動の確認をSTUDIO — Android と iOS 向けに予定されていた AI Studio の単体アプリは中止され、アプリ構築機能が Gemini アプリへ直接組み込まれます。画像生成・動画生成・テキスト分析・コード支援も同じ場所に集まりますBENCH — Gemini 3.7 Flash は長期タスクのコーディング指標 DeepSWE で 49.0 パーセントから 65.3 パーセントへ上がり、同時にトークン単価は半分になりましたREACH — 3.7 Flash は Gemini API に加え、Android Studio、Google Antigravity、Gemini Enterprise Agent Platform、Gemini アプリの Spark から使えますAPI — サンプリング系の temperature・top_p・top_k が非推奨になりました。これらで出力の揺れを抑えていた実装は、再現性の担保をどこで取るか決め直す時期ですROBOTICS — gemini-robotics-er-1.6-preview は8月31日に停止します。残り9日です。後継は er-2-preview と er-2-streaming-preview で、テキスト・画像・動画・音声を入力に取りますASSISTANT — Android の Google アシスタントを Gemini へ置き換える作業は9月4日から始まります。残り13日です。App Actions や音声ショートカットを使うアプリは挙動の確認を
記事一覧/開発ツール
開発ツール/2026-08-22中級

段階公開を止める判断だけは、Gemini に渡さないことにしました

段階公開の初日に見えるクラッシュ率には、良し悪しを判定できるだけの母数がありません。止める・進める・まだ言えないの3状態に分け、Gemini にはレビュー本文の帰属判定だけを任せた配線を残します。

段階公開Gemini API216個人開発105リリース運用responseSchema6

配信率 1% の初日、管理画面のクラッシュ件数は 2 件でした。前の版と並べても増えているようには見えなかったので、私は翌日の引き上げをそのまま承認しました。

5% まで広がった三日目、同じ症状を訴えるレビューが並び始めました。初日のあの 2 件は、いま思えば「問題がない」を意味していませんでした。単に、何も言えないだけの数だったのです。

個人開発でアプリを並行して出していると、段階公開の各日にかけられる時間は数分しかありません。その数分で判断を誤らないために、どこを機械に任せ、どこを言語モデルに任せ、どこを自分の手元に残すかを引き直しました。結論から書くと、止めるかどうかの判断そのものはモデルに渡さない、という線引きになりました。

初日の「静かでした」は、静かさの証拠ではありません

App Store の段階的リリースは 7 日間かけて 1% / 2% / 5% / 10% / 20% / 50% / 100% と配信率が上がります。ここで見落としやすいのは、初日の母数が最終日の 200 分の 1 しかないという点です。

1 日あたりの新規セッションが 100% 配信時に 20,000 件あるアプリを例にします。真のクラッシュ発生率が 0.8% で一定だと仮定して、各日に観測される件数と、その観測から言える範囲(Wilson の 95% 信頼区間)を計算しました。

配信率母数観測件数95%信頼区間区間の幅
Day 11%20020.27% 〜 3.57%3.30pt
Day 22%40030.26% 〜 2.18%1.93pt
Day 35%1,00080.41% 〜 1.57%1.16pt
Day 410%2,000160.49% 〜 1.30%0.80pt
Day 520%4,000320.57% 〜 1.13%0.56pt
Day 650%10,000800.64% 〜 0.99%0.35pt
Day 7100%20,0001600.69% 〜 0.93%0.25pt

Day 1 の行を見てください。観測値は 1.00% ですが、真の値は 0.27% かもしれないし 3.57% かもしれません。平常時の 4 倍に悪化していても、初日の数字は同じ顔をして並びます

私が三日目に取り逃がしたのは、まさにこの幅でした。数字が小さいことを安全と読み替えていたわけです。

「進める・止める」の二択をやめて、「まだ言えない」を状態にする

判断を誤った原因は、判断の選択肢が 2 つしかなかったことにあります。人は 2 択を渡されると、判断できない状況でもどちらかを選んでしまいます。そこで状態を 3 つに増やしました。

import math
 
def wilson(k, n, z=1.96):
    """k 件 / n 件 の観測から、真の発生率がありうる範囲を返します。"""
    if n == 0:
        return (0.0, 1.0)
    p = k / n
    d = 1 + z * z / n
    center = (p + z * z / (2 * n)) / d
    half = z * math.sqrt(p * (1 - p) / n + z * z / (4 * n * n)) / d
    return (max(0.0, center - half), min(1.0, center + half))
 
def verdict(n, k, baseline, ceiling):
    """baseline = 平常時の発生率 / ceiling = ここを超えたら止めるという上限。"""
    lo, hi = wilson(k, n)
    if lo > ceiling:
        return "STOP"        # 上限を超えていることが、母数の少なさを差し引いても言える
    if hi <= ceiling:
        return "GO"          # 上限を超えていないことが言える
    return "UNDECIDED"       # まだどちらとも言えない
 
def required_users(baseline, ceiling, z=1.96, step=100):
    """平常どおりの発生率が続いた場合に、GO と言えるようになる母数。"""
    n = step
    while n <= 2_000_000:
        if wilson(round(n * baseline), n, z)[1] <= ceiling:
            return n
        n += step
    return None

平常時 0.8%、上限を倍の 1.6% に置いて実行すると、次の結果になりました。

母数観測件数観測値信頼区間判定
20021.00%0.27% 〜 3.57%UNDECIDED
20084.00%2.04% 〜 7.69%STOP
1,00080.80%0.41% 〜 1.57%GO
1,000303.00%2.11% 〜 4.25%STOP
4,000902.25%1.83% 〜 2.76%STOP

required_users(0.008, 0.016)900 を返します。つまり平常どおりの数字が並んでいても、900 人に届くまでは「大丈夫でした」と言う根拠がありません。冒頭の 200 人はその 4 分の 1 以下でした。

一方で母数が少なくても STOP は出ます。200 人中 8 件なら、少ない母数を差し引いてもなお上限を超えています。壊れているときは早く分かり、壊れていないことは遅れて分かるという非対称は、そのまま受け入れてよいと考えています。

レビュー本文だけは、数えるだけでは足りません

クラッシュ率は機械で判定できます。困るのはレビューです。「アップデートしてから写真が保存できません」と「広告が多すぎます」は、どちらも星 1 として同じ列に積まれます。片方は今回の版の話で、もう片方は前から言われ続けている話です。

この帰属の判定こそ、言語モデルに向いた仕事だと感じています。ここでは responseSchema で出力の形を固定して、1 件ずつ分類させています。

from google import genai
from google.genai import types
 
client = genai.Client(api_key="YOUR_API_KEY")
 
SCHEMA = {
    "type": "object",
    "properties": {
        "attributable_to_update": {"type": "boolean"},
        "symptom": {"type": "string"},
        "severity": {"type": "string", "enum": ["blocking", "major", "minor", "none"]},
    },
    "required": ["attributable_to_update", "symptom", "severity"],
}
 
PROMPT = """次のアプリレビューを分類してください。
判定するのは「この更新のあとに起きた不具合を述べているか」だけです。
アプリの良し悪しや、公開を続けるべきかどうかは判定しないでください。
価格や広告量など、更新前から存在する不満は attributable_to_update を false にします。
 
レビュー本文:
{body}"""
 
def classify(body: str) -> dict:
    res = client.models.generate_content(
        model="gemini-3.7-flash",
        contents=PROMPT.format(body=body),
        config=types.GenerateContentConfig(
            response_mime_type="application/json",
            response_schema=SCHEMA,
        ),
    )
    return res.parsed

プロンプトの 2 行目と 3 行目は、書き足したのではなく削り出した部分です。最初は「このレビューは公開停止に値しますか」まで聞いていました。返ってくる文章はもっともらしく、しかも母数が少ない日ほど「様子を見るのが妥当です」と穏当な方向へ寄りました。

穏当な答えは反論しにくく、根拠らしい文章が添えられていると、そのまま承認してしまいます。判断をモデルに聞いた瞬間、自分の 3 状態は 2 択に戻っていました。だから聞くのをやめました。

レビュー返信そのものを Gemini に書かせる場合の注意点は、App Store / Google Play のレビュー返信を Gemini API で自動化したときにはまった「8秒ルール」 に別途まとめています。

モデルの出力を、しきい値の分子に混ぜない

分類結果を得たあと、それをクラッシュ率の計算に足したくなります。実際に一度そうしました。結果として、モデルが 1 件を取りこぼすたびに判定が揺れる仕組みになりました。

いまは 2 つの系統を分けたまま合流させています。合流点で行うのは、どちらかが赤なら止める、判断が割れたら人に回すという単純な突き合わせだけです。

def route(judgements, crash_state):
    """judgements: モデルの分類結果 / crash_state: 決定的に算出した3状態。"""
    regressions = [
        j for j in judgements
        if j["attributable_to_update"] and j["severity"] in ("blocking", "major")
    ]
 
    if crash_state == "STOP":
        return ("STOP", "クラッシュ率の下限が上限しきい値を超えました")
    if len(regressions) >= 3:
        return ("HUMAN_REVIEW", f"更新起因の重大レビューが {len(regressions)} 件あります")
    if crash_state == "UNDECIDED":
        return ("HOLD", "母数が不足しています。配信率を上げずに翌日まで待ちます")
    return ("GO", "しきい値内です。次の配信率へ進みます")

HUMAN_REVIEW を独立した戻り値にしたことが、この配線で一番効きました。モデルが 3 件を拾ったとき、システムは止めもしませんし進めもしません。私に本文を読ませます。読むのは 3 件ですから、朝の数分で足ります。

HOLDGO の差も意識して分けました。HOLD は「昨日と同じ配信率でもう一日置く」という積極的な行動です。何もしないことと、待つと決めることは別のものだと考えています。

運用に落とす前に決めた 4 つ

数値を後から動かすと、都合の良い方へ動かしてしまいます。リリース前に固定して、リリース中は触らないと決めました。

決めごと私の設定そう決めた理由
baseline(平常時の発生率)直前 4 週間の中央値平均だと過去の悪い版に引っ張られます
ceiling(止める上限)baseline の 2 倍1.5 倍だと UNDECIDED が最終日まで解けませんでした
最小母数required_users の戻り値この数に届く前の GO は、根拠のない GO です
モデル出力の扱い人へ回す判断のみに使用しきい値の分子に入れると、分類漏れが判定を揺らします

ceiling を 2 倍にした経緯だけ補足します。1.5 倍で試したところ、平常どおりの数字が続いても required_users が 2,800 まで上がり、Day 4 を過ぎるまで UNDECIDED が解けませんでした。厳しくすると安全になるのではなく、7 日間ずっと何も言えないだけになります。しきい値の厳しさと、判断できるようになる速さは交換関係にあります。

次に段階公開を始めるときは、まず自分のアプリの required_users を計算してみてください。その数を配信率で割れば、判断が意味を持ち始めるのが何日目からなのかが分かります。私の場合は Day 3 でした。それより前の数字を眺めていた時間は、安心を買っていただけだったことになります。

リリース直後に届く通知やストア文言のように、生成した文字列を配信前に検査する話は 通知文の長さ指示が英語版だけ効かなかった理由と、生成後に幅で詰める実装 で扱っています。あわせて読んでいただけると、リリース当日の手順がもう少し繋がるはずです。

数字の読み違えは、私自身がつい先日やったばかりの失敗です。同じところで足を止める方が一人でも減れば嬉しく思います。お読みいただきありがとうございました。

シェア

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

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

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

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

関連記事

開発ツール2026-08-20
Gemini に書かせたレビュー返信を、送信前に止めるための最小の検査
ストアのレビュー返信は下書きより送信後が怖い作業です。守れない約束・連絡先の混入・文体崩れを送信前に機械で止める Python の検査を、実際に走らせた結果と誤検出の修正まで含めて置いておきます。
開発ツール2026-08-17
配布済みアプリに残るモデル名と、停止日をまたいだ切り戻しの設計
サーバー側の移行が終わっても、ユーザーの端末で動いている旧バージョンのアプリは古いモデル名を握ったままです。停止日をまたぐと切り戻しが復旧手段でなくなる構造と、モデル解決をサーバーに寄せる設計をまとめます。
開発ツール2026-07-18
難読化されたスタックトレースを Gemini に渡していました — retrace を前段に置くまで、診断はもっともらしく外れ続けます
release ビルドのスタックトレースは R8 で名前が潰れています。それをそのまま Gemini に渡すと、診断は落ち着いた文体のまま外れます。retrace を前段に置き、mapping を versionCode で突合し、復元できないときは断定させない。42件で数え直した記録です。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →