AI API Fallback 策略:建立供應商故障矩陣
依 Failure Class、回應階段、冪等性與 Attempt Budget,決定何時重試、同契約回退、停止或核對副作用。
AI API 的 Retry、Route Fallback 與 Model Substitution 是三種不同動作。Retry 在同一契約下重做一次嘗試;Route Fallback 把相同模型與協定送往另一條合格路徑;Model Substitution 則改變模型,可能連帶改變品質、價格、延遲、工具行為、Context Limit 與輸出格式。
可靠的策略不應在事故發生後才臨時決定。它必須預先回答:這是什麼類型的失敗、回應是否已交付、完整業務操作能否安全重播,以及使用者 Deadline 內還容得下幾次嘗試。
分清 Retry、Fallback 與 Model Substitution
在設定、日誌與 Runbook 中使用不同名稱。
| 動作 | 改變內容 | 合適用途 | 主要風險 |
|---|---|---|---|
| Same-route Retry | 時間與 Attempt Number | 從同一路徑的短暫故障恢復 | 持續向不健康依賴增加負載 |
| Same-contract Fallback | Upstream Channel、Account 或有序 Group | 某一路徑失敗時維持原模型與協定 | 名義相同的路徑其實不相容 |
| Model Substitution | Model ID 或命名 Model Policy | 經產品核准的品質、成本或可用性取捨 | 靜默改變行為與計費 |
不要把三者都寫成「重試」。營運人員必須知道請求是原路重播、換了供應商路徑,還是由另一個模型回答。模型替換也必須是明確的產品契約,不應成為隱藏的救援捷徑。
部分 Gateway 支援有序 Provider 或 Model Step。例如 Cloudflare 的 Fallback 文件會揭示最後成功的步驟。值得採用的不是某家供應商的固定順序,而是「路徑一旦改變,就保留 Attempt-level Evidence」的設計原則。
重播前通過四道 Gate
Status Code 本身不是 Retry Policy。每次重播前都要判斷:
- Failure Class:失敗是暫時性、永久性、由呼叫端造成,還是完成狀態不明?
- Response Phase:發生在 Header 前、有效輸出前,還是輸出已交付後?
- Idempotency:完整應用操作能否重做而不產生重複副作用?
- Attempt Budget:剩餘 Wall-clock Time 是否足夠,且還有未使用的 Attempt?
Google Cloud 的 Retry Strategy對一般 API 也強調兩個基礎判斷:回應是否代表重試可能有效,以及操作是否具備 Idempotency。408、429、5xx、Socket Timeout 與 Disconnect 常屬暫時性故障,但非冪等操作仍需要更嚴格條件。
對 AI Workflow 而言,冪等邊界不只在模型 HTTP Request。重播 Prompt 可能再次提出寄信、退款、部署或資料庫寫入。即使推論本身唯讀,Tool Execution 仍需要穩定的 Idempotency Key 與持久化結果。
從 Failure Matrix 建立策略
以下矩陣是偏保守的應用層策略。Gateway 可能在應用收到終態前,已完成內部 Same-contract Channel Failover,因此兩層必須協調,不能重複放大嘗試次數。
| 失敗或階段 | Same-route Retry | Same-contract Fallback | 停止或調查 | 原因 |
|---|---|---|---|---|
| Client Validation Error、Unsupported Field、Malformed Request | 否 | 否 | 修正請求 | 重播相同錯誤契約不會成功 |
| Gateway Authentication、Authorization、Quota 或 Policy Denial | 否 | 否 | 修正帳戶或政策 | 不能用另一條 Provider Route 繞過 Gateway 決策 |
| 輸出前的 Upstream Credential 或 Account Failure | 不重試失敗路徑 | 有已驗證的合格 Channel 時可以 | 隔離並調查失敗 Channel | 可以在不改使用者契約下移除不健康憑證 |
輸出前 Network Failure 或 408 |
冪等時最多一次有界嘗試 | 可以 | 到 Deadline 即停止 | 故障可能短暫,但 Disconnect 後完成狀態可能不明 |
輸出前 429 |
延後重試並遵守 Retry-After |
其他同契約路徑有容量時可以 | Budget 用盡即停止 | 立即連續重試會放大限流 |
輸出前 500、502、503、504 |
有界 Backoff | 可以 | 路徑反覆失敗時調查 | 通常短暫,但不代表所有路徑都安全 |
| 下游輸出前收到 Schema-invalid 或 Malformed Provider Response | 通常否 | 僅限已驗證相同 Schema 的路徑 | 隔離或調查相容性 | 重複呼叫不相容實作通常無效 |
| Model Refusal 或符合安全政策的 Completion | 否 | 否 | 回傳模型結果 | 合法拒絕不是基礎設施故障 |
Caller Cancellation 或 Downstream 499 |
否 | 否 | 立即停止 | 呼叫端已不需要結果,繼續只會浪費容量與成本 |
| 可見內容或 Tool Arguments 已送達後的 Partial Stream | 不透明重播 | 不透明回退 | 標記 Partial,由應用決定 | 第二條 Stream 可能重複或矛盾 |
| Tool Side Effect 完成狀態不明 | 核對前否 | 核對前否 | 查詢 Idempotency Record 或下游系統 | 再次推論可能重複提出同一副作用 |
這個矩陣刻意納入 Response Phase。輸出前收到 503,與已渲染 400 個 Text Token 後連線中斷,不是同一種故障。
把 Stream 開始視為 Commit Boundary
在下游輸出開始前,Gateway 通常能捨棄失敗 Attempt,改走另一條合格路徑,而不讓呼叫端看到兩份答案。第一個有意義的 Byte 一旦到達呼叫端,透明重播就不再安全。
重新啟動 Stream 可能:
- 重複答案開頭;
- 產生不同續寫;
- 以新的 Call ID 發出重複 Function Call;
- 在沒有清楚邊界下增加 Usage 與 Cost;
- 讓 Client 無法判斷 Event 屬於哪次嘗試。
輸出後 Stream 中斷時,應以原 Request Identity 回傳明確的 Partial 或 Transport Error。應用可以提供顯式「再試一次」、從安全 Checkpoint 繼續,或捨棄部分結果;不應把新模型 Stream 拼接到舊 Stream,假裝沒有發生故障。
Function Calling 的安全邊界更嚴格:任何重試可能重新建立 Tool Call 前,先持久化已接受的 Tool Call Identity 與 Side-effect Result。Function Calling 比較進一步說明 Call ID 與應用冪等性的配合方式。
同時限制 Attempt 與 Wall-clock Time
Exponential Backoff 讓嘗試分散在時間上,Jitter 則避免大量 Client 在共同故障後同步重試。
delay_cap = min(max_delay, base_delay * 2^retry_index)
sleep_for = random_between(0, delay_cap)
有效的 Retry-After 若沒有超過使用者 Deadline,應優先遵守。但 Backoff 並不等於獲得重試許可;Failure 與 Idempotency Gate 仍須先通過。
策略需要 Total Budget,而不只是 Retry Count:
- 單一 User Action 的最大 Attempt;
- 包含 Queue 與 Backoff 的最大 Elapsed Time;
- 選擇 Fallback Group 前後各自的 Attempt 上限;
- 產生有用答案至少需要保留的時間;
- Caller Cancellation 向所有 Active Attempt 的傳播。
若互動請求 Deadline 為 15 秒,安排三次各 10 秒的 Attempt 並不是可執行策略。Batch Workload 可以使用較長 Budget,但仍需 Terminal Deadline 與 Durable Job Identity。
避免跨層 Retry Amplification
假設 SDK 做一次請求加兩次重試,共三次 Client Attempt;Gateway 對每次 Client Attempt 做 Primary 加兩條 Channel Fallback,共三次 Gateway Attempt;Upstream Proxy 又各重試一次,共兩次 Provider Call:
3 client attempts × 3 gateway attempts × 2 upstream attempts = 18 provider calls
一個使用者動作因此變成 18 次 Provider Call。事故期間,這會同時增加 Queue、Rate Limit、成本與恢復時間。
應明確分配 Retry Ownership:
- Gateway 負責立即的 Same-contract Channel Failover;
- Application 決定完整 User Action 是否可以重播;
- Gateway 已重試時,SDK Automatic Retry 應停用或嚴格限制;
- Async Job 使用單一 Durable Job ID 與 Attempt Ledger;
- Caller Cancel 後,任何一層都不得啟動新 Attempt。
同時記錄「本層 Attempt Number」與穩定的 End-to-end Request ID,否則每層看起來只重試兩三次,整體放大卻無法察覺。
驗證 Fallback 是否真的維持契約
相同公開模型名稱不代表兩條 Route 行為一致。把 Channel 加入 Same-contract Fallback Set 前,至少驗證:
| 契約範圍 | 所需證據 |
|---|---|
| Model Identity | Requested Model 可用,且沒有 Silent Mapping |
| Endpoint | 設定的 Responses 或 Chat Completions Request 能被接受 |
| Streaming | Event Type、Termination、Usage 與 Cancellation 都能處理 |
| Structured Output | 必要 JSON Schema 子集與 Strict Behavior 可運作 |
| Function Calling | Tool Definition、Call ID、Argument Streaming 與 Result 能 Round-trip |
| Limits | Context、Output、Rate 與 Concurrency Limit 符合 Workload |
| Errors | Status 與 Error Body 可分類且不洩露 Secret |
| Usage and Cost | Token、Cache Field、Service Tier 與 Price Policy 已釐清 |
| Safety and Region | Policy、Data Path 與 Residency 要求仍符合 |
只要候選 Route 未通過任何必要範圍,它就不是該 Workload 的透明 Fallback。它仍可能在另一套顯式產品政策下使用。
換成不同模型永遠是產品決策。必須定義允許的 Model、Quality Floor、Price Ceiling、Tool Contract 與 User-visible Disclosure,不能只因某條 Route 報錯就靜默換成較弱或較便宜的模型。
正確理解 Modelflare 的 Fallback Semantics
Modelflare 會為 API Client 指定的模型搜尋合格路徑。一般 API Key 有一個 Primary Group,也可以配置有序 Fallback Group;Smart API Key 則依 Routing Strategy 評估帳戶可用 Group。兩種機制都不應靜默把 Requested Model 換成另一個模型。
Group-level RPM Admission 發生在計費與 Upstream Request 前。選定 Group 已滿時,可以評估有序 Fallback Group 或 Smart Routing Candidate;若沒有合格 Group,請求回傳 429。
在 Group 內,Channel Priority 定義 Account Failover 順序。Upstream Error 後,失敗 Channel 會被排除,選擇器繼續尋找其餘合格 Channel。現行 Channel Failover 不依賴 RetryTimes 或 AutomaticRetryStatusCodes;成功、路徑耗盡、Caller Cancel,或 Downstream Response 已開始而無法透明重播時即停止。
這些是內部 Same-model Path Decision,並不代表 Client 可以再加一個無限 Retry Loop。Group 與 Channel 設計可參考 Reliable AI API Routing;AI API Error Troubleshooting則可協助區分 Gateway Policy Error 與 Upstream Failure。
為每次 Attempt 保留可重建證據
最終 200 不代表第一條 Route 成功;Final Channel ID 也無法描述前面的失敗。至少保留:
- 穩定 Request ID 與呼叫端可見 Correlation ID;
- Attempt Sequence 與選中的 Group/Channel Reference;
- 各 Attempt 使用的 Model 與 Endpoint Contract;
- Failure Status、Error Class 與 Stream Phase;
- Downstream Output 是否已開始;
- Timing Milestone 與 Cancellation State;
- 可取得時的 Input、Output 與 Cached-token Usage;
- Completed 或 Billable Attempt 的 Cost Attribution;
- Success、Exhausted、Cancelled、Partial 或 Policy Stop 等 Terminal Reason。
不要只為診斷 Fallback 就保留 API Key、Raw Prompt、Raw Response 或 Provider Credential。一般情況使用去識別 Error Class 與 Timing Metadata 即足夠;只有在明確啟用 Failure Investigation 時,才使用受限且短期的 Request Archive。
在 Production 前演練政策
以真實 Protocol Boundary 與安全、可重現輸入進行 Staging Exercise:
- 在 Header 前讓 Primary Channel 不可用,確認下一條合格 Same-model Path;
- 回傳 Rate Limit,確認 Attempt 上限與
Retry-After行為; - 取消 Caller,證明不會啟動後續 Attempt;
- 在輸出後中斷 Stream,證明沒有透明重播;
- 送出 Invalid Request,證明 Fallback 不會掩蓋錯誤;
- 重複 Tool Workflow,證明只記錄一次 Side Effect;
- 耗盡所有 Route,確認只有一個清楚 Terminal Error;
- 檢查 Attempt Ledger,核對 Usage 與 Cost。
先在小流量 Workload 上推出,分開監控 Attempt Count、Success-after-fallback 與 Raw Success Rate,並保留快速移除不健康 Route 的能力。目標不是讓 Fallback 次數最大化,而是在不改變原模型契約的前提下,於有限 Deadline 內安全恢復,且每次嘗試都有證據。