LLMアプリのAPIコスト高騰を防ぐ、コンテキスト管理と節約設計
LLMアプリのAPIコストは設計で決まります。プロンプトキャッシュ前置・履歴圧縮・軽量モデル分担など、実務で効くコンテキスト管理パターンを整理します。
LLMアプリを作り始めると、最初に気になるのは「どのモデルを使うか」です。 しかし、運用フェーズで本当に効いてくるのは モデル選定よりも、APIに何をどれだけ送っているか です。
LLM APIのコストは、基本的に「入力トークン」「出力トークン」「会話履歴」「ツール呼び出し」「推論用トークン」などの積み上げで増えます。OpenAIの公式ドキュメントでも、コスト削減の基本方針として、リクエスト数を減らす、入力・出力トークンを減らす、小さめのモデルを選ぶ、といった戦略が挙げられています。(OpenAI Platform)
つまり、APIコスト節約の本質はこうです。
「毎回、全部読ませる」のをやめる。
コンテキストは“記憶”ではなく“作業机”
LLMに渡すコンテキストは、人間でいう記憶というより「いま机の上に広げている資料」です。 必要な資料が置かれていればよい回答ができますが、無関係な資料まで山積みにすると、コストも遅延も増え、場合によっては回答品質も落ちます。
よくある失敗は、チャット履歴をそのまま全量送り続ける設計です。
最初の数ターンでは問題ありません。しかし、会話が長くなるにつれて、1回の質問に対して過去のやり取り全体を再送することになります。ユーザーが「さっきの件だけど」と言ったときに必要なのは、過去ログ全文ではなく、関連する決定事項・制約・直近の文脈だけです。
OpenAIのResponses APIでは、previous_response_id などを使って会話状態を扱いやすくできますが、過去の入力トークンが無料になるわけではありません。公式ドキュメントでも、previous_response_id を使ってもチェーン内の過去入力トークンは入力トークンとして課金対象になると説明されています。(OpenAI Platform)
コストを下げるコンテキスト設計
実務では、コンテキストを次の4層に分けると管理しやすくなります。
1つ目は 固定指示 です。 システムプロンプト、出力形式、禁止事項、トーン、役割定義など、毎回変わらない情報です。
2つ目は ユーザー・セッション情報 です。 ユーザーの目的、設定、現在のタスク、進行中のプロジェクトなどです。
3つ目は 直近の会話 です。 最後の数ターンだけを残します。すべての履歴ではなく、いまの応答に必要な近傍文脈だけを渡します。
4つ目は 検索・取得した外部知識 です。 ドキュメント、FAQ、DB、社内ナレッジなどから、今回の質問に関係する部分だけを取得して渡します。
この4層を分けずに、全部を1つの巨大なプロンプトに詰め込むと、どこを削ってよいか分からなくなります。逆に層を分けておけば、「固定指示はキャッシュしやすくする」「古い会話は要約する」「外部知識は検索で必要分だけ取る」といった最適化ができます。
プロンプトキャッシュを効かせる
コスト節約で特に重要なのが、プロンプトキャッシュです。
OpenAIのプロンプトキャッシュは、同じようなプロンプトを再処理せずに済むようにし、レイテンシと入力トークンコストを下げる仕組みです。公式ドキュメントでは、プロンプトキャッシュによりレイテンシを最大80%、入力トークンコストを最大90%削減できる可能性があると説明されています。(OpenAI Platform)
ただし、キャッシュを効かせるにはプロンプトの構造が重要です。 キャッシュヒットは「完全に一致する先頭部分」に対して起こるため、固定の指示・ルール・例・ツール定義などはプロンプトの前半に置き、ユーザーごとに変わる内容は後半に置くのが基本です。(OpenAI Platform)
悪い例はこうです。
ユーザーID: 12345現在時刻: 2026-04-24今回の質問: ...あなたは優秀なサポートAIです。回答ルールは...FAQ一覧は...この形だと、冒頭が毎回変わるため、共通部分がキャッシュされにくくなります。
良い例はこうです。
あなたは優秀なサポートAIです。回答ルールは...FAQ一覧は...出力形式は...
--- ここから可変情報 ---ユーザーID: 12345現在時刻: 2026-04-24今回の質問: ...固定部分を前に、可変部分を後ろに置く。 これだけで、同じアプリ内のリクエストがキャッシュに乗りやすくなります。
また、OpenAIでは prompt_cache_key を使うことで、共通プレフィックスを持つリクエストのキャッシュヒット率を高めやすくなります。公式ドキュメントでは、同じプレフィックスを共有するリクエストでは prompt_cache_key を一貫して使うことが推奨されています。(OpenAI Platform)
長い会話は“要約”ではなく“圧縮”する
会話履歴を短くする方法として、単純に古い発話を削るだけでは不十分です。重要な制約や決定事項まで消えてしまうからです。
そこで使うのが コンテキスト圧縮 です。
たとえば、10ターン分の会話を次のような状態メモに変換します。
現在の目的:- ユーザーはECサイト向けの商品推薦Botを作っている
決定済み仕様:- 回答は日本語- 価格帯、在庫、レビュー件数を考慮する- 出力はJSON
未解決事項:- レコメンド理由を短文にするか詳細にするか未定
注意点:- 存在しない商品を生成しないこのように、古い会話を「全文」ではなく「状態」に変換します。 LLMアプリに必要なのは、過去ログそのものではなく、次の応答に影響する状態です。
OpenAIのドキュメントでも、長時間のインタラクションではコンパクションを使って、後続ターンに必要な状態を保持しながらコンテキストサイズを減らす方法が説明されています。サーバーサイドのコンパクションでは、context_management と compact_threshold を設定することで、しきい値を超えたときに圧縮を走らせることができます。(OpenAI Platform)
出力トークンも制御する
コスト削減というと入力ばかりに目が行きますが、出力も大きなコスト要因です。
特に、モデルに「詳しく説明して」と毎回頼む設計は危険です。 ユーザーが求めているのが分類・判定・抽出であれば、長文回答は不要です。
たとえば問い合わせ分類なら、こう返せば十分です。
{ "category": "billing", "priority": "high", "needs_human": true}このように、JSONや固定フォーマットで返させると、出力トークンを抑えやすくなります。 要約、分類、タグ付け、ルーティング、スコアリングのような処理では、自然文の説明を毎回生成させない設計が有効です。
小さいモデルに任せる処理を分ける
すべてを高性能モデルに投げる必要はありません。
たとえば、次のように役割を分けます。
軽量モデル:- 入力分類- 言語判定- 意図判定- 簡易要約- NGチェック- 検索クエリ生成
高性能モデル:- 最終回答- 複雑な推論- 長文生成- 仕様設計- コードレビューこの構成にすると、高価なモデルの呼び出し回数と入力サイズを減らせます。 重要なのは「安いモデルを使う」ことではなく、高いモデルにしかできない仕事だけを渡す ことです。
非同期処理はBatchや低優先度処理を使う
リアルタイムで返す必要がない処理は、同期APIで逐次実行しない方がよい場合があります。 OpenAIの公式ドキュメントでは、コスト削減手段としてBatch APIやflex processingが紹介されています。Batch APIは複数リクエストをまとめて非同期処理する仕組みで、flex processingは遅い応答や一時的なリソース制約を許容する代わりに低コストで処理する選択肢です。(OpenAI Platform)
向いているのは、次のような処理です。
- 大量レビューの要約- FAQデータの整形- 商品説明文の下書き生成- ログ分析- 評価データセットの採点- 社内文書のタグ付けユーザーが画面の前で待っている処理と、裏側で後から完了すればよい処理は分けて設計しましょう。
計測しないと節約できない
APIコストは、感覚では最適化できません。
最低限、次の項目をログに残します。
- model- input_tokens- output_tokens- cached_tokens- total_tokens- latency_ms- user_id または session_id- endpoint / feature name- request purpose特に cached_tokens は重要です。OpenAIのAPIでは、プロンプトキャッシュにヒットしたトークン数を usage.prompt_tokens_details.cached_tokens で確認できます。(OpenAI Platform)
見るべき指標は、単なる総コストではありません。
- 1ユーザーあたりの月間コスト- 1会話あたりの平均コスト- 1機能あたりの平均コスト- キャッシュヒット率- 入力:出力のトークン比率- 高性能モデルの呼び出し比率このあたりを見れば、「どの機能が無駄に高いか」「どのプロンプトが肥大化しているか」「キャッシュが効いていない箇所はどこか」が分かります。
まとめ
APIコストを下げるコツは、単に安いモデルを選ぶことではありません。
重要なのは、以下の設計です。
- 固定プロンプトを前に置く- 可変情報を後ろに置く- 会話履歴を全文で送らない- 古い履歴は状態メモに圧縮する- 必要な外部知識だけ取得する- 出力フォーマットを絞る- 軽量モデルと高性能モデルを使い分ける- 非同期処理はBatch系に逃がす- token / cached_tokens / latency を計測するLLMアプリのコストは、使えば使うほど自然に増えるものではありません。 設計が雑だと増え、設計がうまいと抑えられます。
コンテキスト管理とは、単なる履歴管理ではありません。 それは、モデルに「いま本当に必要な情報だけ」を渡すための編集作業です。 この編集がうまいほど、APIコストは下がり、応答速度は上がり、回答品質も安定します。
関連記事として AIエージェントに実装を任せる前に書くべき指示テンプレート では、固定指示を短く保つための書き方を、AGENTS.md / CLAUDE.mdに何を書くべきか ではルールファイルの最小構成をまとめています。
Further reading
Claude CodeとCodexはどう使い分けるべきか: 個人開発者向けの現実的な判断基準
Claude CodeとOpenAI Codexの違いを、個人開発者の実務目線で比較し、用途別の使い分けを整理します。
CodexのPC操作アップデートで、開発者の仕事はどこまで任せられるか
Codexがアプリ操作、ブラウザ、PRレビュー、複数ターミナルに踏み込んだことで、エージェントへの任せ方はどう変わるのかを整理します。
Agents SDKのサンドボックス実行で見る、エージェントアプリの新しい最小構成
OpenAI Agents SDKの更新をもとに、ファイル・コマンド・編集を扱うエージェントを安全に設計するための実務ポイントをまとめます。