マルチモデル LLM API 用のプロバイダー中立のレート制限ブローカーを構築する方法
プロバイダー クォータの正規化、リクエストとトークンの容量の予約、テナントの公平性の強制、SDK とゲートウェイ間での再試行を増やすことなく 429 および 503 応答の処理を行うための実用的なアーキテクチャ。
複数のチームが複数の LLM プロバイダを共有すると、レート制限はプロバイダ統合の詳細ではなくなります。それは共有容量の問題になります。 1 つのプロバイダーはリクエストと入力トークンを制限し、別のプロバイダーは入力トークンと出力トークンを分離し、3 番目のプロバイダーはプロジェクト レベルまたはローリング支出ウィンドウ全体でクォータを適用できます。各 SDK 内の再試行ループは、テナント、アプリケーション、パートナー キー、モデル ルート全体でこれらの制約を調整できません。
実際的な解決策は、ゲートウェイにある中央のレート制限ブローカーです。ブローカーは需要を見積もり、発送前に容量を予約し、ポリシーに従って作業をキューに入れるか拒否し、完了後に予約と実際の使用量を調整します。プロバイダーの応答により、独立した再試行の嵐を引き起こすのではなく、利用可能な容量に関するブローカーのビューが調整されます。
このアーキテクチャは、内部チーム、運用アプリケーション、自動化エージェント、または外部パートナー全体で予測可能なスループットを必要とする エンタープライズ LLM API に役立ちます。
プロバイダのレート制限を 1 分あたりのリクエスト数に減らすことができない理由
事実: プロバイダの割り当てでは、さまざまなディメンションとスコープが使用されます。一般的なディメンションには、1 分あたりのリクエスト、1 分あたりの入力トークン、1 分あたりの出力トークン、総トークン、1 日あたりのリクエスト、同時実行性、支出ウィンドウ、および加速またはランプレートの制限が含まれます。同じプロバイダーが、組織、プロジェクト、ワークスペース、モデル、または API 製品に対して異なる制限を公開する可能性があります。
たとえば、プロバイダのドキュメントには次のような組み合わせが説明されています:
- リクエストとトークンの制限と、応答ヘッダー内の残りの容量およびリセット情報。
- メッセージ API の入力トークンと出力トークンの制限を分けます。
- 個々の API キーに割り当てられた割り当てではなく、プロジェクト レベルの割り当て。
- プロバイダーが定義した時間にリセットされる毎日のリクエスト制限。
- リクエストとトークンのレートが許容できるように見える場合でも、トラフィックを拒否できるローリング費用ベースのウィンドウ。
- 定常状態の使用量が公開されている割り当てを下回っている場合でも、トラフィックの急激な増加に反応する加速制限。
プロバイダー RPM という番号を 1 つだけ保存するゲートウェイは、最終的に、ある次元でトラフィックを過剰に受け入れたり、別の次元で容量を過小利用したりすることになります。また、拒否がテナント ポリシーによるものなのか、プロバイダー プロジェクトの割り当てによるものなのか、1 日あたりの制限によるものなのか、それとも過負荷応答によるものなのかも説明できません。
レート制限ブローカーのリファレンス アーキテクチャ
ブローカーをリクエスト パスのプロバイダー アダプターの前に配置します。すべてのリクエストは、SDK、内部サービス、自動化エージェント、またはパートナー API キーのいずれを介して到着したかに関係なく、同じ予約フローを通過する必要があります。
- ID を正規化します。 組織、テナント、チーム、アプリケーション、環境、パートナー、API キー、モデル ルート、ワークロード クラスを解決します。
- 需要を見積もります。 予想される入力トークン、最大出力トークン、推定費用、および同時実行コストを計算します。
- ポリシーを評価します。 テナントの予算、キューの期限、ルートの適格性、優先順位、およびフォールバック ルールを確認します。
- 容量を予約します。 関連する内部バケットおよびプロバイダー側のバケットで容量をアトミックに予約します。
- 送信。 予約が成功した後にのみリクエストを送信します。
- 調整します。 見積もりを実際の使用量に置き換え、未使用の予約を解放し、プロバイダーのヘッダーと応答分類を記録します。
- 次のアクションを決定します。 結果を返し、作業をキューに入れ、集中的に再試行し、フォールバックするか、ワークロード契約に従って拒否します。
予約サービスは水平方向にスケーラブルである必要がありますが、その決定はリクエストごとにアトミックである必要があります。 2 人のワーカーが同じ残りのキャパシティを監視できる分散カウンターを使用すると、ゲートウェイ内でプロバイダー 429 の問題を再現できます。
プロバイダーの違いを隠さずに正規の割り当てモデルを使用する
すべてのプロバイダーを 1 つの抽象化に強制するのではなく、プロバイダー固有の制約を表現できる正規モデルを定義します。
| ディメンション | 制御内容 | 一般的なブローカーのアクション |
|---|---|---|
| リクエスト | 時間枠内のディスパッチ数 | 1 つのリクエスト ユニットを予約 |
| 入力トークン | プロンプトとコンテキストのスループット | 推定プロンプト トークンを予約 |
| 出力トークン | 生成スループット | 要求された最大値またはポリシーの上限を予約 |
| 合計トークン数 | プロンプトと完了の使用量を組み合わせた | プロバイダー固有の合計を予約 |
| 毎日のリクエスト | 長期リクエスト割り当て | 毎日のプールが使い果たされた場合は拒否またはリダイレクト |
| 支出枠 | ローリング間隔でのコスト | 安全マージンを持って推定コストを予約 |
| 同時実行数 | 同時にアクティブなリクエスト | 完了またはタイムアウトまでリースを取得 |
| 増加率 | 短期間でのトラフィック増加 | バケットに余裕がある場合でも入場を制限 |
各制限は、スコープ、容量、補充またはリセット ルール、ユニット、およびソースを備えたバケットとして表されます。プロバイダー プロジェクト バケットには、リクエストと入力トークンが含まれる場合があります。ワークスペース バケットには出力トークンが含まれる場合があります。内部パートナー ポリシーにより、同時実行性と支出制限が追加される場合があります。必要な予約がすべて成功した場合にのみ、入場の決定が成功します。
プロバイダー ヘッダーを完全な信頼できる情報源として扱わないでください。これらを使用してブローカーの推定値を修正しますが、すべての応答で公開されるわけではない制限について設定されたモデルを保持します。ヘッダー名、可用性、リセット セマンティクスはプロバイダーとルートによって異なります。
発送前にトークンを予約し、調整します
トークンの予約は、ブローカーと再試行ラッパーの最も重要な違いです。ブローカーはリクエストを送信する前に需要推定を必要とします。
入力トークンの場合は、シリアル化されたメッセージ、ツール定義、構造化出力スキーマ、および取得されたコンテキストから推定します。出力トークンについては、利用可能な場合はリクエストの最大値を使用し、クライアントが提供しない場合はモデルおよびワークロード固有の推定値を使用します。後で実際の使用量と比較できるように、見積もりを予約に添付しておいてください。
単純な予約レコードには次のものが含まれます:
- 一意のリクエストと予約 ID。
- テナント、アプリケーション、API キー、ルート、ワークロード クラス。
- 推定入力トークン、出力トークン、合計トークン、および支出。
- 予約によって請求されるすべてのバケット。
- 作成時間、有効期限、キューの期限、冪等性キー。
- 最終的な実際の使用量と、調整中に解放または請求された金額。
控えめに見積もるとプロバイダー 429 の応答が減りますが、容量が不足する可能性があります。モデル、ルート、プロンプト ファミリ、コンテキストの長さ、および構造化出力モードによる推定誤差を測定します。次に、単一の異常なリクエストによってモデル全体が歪むのを許容するのではなく、制限付き補正を使用して推定値を調整します。
ストリーミングには特定のポリシーが必要です。最大の出力許容量を予約し、ストリームの終了時に未使用部分を解放したり、トークンの到着に応じて出力容量を少しずつ予約したりできます。最初のアプローチは推論が簡単です。 2 番目の方法では使用率を向上できますが、信頼性の高いキャンセル、タイムアウト、切断処理が必要です。
割り当てを階層的に適用する
容量は、最も狭いポリシーから最も広い共有リソースまでチェックする必要があります。一般的な階層は次のとおりです:
- API キーまたはサービス ID。
- アプリケーションと環境。
- チームまたは顧客のテナント。
- パートナーまたは再販業者のアカウント。
- プロバイダーのワークスペースまたはサブアカウント。
- プロバイダーのプロジェクトまたは組織。
- モデルとルート。
したがって、パートナー アプリケーションからのリクエストには、パートナーの同時実行ポリシー、顧客テナントのトークン予算、ゲートウェイのルート割り当て、プロバイダー プロジェクトの利用可能な割り当てという 4 つの予約が成功する必要がある場合があります。いずれかの予約が失敗した場合は、すでに取得されている予約を解放し、失敗したバケットの決定を適用します。
公平性を保つため、最初に到着したワーカーが共有プールを消費できるようにするのではなく、加重公平キューイングまたは不足ラウンドロビンを使用してください。各テナントのバースト クレジットを維持しながら、運用トラフィックに高い重みを割り当て、バックグラウンド ジョブに低い重みを割り当てます。ハード パーティショニングの方が説明は簡単ですが、1 つのテナントが静かな場合、容量がアイドル状態のままになる可能性があります。ノイズの多いテナントのバースト制限が制限されている場合、加重共有は通常、容量をより効率的に使用します。
ワークロード契約に基づいてキューを設計する
キューは自動的に信頼性機能になるわけではありません。目に見える 429 を、目に見えない 10 分間の遅延に変えることができます。すべてのキュー クラスには、期限、キャンセル動作、最大深さ、および過負荷アクションが必要です。
- インタラクティブ: 短い期限、小さなキュー、予測可能な拒否、または容量が利用できない場合のモデルの劣化。
- 制作の背景: 長い期限、耐久性のあるキュー、冪等性キー、および制御された再試行予算。
- パートナー: テナント固有の割り当て、公開された応答メタデータ、および別のテナントのキュー状態へのアクセスはありません。
- バッチ可能: ワークロードが許可する場合、遅延実行、より大きなキュー、およびプロバイダー バッチ API へのオプションのルーティング。
キューへの入場は明確な決定を返す必要があります。 API コントラクトに応じて、retry-after 値、キュー ID、および理由コードを含む 429 またはゲートウェイ固有のオーバーロード応答を公開します。システムが完了時間を強制できる場合を除き、完了時間を約束しないでください。
バッチ処理では、同期能力から非対話型作業を削除できますが、結果のタイミング、再試行動作、キャンセル、調整が変更されます。同期リクエストを単に非常に長いキューに入れるのではなく、別の実行パスとして扱います。バックグラウンド ワークロードの場合は、AI API コスト管理ポリシーと既存のバッチ操作との運用上のトレードオフを比較します。
再試行とオーバーロードの処理を一元化する
事実: 一時的なレート制限応答では通常 HTTP 429 が使用されますが、プロバイダーの過負荷状態では 503 またはプロバイダー固有のエラー コードが使用される場合があります。一部のプロバイダーは Retry-After ヘッダーを返します。プロバイダーのドキュメントでは、それが存在する場合はそれを尊重することを推奨しています。急激な交通量の増加によっても、通常のバケットの枯渇を伴わずに加速または減速の動作が発生する可能性があります。
推奨事項: Retry-After は、オプションの提案としてではなく、下限として扱います。それまで影響を受けるプロバイダー スコープを一時停止し、同期ウェイクアップを防ぐために制限付きジッターを追加し、回復された容量を使用できるキュー内のリクエストをブローカーに決定させます。
Retry-After が存在しないか無効な場合は、ジッターのある上限付き指数バックオフを使用します。再試行バジェットは、SDK およびプロバイダー アダプターごとに個別に保持するのではなく、ブローカー内に保持します。それ以外の場合、1 つの論理リクエストにより、ゲートウェイの再試行、SDK の再試行、HTTP のクライアントの再試行、およびプロバイダ側のリプレイが生成される可能性があります。
再試行する前にエラーを分類します:
- 再試行可能な容量: 一時的な 429 または文書化された一時的な割り当て応答。
- 再試行可能なオーバーロード: 一時的な 503 または同等のプロバイダーのオーバーロード信号。
- 再試行不可能なポリシーの失敗: 1 日の割り当て、支出上限、無効になっているプロジェクト、またはテナント制限。
- 再試行不可能なリクエストの失敗: 無効なスキーマ、サポートされていないパラメータ、認証の失敗、または不正な形式の入力。
- 期限の失敗: 残りのユーザーまたはワークフローの期限が次の安全な試行より短いリクエスト。
フォールバックは別の決定です。プロバイダーが異なれば、出力動作、価格設定、レイテンシ、常駐性、またはコンテキスト制限も異なる場合があります。フォールバックは、ワークロード コントラクトがこれらの違いを許容できることがルート ポリシーで確認されている場合にのみ使用します。
意思決定を公開し、飽和度を測定する
ゲートウェイが汎用 429 のみを返す場合、チームはスロットルのトラブルシューティングを行うことができません。適用可能な制限、残りの容量、リセット時間、キューの決定、ワークロード クラス、拒否理由などの安全なメタデータを返します。別のテナントの使用状況や未加工のプロバイダー認証情報を公開することは避けてください。
少なくとも次のことを監視します:
- テナント、ルート、バケットごとの予約の成功率と拒否率。
- キューの深さ、キューの待機時間、期限切れ、キャンセル。
- プロバイダー 429 および 503 のレート、再試行後の頻度、ランプレートの拒否。
- 過剰予約によって無駄になるトークン使用量および容量と実際の推定量との比較。
- 同時実行の飽和と各テナントによって消費される容量のシェア。
- 論理リクエストごとの再試行とフォールバック頻度。
- 1 日の割り当てと支出枠の余裕。
負荷テストには、バースト トラフィック、長いコンテキストのリクエスト、最大出力リクエスト、ストリーミングの切断、毎日の割り当ての枯渇、プロバイダ 429 および 503 の応答、運用トラフィックと競合する 1 つのノイズの多いテナントを含める必要があります。リクエストが最終的に完了するかどうかだけでなく、キューの期限、公平性、再試行の予算がそのまま残っているかどうかも検証します。
実装チェックリスト
- プロバイダー固有の制限を破棄せずに正規のディメンションを定義します。
- すべてのリクエストに正規化されたテナント、ルート、ワークロード クラス、冪等キーを割り当てます。
- ディスパッチ前に、入力、出力、合計トークン、支出、リクエスト、同時実行性を見積もって予約します。
- 複数バケットの予約をアトミックにし、放棄された予約を安全に期限切れにします。
- 試行のたびに実際のプロバイダーの使用状況と応答ヘッダーを調整します。
- 重み付けされた公平性、バースト クレジット、および明示的な優先クラスを使用します。
- すべてのキューに期限、最大深さ、および過負荷アクションを与えます。
- 再試行を一元管理し、プロバイダーの Retry-After 値を尊重します。
- 一時的な容量エラーを永続的なポリシーおよびリクエストのエラーから分離します。
- スロットル メタデータを公開し、テナントおよびルートごとの飽和度を監視します。
- プロバイダーの割り当ての枯渇、ランプ制限、ストリーミング、フォールバック、およびノイジーネイバーの動作をテストします。
結論
マルチモデル ゲートウェイは、独立した SDK 設定の集合としてではなく、共有インフラストラクチャ容量としてプロバイダー割り当てを管理する必要があります。プロバイダー中立のレート制限ブローカーは、プラットフォーム チームに 1 つのアドミッション パス、1 つの公平性ポリシー、1 つの再試行バジェット、および見積もりと現実を調整する 1 つの場所を提供します。
この設計では、一般的なトークン バケット以上のものを必要とします。これは、リクエスト、入力トークンと出力トークン、毎日のクォータ、支出ウィンドウ、同時実行性、プロバイダーの範囲、およびランプ レートを表す必要があります。これらのディメンションが明確になると、ゲートウェイは予測可能な選択を行うことができます。つまり、今すぐディスパッチする、期限付きでキューに入れる、作業を中断する、集中的に再試行する、コントラクトセーフなフォールバックを使用するなどです。このようにして、スループット制御は、実稼働 429 および 503 インシデントの繰り返し発生源ではなく運用機能になります。