Tech カテゴリのイメージ

LLMアプリの費用をどう測る?トークン数から成功一件当たりの原価まで

LLMの費用を月末の請求額だけで見ていると、どの機能、利用者、モデル変更が増加の原因か分からない。反対に、API応答のトークン数だけを足しても、検索、コード実行、音声、画像、再試行、アプリ基盤の費用が抜ける。

運用で必要なのは、一回のモデル呼び出し、利用者が完了させた一つの仕事、請求期間の三つの粒度をつなぐことである。最終的には、品質条件を満たして完了した仕事一件にいくらかかったかを測る。

トークンは利用量であり請求額そのものではない

テキストモデルの応答には、入力トークン、キャッシュ済み入力トークン、出力トークン、推論トークンなどの利用量が含まれる。どの区分をどの単価で課金するかは、モデルと処理方式によって異なる。

入力と出力が同じ単価とは限らない。キャッシュ済み入力、Batch API、優先度の異なる処理にも別の条件がある。検索やファイル処理など、トークン以外に道具の呼び出し料金や保存料金が発生する機能もある。

そのため、総トークン数に一つの単価を掛けるだけでは正しい見積もりにならない。利用量は区分別に保存し、計算時点の公式料金表と結び付ける。

見える文章より出力トークンが多い場合がある

画面に表示した文字だけを再びトークン化しても、APIが報告する利用量と一致しないことがある。OpenAIのToken counting資料では、報告される出力トークンには、表示テキストだけでなく、推論、道具呼び出し、応答構造のために生成された非表示のトークンが含まれ得ると説明されている。

入力も同様である。開発者指示、会話履歴、道具定義、JSON Schema、画像、ファイル、検索結果など、利用者が入力欄へ書いた文章以外もモデルへ渡される。

費用の記録には、手元で文章を数え直した推定値より、APIが返した usage を使う。送信前の上限確認には、対象APIが提供するToken counting機能を使うと、道具やファイルを含む実際の要求形式に近い値を得られる。

一回の応答に必要な記録を決める

モデル呼び出しごとに、少なくとも次を保存する。

  • 自分のアプリで発行した要求IDと作業ID
  • 機能名、環境、顧客や組織を示す内部ID
  • 提供者、モデル、処理方式、リージョン
  • 入力、キャッシュ済み入力、出力、推論の各トークン数
  • 検索やコード実行など有料の道具の種類と回数
  • 成功、失敗、取消、期限切れの状態
  • 要求開始、最初の応答、完了の時刻
  • プロンプト、道具定義、ルーティング規則の版

プロンプト本文や利用者の生の識別情報を費用分析のために保存する必要はない。安全な内部IDと版を使い、内容ログとは保持期間と権限を分ける。

提供者の要求IDも記録しておくと、請求の差異や障害を調べやすい。ただし、提供者側のIDをアプリの重複防止キーや業務上の正本にしない。

モデル呼び出しを一つの仕事へ束ねる

AIエージェントやRAGでは、一回の利用者操作から複数のモデル呼び出しが発生する。質問の書き換え、検索、回答生成、自己評価、道具呼び出し後の再生成を個別に数えるだけでは、利用者が一つの回答を得る費用が分からない。

すべての呼び出しに同じ作業IDを付け、次を合計する。

  • モデル呼び出しの各費用
  • 埋め込み、検索、再ランキングの費用
  • Web検索、ファイル検索、コード実行などの道具費用
  • 失敗と再試行で消費した費用
  • 必要ならアプリ基盤や人手確認の費用

サブエージェントを使う場合も、親の作業IDへ結び付ける。個別の呼び出しが安くても、呼び出し回数が増えれば一つの仕事は高くなる。

成功一件当たりで比較する

一要求当たりの平均費用だけでは、安いモデルが何度も失敗し、高いモデルへ昇格した影響を見落とす。分母をAPI要求数ではなく、品質条件を満たして完了した業務件数にする。

例えば問い合わせ回答なら、応答を返しただけで成功とせず、根拠の一致、必要項目、利用者による解決、重大な安全違反なしなど、機能に合う成功条件を決める。

同時に次の指標を見る。

  • 成功一件当たりの総費用
  • 失敗一件当たりに消費した費用
  • 一仕事当たりのモデル呼び出し数
  • 再試行率と上位モデルへの昇格率
  • 機能、顧客、モデル、構成版ごとの分布
  • 費用と品質、遅延の関係

平均だけでは一部の長い会話や異常なループが隠れる。中央値に加えて上位百分位と最大値を確認する。

見積もりと確定請求を分ける

API応答の利用量と料金表から、その場で概算費用を計算できる。ただし、月次の会計や請求照合では、提供者のCosts APIや請求画面を正本として扱う。

OpenAIのUsage APIは、モデル、プロジェクト、利用者、APIキー、Batch利用などの区分で利用量を集計できる。Costs APIは請求上の支出を確認するための別の経路である。公式資料も、利用量と費用は集計時差などで完全に一致しない場合があり、財務上はCosts側を使うよう案内している。

アプリ側の概算と提供者側の確定値には、次のような差が生じる。

  • 料金表を更新した時刻と実行時刻のずれ
  • 利用量の集計遅延
  • 道具、保存、画像、音声など別体系の料金
  • 税、割引、クレジット、契約条件
  • 欠落、重複、取消途中の記録

日次または月次で、アプリの合計、Usage API、Costs APIを照合し、差が一定範囲を超えたら調べる。

単価には適用期間を持たせる

料金は変わり得る。現在の料金表を過去の利用量へ掛け直すと、当時の原価と異なる値になる。

モデル名、処理方式、単価、通貨、適用開始日時、参照した料金表のURLを版として保存する。実行時刻に対応する単価を選び、概算を再現できるようにする。

固定したモデル名でも、提供者の価格体系や含まれる機能が更新される可能性がある。記事や運用手順へ具体的な金額を固定せず、実装時には公式料金表を確認する。

通貨換算が必要なら、API費用と為替換算後の社内費用を別項目にする。どの時点の為替を使ったかを記録しないと、モデル改善と為替変動を区別できない。

予算は警告・制御・請求上限に分ける

予算超過への対策は、一種類ではない。

最初に、一定額へ近づいたことを知らせる警告を置く。次に、アプリ側で一利用者、一作業、一日ごとのトークン数、呼び出し回数、道具回数を制御する。最後に、提供者側のプロジェクトや組織の支出上限を設定する。

OpenAIのSpend limits資料では、通知用のSpend alertと、要求を止めるHard spend limitを区別している。Hard limitの反映は瞬時ではなく、記録額が設定値を少し超える場合がある。また、上限へ達すると本番APIが 429 で失敗する。

したがって、Hard limitだけを唯一の安全装置にしない。利用者へ影響する前に警告し、低優先度のバッチを止め、出力上限を下げ、必要なら安全な縮退運転へ切り替える。

上限到達とレート制限を区別する

同じ 429 でも、短時間の要求数やトークン数が多すぎるレート制限と、月間の支出上限やクレジット不足は原因が異なる。

短時間のレート制限には、待機、指数バックオフ、並列数の抑制が有効である。支出上限へ達した要求を同じ条件で再試行しても回復しない。エラーコードを確認し、予算担当への通知や縮退へ切り替える。

エラーをすべて同じ再試行キューへ入れると、不要な要求とログが増え、復旧後に古い仕事が一斉に流れる。原因別に終了条件を持つ。

費用削減は品質を固定して比べる

入力を短くする、小さいモデルへ替える、出力上限を下げる、キャッシュやBatch APIを使うと、費用は減る可能性がある。しかし、回答品質が落ちて再質問や人手修正が増えれば、仕事全体では高くなる。

変更前後で同じ評価データを使い、品質、成功一件当たりの費用、完了時間を比較する。一度に複数の変更を入れると、どれが効いたか分からない。

削減候補は大きい順に探す。まず不要な呼び出しとループ、次に長すぎる入力と出力、その後にモデル選択、キャッシュ、バッチ処理を検討する。小さな文字列最適化より、使われていない呼び出しを一回なくす方が効果は明確である。

個人情報を費用ラベルへ入れない

顧客別、チーム別、機能別の配賦にはラベルが必要だが、メールアドレスや氏名をそのまま提供者のメタデータや監視基盤へ送らない。内部で発行した疑似IDを使い、対応表への権限を限定する。

ラベルの種類も増やしすぎない。要求ごとに無制限の値を持つと、監視基盤の集計費用と検索負荷が増える。詳細な要求IDはログに、集計に使う機能名、環境、顧客区分、構成版は指標に分ける。

費用観測のために本文、検索資料、道具結果を長期間保存しない。トークン区分、状態、版、時間だけで調査できる範囲を先に広げる。

LLMの費用管理は、トークン単価を眺める作業ではない。一回のAPI利用量を作業IDで束ね、品質条件を満たした完了件数へ結び付け、提供者の確定費用と照合する運用である。見積もり、警告、制御、請求照合を分ければ、突然の増加を止めるだけでなく、どの改善が本当に原価を下げたかを判断できる。

参照資料

生成AI・機械学習講座の一覧へ