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-05-24中級

Gemini File API に半年分の AppStore レビュー CSV を投げて分類した2週間の運用ログ

App Store Connect から書き出した半年分のレビュー CSV を、Gemini File API に直接投げて分類・要約させる仕組みを2週間動かしました。Batch Mode との使い分け、トークン消費の落とし所、つまずいたところを淡々と記録します。

gemini-api279file-api6app-store-connect2indie-dev21admob4

App Store Connect の「評価とレビュー」画面を毎週開いて、星3つ以下のコメントだけを目で追いかける——個人開発を2014年から続けていると、これがじわじわ時間を奪います。私が運営している壁紙アプリは累計5,000万ダウンロードを超え、現在も日次で50〜120件ほどのレビューが日本語・英語・スペイン語・ドイツ語などで届きます。1週間まとめると軽く700件を超え、週末にまとめて読もうとして「結局読み切れずに月曜になる」ことが何度もありました。

そこで2週間前から、レビューを CSV にまとめて Gemini File API に投げ、「謝罪が必要」「機能要望」「広告への苦情」「OS バージョン依存の不具合報告」のように仕分けさせる運用を始めました。Batch Mode で夜間に流す案も並行で試しましたが、CSV を直接 File API に渡す方が小回りが効く場面が多く、今は両者を組み合わせて回しています。この記事は、2週間で見えてきた挙動と判断材料を整理したメモです。

なぜ File API に CSV を直接投げる方針にしたか

最初は素直に「1レビュー = 1リクエスト」で generateContent に投げていました。リクエストの粒度が細かいので失敗時の再試行は楽です。ただ、半年分(約1.2万件)を一気に再分類しようとすると、API のレートリミットに引っかかってしまいます。リトライ間隔を入れても、丸1日のジョブになってしまいました。

File API は、最大2GB のファイルをいったんアップロードしておけば、48時間は同じファイル参照を parts から指定できる仕組みです。1ファイルにつき1回のアップロード、あとは何度でもプロンプトを差し替えてモデルに渡せるため、「同じレビュー群を別の観点で2度・3度分類し直す」用途にぴったりはまりました。

もうひとつの理由は、トークン消費の見通しが立てやすいことです。CSV をテキストとして展開してプロンプトに直接埋め込むと、行数次第で入力トークンが激しくぶれます。File API 経由なら、Gemini 側で「ファイル参照」として扱われ、入力トークンの計上が安定します。私の場合、500行程度の CSV を1日に5〜8回読み直す運用なので、この安定感は地味に効いてきました。

2週間でやらせた3種類の分類

具体的に走らせたタスクは3つです。

  1. 重要度ラベル付け — 各レビューに「critical(クラッシュ報告・課金トラブル)」「support(操作疑問・要望)」「neutral(感想・低星でも具体性なし)」のいずれかを付ける
  2. クラスタリング要約 — 同じ訴えが何件あるかをまとめ、「広告頻度が高すぎる」「特定の壁紙のダウンロードが失敗する」のような塊で見せる
  3. 返信ドラフト下書き — 重要度 critical のものだけ、お詫び+一次回答の文面を日本語・英語の両方で生成する

最初の1週間は (1) と (2) だけ動かし、出力の方向性に手応えが出てから (3) を追加しました。順に追加していくと、どの段階で何にトークンを使っているかが切り分けやすくなります。

File API に CSV をアップロードする最小コード

実際に動いている最小構成は、Python の google-genai SDK で組んでいます。upload_file で CSV を上げて、その参照をプロンプトの先頭に置く形です。

import csv
import io
import pathlib
from google import genai
from google.genai import types
 
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
 
csv_path = pathlib.Path("reviews_2026-05-week2.csv")
 
uploaded = client.files.upload(
    file=csv_path,
    config=types.UploadFileConfig(
        display_name="reviews_2026-05-week2",
        mime_type="text/csv",
    ),
)
 
prompt = """
次の CSV は App Store Connect から書き出したレビューです。
1行 = 1レビュー。列は rating, locale, title, body, app_version, os_version, created_at。
 
各レビューに、次のラベルを1つだけ JSON 配列で返してください。
- critical: クラッシュ・課金トラブル・データ消失・購入したのに反映されない 等
- support: 操作方法の疑問・機能要望・UI わかりにくい
- neutral: 感想のみ・低評価でも具体性がない・スパム
 
JSON 以外は出力しないでください。
出力形式: [{"row": 1, "label": "critical"}, ...]
"""
 
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=[uploaded, prompt],
    config=types.GenerateContentConfig(
        response_mime_type="application/json",
        temperature=0.1,
    ),
)
 
print(response.text)

temperature=0.1 にしておくと、同じ CSV を2回投げても結果がほぼ揃います。ラベル付けのように「揺らがないこと」が価値になるタスクでは、揺らぎを抑える側に倒した方が後工程の差分検出が楽になります。

ファイルは48時間で自動的に消える仕様なので、毎週まとまったタイミングで上げ直す運用にしています。1.2万件規模を扱うときは、月ごとに分割して個別ファイルにする方が、エラー時の切り分けがしやすくなりました。

ぶつかった3つの壁と対処

2週間動かして、ぶつかった壁を3つに整理しておきます。同じことをする方の参考になればと思います。

ひとつ目は、CSV 内に改行入りの本文があるとパース順がずれる問題です。レビュー本文に絵文字混じりの改行が入っていると、Gemini が「行番号」をモデル側で再カウントすることがありました。対処として、CSV をエンコードする段階で csv.writer(quoting=csv.QUOTE_ALL) にして、全フィールドをダブルクォートで囲むようにしています。これだけで行番号のずれは収まりました。

with open("reviews_2026-05-week2.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f, quoting=csv.QUOTE_ALL)
    writer.writerow(["row", "rating", "locale", "title", "body", "app_version", "os_version", "created_at"])
    for i, r in enumerate(reviews, start=1):
        writer.writerow([
            i, r.rating, r.locale, r.title, r.body,
            r.app_version, r.os_version, r.created_at,
        ])

行番号を自前で row 列として持たせるのも重要でした。Gemini に「何行目」を聞くのではなく、CSV 側に書いてあるラベルを返してもらう設計にすると、後段で本文と照らし合わせるのが一気に楽になります。

ふたつ目は、ラベルの偏りです。最初の数日は、critical の比率が想定より少なく出ました。理由を探っていくと、英語レビューで「Crashed once」「Couldn't restore purchase」のような短い書き方を neutral に寄せてしまっていました。プロンプトの critical 定義に「short reports of crash or purchase failure even without details」と一文追加しただけで、肌感に合う比率になりました。

3つ目は、返信ドラフトの口調が定型化しすぎる問題です。Gemini に文面を任せると、お詫び→事象確認→ご協力のお願い、というテンプレに収まりがちでした。私自身、お詫びはあまり長くしたくない性格なので、プロンプトの例示を2件、自分が過去に手書きで返した実例(個人情報を除いたもの)に差し替えました。例示を変えると、生成される文面のトーンがはっきり寄ります。プロンプトでルールを書き連ねるより、自分の手書きを2〜3例見せる方が早かったです。

Batch Mode との使い分けで見えてきたこと

並行で試していた Batch Mode は、夜間に流して翌朝まとめて結果を回収できる点が魅力でした。50%のコストで動くのも個人開発者には大きな利点です。一方で、レイテンシが「24時間以内」と保証される性質なので、「明日朝までに critical だけ拾って手で返したい」用途には少し合いません。

2週間使った今は、次のような切り分けに落ち着いています。

  • File API + generateContent(同期) — 当日分のレビューをその日のうちに分類・要約したいとき。週次の gemini-2.5-flash 中心
  • Batch Mode — 過去ログ(半年分・1年分)の再分類、ラベル定義を変えて全件にかけ直すとき。gemini-2.5-pro で精度寄せ

夜間バッチで雑にラベルを振り直し、翌日 File API で再確認しながら回答ドラフトを当てる、という流れが今は一番安定しています。指標としては、私が手で読むレビュー数が週700件→週90件まで下がりました。critical 候補だけを開いて、Gemini の下書きに2割ほど手を入れて返信、という運用です。

これから2ヶ月で取り組むこと

直近で手を入れたいところは3つあります。ひとつは、App Store Connect API でのレビュー自動取得を組み込んで、CSV エクスポート手順を完全自動化することです。今は週末に手で書き出しているのですが、ここを CI 化すれば「気づいたら critical の下書きが Slack に並んでいる」状態にできます。

ふたつ目は、Google Play 側のレビューを同じパイプラインに乗せることです。Android 版の壁紙アプリも別アプリで運用していて、こちらは Reply to Reviews API があるのでフローが組みやすそうです。

3つ目は、返信文面の効果計測です。返信したレビューが後日「星を上げ直してもらえたか」を追えるようにすれば、Gemini の下書きをどの方向にチューニングすべきかの根拠になります。私は1997年に16歳でインターネットに触れて「国境を越えて人とつながれる」体験をしたことを今でも覚えていて、レビューに返信することは「同じ画面の向こう側にいる人に手紙を返す」感覚に近いと思っています。だからこそ、文面の手触りを定量で見直す土台を作っておきたいと考えています。

同じように個人開発でレビュー対応に追われている方の参考になれば幸いです。お読みいただきありがとうございました。

シェア

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

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

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

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

関連記事

API / SDK2026-05-30
Gemini 2.5 Flash で App Store Connect の日次売上をSlack要約に変えて2ヶ月運用した所感
App Store Connect の Sales/Trends API から落とした日次レポートを、Gemini 2.5 Flash で短いSlack要約に変える運用を2ヶ月続けた所感をまとめます。Pro との使い分け、AdMob 収益と並べて読むときの工夫、要約が滑った日の対処を運用ログから残します。
API / SDK2026-05-25
Gemini 2.5 Flash で個人開発アプリのヘルプ翻訳を3ヶ月運用した所感
iOS / Android の個人開発アプリで提供してきた多言語ヘルプを、Gemini 2.5 Flash を中心とした翻訳パイプラインで運用し始めて3ヶ月が経ちました。Pro との使い分け、訳文ドリフトへの備え、AdMob 収益に与えた小さな効果まで、運用ログに残った所感を淡々と記録します。
API / SDK2026-05-13
AdMob収益の急落を朝8時に知る仕組みをGemini APIで作った
AdMob収益の異常をGemini APIのFunction Callingで自動検知する仕組みの実装方法を、個人開発10年以上の実体験をもとに解説します。前日比の閾値設定から原因分析まで、実際に動くPythonコードで紹介します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →