生成AIの活用ノウハウや、 注目の技術に関する記事を掲載
公開
更新

生成AIのバッチAPIとは

はじめに

生成AIをシステムに組み込んでいると、「大量のデータを一括でAIに処理させたい」という場面に遭遇します。商品説明の一括生成、評価データセットの処理、ユーザーレビューの分類 ― いずれもリアルタイムの応答は不要で、数百〜数万件のリクエストをまとめて投げたいケースです。こうした場面で活躍するのがバッチAPIです。
バッチAPIを使えば、通常のAPI呼び出しと比べてコストを最大50%削減しつつ、大量のリクエストを効率よく処理できます。OpenAI・Anthropic・Googleといった主要ベンダーがそれぞれバッチ処理の仕組みを提供しており、いずれも50%のコスト割引が共通の特徴です。
本記事では、OpenAIのBatch APIを中心に仕組みと使い方を解説し(OpenAI公式ドキュメント)、Claude・Geminiでの対応状況も紹介します。
なお、APIコストを削減する別のアプローチとしてプロンプトキャッシュがあります。プロンプトの共通部分を再利用することで入力トークンのコストを削減する手法です。詳しくは以下の記事をご参照ください。

生成AI関連
プロンプトキャッシュ(コンテキストキャッシュ)とは

バッチAPIとは

バッチAPIとは、複数のAPIリクエストを非同期でまとめて処理する仕組みです。通常のAPIは1リクエストごとにリアルタイムで応答を返しますが、バッチAPIでは「まとめて送って、あとで結果を受け取る」という流れになります。

バッチAPIの概念図

通常のAPIは1件ずつリアルタイム処理。バッチAPIは複数リクエストをまとめて非同期処理し、完了後に一括で結果を取得する

通常のAPIとバッチAPIの比較

項目 通常のAPI バッチAPI
処理方式 同期(リアルタイム) 非同期(バックグラウンド)
レスポンス 即時 最大24時間以内(多くはより早い)
コスト 通常料金 最大50%割引
レート制限 標準のレート制限 別枠のレート制限(より緩い)
適したユースケース チャット、リアルタイム応答 大量データ処理、評価、一括変換

ポイントは、バッチAPIは即時応答が不要な処理に特化しているという点です。リアルタイム性を犠牲にする代わりに、コスト削減を実現しています。

OpenAIにおけるバッチAPIの仕組み

OpenAIのBatch APIは、JSONLファイルにリクエストをまとめて送信し、結果をJSONLファイルで受け取るシンプルな設計です。

処理の流れ

バッチAPIの処理は、大きく4つのステップで構成されます。

  1. 入力ファイルのアップロード

    JSONLファイルを Files APIでアップロード
  2. バッチの作成

    アップロードしたファイルIDを指定してバッチを作成
  3. ステータスの確認

    バッチの処理状況を定期的に確認
  4. 結果の取得

    完了後、出力ファイルをダウンロード

バッチAPIの処理フロー

バッチAPIの処理フロー

対応エンドポイント

バッチAPIは以下のエンドポイントに対応しています。テキスト生成だけでなく、画像生成やビデオ生成にも対応しており、幅広いユースケースで活用できます。

エンドポイント 用途
/v1/responses Responses API
/v1/chat/completions Chat Completions
/v1/embeddings Embeddings
/v1/completions Completions
/v1/moderations Moderations
/v1/images/generations 画像生成
/v1/images/edits 画像編集
/v1/videos ビデオ生成

入力ファイルの形式

入力はJSONL(JSON Lines)形式で、1行が1リクエストに対応します。各リクエストには結果と紐づけるための custom_id を設定します。通常のChat Completions APIと同様に、システムプロンプトも指定できます。

input.jsonl

{"custom_id": "request-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-5.4-mini", "messages": [{"role": "system", "content": "あなたは技術用語を初心者にもわかりやすく説明するアシスタントです。回答は3文以内で簡潔にまとめてください。"}, {"role": "user", "content": "Pythonのリスト内包表記について教えてください。"}], "max_completion_tokens": 500}}
{"custom_id": "request-2", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-5.4-mini", "messages": [{"role": "system", "content": "あなたは技術用語を初心者にもわかりやすく説明するアシスタントです。回答は3文以内で簡潔にまとめてください。"}, {"role": "user", "content": "HTTPステータスコード404と500の違いを説明してください。"}], "max_completion_tokens": 500}}
{"custom_id": "request-3", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-5.4-mini", "messages": [{"role": "system", "content": "あなたは技術用語を初心者にもわかりやすく説明するアシスタントです。回答は3文以内で簡潔にまとめてください。"}, {"role": "user", "content": "データベースのインデックスはなぜ必要ですか?"}], "max_completion_tokens": 500}}

条件と制約

項目 内容
1バッチあたりの上限 最大50,000リクエスト
ファイルサイズ上限 200MB
完了期限 24時間(多くはより早く完了)
コスト 通常料金の50%(入力・出力トークン共に)
結果の保持期間 バッチ完了後30日間(ビデオは24時間)
バッチ作成レート制限 1時間あたり最大2,000バッチ

バッチのステータス

バッチの処理状況は以下のステータスで管理されます。

ステータス 説明
validating 入力ファイルを検証中
in_progress リクエストを処理中
finalizing 結果を準備中
completed 処理完了(結果をダウンロード可能)
expired 24時間以内に完了しなかった
cancelling キャンセル処理中
cancelled キャンセル済み
failed 入力ファイルの検証失敗

デモ:バッチAPIで質問を一括処理する

実際にOpenAI APIを使って、バッチAPIの動作を確認してみましょう。複数の質問を一括で処理するシナリオで実装します。

実験の構成

今回のデモでは、以下の流れで実装します。

  1. 入力ファイル(JSONL)を用意する
  2. バッチを作成する
  3. ステータスの確認と結果の取得

ステップ1:入力ファイルの準備

まず、処理対象の質問をJSONLファイルとして用意します。今回はシステムプロンプトで「初心者向けに3文以内で回答する」というルールを設定し、5件の技術的な質問を投げます。
以下は入力ファイルの1行目を整形したものです。

json

{
  "custom_id": "q-001",
  "method": "POST",
  "url": "/v1/chat/completions",
  "body": {
    "model": "gpt-5.4-mini",
    "messages": [
      {
        "role": "system",
        "content": "あなたは技術用語を初心者にもわかりやすく説明するアシスタントです。回答は3文以内で簡潔にまとめてください。"
      },
      {
        "role": "user",
        "content": "Pythonのリスト内包表記について教えてください。"
      }
    ],
    "max_completion_tokens": 500
  }
}

各リクエストには custom_id を設定します。この値が結果と元データを紐づけるキーになります。実際のJSONLファイルでは、このようなJSONを1行1リクエストで記述していきます。
今回は共通のシステムプロンプトを設定し、以下の5件の質問を用意しました。

custom_id 質問内容
q-001 Pythonのリスト内包表記について教えてください。
q-002 HTTPステータスコード404と500の違いを説明してください。
q-003 データベースのインデックスはなぜ必要ですか?
q-004 RESTとGraphQLの主な違いを3つ挙げてください。
q-005 Gitでブランチを使う利点を教えてください。

ステップ2:バッチの作成

JSONLファイルをアップロードし、バッチを作成します。

batch_submit.py

import argparse

from dotenv import load_dotenv
from openai import OpenAI


def main() -> None:
    load_dotenv()

    parser = argparse.ArgumentParser(description="JSONLファイルをバッチAPIで実行する")
    parser.add_argument("input_file", help="入力JSONLファイルのパス")
    parser.add_argument(
        "--endpoint",
        default="/v1/chat/completions",
        help="バッチAPIのエンドポイント(デフォルト: /v1/chat/completions)",
    )
    args = parser.parse_args()

    client = OpenAI()

    # 1. ファイルをアップロード
    with open(args.input_file, "rb") as f:
        file = client.files.create(file=f, purpose="batch")
    print(f"ファイルアップロード完了: {file.id}")

    # 2. バッチを作成
    batch = client.batches.create(
        input_file_id=file.id,
        endpoint=args.endpoint,
        completion_window="24h",
    )
    print(f"バッチ作成完了: {batch.id}")
    print(f"ステータス: {batch.status}")

if __name__ == "__main__":
    main()

completion_window には "24h" を指定します。これはバッチ処理の完了期限で、現時点ではこの値のみ対応しています。実際には多くのバッチがこれよりも早く完了します。

ステップ3:ステータスの確認と結果の取得

バッチの処理には時間がかかるため、定期的にステータスを確認します。completed になったら出力ファイルをダウンロードします。なお、バッチIDを控え忘れた場合は client.batches.list() で過去のバッチ一覧を取得できます。

batch_retrieve.py

import argparse

from dotenv import load_dotenv
from openai import OpenAI


def main() -> None:
    load_dotenv()

    parser = argparse.ArgumentParser(description="バッチAPIのステータス確認と結果取得")
    parser.add_argument("batch_id", help="バッチID(例: batch_abc123)")
    args = parser.parse_args()

    client = OpenAI()

    # ステータスを確認
    batch = client.batches.retrieve(args.batch_id)
    counts = batch.request_counts

    print(f"バッチID: {batch.id}")
    print(f"ステータス: {batch.status}")
    print(f"進捗: {counts.completed}/{counts.total} 完了")

    if batch.status != "completed":
        raise SystemExit(0)

    # 結果を取得
    result_content = client.files.content(batch.output_file_id).text
    print(result_content)


if __name__ == "__main__":
    main()

completed になるまで数分おきに実行して確認します。なお、このステータス確認をループ処理(ポーリング)として組むことも可能です。
なお、この実装は簡易的なもので、エラーが出る想定をしていません。
出力もJSONL形式で返ってきます。以下は結果の1行を整形したものです。

json

{
  "id": "batch_req_XXXXXXXXXXXX",
  "custom_id": "q-001",
  "response": {
    "status_code": 200,
    "request_id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "body": {
      "id": "chatcmpl-XXXXXXXXXXXX",
      "object": "chat.completion",
      "created": 1776148910,
      "model": "gpt-5.4-mini-2026-03-17",
      "choices": [
        {
          "index": 0,
          "message": {
            "role": "assistant",
            "content": "Pythonのリスト内包表記は、**for文でリストを作る処理を1行で簡潔に書ける**書き方です。  \nたとえば `[x * 2 for x in range(5)]` は、0〜4を2倍した `[0, 2, 4, 6, 8]` を作ります。  \nさらに `if` を付けて、条件に合う要素だけを集めることもできます。",
            "refusal": null,
            "annotations": []
          },
          "finish_reason": "stop"
        }
      ],
      "usage": {
        "prompt_tokens": 60,
        "completion_tokens": 111,
        "total_tokens": 171,
        "prompt_tokens_details": {
          "cached_tokens": 0,
          "audio_tokens": 0
        },
        "completion_tokens_details": {
          "reasoning_tokens": 0,
          "audio_tokens": 0,
          "accepted_prediction_tokens": 0,
          "rejected_prediction_tokens": 0
        }
      },
      "service_tier": "default",
      "system_fingerprint": null
    }
  },
  "error": null
}

custom_id で元のリクエストと結果を紐づけることができます。出力ファイル内のリクエスト順は入力と一致する保証がないため、この custom_id でのマッピングが重要です。
なお、バッチ内で一部のリクエストが失敗した場合、成功分は output_file_id から、失敗分は error_file_id から取得できます。24時間以内に完了しなかったリクエストには batch_expired エラーが記録されます。

バッチAPIを活用するためのポイント

バッチAPIを効果的に使うための設計上のポイントをまとめます。

custom_idの設計

custom_id は結果と元データを紐づける唯一の手段です。出力ファイルのリクエスト順は入力と一致する保証がないため、custom_id で確実にマッピングする必要があります。
実務では、データベースのレコードIDや処理対象のドキュメントIDなど、元データを特定できる値を設定しましょう。

完了期限と期限切れの扱い

バッチ処理の完了期限は24時間です。期限内に処理が完了しなかったリクエストは batch_expired エラーとなりますが、期限内に完了したリクエストは正常に課金・取得できます。大量のリクエストを扱う場合は、バッチの進捗を定期的に確認しましょう。

各ベンダーの比較

バッチAPIの仕組みはベンダーごとに異なります。以下のテーブルに主要な違いをまとめました(OpenAI公式ドキュメント 、Anthropic公式ドキュメント 、Google AI公式ドキュメント)。

比較軸 OpenAI Claude(Anthropic) Gemini(Google)
API名称 Batch API Message Batches API Batch API
入力形式 JSONLファイルアップロード APIリクエストで直接送信 インライン / JSONLファイル
1バッチの上限 50,000リクエスト / 200MB 100,000リクエスト / 256MB インライン: 20MB / ファイル: 2GB
完了期限 24時間(多くはより早く完了) 24時間(多くは1時間以内) 24時間目標(多くはこれよりはるかに早く終了)
コスト割引 50%オフ 50%オフ 50%オフ
結果の保持期間 30日間(ビデオは24時間) 29日間 記載なし

ユースケース

バッチAPIが特に効果を発揮するのは、大量のデータを同じルールで処理するパターンです。

ユースケース 処理内容 バッチAPIが有効な理由
大規模評価(Evaluation) テストケースの一括評価 数千件のテストを低コストで実行
コンテンツモデレーション ユーザー投稿の一括チェック リアルタイム性不要で大量処理
商品説明の一括生成 ECサイトの商品データから説明文を生成 数百〜数万件の商品を一括処理
ドキュメント翻訳 マニュアルや契約書の大量翻訳 即時性が不要で、コスト削減効果が大きい
データラベリング 学習データへのラベル付け 大量データに対して一貫したルールで処理

いずれも「即時応答は不要だが、大量のデータを一括で処理したい」というパターンです。このパターンに当てはまるシステムでは、通常のAPIをバッチAPIに置き換えるだけでコストを半減できます。

まとめ

  • バッチAPIは、複数のAPIリクエストを非同期でまとめて処理する仕組みで、コストを最大50%削減できる
  • OpenAIではJSONLファイルベースのシンプルな設計で、テキスト・画像・ビデオと幅広いエンドポイントに対応
  • custom_id で結果を元データに紐づけるため、IDの設計が重要
  • 24時間以内に処理が完了し、多くの場合はそれよりも早く結果が得られる

リアルタイム応答が不要な大量処理を行っている場合、バッチAPIへの切り替えを検討してみてはいかがでしょうか。

生成AI活用支援サービスのご紹介

Tech Funでは、お客様のフェーズに合わせ、生成AI活用に向けた支援を3つのパックでご提供しています。

  1. 無料診断パック:業務・プロセスの現状を無料で診断し、生成AI活用の可能性をレポートします。
  2. 検証(PoC)パック:診断で有効性が確認された業務を対象に、プロトタイプ構築を支援します。
  3. コンサルティングサービス:生成AI導入戦略の策定から運用体制構築までを包括的に支援します。

生成AIに限らず、Web・業務システム開発やインフラ設計など、技術領域を問わずご相談を承っています。「何から始めれば良いか分からない」という段階でも構いませんので、ぜひお気軽にお問い合わせください。

執筆・編集

Tech Fun Magazine R&Dチーム
Tech Funの生成AI研究に携わるエンジニアが、最新のAIモデル動向やプロンプト設計、実業務への応用手法など、生成AIに特化した知見を執筆・編集しています。
モデル評価や業務シナリオに応じたAI活用設計など、日々のR&D活動で得られる実践的なノウハウをわかりやすく紹介します。

ARTICLE
生成AI関連記事一覧

生成AI関連

Amazon Bedrock Managed Knowled…

生成AI関連

Google Sheets canvasはどこまで業務アプリ…

生成AI関連

Amazon BedrockのRerank APIで検索順位…

生成AI関連

OpenAI Agents APIとは?本番運用に必要な5つ…

生成AI関連

Codex App Serverとは?Pythonでの使い方…

生成AI関連

Amazon Bedrockの基盤モデルパーサーを実測する―…

生成AI関連

ChatGPT WorkのScheduled TasksをW…

生成AI関連

Amazon Bedrock Knowledge Bases…

生成AI関連

ChatGPTのChat・Work・Codexの違い|5時間…

記事一覧を見る