Gemini API を本番運用していると、こんな要件に必ず当たります。
- 数千〜数百万件の文章を要約したい(前処理)
- テキスト分類やラベリングを一括で回したい(評価/データセット作成)
- Embedding を大量に作りたい(RAG構築)
- 画像生成/解析などを「夜間にまとめて」回したい(非同期バッチ処理)
こういった **「今すぐ結果いらないけど大量に処理したい」**ユースケースに最適なのが Gemini Batch API です。
しかも Batch API は 標準料金の 50% で利用できるのが大きい。
「速度を捨ててコストを取る」選択肢が公式に用意された、というのがポイントです。
1. Batch API とは?(どんな時に使うのか)
Gemini Batch API は、大量のリクエストを 非同期 で処理するAPIです。
- 目標応答時間:24時間
- ただし「ほとんどの場合もっと早い」
- 緊急性の低い大規模タスク向け
つまり、リアルタイム応答が必要なプロダクト(チャット/検索/UX直結)ではなく、
データ基盤・評価・オフライン処理のラインに向きます。
2. Batch API の送信方法は2種類(インライン vs JSONLファイル)
Batch API では、リクエストを渡す方法が2つあります。
✅ (A) インラインリクエスト方式(小規模向け)
- バッチ作成リクエスト内に
GenerateContentRequestを配列で埋め込む - 合計サイズ 20MB 未満の小さめバッチ向き
- 結果は
inlineResponseの配列で返る
✅ (B) 入力ファイル方式(推奨:大規模向け)
- 1行に1リクエストの JSON Lines (JSONL) を作る
- File API でアップロードして参照させる
- 結果も JSONL ファイルで返る
- 入力ファイル最大サイズは 2GB
結論:
- 試作/少数 → インライン
- 本番/大量 → JSONL(File API)
が現実的です。
3. インラインでバッチを作る(Python/JS)
Python(インライン)
from google import genai
client = genai.Client()
inline_requests = [
{
"contents": [{
"parts": [{"text": "Tell me a one-sentence joke."}],
"role": "user"
}]
},
{
"contents": [{
"parts": [{"text": "Why is the sky blue?"}],
"role": "user"
}]
}
]
job = client.batches.create(
model="models/gemini-2.5-flash",
src=inline_requests,
config={"display_name": "inlined-requests-job-1"},
)
print(job.name)
公式の通り、batches.create() に src としてインライン配列を渡します。
4. JSONLファイルでバッチを作る(本番向け)
4.1 JSONLのフォーマット(超重要)
JSONLは「1行1JSON」です。
さらに、各行に必ず以下を含めます。
-
key:ユーザー定義キー(レスポンスに同じ key が付いて返る) -
request:GenerateContentRequest本体
例:
{"key":"request-1","request":{"contents":[{"parts":[{"text":"Describe photosynthesis."}]}],"generation_config":{"temperature":0.7}}}
{"key":"request-2","request":{"contents":[{"parts":[{"text":"Ingredients of Margherita pizza?"}]}]}}
この key があることで「どの結果がどのリクエストか」を確実に紐付けできます。
(本番では UUID や DB の主キーを入れるのがおすすめ)
4.2 File API にアップロード(Python)
import json
from google import genai
from google.genai import types
client = genai.Client()
with open("my-batch-requests.jsonl", "w") as f:
requests = [
{"key":"request-1","request":{"contents":[{"parts":[{"text":"Describe photosynthesis."}]}]}},
{"key":"request-2","request":{"contents":[{"parts":[{"text":"Ingredients of Margherita pizza?"}]}]}}
]
for r in requests:
f.write(json.dumps(r) + "\n")
uploaded = client.files.upload(
file="my-batch-requests.jsonl",
config=types.UploadFileConfig(display_name="my-batch-requests", mime_type="jsonl")
)
print(uploaded.name)
4.3 バッチジョブ作成(ファイル入力)
job = client.batches.create(
model="models/gemini-2.5-flash",
src={"file_name": uploaded.name},
config={"display_name": "file-batch-job-1"}
)
print(job.name) # 例: batches/123456789
作成すると、batches/xxxx のような ジョブ名が返ります。
これを後続の ステータス確認と 結果取得に使います。
5. ジョブステータス監視(運用の要)
Batch API は非同期なので、ジョブ状態をポーリングして完了を待ちます。
状態は以下いずれかです:
-
JOB_STATE_PENDING:待機中 -
JOB_STATE_RUNNING:実行中 -
JOB_STATE_SUCCEEDED:成功(結果取得OK) -
JOB_STATE_FAILED:失敗(エラー確認) -
JOB_STATE_CANCELLED:キャンセル済み -
JOB_STATE_EXPIRED:48時間以上 pending/running で期限切れ(結果なし)
EXPIREDは「48時間経過で強制終了」
→ 再送 or バッチを分割しましょう。
Python(ポーリング例)
import time
from google import genai
client = genai.Client()
job_name = "batches/your-batch-id"
completed = {
"JOB_STATE_SUCCEEDED",
"JOB_STATE_FAILED",
"JOB_STATE_CANCELLED",
"JOB_STATE_EXPIRED",
}
while True:
job = client.batches.get(name=job_name)
if job.state.name in completed:
break
print("waiting...", job.state.name)
time.sleep(30)
print("final:", job.state.name)
6. 結果の取り出し(インライン vs ファイル)
✅ インライン方式の場合
レスポンスは dest.inlined_responses に入っています。
for r in job.dest.inlined_responses:
if r.response:
print(r.response.text)
✅ ファイル方式の場合
結果は JSONLファイル として返ります。
- ジョブが成功すると
responses_fileのような出力ファイル参照が得られる - それを File API のダウンロードで取得する
運用では「出力JSONL → ETL → DB/BigQuery投入」まで含めるとスムーズです。
7. ジョブのキャンセル(想定外のコスト/処理停止)
進行中ジョブはキャンセルできます。
キャンセルすると「新しいリクエストの処理が停止」します。
Python
from google import genai
client = genai.Client()
client.batches.cancel(name=job_name)
8. Batch API は Embeddings も強い(RAG勢はここ重要)
Batch API は batches.create_embeddings で Embeddingモデルの大量処理にも対応しています。
例えば:
- ベクトルDB投入用のEmbedding大量生成
- RAGの評価用にEmbeddingを一括更新
- 分析基盤で夜間バッチ実行
などが コスト効率よく回せます。
9. 設計・運用のコツ(実務視点)
ここからが本題。
Batch API を本番で回すなら「APIの使い方」より ジョブ設計が重要です。
✅ 9.1 key はユニークに(必須)
-
keyがレスポンス紐付けの命綱 - DBの主キーやUUIDを入れるのが鉄板
✅ 9.2 EXPIRED を前提に分割設計
- 48時間で期限切れになる可能性がある
- 大きすぎるバッチは分割する(例:1万件ごと)
✅ 9.3 失敗時の再送戦略
-
JOB_STATE_FAILEDの場合、エラー内容をログに残す - 再送できるように JSONL を生成可能な状態で保持する
✅ 9.4 JSONL結果をそのままETLしやすい
-
出力も JSONL なので
- BigQuery
- Spark
- Python/pandas
- Dataflow
などに流しやすい
10. まとめ:Batch API は「LLMバッチ基盤」の主役になれる
Gemini Batch API は、以下を満たす人に刺さります:
✅ 大量データを処理したい
✅ 24時間以内に返ってくれば良い
✅ コストを極限まで抑えたい(50%)
✅ JSONLでETLパイプラインを組みたい
✅ Embeddingsを大量生成したい
リアルタイム性のあるプロダクト処理は通常の generateContent を使い、
非同期バッチ処理は Batch API に切り分けると、LLM利用のコスト/運用が一気に安定します。