生成AI予算を超えても仕事は止めない、Jamf式の段階制限

Amazon Bedrockの費用を利用者別に制御するには、呼び出しログをS3へ保存し、Athenaで当日のトークン費用に変換する。その結果を定期実行するLambdaで判定し、高価格モデルだけをIAMの明示的拒否へ追加すれば、予算到達後も低価格モデルを使った業務は継続できる。
AWSが公開したJamfの本番構成 では、日次予算の80%でClaude Opus、100%でClaude Sonnetを拒否し、Claude Haikuは利用可能なまま残す。判定は15分ごとに行われ、制限は次の日次リセットで自動解除されるほか、正当な追加利用には期限付きの上限変更を設定できる。
計測・判定・制御を非同期につなぐ

この方式は、Bedrockの推論リクエストに予算判定を同期的に挟むものではない。蓄積したログを一定間隔で集計し、その時点の状態を次回以降の呼び出しへ反映するため、厳密な即時上限ではなく、ログ配送と集計間隔を含む準リアルタイム制御になる。
- IAM Identity Centerのセッションから利用者を識別できるようにする。
- Bedrockのモデル呼び出しログをS3へ配送する。
- Athenaで利用者別、モデル別の当日費用を算出する。
- EventBridgeでLambdaを定期起動し、費用を日次予算で割って到達率を求める。
- 到達した段階に応じて、対象モデルを拒否するIAM Customer Managed Policyを更新する。
- DynamoDBの例外と前回状態を照合し、必要な変更と通知だけを実行する。
制御状態は、80%未満、80%以上100%未満、100%以上のように分け、それぞれで利用可能なモデル集合を決める。高価格モデルを先に外し、業務上必要な低価格モデルを最後まで残すことが、「仕事は止めない」という設計の中身である。
ログから利用者とトークン数を確実に取り出す
モデル呼び出しログはデフォルトで無効なので、S3バケットを作成しただけでは記録されない。Bedrockの呼び出しログ仕様 では、ログにmodelId、identity.arn、入力・出力トークン数が含まれ、S3の保存先はログ設定と同じAWSアカウント、同じリージョンに置く必要がある。
identity.arnはリクエストを実行したIAMまたはSTSプリンシパルを表す。共有ロールを使う場合はセッション名だけで個人を安定して識別できるとは限らないため、呼び出し側が付与できるrequestMetadataも候補になる。ただしrequestMetadataは利用者側から渡される値なので、予算台帳との対応、欠落時の扱い、値を信頼できる経路をあらかじめ定める必要がある。
集計キーは、一時的なセッション名や表記揺れのあるメールアドレスをそのまま採用せず、IAM制御に使うsaml:subなどの識別子へ一意に対応させる。導入前に、一人の利用が複数キーへ分裂しないことと、別人の利用が同じキーへ混ざらないことをテストする。
Athenaで当日分の推定費用へ変換する

S3上のJSONログにAthenaテーブルを定義し、その上に「利用者×日」を基本単位とする費用ビューを作る。各呼び出しの入力トークン数と出力トークン数へモデル別単価を掛け、モデルごとの小計を利用者単位で合算する。入力と出力の単価が異なる場合は、別々に計算してから加算する。
料金マッピングには、モデルID、入力単価、出力単価、対象リージョン、適用開始日を持たせる。新しいモデルを許可するときは対応する単価の登録も必須にし、未登録モデルをゼロ円として扱わない。Jamfの実装例と同様に最高価格帯で暫定計算するか、判定を保留して警告するかは運用方針として決める。
判定用ビューが返す主な列は、利用者ID、集計日、モデル別の入力・出力トークン数、推定費用、適用予算、予算到達率である。この計算は請求書の完全な再現ではなく、アクセス制御のための運用上の推定値と位置付ける。通貨、単価の単位、端数処理、日次窓の基準タイムゾーンを固定しなければ、境界付近で判定が揺れる。
到達率をIAMのモデル別拒否へ変える
LambdaはAthenaクエリを開始し、完了状態を確認してから結果を読む。Athenaは非同期で処理されるため、送信直後に結果を取得できる前提にはしない。タイムアウトや失敗を記録し、集計に失敗した回に既存の制限を解除しない設計が安全だ。
BedrockのIAMポリシー例 は、特定の基盤モデルARNに対してbedrock:InvokeModel、bedrock:InvokeModelWithResponseStream、bedrock:CreateModelInvocationJobを明示的に拒否する方法を示す。InvokeModelの拒否はConverseなどにも作用するが、基盤モデルだけでなく推論プロファイルを経由する構成もあるため、実際に許可するAPIとリソースARNの組み合わせで拒否を確認する。
Jamf式では、拒否するモデル群ごとにCustomer Managed Policyを用意し、saml:sub条件で対象利用者を絞る。Lambdaは毎回、その日の累積費用から対象者一覧を再計算してポリシーの新版を発行する。同じ入力で再実行しても同じ結果になるため、処理の重複や一回の実行漏れで制限状態が積み上がらない。
IAM管理ポリシーが保持できる版には上限がある。新版を発行する前に古い非デフォルト版を整理し、状態が変わらない回には不要な版を作らない。Lambdaの実行ロールには対象ポリシーの更新に必要な権限だけを与え、一般利用者から変更権限を分離する。
例外と日次解除を同じ判定ループで処理する

承認済みの移行作業や顧客対応で追加利用が必要な場合も、IAMポリシーを手作業で外さない。例外テーブルに利用者ID、変更後の予算、失効時刻、承認者、チケット識別子を記録し、Lambdaが通常予算より先に有効な例外を参照する。失効時刻をDynamoDBのTTL対象にすれば、期限切れの上限変更を残しにくい。
日次窓が切り替わるとAthenaの当日費用は新しい期間で再計算される。次のLambda実行で閾値未満になった利用者が拒否対象一覧から外れ、新しいポリシー版が反映された時点で制限が解除される。付与と解除を別々の処理にせず、毎回一覧を作り直すことで状態のずれを避けられる。
通知は段階が変わったときだけ送ればよい。予算到達率、利用できなくなったモデル群、次のリセット時刻、例外申請先を示し、プロンプトや応答の本文は含めない。監視ではAthenaの失敗、ログ配送遅延、IAM更新失敗、未登録モデル、例外失効を分けて検知し、費用がゼロの場合も最新ログ時刻と呼び出し件数を確認する。
本文ログは費用台帳より厳しく保護する
モデル呼び出しログには、トークン数だけでなく、設定したモダリティーのリクエスト本文と応答本文も保存され得る。JSON本文は各方向とも100KBまでログ内へ入り、それを超える本文やバイナリデータはS3上の別オブジェクトになる。Converse APIへ渡した画像や文書も、該当するS3配送と画像ログを有効にしていれば記録対象になる。
入力に顧客情報、ソースコード、認証情報、未公開資料が含まれる環境では、ログを単なる費用データとして扱えない。費用計算に本文が不要なら、必要なメタデータとトークン数だけを残す構成を優先する。本文ログが必要な場合は、S3の暗号化、バケットポリシー、閲覧権限、保持期間、削除手順、監査証跡を先に定める。
Athenaで費用を分析する担当者には、利用者別集計とトークン数だけを見せ、本文オブジェクトへの権限を分離する。最初は少人数で識別子と費用計算を検証し、通知のみの期間を経てからIAM拒否を有効にすると、ログ欠落や料金マッピングの誤りによる意図しない制限を見つけやすい。
ニュースレターを購読
Web3、AI、暗号資産の最新ニュースを受信箱にお届けします。