人工知能機能は便利でも、特定の処理に対して遅すぎたり、コストが高すぎたりすることがあります。すべての呼び出しに同じ要件があるかのように扱うと、問題が生じます。バックグラウンドでテキストを要約する場合と、決済中の問い合わせに回答する場合では、影響が異なるためです。PHPでAIのコストとレイテンシを制御するには、ユースケースごとに運用上の予算を定め、上限に達した場合の対応をあらかじめ決めておくとよいでしょう。
この予算は、品質を約束するものでも、プロバイダーが一定時間内に応答することを保証するものでもありません。影響を抑え、ユーザーに状況を伝え、アプリケーションの挙動を管理できるようにするための上限とプロダクト上の判断の組み合わせです。
処理ごとに異なる予算を設定する

運用上の予算とは、機能が消費できるリソースと、待つ意味がある時間をまとめたものです。最大処理時間、推定コストの上限、試行回数、処理するテキスト量、またはこれらを組み合わせた制御を含められます。抽象的な設定としてすべての呼び出しで共有するのではなく、プロダクト内で識別できる処理に紐づける必要があります。
たとえば、パネル内の任意の提案機能なら、時間がかかりすぎる場合に省略しても問題ないでしょう。一方、必須のプロセスに含まれる機能なら、AIを使わずにフローを完了できる代替手段が必要かもしれません。バッチ分類処理ではキューへの登録と保留状態を許容できても、対話型の応答にはより厳しい待ち時間の上限が必要です。
上限を決める前に、ユーザーが必要とする結果、その時点での必須性、結果が利用できない場合に何が起きるかを明確にします。また、予算と品質評価は分けて考えましょう。速く安価な応答でも誤っている場合があり、正しい応答でも役に立つには遅すぎる場合があります。それぞれに固有の測定方法と基準が必要です。
しきい値を決める前に測定する
ベースラインがなければ、上限は推測にすぎません。処理の種類ごとにメトリクスを記録し、負荷、入力サイズ、利用状況によってどう変化するかを確認します。最低限、総処理時間、該当する場合は最初に有用な結果が得られるまでの時間、利用頻度、推定コストを測定しましょう。非同期処理では、キュー内の時間と処理時間も記録します。
各測定値を処理ID、結果、リクエストのおおよそのサイズや実行モードなど、機密性のないコンテキスト情報に紐づけます。診断に不要であれば、ユーザーのテキスト、シークレット、個人情報、回答全文を保存しないでください。事例の調査が必要な場合は、適切なアクセス制御、保持期間、データ最小化の対策を適用します。
推定コストは、利用するサービスで入手できる情報を基にし、その制約を反映させる必要があります。確定した請求額と混同してはいけません。価格、計上単位、課金対象の構成要素は変わる可能性があります。呼び出し前に信頼できるコストを算出できない場合は、レート制限、最大サイズ、ユーザーごとのクォータ、監視対象となる合計利用額など、代替の制御を使います。
予算を検証可能な上限にする
各制御をどこに適用するかを決めます。リクエスト単位の上限は、個々の実行が長引いたりリソースを使いすぎたりするのを防ぎます。ユーザーまたはアカウント単位のクォータは、繰り返しの利用を制限します。プロセス単位の上限は、複数の処理をまとめるタスクを保護します。全体の支出を管理するには、合計消費量も監視します。個別の上限だけでは、多数の同時リクエストがシステム全体の予算を超えるのを防げません。
リトライの挙動も決めておきます。リクエストを自動的に再試行すると、コストが二重にかかったり、レイテンシが悪化したりすることがあります。特に、サービスがリクエストを処理したかどうか分からない場合は注意が必要です。許可する試行回数、対象となるエラー、待機時間を定義します。データを変更する処理では、対応可能で有効な場合に冪等性キーを使い、重複した影響を防ぎます。
しきい値に達した場合の選択肢には、リクエストの停止、対象範囲の縮小、キューへの延期、人によるレビューへの振り分けがあります。どれを選ぶかはユースケースによって異なります。一部の結果を返すのは、インターフェースで明確に示され、その結果が安全で有用な場合に限り許容できます。機微なタスクや不完全な結果を許容できないタスクでは、生成結果を表示しないほうがよいこともあります。
PHPの統合レイヤーで制御を適用する
外部への呼び出しを、処理とその予算を受け取り、該当する制御を適用して、明示的な結果を返す統合レイヤーに集約します。これにより、ビジネスロジックが特定のプロバイダーに直接依存せず、アプリケーション内の場所ごとにタイムアウトやエラーを異なる方法で解釈する事態も避けられます。
次のコードは、コンストラクターのプロパティ昇格と名前付き引数を使うため、PHP 8.0以降が必要です。これは一部の機能を示す例です。入力サイズを検証し、クライアントにタイムアウトを渡しますが、クォータ、支出上限、キューは実装していません。これらの制御は、アプリケーションの要件に応じて別途追加する必要があります。
final class AiOutcome
{
public function __construct(
public string $status,
public ?string $content = null,
public ?string $reason = null,
) {}
}
function runAiOperation(
AiClient $client,
string $input,
int $timeoutSeconds
): AiOutcome {
if (strlen($input) > 12000) {
return new AiOutcome('rejected', reason: 'input_limit');
}
try {
$response = $client->generate($input, $timeoutSeconds);
return new AiOutcome('completed', $response->text);
} catch (TimeoutException $e) {
return new AiOutcome('timed_out', reason: 'timeout');
} catch (ProviderException $e) {
return new AiOutcome('unavailable', reason: 'provider_error');
}
}クライアントと例外は、選択した統合方式によって異なります。本番環境では、HTTPクライアントにも時間の上限を設定し、データ送信前にサイズを検証してください。timed_out状態は、リクエストがタイムアウトしたことを示します。キューに登録された、または処理が続行されるという意味ではありません。アプリケーションがタスクをキューに保存し、再開して結果を通知できるプロセスがある場合に限り、deferred状態を返します。
制御レイヤーを完成させるには、プロセス間で共有するカウンターを使ってレート制限またはクォータを適用し、合計支出を監視します。各呼び出しの前にコスト上限を適用する必要がある場合は、リクエストの推定消費量を計算し、利用可能な予算と比較します。信頼できる推定ができない場合は、代替の上限と消費量のアラートを使います。共有クォータをPHPリクエスト内のメモリだけに依存させてはいけません。
完了、上限による拒否、タイムアウト、利用不可など、状態を区別して返します。これによりビジネスロジック側は、遅い応答と品質の低い応答、運用上の上限とプロバイダーの障害を混同せずに、表示内容を判断できます。
明確で役立つ縮退動作を設計する
縮退とは、エラーを隠したり、代替結果を同等であるかのように示したりすることではありません。機能が処理を完了できない場合でも、ユーザーが理解できる体験を維持することです。任意のアクションなら、提案を利用できないことを伝え、続行できるようにするだけで十分な場合があります。時間のかかるタスクでは、アプリケーションが状態を確実に維持できることを前提に、保留中であることを示し、状態を確認できるようにします。
対象範囲を縮小できる場合は、省略した内容を説明します。レビューに回す場合は、結果がすでに検証済みであるかのように示してはいけません。既存のビジネスルールのような決定論的な代替手段を使う場合、ユーザーの判断に影響するのであれば、その役割を明確にします。実行を保証できるキューとプロセスがないのに、後で提供すると約束するメッセージは避けてください。
障害時のフォールバックは、予算制御とは異なります。利用不能、ネットワークエラー、無効な応答などをきっかけに動作します。サービスが正常に稼働していても、予算を使い切ることはあります。両方の仕組みを別々に定義・テストし、それぞれの原因に応じた状態とメッセージを用意します。
テスト、アラート、根拠に基づく調整
代表的な負荷と、入力サイズが大きい場合、リクエストの繰り返し、応答の遅延、同時実行、プロバイダーエラー、クォータ上限などの逆境シナリオで、しきい値をテストします。ユーザーに何が表示され、何が記録されるかを確認します。キャンセルのケースも含め、停止したリクエストが不要なままバックグラウンドでリソースを消費し続けないことを検証してください。
レイテンシの増加、拒否されるリクエストの増加、推定支出の増加、保留中のジョブの蓄積など、運用上の異常に対するアラートを設定します。アラートは調査が必要な状態を示すものであり、分析の代わりではありません。問題のあるフローが全体の平均値に隠れないよう、処理ごとに分けて確認します。
利用量、プロダクト体験、入力サイズ、技術的な統合方式が変わったら、上限を見直します。アラートを消すためだけに上限を緩めてはいけません。まず、期待値の定義に問題があるのか、想定外の負荷なのか、ネットワーク障害なのか、処理自体の再設計が必要なのかを特定します。
本番環境向けチェックリスト

- 目的:処理にユースケースと利用者が定義され、AIが応答しない場合の代替手段がある。
- 測定:不要な機密情報を収集せずに、処理時間、利用頻度、結果、推定コストを記録している。
- 上限:リクエスト単位で適切な上限があり、必要に応じてユーザー、プロセス、システム単位の上限も設定されている。
- 挙動:リトライ、キャンセル、キュー、各しきい値に達した場合の応答が定義されている。
- 体験:状態とメッセージで、待機、上限による拒否、サービス障害を区別している。
- 運用:テストとアラートがあり、上限を見直す担当者またはチームが決まっている。
PHPでAIのコストとレイテンシを制御することは、アプリケーション全体に単一のタイムアウトを設定することではありません。各上限を具体的なニーズに結びつけ、その影響を測定し、機能を完了できない場合にもプロダクトを分かりやすく安全に保つ代替手段をあらかじめ決めておくことです。



