トークン予算実装ガイド
トークン予算はLLMコスト制御の運用レイヤーです。属性付けはお金の行き先を示しますが、予算は望まない場所に流れるのを防ぎます。予算がなければ、設定ミスのあるエージェントループやユーザートラフィックの急増が数時間で月間配分を使い切ってしまう可能性があります。このガイドでは、4種類のトークン予算を本番環境で実装する方法を、各パターンの疑似コード付きで説明します。
予算タイプ
| 予算タイプ | 粒度 | 適用方法 | ユースケース |
|---|---|---|---|
| リクエストごと | 単一のAPI呼び出し | max_tokensパラメーターによるハードリミット | 暴走する補完の防止、レイテンシの制限 |
| チームごとの割り当て | 期間内のチームまたはプロジェクト | アラート付きソフトリミット、しきい値でのハードリミット | 部門別コスト配分、1チームが共有予算を消費するのを防ぐ |
| 期間ごと | 日次、週次、月次 | グレースピリオド付きハードリミット | 月間予算上限、スプリントレベルの支出 |
| ワークフローごと | 単一のパイプラインまたはエージェント実行 | ステップごとおよび合計のハードリミット | マルチステップエージェント、RAGパイプライン、評価実行 |
リクエストごとの制限
最もシンプルな予算:すべてのリクエストをmax_tokensで制限します。これはオプションではありません - 本番のすべてのリクエストには明示的な出力トークン制限が必要です。これがないと、冗長なモデル応答が予期しないトークンを消費し、レイテンシを膨らませる可能性があります。
// リクエストごとの予算適用
function callLLM(prompt, config):
response = provider.complete(
prompt: prompt,
model: config.model,
max_tokens: config.max_output_tokens, // ハードキャップ
temperature: config.temperature
)
if response.usage.total_tokens > config.warn_threshold:
log.warn("リクエストがソフトリミットを超過",
tokens: response.usage.total_tokens,
threshold: config.warn_threshold
)
return response
チームごとの割り当て
チーム割り当てには、リクエスト間で持続する共有カウンターが必要です。パターン:各呼び出し前に残り予算をチェックし、予算が尽きた場合は拒否またはダウングレードします。
// Redis バックエンドのカウンターによるチーム割り当て
function checkTeamBudget(teamId, estimatedTokens):
key = "budget:" + teamId + ":" + currentPeriod()
remaining = redis.get(key) or getTeamQuota(teamId)
if remaining < estimatedTokens:
if remaining < estimatedTokens * 0.1:
return DENY // ハードリミット:リクエストを拒否
else:
return DOWNGRADE // ソフトリミット:安価なモデルを使用
return ALLOW
function recordUsage(teamId, actualTokens):
key = "budget:" + teamId + ":" + currentPeriod()
redis.decrby(key, actualTokens)
remaining = redis.get(key)
if remaining < getTeamQuota(teamId) * 0.2:
alert.quotaLow(teamId, remaining)
期間ごとの予算
期間ごとの予算はチーム割り当てを時間ウィンドウでラップします。重要な違い:グレースピリオドメカニズムが必要です。チームが月間予算の80%に達した場合、アラートを送信します。100%では、構成可能なグレースピリオド(例:24時間)を許可してからハード適用が開始されます。これにより、月末にチームがタスク途中でブロックされるのを防ぎます。
// グレースピリオド付き期間予算
function enforceBudget(teamId):
usage = getUsageForPeriod(teamId, currentMonth())
limit = getTeamMonthlyLimit(teamId)
if usage < limit * 0.8:
return ALLOW
if usage < limit * 1.0:
alert.budgetWarning(teamId, usage, limit)
return ALLOW // ソフト警告ゾーン
if usage < limit * 1.1 and withinGracePeriod(teamId):
alert.budgetExceeded(teamId, usage, limit)
return ALLOW // グレースピリオド:超過を許可
return DENY // ハードストップ
ワークフローごとの予算
マルチステップエージェントとパイプラインには2つのレベルの予算が必要です:ステップごと(単一ステップが消費しすぎるのを防止)と実行ごと(パイプライン全体が割り当てを超過するのを防止)。ワークフローコンテキストの両方を追跡します。
// ワークフロー予算トラッカー
class WorkflowBudget:
constructor(maxPerStep, maxTotal):
this.maxPerStep = maxPerStep
this.maxTotal = maxTotal
this.spent = 0
function callStep(stepFn, prompt):
if this.spent >= this.maxTotal:
return fallbackResponse("予算超過")
response = callLLM(prompt, {
max_tokens: min(this.maxPerStep,
this.maxTotal - this.spent)
})
this.spent += response.usage.total_tokens
return response
予算超過時のグレースフルデグラデーション
予算に達したときにエラーを返すだけにしてはいけません。グレースフルにデグレードします。安価なモデルに切り替える(GPT-4oの代わりにGPT-4o-mini)、コンテキストウィンドウサイズを縮小する、オプションの処理ステップをスキップする、または完全な処理には予算承認が必要であるというメモ付きで部分的な結果を返します。ユーザーエクスペリエンスは壊れるのではなく、低下すべきです。
// デグラデーションチェーン
function callWithDegradation(prompt, config):
if checkBudget(config.teamId, FULL_MODEL):
return callLLM(prompt, { model: config.primaryModel })
if checkBudget(config.teamId, CHEAP_MODEL):
log.info("予算のためモデルをダウングレード")
return callLLM(prompt, { model: config.fallbackModel })
if checkBudget(config.teamId, MINIMAL_TOKENS):
truncated = truncateContext(prompt, 50%)
return callLLM(truncated, {
model: config.fallbackModel,
max_tokens: 256
})
return cachedOrFallback(prompt)
予算の健全性監視
3つの指標を追跡します:バーンレート(1時間あたりの消費トークン 対 予算)、予測(現在のレートで予算がいつ枯渇するか)、オーバーライド回数(グレースピリオドが何回使用されたか)。グレースピリオドの使用が総リクエストの10%を超える場合、予算がワークロードに対して低すぎます。
関連項目
- LLM予算ガバナンス - 予算背后的組織ポリシー。
- エージェント支出ガードレール - 自律エージェントの予算パターン。
- 推論コストの上限設定方法 - プロバイダー側のコスト制御。
これをご自身のLLM支出に適用しませんか?FinOps LLMはAIコストの無料監査を実行し、削減のポイントを示します。無料監査を予約 →