7月14日、Kanwal Mehreenが「12 Ways to Reduce LLM Latency and Inference Costs in Production」と題した記事を公開した。この記事では、本番環境でのLLMレイテンシと推論コストを削減するための12の実践的手法について詳しく紹介されている。
プロトタイプでは問題なく動いていたLLMアプリが、本番に出た途端に遅くなり、コストが膨らむ——この現象に直面したエンジニアは多い。原因はRAGパイプラインによるコンテキスト肥大、エージェントの多段ツール呼び出し、トークン上限の緩い設定などだ。記事の核心にある主張は明快である。「解決策はより大きなモデルやGPUの増強ではなく、そもそもやらなくていい処理を削ることだ」。
最初にやるべきこと:正しいメトリクスの計測
最適化の前に、どこで時間を消費しているかを把握する必要がある。エンドツーエンドのレイテンシだけを見ていても原因は特定できない。計測すべき指標として以下が挙げられている。
- TTFT(Time to First Token):最初のトークンが返るまでの時間。高い場合はプロンプトの長さ、検索の遅延、またはキューの詰まりが原因である可能性が高い
- トークン間レイテンシ:モデルのサイズ過剰、GPUの過負荷、バッチング設定の問題を示すことがある
- キャッシュヒット率:繰り返し処理を回避できているかの指標
- P95・P99レイテンシ:平均値より末尾レイテンシが実際のユーザー体験に直結する
「計測なしに最適化すると、ボトルネックでない箇所を改善してしまうことが多い」と記事は指摘する。
最も即効性の高い施策:出力トークンの削減
全手法の中で費用対効果が最も高いのが出力トークンの削減だ。モデルはトークンを逐次生成するため、応答が2倍長ければレイテンシもコストも概ね2倍になる。他の手法がインフラ構成や設計変更を伴うのに対し、出力削減はプロンプト修正とパラメータ設定だけで即座に効果が出るため、着手の優先度が高い。
具体的な対策として以下が示されている。
max_tokens(最大補完数)を現実的な値に設定する- ユーザーが不要な場合は簡潔な回答を求める
- モデルに質問を言い直させない
- JSONスキーマはコンパクトに、フィールド名は短く
- 不要なサマリー、免責事項、繰り返しコンテキストを除去する
- UIで「簡潔モード」と「詳細モード」を分ける
「ユーザーが読まないトークンに金を払うな」というのが記事の表現だ。社内サポートアシスタントなら700語の解説は不要で、箇条書き3点とソースリンクで十分という例が挙げられている。
プレフィックスキャッシュを活かすプロンプト設計
プロンプトキャッシングは、長い繰り返しプロンプトのコストと時間を削減する手法として効果的だ。キャッシュを最大限に活用するにはプロンプトの構造に注意が必要である。
- 前半に置くべき固定コンテンツ:システム指示、安全ポリシー、ツール定義、Few-shotサンプル、プロダクトドキュメント
- 後半に置くべき可変コンテンツ:ユーザーリクエスト、会話履歴、タイムスタンプ、検索結果
可変コンテンツをプロンプトの前半に置くと、キャッシュ可能なプレフィックスが無効化される。この順序を守るだけで、毎リクエストのコンテキスト処理をキャッシュヒットに変換できる。
残り9手法の要点
モデルルーティング(手法3):感情分析、データ抽出、FAQへの回答など構造化された繰り返しタスクは、小型モデルで十分なことが多い。難度の高いリクエストのみ高性能モデルにエスカレーションするルーティング設計が有効だ。
LLM呼び出し回数の削減(手法4):「分類→リライト→検索→要約→生成→批評→リライト」のように逐次呼び出しを重ねるのは典型的な失敗パターンだ。日付フォーマット、バリデーション、権限チェック、計算処理には決定論的なコードを使うべきで、独立したタスクは並列実行する。
ストリーミングの活用(手法5):モデルの実際の処理時間は変わらなくても、レスポンスをストリーミングで返すことでユーザーが感じる待ち時間を大幅に短縮できる。最初のトークンが届いた瞬間からユーザーは読み始められるため、体感レイテンシの改善に直結する。UIに「考え中…」といったプログレッシブな表示を組み合わせることも推奨されている。
複数キャッシュ層の追加(手法6):完全一致のレスポンスキャッシュ、意味的類似度によるセマンティックキャッシュ(「メールアドレスの変更方法は?」と「アカウントのメールを更新できますか?」は同一回答を返せる)、検索結果・埋め込みのキャッシュ、ツール出力のキャッシュを組み合わせることが推奨されている。
RAGのコンテキスト予算管理(手法7):「念のため全部入れる」発想は逆効果だ。多すぎるコンテキストはプロンプトを肥大化させ、モデルが無関係な情報の中から答えを探すことになり精度も落ちる。システム指示・検索コンテキスト・チャット履歴・出力それぞれにトークン予算を設定する。
バッチ処理への移行(手法8):データラベリング、評価実行、一括要約、レポート生成はリアルタイムで処理する必要がない。バックグラウンドジョブをインタラクティブトラフィックから切り離すことで、ユーザー向けシステムのリソースが守られる。
バッチングのチューニング(手法9):GPUの稼働率最大化を目標にすると、ユーザーの体験が犠牲になる。P95・P99のTTFTを基準にバッチングを調整すべきだ。自ホストモデルでは、完了したリクエストをバッチから離脱させながら新リクエストを受け入れる「コンティニュアスバッチング」が有効である。
KVキャッシュとコンテキスト長の管理(手法10):Key-Valueキャッシュはトークン生成に必要な情報を格納するが、コンテキストが長くなるほどGPUメモリを圧迫する。最大コンテキスト長・最大出力長・同時リクエスト数・ツール出力サイズに現実的な上限を設定する。「モデルがサポートしているからといって最大コンテキストウィンドウを公開する必要はない」と記事は述べている。
本番トラフィックでのベンチマーク(手法11):量子化、スペキュラティブデコーディング、テンソル並列などのサービング最適化は、ワークロードによって効果が異なる。孤立したベンチマーク数値やトークン毎秒の公称値だけを信頼するのは禁物で、実際のプロンプト長・出力長・並列数・キャッシュヒット率を使って検証する必要がある。
アドミッションコントロールとグレースフルデグラデーション(手法12):トラフィックスパイク時に備え、ユーザーごとのレート制限、優先度キュー、より小さなモデルへのフォールバック、オプションのエージェントステップを無効化する仕組みを持つべきだ。「全リクエストがキューに積み上がってシステム全体が使い物にならなくなるよりも、グレースフルデグラデーションの方がはるかにマシだ」としている。
詳細は12 Ways to Reduce LLM Latency and Inference Costs in Productionを参照していただきたい。