LatencyLLM APIPerformance

LLM API 延遲最佳化完全指南 2026:從量測到逐層修復

閱讀 1 分鐘

你的儀表板顯示 P95 延遲 4.2 秒。基準測試網站說你的模型每秒跑 800 tokens——「很快」——而你的使用者還是在第一個 token 送達之前就關掉了分頁。

這個落差就是 LLM 延遲的完整故事:大家拿去基準測試的那個數字,和使用者真正感受到的那個數字是兩個不同的數字,而大多數團隊最佳化錯了那一個。

延遲是 LLM 技術棧中資料最豐富、但處方最貧乏的角落:基準測試網站發佈的 TTFT 與每秒 token 數表格多達數百張——Artificial Analysis 的供應商頁面AI API Cost 的即時速度排行榜是參考指標——但幾乎沒有一張告訴你該怎麼處理你的數字。供應商文件解釋的是它們自己的技術棧,不是你的。而這個領域最受歡迎的指標——每秒 token 數——經常被誤認為使用者真正感受到的東西。

這份指南就是處方層:延遲真正的意義是什麼(四個不同的數字,其中只有一個是 TPS)、為什麼它現在是產品指標、如何在一個經得起辯護的預算內量測它、如何修復每一層——串流、快取、模型分層、區域路由——以及那些把最佳化變成迷信的錯誤。

「延遲」對 LLM API 來說真正的意義

重點:延遲有四個數字,最佳化錯的那一個,正是團隊推出「很快」卻讓人覺得很慢的模型的原因。

  • TTFT——第一個 token 的時間。 使用者最先感受到的:介於「送出」與第一個串流 token 之間的空檔。對互動式產品來說,是唯一最重要的數字。
  • Token 間延遲——TPS 的倒數。 其餘回應串流過來的速度。對長輸出與 agent 迴圈很重要;對一行字的答案無關緊要。
  • 總請求時間。 總和,扣掉串流的感受。這是 batch 與背景工作關心的;不是使用者感受到的。
  • 感受延遲(perceived latency)。 串流轉化出來的東西:TTFT 加上串流的節奏。一個 TTFT 好、節奏穩定的系統,即使總時間很長,感覺起來還是很快。

這個領域對 TPS 的執著就是陷阱:一台 800 tokens/秒、TTFT 1.5 秒的模型,第一印象輸給一台 300 tokens/秒、TTFT 300ms 的模型。四個數字都要量;依使用情境最佳化。

為什麼延遲是產品指標

重點:agent 會把延遲放大,而使用者感受的是產品——數字從基準測試表移到了流失率圖表上。

延遲現在是產品決策,有兩個結構性原因:

  1. Agent 迴圈會把每一次等待放大。 一段對話要做 N 次循序的模型呼叫;每次呼叫快 500ms 的優勢,在 10 次呼叫的迴圈上就變成 5 秒的優勢。與驅動互動式系統 800ms 法則同樣的複利邏輯在這裡也適用:循序呼叫會相乘,所以每次呼叫的延遲是產品決策,不是效能點綴。

  2. 感受速度就是留存率。 串流 UI 的研究一再顯示,第一個 token 的時間驅動感受品質;最快的基準測試模型,如果 TTFT 慢就會輸。產品問題不是「模型多快」——而是「使用者的第一個 token 多快」。

如何量測:延遲預算

重點:量測是預算,不是基準——先拆解預算,再在你的區域、用你的 prompt 尺寸,同時量 P50 P95。

預算拆解:

階段包含什麼典型範圍
網路DNS、TLS、連線、區域距離20-200ms
佇列供應商端、接近速率限制0-500ms+
TTFT模型 prefill + 第一個 token200-1500ms
Token 間生成節奏1-5ms/token
用戶端解析、渲染、串流管線10-100ms

讓預算誠實的規則:

  1. 在正式環境的區域量測。 在美國東岸量測一個服務新加坡的產品,是全然不同的數字——區域延遲可能超過模型延遲。
  2. P50 藏起故事;P95 說出故事。 中位數藏起逾時;尾巴才是使用者記得的。
  3. 同樣的 prompt 尺寸、同樣的並發數。 用迷你 prompt 的基準測試會美化 TTFT,而且什麼都不懲罰。不是你的 prompt 組合,就是量測本身在行銷。

量測腳本,最小但誠實:

import time
from openai import OpenAI

client = OpenAI()          # your production endpoint and region
PROMPT = "..."             # a representative production prompt
N, STREAM = 50, True       # 50 runs, streaming on

ttfts, ipss = [], []
for _ in range(N):
    t0 = time.perf_counter()
    first = True
    stream = client.chat.completions.create(model="gpt-4o-mini",
                                            messages=[{"role": "user", "content": PROMPT}],
                                            stream=STREAM)
    for chunk in stream:
        if first:
            ttfts.append((time.perf_counter() - t0) * 1000)  # TTFT in ms
            first = False
            t_last = time.perf_counter()
        else:
            ipss.append((time.perf_counter() - t_last) * 1000)  # inter-token ms
            t_last = time.perf_counter()

def pct(xs, p):
    xs = sorted(xs); return xs[int(len(xs) * p)]
print(f"TTFT  P50={pct(ttfts, .5):.0f}ms  P95={pct(ttfts, .95):.0f}ms")
print(f"Inter-token  P50={pct(ipss, .5):.1f}ms  P95={pct(ipss, .95):.1f}ms")

從使用者實際所在的區域執行它,用你真正的 prompt 尺寸,然後把結果記錄下來,作為你的 CI 套件拿來比較的基準線。

量測習慣應該進到 CI:一個延遲回歸套件,在 TTFT 漂移時失敗——這是唯一能讓「模型變好了」保持誠實的東西——良好的可觀測性實務會為你技術棧的其他部分建立同樣的紀律。

如何最佳化:串流、快取、路由

重點:三根槓桿,照實作順序——全部都串流、快取重複的、依分層路由——而且三根都是設定,不是專案。

第 1 層——串流。 第一根槓桿,也是最便宜的:串流回應,讓 token 一到就渲染。互動式的決策是 SSE 還是 WebSocket——請求-回應串流用 SSE(更簡單、HTTP 原生、能穿過大多數 proxy),雙向流程用 WebSocket(agent、即時語音)。會打破天真串流的正式環境細節:proxy 緩衝(中間層把回應一直扣到完整才放行,就失去了意義)、斷線處理(用戶端放棄了;串流必須中止)、以及背壓。串流不會讓模型變快——它只是讓使用者的等待消失在串流的節奏裡。

第 2 層——快取。 兩個截然不同的好處:prompt caching(重複的 prefix 跳過 prefill,第二個相同呼叫的 TTFT 直接砍掉)與 response caching(相同的請求不需要接觸模型就能回應)。Prompt caching 指南涵蓋經濟學;延遲的角度是同一根槓桿:穩定的 prefix 讓第二次呼叫更快更便宜。注意 miss rate——一個 90% 都 miss 的快取只會增加開銷,沒有好處。

第 3 層——模型分層與路由。 互動路徑不需要每一輪都用前沿模型:把 UX 關鍵的呼叫路由到快速分層(包括我們快速推論比較中涵蓋的專用晶片供應商),背景工作路由到成本分層。自訂路由讓每個請求的決策變成機械式的,fallback 讓快速分層偶爾不可用不會變成你的延遲故事。

如何修復全球延遲:區域路由

重點:對全球使用者來說,選區域比選模型重要——同一個模型、選對區域,就是 300ms 和 900ms 的差別。

數字不會說謊:一台從美國伺服到歐洲使用者的模型,每一跳比區域端點多背 100-200ms 的網路延遲,而這個差距在 agent 迴圈中會複利。修法是架構性的:

  1. 最近區域路由。 讓每個使用者從離他最近、且提供該模型的區域獲得服務——負載平衡層在 endpoint 層級做這件事。
  2. 跨區域自動 failover。 當某個供應商或區域效能劣化時,在使用者的 TTFT 預算花完之前 failover 到下一個區域——自動 failover 文件涵蓋機制。
  3. 邊緣呼叫,短期用。 對極度延遲敏感的路徑,edge function 可以站在 LLM 呼叫前面——減少網路跳數並處理連線重用。誠實的註記:edge 有自己的 cold-start 成本,而對大多數工作負載來說,區域端點會勝出;採用前先測試(這是我們會點名、而不是過度承諾的邊緣案例)。

前面提到的量測規則在這裡要更用力地套用:區域路由決策需要區域量測——用美國的基準測試來評斷全球路由變更,不是量測。

常見錯誤

重點:四種失敗模式——每一種都會把延遲專案變成表演。

  1. 最佳化單一指標。 執著 TPS、無視 TTFT;執著 TTFT、無視串流。這份指南的四數字模型就是解藥。
  2. 忽略網路層。 全部做模型端最佳化、零區域路由——對全球產品來說,那是最佳化錯了預算的一半。
  3. 沒有命中率紀律的快取。 因為「快」就快取,卻有 90% 的 miss rate——快取經濟學只有在 prefix 穩定、命中率有量測時才成立。
  4. 最佳化前沒有基準線。 改了技術棧、上線了變更、從沒量過「之前」。沒有 CI 延遲套件,「最佳化」就只是掛著儀表板的希望。

常見問題

我應該先最佳化哪個延遲指標?

互動式產品最佳化 TTFT——那是使用者最先感受到的。Agent 迴圈與長輸出最佳化 TPS。最佳化你的使用情境感受到的那個指標,然後量測其他的,以免它們默默退化。

串流比較快,還是只是感覺比較快?

兩者都有,只是意義不同:總時間通常不變,但感受延遲會大幅縮減,因為第一個 token 提早送達、串流又幫其餘部分定下節奏。對互動式產品來說,感受延遲就是產品指標——全部都串流。

區域選擇對延遲影響多大?

通常比選模型還大:跨洲的網路跳數每次呼叫多出數百毫秒,在 agent 迴圈中複利。最近區域路由是全球產品最該做、卻幾乎沒做的高槓桿延遲變更。

串流用 SSE 還是 WebSocket?

請求-回應串流用 SSE——更簡單、HTTP 原生、對 proxy 友善。雙向流程(例如即時 agent)用 WebSocket。依照流程形狀選擇,而不是依熱度選擇,這就是完整答案。

快取真的能降低延遲嗎?

Prompt caching 會砍掉重複 prefix 的 TTFT(prefill 是昂貴的部分),response caching 對相同請求完全消除模型延遲——但前提是命中率是真的。量測命中率;miss rate 就是稅。

為什麼我的 P95 比 P50 糟這麼多?

LLM API 的尾巴延遲來自供應商在高負載下的佇列、接近速率限制、以及區域網路變異。如果尾巴很重要(確實很重要),修法是餘裕、fallback 與區域路由的組合——不是更快的模型。

總結

LLM API 延遲最佳化是一個四數字問題:在正式環境區域以 P50 與 P95 量測 TTFT、token 間、總量與感受延遲;然後逐層修復——串流解決感受、快取解決重複、分層解決成本與速度的平衡、區域路由解決預算中的網路那一半。基準測試表告訴你什麼是可能的;你的預算告訴你什麼是你的。先量測、後最佳化,世界上最快的模型就會變成你的使用者真正感受到的那一台。

你無法修復一個從沒量測過的延遲預算。取得你的 TokSpan API Key——$5 免費額度拿來量測——然後從幾個區域跑同樣的 prompt。