HappyHorse 1.0 リリース今すぐ試す
AI APIタイムアウト:原因、リトライパターン、フォールバック設計
guide

AI APIタイムアウト:原因、リトライパターン、フォールバック設計

EvoLink Team
EvoLink Team
Product Team
2026年5月13日
15 分

AI APIリクエストがタイムアウトした。しかし「タイムアウト」は一つの問題ではなく、同じエラーメッセージの裏に少なくとも4つの異なる問題が潜んでいる。

テキストモデルが30秒後にタイムアウトするのと、動画生成ジョブが5分後にタイムアウトするのはまったく別の問題だ。間違ったタイプに対処すればエンジニアリング時間を無駄にし、問題を悪化させる可能性すらある。

このガイドでは、どのタイプのタイムアウトに直面しているかを診断し、適切な対処パターンを選ぶ方法を解説する。

まとめ

  • AI APIタイムアウトには異なる根本原因がある:モデルのレイテンシ、プロバイダーのキュー、大きな入力データ、ネットワークの問題。
  • テキストモデルのタイムアウトと動画/画像生成のタイムアウトでは、対処戦略が異なる。
  • むやみにリトライしない — タイムアウトの中にはリクエストがまだ処理中であることを意味するものもある。
  • 長時間タスク(動画、画像)には、同期レスポンスを待つのではなく非同期パターンを使う。
  • フォールバックは必要になる前に設計する:短いタイムアウト+フォールバックモデルの方が、長いタイムアウト+フォールバックなしよりも多くの場合優れている。

タイムアウト診断テーブル

修正方法を選ぶ前に、このテーブルでタイムアウトのタイプを特定しよう:

タイムアウトタイプ典型的な時間根本原因確認方法適切な対処
テキストモデル — レスポンスが遅い15〜60秒大きな入力、複雑な推論、または大量の出力トークン入力サイズとmax_tokensを確認入力を削減、max_tokensを下げる、またはより高速なモデルに切り替える
テキストモデル — プロバイダー過負荷30〜120秒プロバイダーが高負荷状態;リクエストがキューに入っているオフピーク時に同じリクエストを試すバックオフ付きリトライ、または別のプロバイダーにルーティング
動画/画像生成 — 通常の処理60〜300秒以上生成には本来時間がかかる(特に動画)プロバイダーのドキュメントで想定生成時間を確認非同期ポーリングを使用、同期待ちはしない
動画/画像生成 — キューの滞留300秒以上プロバイダーのキューに大量のジョブが滞留プロバイダーのキュー状態または位置を確認キュー管理を追加、ユーザーの期待値を設定、または別のプロバイダーを使用
ネットワークタイムアウト不定DNS、ファイアウォール、プロキシ、接続の問題シンプルなヘルスチェックリクエストでテストネットワーク設定を修正、API呼び出しではない
クライアント側タイムアウトが短すぎる設定依存HTTPクライアントのタイムアウトがモデルの必要時間より短いタイムアウト設定を延長して再テストクライアントのタイムアウトを想定レスポンス時間に合わせる

パターン1:テキストモデルのタイムアウト対処

テキストモデルのタイムアウトは通常、以下の3つのいずれかが原因だ:

1.1 大きな入力またはmax_tokensが大きい

長い入力は処理に時間がかかる。max_tokensの値が大きいと、より長い生成が可能になり、その分時間がかかる。
# 問題:大きな入力 + 高いmax_tokens = 遅いレスポンス
response = client.chat.completions.create(
    model="gpt-4o",
    messages=very_long_messages,  # 100K+ tokens
    max_tokens=4096  # 長い出力を要求
)

# 解決策:入力を減らすか出力を制限
response = client.chat.completions.create(
    model="gpt-4o",
    messages=trimmed_messages,  # 50Kトークンに削減
    max_tokens=1024  # 短い出力
)

1.2 プロバイダーが高負荷

ピーク時には、プロバイダーがリクエストをキューに入れることがある。これは明示的なキューメッセージではなく、タイムアウトとして表れる。

兆候:
  • 同じリクエストがオフピーク時には問題なく動作する
  • エラーが断続的で、一貫しない
  • 同時に他のユーザーも同様の問題を報告している
対処:
  • ジッター付きバックオフでリトライ
  • 代替プロバイダーまたはモデルにルーティング
  • ストリーミングを使って部分的な結果をより早く取得

1.3 タイムアウト緩和としてのストリーミング

ストリーミングは生成を高速化するわけではないが、トークンの返却がより早く始まる。これにより、クライアント側のタイムアウトの発動を防ぐことができる:

# 同期 — クライアントが完全なレスポンスを待つ間にタイムアウトする可能性
response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    max_tokens=2048
)

# ストリーミング — 最初のトークンがより早く到着し、接続を維持
stream = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    max_tokens=2048,
    stream=True
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

パターン2:動画/画像生成のタイムアウト対処

動画と画像の生成はテキストとは根本的に異なる。30秒から数分の生成時間は正常であり、エラーではない。

2.1 同期生成 vs 非同期生成

アプローチ仕組み使い所
同期1回のHTTP呼び出しで完全なレスポンスを待つ高速な生成(30秒未満)、シンプルな統合
非同期ポーリングジョブ送信 → ジョブID取得 → ステータス確認 → 結果取得動画生成、バッチ処理、30秒以上のタスク
Webhooksジョブ送信 → 完了時にプロバイダーがエンドポイントを呼び出す大量パイプライン、イベント駆動アーキテクチャ
動画生成では同期待ちは絶対に使わないこと。ほとんどの動画モデルは60〜300秒以上かかる。HTTPクライアントはほぼ確実にタイムアウトする。

2.2 非同期ポーリングパターン

import asyncio
import httpx

async def generate_video_async(client, prompt: str, timeout: int = 600):
    """動画生成ジョブを送信し、完了までポーリングする。"""

    # ステップ1:ジョブを送信
    submit_response = await client.post(
        "/v1/video/generations",
        json={"model": "veo-3-fast", "prompt": prompt}
    )
    job_id = submit_response.json()["id"]

    # ステップ2:完了までポーリング
    for _ in range(timeout // 5):  # 5秒ごとに確認
        status_response = await client.get(f"/v1/video/generations/{job_id}")
        status = status_response.json()

        if status["status"] == "completed":
            return status["result"]
        elif status["status"] == "failed":
            raise RuntimeError(f"Generation failed: {status.get('error')}")

        await asyncio.sleep(5)

    raise TimeoutError(f"Video generation did not complete within {timeout}s")

2.3 キュー位置の把握

動画生成プロバイダーにバックログがある場合、ジョブは処理開始前にキューで待機する。一部のプロバイダーはキュー位置を公開している:

Status: queued → position 42
Status: queued → position 15
Status: processing → estimated 90s remaining
Status: completed → download URL available

プロバイダーがキュー位置を公開していない場合は、過去の待ち時間から推定し、それに応じてユーザーの期待値を設定する。

パターン3:タイムアウトのためのスマートリトライロジック

すべてのタイムアウトを同じ方法でリトライすべきではない:

import asyncio
import random

async def retry_with_timeout_awareness(
    make_request,
    max_retries: int = 3,
    base_timeout: float = 30.0
):
    """タイムアウトタイプを意識したリトライ。"""
    for attempt in range(max_retries):
        try:
            return await asyncio.wait_for(
                make_request(),
                timeout=base_timeout * (1.5 ** attempt)  # リトライごとにタイムアウトを延長
            )
        except asyncio.TimeoutError:
            if attempt == max_retries - 1:
                raise

            # サンダリングハード効果を防ぐためにジッターを追加
            delay = min(30, (2 ** attempt) + random.uniform(0, 1))
            await asyncio.sleep(delay)

        except Exception as e:
            # タイムアウト以外のエラー:自動リトライしない
            if "429" in str(e):
                delay = min(60, (2 ** attempt) + random.uniform(0, 2))
                await asyncio.sleep(delay)
            else:
                raise

タイムアウトタイプ別のリトライルール

タイムアウトタイプリトライすべきか方法
テキストモデルが遅いはいバックオフ付きリトライ;リトライ時により高速なモデルを検討
プロバイダー過負荷はい(慎重に)より長いバックオフでリトライ;別のプロバイダーを検討
動画生成がまだ処理中いいえ — ジョブがまだ実行中の可能性再送信ではなくステータスをポーリング
ネットワークタイムアウトはいまずネットワークを修正;接続確認後にリトライ
クライアントタイムアウトが短すぎるいいえ — 代わりにタイムアウトを延長設定を調整、リトライはしない

最も危険な間違いは、まだ処理中の動画生成ジョブをリトライすることだ。これはジョブの重複を生み、コストを無駄にし、プロバイダーのキューを過負荷にする可能性がある。

パターン4:本番環境のためのフォールバック設計

タイムアウトトリガーのモデルフォールバック

async def call_with_fallback(messages, client, primary_model, fallback_model):
    """プライマリモデルを試し、タイムアウト時にはより高速なモデルにフォールバック。"""
    try:
        return await asyncio.wait_for(
            client.chat.completions.create(
                model=primary_model,
                messages=messages
            ),
            timeout=30.0
        )
    except asyncio.TimeoutError:
        # より高速な(場合によってはより小さな)モデルにフォールバック
        return await client.chat.completions.create(
            model=fallback_model,
            messages=messages
        )

ルーティングゲートウェイによるタイムアウト耐性

すべてのサービスにフォールバックロジックを実装する代わりに、ルーティングゲートウェイでインフラレベルのタイムアウト処理が可能だ:

  • プライマリルートが遅い場合、より高速なプロバイダーにルーティング
  • 異なるアップストリームパスで自動リトライ
  • 実際に使用されたモデルを返し、アプリケーションに何が起きたかを通知
EvoLinkのSmart Routerは、OpenAI互換インターフェースでゲートウェイレベルのこの機能を提供する:
from openai import OpenAI

client = OpenAI(
    api_key="your-evolink-key",
    base_url="https://api.evolink.ai/v1"
)

# Smart Routerがプロバイダー選択とフォールバックを処理
response = client.chat.completions.create(
    model="evolink/auto",
    messages=messages
)

タイムアウト設定リファレンス

設定項目推奨値理由
HTTPクライアントタイムアウト(テキスト)60〜120秒大きな入力と複雑な推論に対応
HTTPクライアントタイムアウト(画像)120〜300秒画像生成はモデルと解像度により異なる
HTTPクライアントタイムアウト(動画)非同期ポーリングを使用同期タイムアウトは動画には不適切
リトライ回数テキストは2〜3回、処理中の動画は0回動画/画像ジョブの重複を防止
バックオフの基本遅延ジッター付き2秒プロバイダー復旧時のサンダリングハード効果を防止
フォールバックモデル切り替えタイムアウト15〜30秒ユーザーがフラストレーションを感じる前により高速なモデルに切り替え

関連記事

Explore EvoLink Smart Router

FAQ

AI APIリクエストがモデルは動作しているのにタイムアウトするのはなぜ?

タイムアウトは通常、以下のいずれかが原因だ:(1) 大きな入力データの処理に時間がかかっている、(2) プロバイダーが高負荷、(3) クライアント側のタイムアウト設定が短すぎる、(4) ネットワークの問題。モデル自体は正常に動作している可能性がある。

タイムアウトを延長すべきか、それとも別のアプローチを取るべきか?

場合による。テキストモデルでは、タイムアウト延長は時折遅いレスポンスに対して有効だ。動画/画像生成では、同期タイムアウトを延長するのではなく非同期ポーリングに切り替えるべきだ。継続的なタイムアウトの場合は、制限を引き上げる前に根本原因を調査しよう。

タイムアウトとレート制限エラーは同じもの?

いいえ。タイムアウトはサーバーが制限時間内に応答しなかったことを意味する。レート制限(429)はサーバーがリクエストを能動的に拒否したことを意味する。タイムアウトは処理の遅延を示すことが多く、429はリクエスト過多を示す。

動画生成でのタイムアウトはどう対処する?

動画生成を同期的に待つことは絶対にしない。ポーリングまたはWebhooksを使った非同期ジョブ送信を使用する。ポーリング中に動画ジョブがタイムアウトした場合、再送信前にステータスを確認すること — ジョブがまだ処理中の可能性がある。

ストリーミングでタイムアウトを防げる?

ストリーミングは最初のトークンが素早く到着して接続を維持するため、クライアント側のタイムアウトを防ぐことができる。ただし、ストリーミングが全体の生成速度を上げるわけではない — 配信パターンが変わるだけだ。

タイムアウト時にフォールバックモデルに切り替えるタイミングは?

閾値を設定し(例:テキストなら15〜30秒)、プライマリモデルがタイムアウトしたらより高速なモデルに切り替える。これにより、エラーではなくレスポンスをユーザーに返すことができる。フォールバックモデルは性能が劣るかもしれないが、やや劣る回答でも回答がないよりはましだ。

AIコストを89%削減する準備はできましたか?

今すぐEvoLinkを始めて、インテリジェントなAPIルーティングの力を体験してください。