5月の半ばに AdMob の月次レポートを開いて、ふと「同じ CSV を Gemini 3 Pro と Gemini 3 Flash の両方に同時に投げたら、どちらの結論を採用するか自分の中で迷うだろうか」と考えました。個人でアプリを運営していると、月次の収益レポートを開くたびに「数字を眺めるだけの時間」が少しずつ増えていくのが気になっておりました。
この記事は、月次の AdMob レポートを Gemini 3 Pro と Flash の両方に並列で投げ、コスト・レイテンシ・要約品質の三軸を10日間ほど計測したときの実装メモです。結論だけ先に書くと、Pro と Flash は「同じレポートを読んでも違う部分に目を留める」という発見があり、最終的には片方を選ぶのではなく 役割を分ける運用 に落ち着いています。
なぜ並列で投げる気になったか
きっかけは、Pro 単独の要約を1ヶ月ほど使ってみて「結論はもっともらしいが、この解釈が妥当かどうかを確かめる手段が自分の側にない」と感じたことでした。1つのモデルの結論だけを読むより、2つのモデルの結論の「差分」を読むほうが、解釈の偏りや取りこぼしに気づきやすいのではないか。そう考えて併用を試すことにしました。
実務的な動機はもう少し具体的でした。
- 月次の AdMob CSV は、国別 eCPM・広告ユニット別 RPM・フィルレートの3シートに分かれており、毎月15分以上眺めてしまう
- Pro 単独だと「結論はもっともらしいが、コストの増減が小さい時の精度差が体感しづらい」
- Flash 単独だと「速いし安いが、稀に数値の解釈を雑に丸める」
- 両方に投げて並べたら、自分が次の月にどこを触るかの判断が早くなりそう
判断材料は増やしすぎると、かえって決断が遅くなります。今回は「2モデル並列で投げて要約を比較し、結論は人間がまとめる」運用に絞りました。
並列実行のセットアップ
非同期で同じプロンプトを Pro と Flash に投げ、戻ってきた要約を並べる構造にしました。実装は Python の asyncio とリトライ付きの軽い HTTP クライアントだけです。
import asyncio
from google import genai
from google.genai import types
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
PROMPT = """
添付した AdMob 月次レポート(CSV テキスト)について、
次の3点を箇条書きで日本語で書いてください。
- 前月比で eCPM が5%以上動いた国とその要因仮説
- フィルレートが落ちている広告ユニットと推測される原因
- 翌月にテストすべき調整候補(フロアプライス・メディエーション順序・新フォーマット)
推測には「推測:」プレフィックスを付けてください。
""".strip()
async def call(model: str, csv_text: str) -> dict:
resp = await client.aio.models.generate_content(
model=model,
contents=[csv_text, PROMPT],
config=types.GenerateContentConfig(
temperature=0.3,
max_output_tokens=1200,
),
)
usage = resp.usage_metadata
return {
"model": model,
"text": resp.text,
"input_tokens": usage.prompt_token_count,
"output_tokens": usage.candidates_token_count,
}
async def run(csv_text: str):
return await asyncio.gather(
call("gemini-3-pro-latest", csv_text),
call("gemini-3-flash-latest", csv_text),
)asyncio.gather はデフォルトでは1つの例外で全体が失敗するため、このままだと片方のモデルだけ落ちた朝に、成功した側の要約まで取り損ねます。本番では try/except を call の中に閉じ込めて、「片方だけ成功した結果」も使えるようにしています。
async def call_safe(model: str, csv_text: str) -> dict:
try:
return await call(model, csv_text)
except Exception as e:
return {"model": model, "text": None, "error": str(e)}
async def run(csv_text: str):
results = await asyncio.gather(
call_safe("gemini-3-pro-latest", csv_text),
call_safe("gemini-3-flash-latest", csv_text),
)
return [r for r in results if r.get("text")]実際、10日間の計測中に Flash 側だけ 503 が返ってきた朝が1回ありました。その日は Pro の要約だけでルーチンを回せたので、この数行の保険は最初に入れておいてよかったと感じております。
10日間の実測 — コストとレイテンシ
5月15日から24日まで、毎朝同じ CSV(前日までの月初〜月中レポート)を投げて記録しました。1日1回・10回分の平均値です。
- 入力トークン数: 約 9,500(CSV をテキスト化したまま投入)
- Pro の所要時間: 平均 11.4 秒、出力 540 トークン
- Flash の所要時間: 平均 3.2 秒、出力 480 トークン
- コスト感: Flash は Pro の約 1/7 程度に収まりました(公式の料金表に基づく試算)
10日間の運用全体で、API コストは Pro 側で日本円換算 80 円ほど、Flash 側で 12 円ほどでした。この程度のコストなら毎日回しても、「月次レポートを15分眺める時間」への投資としては十分に回収できると判断しています。
レイテンシ差は思ったより体感的に大きく、朝のルーチンで「Flash が返ってきた段階で Pro を待つかどうかを決める」という判断が自然に生まれました。Pro の返答を待つ価値があるかは、Flash の最初の3行を読めば大体わかります。
ひとつ、計測の再現性について後から気づいた反省点があります。コード例では gemini-3-pro-latest / gemini-3-flash-latest という -latest エイリアスを使いましたが、エイリアスの実体は予告なく新しい世代へ切り替わります。実際、2026年7月には gemini-flash-latest の指す実体が Gemini 3.5 Flash に切り替わりました。コストとレイテンシを比較する計測では、期間の途中で実体が変わると平均値の意味が失われてしまいます。計測目的の呼び出しではバージョンを固定したモデルIDを明示し、エイリアスは「常に最新を追いたい日常運用」に限る。この使い分けは、計測を始める前に決めておくべきでした。
要約の差分は「数字の解釈の深さ」に出た
10日分の出力を読み比べて感じたのは、Pro と Flash で「拾う情報」よりも「数字の意味を読む深さ」が違うことです。
例えば、ある日のレポートでインドの eCPM が前月比 +18% でした。
- Flash の要約: 「インドの eCPM が +18%。広告需要の季節要因と推測」
- Pro の要約: 「インドの eCPM が +18%。同月のフィルレートが −3 ポイント低下しているため、需要増ではなく『フィルが渋くなって単価の高い在庫だけが通っている』可能性。フロアプライスを 0.05 上げてフィルへの影響を見るテスト推奨」
Flash の要約も間違ってはいないのですが、Pro はフィルレートとの関連まで踏み込みます。これは月次レポートのように「複数の指標を組み合わせて読む」タスクで顕著でした。
逆に、Flash の方が「短く・本数で並べる」のは上手で、Slack に貼る用のサマリーや、毎週のメモに記録する用途では Flash の方が読みやすいと感じる日もありました。
役割を分ける運用に落ち着いた
10日のあと、結局以下の使い分けに落ち着いています。
- 毎日のチェック: Flash 単独。3秒で返ってくる要約を眺めて、Pro を呼ぶべき日かを判断
- 週1回の深掘り: Pro 単独。複数指標の解釈・翌週のテスト候補まで踏み込んでもらう
- 月末のまとめ: 両方を並列で呼んで、Flash のリストと Pro の解釈を手元で統合
公式ドキュメントには「Pro は推論、Flash は速度とコスト」という整理がよく書かれていますが、実プロジェクトで毎日使い分けてみると、「Flash で全体を見渡して、Pro で深く読み込む」という二段構えが個人開発の運用には合っていると感じます。
これから取り組むこと
今後試したいのは、Pro の出力を Flash で要約し直して Slack に流す 二段パイプライン です。Pro の長い解釈を Flash で 3 行に圧縮すると、朝のルーチンの「読む量」がさらに減りそうです。Gemini Batch API を使って前月分を一括処理する案も並行で試しています。
レポートの行数が増えるほど、数字を眺めるだけで時間は溶けていきます。AI に「最初の解釈」を任せ、自分は「どこに手を入れるか」の判断に集中する。この形に寄せるほうが、個人での運用には現実的だと感じています。
同じように個人で AdMob を運用されている方の参考になれば嬉しいです。お読みいただきありがとうございました。