Bedrock(Claude)のトークンquotaを監視する
かわごえです、タイトルの通りです、
先日Bedrockで「429 Too Many Token」というエラーにでくわしました。
事象はログの通り、AWS側のトークンの使用量が上限に達しているため発生するエラーです。
根本解消には、上限緩和を依頼するか、Exponential backoffのようなものを入れるかなどいくつか解決策はありますが、今回はその前段の「そもそものquotaに抵触しそうかをモニタリングする」方法です。
バーンダウンレートを理解する
bedrockの一部モデルには、バーンダウンレートというものが存在します。
これはquotaの計算にのみ使われるもので、以下のモデルでは実際の出力トークンの5倍の値でquotaの計算上は利用されます。
- Opus 4
- Sonnet 4
- 3.7 Sonnet
例えば、
IN: 100 Token
OUT: 500 Token
だった場合、quotaの計算としては、100+500*5=2600という値が使われるという形です。
どのメトリクスをモニタリングするか
一番上の参考ドキュメントにも記載はあるのですが、プロンプトキャッシュを利用する場合には、CacheWriteInputTokensの値も考慮する必要があります。
そのため、quotaの計算に利用されるトークンの計算式は以下のようになります。
InputTokenCount + CacheWriteInputTokens + (OutputTokenCount x burndown rate)
つまり、
- InputTokenCount
- CacheWriteInputTokens
- OutputTokenCount
のメトリクスさえ特定できれば、あとは数式でいい感じにquotaのモニタリングが実現できることになります。
CDKで書くとこう
これらのメトリクスを、いい感じに足し算掛け算して、一発アラームまで流すCDKがこちらです。
import * as cdk from "aws-cdk-lib";
import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
import { Construct } from "constructs";
export class BedrockTokenSumStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const period = cdk.Duration.minutes(1); // quotaは1分ごとにリセットされるため、1分間隔で集計
const region = this.region;
const account = this.account;
const modelId = "us.anthropic.claude-sonnet-4-20250514-v1:0"; // 例: 使用するモデルID
const inputTokens = new cloudwatch.Metric({
namespace: "AWS/Bedrock",
metricName: "InputTokenCount",
dimensionsMap: { ModelId: modelId },
statistic: "Sum",
period,
region,
account,
});
const outputTokens = new cloudwatch.Metric({
namespace: "AWS/Bedrock",
metricName: "OutputTokenCount",
dimensionsMap: { ModelId: modelId },
statistic: "Sum",
period,
region,
account,
});
const cacheWriteTokens = new cloudwatch.Metric({
namespace: "AWS/Bedrock",
metricName: "CacheWriteInputTokens",
dimensionsMap: { ModelId: modelId },
statistic: "Sum",
period,
region,
account,
});
// m1 + m2 で新しい“合計トークン数メトリクス”
const totalTokens = new cloudwatch.MathExpression({
expression: "m1 + m2*5 + m3",
usingMetrics: { m1: inputTokens, m2: outputTokens, m3: cacheWriteTokens },
label: "TotalTokenCount",
period,
});
// 例: ダッシュボードに表示
const dashboard = new cloudwatch.Dashboard(this, "BedrockTokensDashboard", {
dashboardName: "bedrock-token-usage",
});
dashboard.addWidgets(
new cloudwatch.GraphWidget({
title: "Bedrock Total Tokens (Input + Output + Cache Write)",
left: [totalTokens],
})
);
// 例: アラーム(しきい値は適宜)
new cloudwatch.Alarm(this, "HighTotalTokens", {
metric: totalTokens,
threshold: 100000,
evaluationPeriods: 1,
comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
alarmDescription: "Total tokens exceeded threshold",
});
}
}
中身は一般的なCloudWatch AlarmのCDKなので詳細は割愛しますが、
こんな感じでいい感じに足し算できるはずです。
私のプライベート環境ではまだToo Many Tokenを再現できてないので
メトリクスの正確性まで細かく見れていないのですが、
もしquotaの確認に手間取ってる方がいて手助けになれば幸いです。
Discussion