Nullstead

AI

2026年版 LLMコスト最適化実践ガイド:Prompt CachingとBatch処理で「賢く速く安く」回す個人開発術

OpenAI・Gemini・BedrockのPrompt Caching仕様と、Batch APIを組み合わせた実践的なコスト最適化手順を、個人開発者向けにコード付きで解説します。

約9分

はじめに:トークン課金は、だいたい「静かなサブスク」です

AI機能を個人開発に入れると、最初はだいたいこうなります。
「お、賢い!すごい!これは勝ち確!」
翌月の請求:「こんにちは、未来の自分です。先月の自分を止めてください。」

私も同じ道を歩きました。とくにエージェント系※を実装すると、毎回同じ長いシステムプロンプト、同じツール定義、同じドキュメント要約を投げがちです。ここにメスを入れないと、機能追加より先に財布が軽量化されます。軽量化したいのはコンテナ※であって、財布ではありません。

この記事では、2026年3月時点の公式情報をベースに、次の2つを組み合わせる実践手順を整理します。

  • Prompt Caching(同じ前半プロンプトの再計算を減らす)
  • Batch処理(急がないジョブを非同期で安く回す)

「RAG※をやめる」みたいな極論ではなく、普段の構成をなるべく崩さずにコストとレイテンシを落とすのが狙いです。

※エージェント: ツール呼び出しや複数ステップ処理を自律的に行うLLMアプリ設計。
※コンテナ: 実行環境を分離する仕組み。軽くすべきはこっち。
※RAG: Retrieval-Augmented Generation。検索で取り出した知識をプロンプトに注入する手法。

なぜ効くのか:Prompt Cachingは「前半の計算を使い回す」仕組み

Prompt Cachingの本質はシンプルです。入力の先頭(prefix)が同じなら、モデル内部の前計算を再利用する。
OpenAIのドキュメントでも、長い共通プレフィックスを繰り返すケースでレイテンシとコストを大きく下げられると明示されています。

実装上のポイントは次です。

  • キャッシュヒットは「先頭一致」が前提
  • 静的な情報は前に、可変情報は後ろに置く
  • 1回で短く詰め込むより、再利用しやすい構造にする

例えば、以下の並びはヒット率が上がりやすいです。

  1. system指示(固定)
  2. ツール定義JSON(ほぼ固定)
  3. ナレッジ要約(短期固定)
  4. ユーザーの都度入力(可変)

逆に、ユーザー入力を前に置いたり、毎回微妙に違うタイムスタンプ文字列を先頭に埋めると、キャッシュが崩れます。
「1文字違うだけで別物」になりうるので、プロンプト整形は地味に重要です。ここは“気合い”ではなく“整形ルール”で勝つ領域です。

2026年3月時点の仕様比較:OpenAI / Vertex AI / Bedrock

ここは実務で詰まりやすいので、要点を短く比較します。

OpenAI(Prompt Caching + Batch API)

OpenAIのPrompt Cachingは、一定以上の長さのプロンプトで自動適用されます。公式ガイドでは、1024トークン以上でキャッシュ対象、先頭一致が重要という説明です。さらにprompt_cache_keyでルーティングを助ける設計が可能です。

また、OpenAIはBatch APIを用意しており、非同期ジョブを24時間以内完了の前提で50%割引にできます。評価実行、分類、埋め込み作成など「急がない仕事」に最適です。

Vertex AI(GeminiのContext Caching)

Vertex AIのドキュメントでは、Implicit(自動)とExplicit(明示)キャッシュの2系統があります。
Implicitは既定で有効、ExplicitはTTL※管理を含めて自分で制御できます。共通prefixを先頭に置くのは同様です。

公式記載では、キャッシュヒット時の割引や、Explicitキャッシュの保存コスト、デフォルトTTL 60分などが重要な運用ポイントです。

Bedrock(Prompt Caching)

Bedrockも「チェックポイント」で先頭部分をキャッシュする方式です。
モデルごとの最小トークン要件(例: 1,024トークン)やTTL(5分、モデルによって拡張1時間)を意識する必要があります。

※TTL: Time To Live。キャッシュ有効期限。ここを超えると再計算が発生します。

結論として、各社で細部は違っても、設計原則はほぼ共通です。
「共通prefixを安定化し、期限内に再利用する」。これがコアです。

実装パターン:個人開発で一番効いた「二層キュー」

私が実運用で扱いやすかったのは、次の二層です。

  • リアルタイム層: ユーザー体験優先(Prompt Caching重視)
  • バックグラウンド層: 締切ゆるめ(Batch重視)

1) リアルタイム層(例: チャット応答)

  • 共通prefixを固定テンプレ化
  • セッション単位でprompt_cache_keyを設計
  • 可変メタ情報は末尾へ移動
// 動作未検証のサンプルです(設計イメージ)
import OpenAI from "openai";

const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY! });

const SYSTEM_PREFIX = [
  "あなたは開発者向けの技術アシスタントです。",
  "回答は敬体で、根拠が薄い点は明示してください。",
  "危険な操作は必ず確認を取ってください。",
].join("
");

export async function answer(userText: string, sessionId: string) {
  return client.responses.create({
    model: "gpt-5.1",
    prompt_cache_key: `sess:${sessionId}:v1`,
    input: [
      { role: "system", content: SYSTEM_PREFIX },
      { role: "user", content: userText },
    ],
  });
}

2) バックグラウンド層(例: 夜間の要約・分類)

  • 24時間以内でよい処理はBatchに集約
  • 同種ジョブを.jsonlでまとめて投げる
  • 完了時だけ通知して人間を起こす(深夜通知は敵です)
# 動作未検証のサンプルです
# 1) バッチ入力を作成
node scripts/build-batch-jsonl.js > jobs/nightly-summary.jsonl

# 2) ファイルをアップロードしてバッチ実行
# (実際のAPI呼び出しは各SDK/CLIに合わせて実装)

この二層に分けるだけで、リアルタイム体験を守りつつ、急がない処理の単価を落とせます。
「全部リアルタイムで処理したい症候群」を抑えるのが、運用ではわりと大事です。

計測しない最適化は、だいたい宗教:見るべき3指標

最適化でありがちな失敗は、効果測定なしで満足することです。
「速くなった気がする」は、たいてい気のせいか、たまたまです。

最低限、次の3つを見ます。

  1. cached_tokens / input_tokens(キャッシュ率)
  2. TTFT※(Time To First Token)
  3. リクエスト種別ごとの1件単価

OpenAIならusage情報でcached_tokensを確認できます。VertexやBedrockでもメタデータ側にキャッシュ関連のカウンタがあります。
これをダッシュボード化して、リリース前後で比較してください。

-- 例: ざっくりKPI集計(動作未検証)
SELECT
  DATE(created_at) AS d,
  AVG(cached_tokens * 1.0 / NULLIF(input_tokens, 0)) AS cache_hit_ratio,
  AVG(ttft_ms) AS avg_ttft_ms,
  AVG(cost_usd) AS avg_cost_usd
FROM llm_request_logs
WHERE created_at >= datetime('now', '-14 day')
GROUP BY DATE(created_at)
ORDER BY d;

※TTFT: 最初の1トークンが返るまでの時間。体感速度に直結します。

ハマりどころ:キャッシュが効かないのは「モデルのせい」だけではない

トラブルの8割は設計で回避できます。よくある落とし穴を先回りで挙げます。

  • 先頭に可変データを置く
    例: 現在時刻: 2026-03-24T11:59:59Z をsystem先頭に入れる。

  • ツール定義が毎回変わる
    JSONのキー順や説明文の空白差分でも崩れます。生成ではなく固定ファイル化推奨です。

  • TTLをまたいで再利用を期待する
    「昨日のキャッシュが残ってるはず」は、だいたい残っていません。

  • Batch向き処理をリアルタイムで回す
    緊急でない処理まで同期にすると、コストも待ち時間も悪化します。

  • 圧縮しすぎて品質が落ちる
    コスト削減に夢中で文脈を削り、回答精度が崩れるパターン。削る順序を決めましょう。

個人的には「prefix固定」と「ジョブ分離(即時/非即時)」の2つをやるだけでも、運用はかなり安定します。

30日導入プラン:とりあえずここまでやれば勝率が上がる

最後に、個人開発向けの現実的な30日プランです。

  • Day 1-3: ログ整備(input/cached/ttft/costを必ず記録)
  • Day 4-7: プロンプト再配置(固定prefixを先頭へ)
  • Day 8-12: prompt_cache_key戦略を導入
  • Day 13-18: 夜間ジョブをBatchへ移管
  • Day 19-24: TTL前提で再実行間隔を調整
  • Day 25-30: 品質劣化がないかAB比較して仕上げ

この順序のポイントは、先に可視化、次に最適化です。
先に最適化すると、改善したのか壊したのか判別不能になります。
開発はロマンですが、運用は算数です。算数は裏切りません(たまに私が計算を間違えますが、それは私の問題です)。

まとめ

Prompt CachingとBatch処理は、派手ではありません。ですが、個人開発のAI機能を長く回すには非常に効く「地味な必殺技」です。

  • リアルタイム処理はprefix設計で勝つ
  • 急がない処理はBatchで単価を下げる
  • 効果は3指標(キャッシュ率・TTFT・単価)で判断する

これだけ守ると、「便利だけど赤字」から「便利で継続可能」へ寄せられます。
AI時代の開発は、モデル選定だけでなく運用設計そのものが競争力です。
明日から実装するなら、まずは“先頭を固定する”ところからどうぞ。そこは無料で始められます。


参考リンク(2026-03-24確認)

  1. OpenAI Prompt Caching Guide
    https://platform.openai.com/docs/guides/prompt-caching
  2. OpenAI API Pricing
    https://openai.com/api/pricing/
  3. OpenAI Batch API Guide
    https://platform.openai.com/docs/guides/batch
  4. Google Cloud Vertex AI Context Caching Overview
    https://docs.cloud.google.com/vertex-ai/generative-ai/docs/context-cache/context-cache-overview
  5. Amazon Bedrock Prompt Caching
    https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html
  6. OpenAI Cookbook: Prompt Caching 201
    https://developers.openai.com/cookbook/examples/prompt_caching_201
Tags #AI #LLM #Prompt Caching #コスト最適化 #個人開発 #自動化