Tech カテゴリのイメージ

AIエージェントを本番運用するには?タイムアウト・再試行・上限を先に決める

AIエージェントを本番へ出すと、モデルの回答品質とは別の問題が起きる。外部APIが遅い、検索が一時的に失敗する、複数の利用者が同時に操作する、再試行が重なって費用が増える。デモでは最後まで待てても、本番では一回の作業に使える時間、呼び出し回数、費用を決め、超えたら止めなければならない。

例えば、複数の資料を検索して報告書を作る架空のエージェントを考える。検索APIが応答しないたびに同じ処理を繰り返すと、利用者には画面が止まって見え、裏側ではモデルと道具の呼び出しが増え続ける。最後に一度だけエラーを返しても、すでに時間と費用を使い切っているかもしれない。

一回の試行と作業全体の期限を分ける

道具ごとのタイムアウトだけでは足りない。検索を20秒、モデルを60秒に設定しても、これを何度も繰り返せば作業全体は数分を超える。一回の呼び出しに対する期限と、エージェント全体に対する締切を別々に持つ。

全体の残り時間を各段階へ渡し、残り10秒しかないのに30秒の処理を始めない。締切に達したら、新しい道具を呼ばず、取得済みの結果で限定的に回答するか、未完了として停止する。書き込みの途中なら、成功した操作と未実行の操作を状態へ残し、前の記事で扱ったチェックポイントから再開できるようにする。

利用者が画面を閉じた、または処理を中止した場合も、下流のモデル呼び出しや道具へキャンセルを伝える。画面だけ閉じて裏側の処理を続けると、誰も待っていない応答に費用を使う。

再試行できる失敗だけを選ぶ

一時的な混雑や接続切れは再試行で回復することがある。一方、入力不正、権限不足、残高不足、存在しない対象は、同じ要求を送り直しても直らない。エラーを「失敗」の一種類にまとめず、再試行可能か、入力修正が必要か、人の対応が必要かに分ける。

レート制限で Retry-After が返った場合は、その時間を最低待機時間として尊重する。指定がなければ、失敗するたびに待ち時間を増やす指数バックオフへ小さなランダム時間を加える。OpenAIのレート制限資料は、試行回数と再試行に使う総時間の両方を制限し、SDKとアプリケーションの二重再試行で要求が増えないよう注意している。失敗した要求も分あたりの制限に数えられるため、即時の連打では回復しない。

読み取りの再試行と書き込みの再試行も区別する。書き込みには一意の実行IDを付け、応答が途切れても同じ処理を二重作成しない。再送前に、外部側で完了済みかを照会する。

回数・トークン・費用に予算を持たせる

エージェントのループには、最大ターン数、モデル呼び出し回数、道具別の回数、入力と出力のトークン、費用の上限を設定する。全体上限だけでなく、一人または一つの組織が一定期間に使える上限も必要だ。OpenAIのレート制限資料も、自動化された大量利用への対策として、利用者ごとの日次、週次、月次上限や、超過時の手動確認を挙げている。

上限に近づいたとき、常に高性能なモデルで続けるとは限らない。分類や形式変換は小さいモデルへ分ける、不要な検索を省く、長い出力を短くする、後で処理できる仕事をキューへ移すといった選択肢がある。ただしモデルを切り替えるなら、同じ評価データで品質低下を確認する。

開発環境と本番環境のプロジェクトや認証情報も分ける。OpenAIの本番運用資料は、ステージングと本番を別プロジェクトにし、本番へのアクセス、レート上限、支出上限を個別に管理する方法を示している。負荷試験が本番の予算を消費する事故を防ぎやすい。

並列化は依存関係を確かめてから行う

独立した三つの文書検索を順番に実行する必要はない。並列にすれば合計の待ち時間を短くできる。一方、最初の結果で次の検索条件が決まるなら、同時実行すると不要な呼び出しが増える。

OpenAIの遅延最適化資料は、出力トークンを減らす、要求回数を減らす、独立した処理を並列化する、LLMが不要な処理には使わないという観点を示している。エージェントでは、依存関係をグラフとして確認し、独立した読み取りだけを同時に走らせる。書き込みや共有状態の更新は、順序と競合の扱いを決めてから並列化する。

同時実行数にも上限を設ける。利用者が増えたとき、全要求をすぐ開始すると外部APIの制限へ一斉に達する。キューとワーカーで処理量をならし、待ち時間が長すぎる依頼は開始前に断るか、非同期処理として受付結果を返す。

速さは平均ではなく分布で見る

平均5秒でも、100回に1回が2分なら利用者には不安定に見える。モデル、検索、各道具、承認待ちをトレース上で分け、中央値だけでなく遅い側の分位点を追う。タイムアウト率、再試行回数、キャンセル率、上限到達率、1作業あたりの費用も一緒に見る。

最初の結果を早く表示するストリーミングは、待っている感覚を減らせる。ただし、最終検査が済む前の文章や、確定していない操作結果を完了として見せない。進行状況と確定結果を画面上でも区別する。

部分的な障害で何を返すかを決める

すべて成功する場合だけを設計すると、一つの道具が落ちたときにエージェントが判断を作り始める。天気APIを取得できなければ「晴れ」と補わず、取得できなかった項目を明示する。複数の資料のうち一つだけ読めた場合は、回答範囲を限定するか、必要条件を満たさないとして停止する。

代替手段を用意するなら、品質とデータの鮮度を明示する。キャッシュを使う場合は取得時刻と有効期限を持ち、書き込み処理を古いキャッシュだけで判断しない。外部サービスが回復した後に再開する仕事はキューへ置き、同じ実行IDで重複を防ぐ。

本番運用で重要なのは、失敗をゼロにすることではない。どこまで待ち、何を再試行し、どの上限で止まり、利用者へ何を返すかを事前に決めることである。その判断をトレースと指標で確認し、実際の遅延や失敗を評価データへ戻して改善する。

参照資料

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