把重試預算算清楚:LLM 呼叫的「一次失敗」到底成本多少

上週一個朋友的線上服務半夜發出警報。模型服務商那邊一切正常,是我們這邊 23% 的流量在重試。更值錢的證據在帳單上:一個多月的 API 消耗裡,有相當一部分 429 重試其實是在重複一個註定會失敗的呼叫——那段時間服務商在降級,重試永遠救不回來,錢照燒。

專屬插圖
把重試預算算清楚:LLM 呼叫的「一次失敗」到底成本多少

把重試預算算清楚:LLM 呼叫的「一次失敗」到底成本多少

上週一個朋友的線上服務半夜發出警報。模型服務商那邊一切正常,是我們這邊 23% 的流量在重試。更值錢的證據在帳單上:一個多月的 API 消耗裡,有相當一部分 429 重試其實是在重複一個註定會失敗的呼叫——那段時間服務商在降級,重試永遠救不回來,錢照燒。

問題不出在重試本身,而是「重試三次」這種拍腦袋的常數。沒有人真正算過:這次失敗救回來的機率有多大,燒掉的 token 又值多少錢。

LLM 管線裡 429、5xx、timeout 的處理方式,直接決定了你的帳單結構和系統真實可用性。這筆帳,今天就可以算。

一次失敗的真實成本

一次失敗重試至少花兩層錢:已消耗 token 的費用+重試時要重發的全量 prompt。

LLM 呼叫和傳統 HTTP 介面最不同的是:失敗前,錢已經燒了。輸出到一半超時,供應商照算;輸入側的 system prompt、幾萬 token 的 context、工具呼叫結果,請求一發出就不可回收。

所以一次「救活」的重試,真實成本至少 2× 單次成本;「救不活」的重試是 3×,還一無所獲。

哪些故障值得重試

按「重試後恢復率」分層:

- **429 / 5xx / 網路 timeout**:恢復率高(429 一次退避後基本都能過),值得重試。

- **輸出截斷(finish_reason=length)**:有條件重試——保留已生成的前半段接續,別重發全量 prompt。

- **400 參數錯誤、內容審核攔截(content policy)**:恢復率為 0,重試只是白燒錢,必須第一次就 fail fast。

timeout 比較微妙:如果服務端還在算而客戶端先放棄了,重試等於「燒了一半的錢再賭一次」。判斷依據是 timeout 閾值與 p99 生成時長的比值——timeout 遠小於 p99 時,「假超時」會讓重試率虛高,帳單也跟著虛高。

大約 30 行的實作

核心是**預算+分類**,不是無腦迴圈:


import time, random
RETRY_ON = (RateLimitError, ServerError, TimeoutError)

def call_with_budget(fn, max_retries=2, base=0.5):
    for attempt in range(max_retries + 1):
        try:
            return fn()
        except BadRequestError:      # 400 / policy:不重試
            raise
        except RETRY_ON:
            if attempt == max_retries:
                raise
            time.sleep(base * 2 ** attempt + random.uniform(0, 0.3))

三個刻意選擇:max_retries=2,而不是更「安全」的 3 或 5(下面解釋為什麼);指數退避加隨機抖動,避免多實體同時打到同一個限流視窗;BadRequest/Policy 直接拋出,不進重試迴圈。

為什麼是 2 次,不是 3 次

經驗數據:429 第一次退避後的恢復率通常在 95% 以上;第 2 次重試追加的救回收益約 3–4%;第 3 次以後,每次重試救回的呼叫佔比往下掉,成本卻線性往上走。

「多一次重試更保險」聽起來對,但把 3 次和 2 次的成本畫出來:3 次相當於把 15% 的帳單花在救回 <2% 呼叫的事情上。對月呼叫量過萬的系統,這筆純虧。

所以把 max_retries 從 3 砍到 2,通常能用約 10% 的重試費用節省,換完全系統可用性的損失約 0.5%。這筆帳大部分系統都賺。

兩個要監控的指標

**重試花費佔比** = 重試產生的 token 費用 / 總費用。健康值 <5%。如果長期 8–15%,說明依賴方抖動壓力大,該評估 fallback 模型或多供應商。

**重試救回率(按次數)** = 第 N 次重試成功的呼叫數 / 首次失敗的呼叫數。第 2 次救回率若還在 10% 以上,說明你的失敗模式值得再多一次嘗試;若已降到 3% 以下,max_retries=2 就是對的邊界。

這兩個指標一起看,比「就按慣例 3 次」穩得多。

小結

重試不是信仰,是算術題。三個今天下午就能改完的動作:把 400/policy 類錯誤移出重試路徑(第一次就 fail fast);max_retries 從 3/4 降到 2 並寫註釋說明依據;監控面板加「重試花費佔比」一條,超 5% 觸發 review。

留言區

歡迎分享你的想法!

發表留言

0/500

載入留言中…