LLMのAPIは入力トークンと出力トークンの従量課金なので、開発中は気にならなくても、本番で継続的に叩くようになると請求額が地味に効いてくる。自分のツールやAPIサーバーに組み込んで運用している人向けに、コストを抑える実践的なテクニックを整理しておく。金額は変動するので、正確な単価は必ず各社の公式料金ページで確認してほしい。ここでは考え方を中心に書く。
(1) モデルの使い分け
一番効くのはこれ。すべてのリクエストを最上位モデルに投げるのはコスト的に無駄が多い。分類・要約・簡単な抽出のようなタスクは、小型で安価なモデルでも十分な精度が出ることが多い。逆に複雑な推論やコード生成のような難しいタスクだけ上位モデルに回す、という使い分けをするだけでコストは大きく変わる。
- 簡単なタスク(分類、簡易な要約、定型応答) — 小型・低価格モデル
- 難しいタスク(複雑な推論、長文の設計、コード生成) — 上位モデル
「とりあえず一番賢いモデルで統一」は開発中は楽だが、本番で継続的に流すバッチ処理などは一度モデル別のコスト試算をしておいた方がいい。
(2) プロンプトキャッシュ
繰り返し使う長い前提(システムプロンプトや参照ドキュメントなど)をキャッシュして、入力コストを大幅に削減できる仕組み。AnthropicもOpenAIも対応している。
Anthropicの場合、システムプロンプトなどの固定的なブロックにcache_controlを付けることでキャッシュ対象にできる。キャッシュを書き込む1回目はやや割高になるが、2回目以降の読み取りはかなり安くなる。仕組み上、プレフィックス(先頭からの一致)でキャッシュされるので、リクエストのたびに変わる値(タイムスタンプなど)を先頭に入れてしまうとキャッシュが効かなくなる点は注意したい。固定部分を前に、変わる部分を後ろに置く、という組み立てを意識するだけでヒット率が変わってくる。
(3) バッチ処理
結果をすぐに受け取る必要がない大量処理は、Batch APIを使うと通常の半額程度の割引になることが多い。夜間バッチでまとめて処理するようなユースケース(大量の要約生成、大量データの分類など)には向いている。リアルタイム応答が要らないタスクをリアルタイムAPIで流しているなら、まずここを見直す価値がある。
(4) 出力を絞る
出力トークンは入力より単価が高いことが多いので、無駄な出力を減らすのも効果が大きい。
max_tokensを用途に見合った値に設定する(必要以上に大きくしない)- 「簡潔に答えて」「箇条書きで」など、出力を絞るプロンプトを入れる
- 不要な前置きや繰り返しの説明を出さないよう指示する
特にAPI経由でシステムに組み込む用途では、人間向けの丁寧な前置きは不要なことが多い。プロンプト側で「結論だけ返して」と指定するだけでも出力トークンはかなり減る。
(5) コンテキストを渡しすぎない
会話履歴やRAGで検索してきたチャンクを、必要以上に長く渡していないか確認する。特に長い会話を続けるチャットボットや、検索結果を大量に詰め込むRAGの実装では、気づかないうちに入力トークンが膨れ上がっていることがよくある。
- 会話履歴は直近の必要な分だけに絞る(古い履歴は要約して圧縮する)
- RAGの検索結果は関連度の高い上位数件に絞る
- 定期的にトークン数を計測して、想定より膨らんでいないか監視する
この監視を怠ると、機能追加を重ねるうちに気づいたら1リクエストのトークン数が倍以上になっていた、というのはよくある話。
(6) ローカルLLMの併用
開発中の動作確認や、定型的な大量処理であれば、Ollamaなどでローカルに立てたLLMをOpenAI互換APIとして使う手もある。クラウドAPIと同じインターフェースで叩けるものが多いので、開発時はローカルモデルで検証し、本番の重要な処理だけクラウドの上位モデルに切り替える、という構成にすればAPIコストをゼロに近づけられる場面もある。VPSのスペック次第では小型モデルなら十分動くので、検証環境として持っておくと便利だ。
まとめ
LLM APIのコストは、モデルの使い分け・プロンプトキャッシュ・バッチ処理・出力の絞り込み・コンテキストの適正化、といった基本を押さえるだけでかなり抑えられる。派手なテクニックというより地味な積み重ねなので、まずは自分のリクエストがどのトークンをどれだけ使っているか可視化するところから始めるのがいい。単価は変わりやすいので、コスト試算のたびに公式の料金ページを見に行く習慣も付けておきたい。
