同一個開頭,被重算了一千次
如果你的 LLM 應用有固定的 system prompt、固定的政策說明、或是 RAG 檢索回來的那份文件,那麼每一次請求的前幾千個 token 其實都一模一樣。AWS Machine Learning Blog 在 2026 年 9 月 10 日的文章中舉了一個客服機器人的例子:開頭的指令大約 3,000 tokens,使用者真正問的問題只有 50 tokens。
vLLM、TensorRT-LLM 這類 serving framework 早就有解法:prefix caching,把算過的 KV pair 快取起來,下次同樣的開頭就直接重用,只算後面新增的 token,time-to-first-token(TTFT)可以明顯下降。
問題出在擴展之後。當 endpoint 後面掛了一整隊機器,請求被平均分散到 A、B、C 各台,同一個 3,000-token 前綴在每台機器都只出現幾次,誰都累積不出可靠的快取。功能明明開著,卻幾乎沒有作用。
SageMaker 把路由決策改成看內容
Amazon SageMaker Inference 推出的 prefix-aware routing,做法是看每個請求的開頭,把開頭相同的請求固定送到同一台 instance。同一個前綴的 KV cache 因此能真正建立起來並被重複使用。你不需要自己標記請求或維護 affinity,endpoint 依請求內容決定。
AWS 公布的 benchmark 用 Llama 3.1 70B Instruct、7 台 ml.p5.48xlarge、vLLM 開啟 prefix caching,對照預設的隨機路由:
- 8,000-token 共享前綴、持續 1 小時:P50 TTFT 降低 71–77%,P90 降低 33–37%,KV cache 命中率從約 25% 升到 82%,吞吐量增加 15–16%。
- ShareGPT 風格的變動長度短對話、30 分鐘:P50 TTFT 降低 13–16%,P90 降低 24–37%,命中率約 30% 升到 80%,吞吐量增加 1.7–2.0%。
路由邏輯本身每請求增加 1.3–1.9 毫秒,而測試中的模型 TTFT 落在 63–280 毫秒之間。流量分布也沒有出現熱點,7 台各拿到 13.3–15.4% 的請求。
兩個保護機制,與三種路由策略的取捨
前綴感知路由內建兩個保險。一是過載保護:如果某個前綴特別熱門,目標 instance 已經到頂,請求會改送到較閒的機器。你設定 concurrency 上限,endpoint 遵守它;代價是那一次可能少一次 cache hit,換來不壓垮單機。二是擴縮容時的穩定行為:增減 instance 時,多數請求仍送往原本的機器,只有少部分流量重新分配,快取不會每次擴容就被清空。
SageMaker 現在提供三種策略:RANDOM 是預設,適合請求可互換、沒有特定親和需求的一般工作負載;LEAST_OUTSTANDING_REQUESTS 把請求送到 in-flight 最少的機器,適合處理時間變異大、想避免慢請求堆積的情境;PREFIX_AWARE 則針對共享開頭、且 serving framework 已開啟 prefix caching 的 LLM 工作負載。策略設定在 production variant 上,改 endpoint configuration 就能切換,不必重新部署模型。
什麼樣的工作負載真的吃得到
AWS 點名的情境都有一個共同特徵:開頭很長、而且重複。RAG 應用把檢索到的文件放在問題前面,多個使用者問同一份文件時就共享同一段前綴;多輪對話每一輪都帶上完整歷史,越聊越長;固定模板的機器人每次都送同一套政策與格式規則;coding assistant 則是把檔案內容當 context,同一個檔案裡的每次補全都共享它。
反過來說,如果你的請求彼此之間沒有共用開頭,這個策略幫不上忙。
設定時真正容易踩到的三個地方
啟用時有兩個參數。PrefixLength(1024–65536)決定拿多少內容來做路由:原生 Invoke API 算的是 request body 開頭的 bytes,OpenAI 相容 API 算的是抽取出的訊息文字字元數。ConcurrencyThreshold(1–1024)則是目標 instance 的 in-flight 上限,超過就溢出到較閒的機器。
aws sagemaker create-endpoint-config \
--endpoint-config-name example-llm-config \
--production-variants '[{
"VariantName": "AllTraffic",
"ModelName": "example-llm-model",
"InitialInstanceCount": 3,
"InstanceType": "ml.p5.48xlarge",
"RoutingConfig": {
"RoutingStrategy": "PREFIX_AWARE",
"PrefixAwareRoutingConfig": {
"PrefixLength": 4096,
"ConcurrencyThreshold": 10
}
}
}]'
第一個坑是序列化一致性。原生 Invoke API 的 PrefixLength 作用在原始 bytes 上,JSON 的空白、key 順序、格式都會影響路由結果。同一個 prompt 用不同方式序列化,可能就被送到不同機器。
第二個坑是 PrefixLength 的長度拿捏。太短,所有共享短前綴的請求全擠到同一台,觸發溢出;太長,連 temperature 這種小差異都會把本該同路的請求打散。AWS 的建議是從共享前綴長度加上一點緩衝開始。
第三個坑是別忘了 serving framework 那一側。路由只負責把重複前綴送到同一台,容器本身要開啟 prefix caching 才會真的存下並重用 KV pair;vLLM 近期版本預設開啟,其他框架可能要明確設定。另外至少要有兩台 instance,只有一台時不管什麼策略都送同一個地方。
這類「把請求送到對的機器」的思路
前綴感知路由本質上是在路由層做一個內容感知的決策,而不是把請求當成可互換的單位平均分配。這個思路和我們先前談過的區域路由:關鍵不是在哪推論,而是請求在哪解密其實是同一類問題:當你把請求送到哪裡會直接影響成本與延遲時,路由策略就從維運細節變成產品決策。
對產品開發者來說,實際的下一步不是先改架構,而是先量測:開啟 SageMaker detailed observability 觀察模型層級的 KV cache 命中率,確認你的工作負載是否真的有共享前綴。如果命中率本來就低,換策略不會變出快取;如果命中率明顯偏低但前綴確實重複,那才值得調整 PrefixLength 與序列化方式。AWS 的 benchmark 是在特定模型、特定 instance 與 vLLM 配置下跑出來的,你自己的數字仍然要自己量。
參考來源
本文由 AI 協助自上述來源整理,經人工審核後發布。
