用 RadixAttention 把 Agent 延遲砍半

用 RadixAttention 把 Agent 延遲砍半

📌 本文重點

  • RadixAttention 讓 Agent 延遲大幅降低
  • 多工具、多會話共享前綴效果最顯著
  • SGLang 可用簡單設定直接落地實作
  • 不適合短 prompt、低共享前綴場景

多工具、多會話的 Agent 系統有一個共同痛點:每次工具呼叫或輪到 LLM 發言時,都在重算一大段相同的前綴——系統提示、工具描述、長對話歷史。SGLang 的 RadixAttention 直接針對這個問題下刀,讓你在相同模型、相同硬體上,僅靠更聰明的前綴重用,把 Agent 推論延遲實測砍到一半左右(視 workload 而定)。

💡 關鍵: 在共享前綴比例高的情境下,RadixAttention 能在不改模型與硬體的前提下,實際將延遲縮減約 50%。

以下會用開發者視角,把 RadixAttention 的原理、實作設定與踩坑點講清楚,讓你可以直接在現有 SGLang 推理伺服器上落地。


重點說明:RadixAttention 在 Agent 場景的三個關鍵

1. 從一般 KV cache / prefix caching 到 RadixAttention

傳統 KV cache(或 prefix caching)做的是:

  • 一條序列裡,從頭到目前 token 的 attention 計算結果被存成 Key/Value;
  • 下一次生成接續 token 時,重用這些 KV,不用再從頭算一次。

問題是:

  • 多會話 / 多工具情境下,彼此只共享一部分前綴(例如相同系統 prompt + 相同工具說明,但 user query 不同);
  • 傳統實作多半以「每條序列一個 cache」為單位,沒辦法精細共享“公共前綴子樹”。

RadixAttention 的觀念可以理解成:

  • 把所有序列的 token 前綴視為一棵 Radix Tree(前綴樹);
  • 相同前綴只存一次 KV 節點,不同的 user query 從公共根節點長出分支;
  • 多 session / 多 tool call 之間,只為分叉之後的部分做新增計算。

在 Agent workload 中,像是:

  • System prompt + 工具說明 + few-shot 手把手範例
  • 後面是每個 user query 與工具執行結果

RadixAttention 讓上述大片公共部分只算一次,每個新任務只負擔“差異部分”的計算。


2. 為什麼多工具、多會話、長上下文特別受益

RadixAttention 的收益跟「共享前綴比例」高度相關,以下這幾類 Agent 會特別有感:

  1. 工具描述很長的 Tool-using Agent
  2. 同一個工具庫(OpenAPI schema、function signatures、範例)對所有 session 共用;
  3. 使用 RadixAttention,工具段落只 encode 一次,後續所有對話都共享。

  4. 多輪長對話 + 連續工具呼叫

  5. 每一輪 LLM respond 之前,都要 re-encode 長對話;
  6. RadixAttention 把已存在的 KV 當「immutable context」,新輪只 append,避免重算整串歷史。

  7. 同一模型,多租戶 / 多房間聊天室

  8. 同一個 system prompt(企業規則、風格指示)在所有房間共用;
  9. RadixAttention 把這個 system prefix 變成共享根節點,TTFT(time-to-first-token)明顯下降。

💡 關鍵: 當 system prompt、工具描述與對話歷史占整體 prompt 的大部分時,前綴重用能直接轉化為明顯的 TTFT 與整體延遲改善。

如果你的 workload 是:

  • 單輪短對話(例如純自然語言問答)、
  • 或者 context 幾乎每次都完全不同,

則 RadixAttention 的收益會有限,甚至因為額外的管理開銷,吞吐可能略降。


3. SGLang 裡 RadixAttention 的實際運作方式

在 SGLang 裡,RadixAttention 主要透過下列概念實作:

  • Prefix sharing pool:把相同開頭(system prompt + tools)的序列放進同一個 pool,建立共享前綴;
  • Chunking:長序列拆成固定大小的 chunk(例如 512 tokens),以 chunk 為單位做 Radix 節點,共享更容易命中;
  • Batch 合併:多個請求在同一個 batch 裡時,會自動檢查可共享的前綴,融合成更大的 Radix 樹,提升 GPU 利用率。

實務上,你需要調的就是:

  • batch size
  • max radix tree depth / chunk size
  • prefix 分組策略(例如依 system prompt hash、toolset ID 分 pool)

下面用 5 組實務建議 config 說明。


實作範例:5 組推薦 SGLang RadixAttention Config

備註:以下設定以假想的 sglang_serve.py / sglang_config.yaml 為例,實際 API 名稱請依 SGLang 當前版本為準,但設計概念與參數層級是可直接參考的。

共同前提:基本啟動範例

python -m sglang.serve \
  --model /models/Qwen2-7B-Instruct \
  --enable-radix-attn true \
  --radix-chunk-size 512 \
  --max-batch-size 64 \
  --port 8000

或 YAML 版本(較好管理):

model: /models/Qwen2-7B-Instruct
server:
  host: 0.0.0.0
  port: 8000
  max_batch_size: 64
radix_attention:
  enabled: true
  chunk_size: 512
  max_depth: 8
  prefix_pool_size: 4096
  min_shared_tokens: 256

下文的 5 組 config 只是在這個基礎上做變化。


Config 1:單 Agent、多會話(TTFT 優先)

場景:單一產品的客服/助理型 Agent,多個使用者同時對話。System prompt 和工具描述完全一樣。

目標:最小 TTFT,穩定回應時間。

radix_attention:
  enabled: true
  chunk_size: 256           # 更細的 chunk,前綴命中率更高
  max_depth: 6
  prefix_pool_size: 2048    # 支援多房間
  min_shared_tokens: 128
batching:
  max_batch_size: 32        # 降低 tail latency
  max_wait_ms: 20           # batch 等待時間不要太長

好處:

  • System prompt + tool 定義只算一次;
  • 每個新對話 session 的 TTFT 實測可降 30–50%;
  • 適合偏互動感受(UX)優先的應用。

Config 2:多工具 Orchestrator(工具段最重)

場景:中控 Agent 使用 10+ 個工具(資料庫查詢、內部 API、search 等),工具 schema 很長。

目標:把工具描述重用到極致,降低工具呼叫頻繁時的開銷。

radix_attention:
  enabled: true
  chunk_size: 512
  max_depth: 10
  prefix_pool_size: 8192
  min_shared_tokens: 512
prefix_pools:
  - name: tools_v1
    match_key: toolset_id   # 依 toolset id 路由
    max_sessions: 4096

batching:
  max_batch_size: 64
  max_wait_ms: 40

實作重點:

  • 在送進 SGLang 前,把「system prompt + tool schema」綁一個 toolset_id;
  • 在 server 端根據 toolset_id 決定把請求丟進哪個 prefix pool;
  • 確保同一批工具的 Agent 都共享同一棵 Radix 樹。

好處:

  • 工具 block 通常占 prompt 50% 以上,
  • 實測在工具重度使用的場景,平均 latency 可降 40–60%,GPU 利用率上升。

💡 關鍵: 當工具描述占 prompt 的半數以上時,集中重用工具前綴能帶來最高比例的延遲與成本優化。


Config 3:RAG + Chat Agent(長 context,延遲與成本平衡)

場景:RAG pipeline,檢索結果(長文)加在 system prompt 後面,Agent 再做對話。

目標:降低重複查詢同一批資料時的成本,避免過度 chunking 帶來的管理成本。

radix_attention:
  enabled: true
  chunk_size: 768             # 長 chunk 降低樹深度
  max_depth: 6
  prefix_pool_size: 4096
  min_shared_tokens: 256

batching:
  max_batch_size: 48
  max_wait_ms: 40

rag:
  cache_key: doc_set_hash     # 同一批檔案的 hash 當成前綴 key

操作方式:

  • 對於同一批檢索結果(例如同一份報告),
  • 計算一個 doc_set_hash,
  • 當作 prefix key,讓這些查詢共享 Radix 前綴。

好處:

  • 同一批資料上的多輪問答幾乎只算一次長 context;
  • 減少 RAG 中「LLM 端」的成本,讓瓶頸回到向量檢索端(容易擴展)。

Config 4:高併發工具 Agent(吞吐優先)

場景:API 形式提供 Agent 能力,QPS 高,允許稍高 tail latency。

目標:最大化吞吐,同時在共享前綴上吃到 Radix 的效益。

radix_attention:
  enabled: true
  chunk_size: 512
  max_depth: 10
  prefix_pool_size: 16384
  min_shared_tokens: 256

batching:
  max_batch_size: 128
  max_wait_ms: 60

gpu:
  max_memory_utilization: 0.9

適用情境:

  • 同時有大量請求共用 system prompt / 工具集;
  • QPS > 50 時仍能維持穩定吞吐;
  • RadixAttention 在高併發下,能把 GPU 的 attention kernel 有效合併計算,吞吐近似提升 1.5–2x(視模型與硬體而定)。

Config 5:多模型 / 多任務共用集群(成本優化)

場景:同一集群跑多個 Agent(不同產品線),各自有不同 system prompt 和工具集,但共用一台 GPU / 多 GPU server。

目標:在成本限制下,利用 RadixAttention 避免為每個 Agent 開獨立模型實例。

models:
  - name: agent_a
    path: /models/Qwen2-7B
    radix_attention:
      enabled: true
      chunk_size: 512
      prefix_pool_size: 4096
  - name: agent_b
    path: /models/Qwen2-7B
    radix_attention:
      enabled: true
      chunk_size: 512
      prefix_pool_size: 4096

router:
  strategy: by_header         # 依 API key 或 header 分路

好處:

  • 單一模型實例上跑多個 Agent,RadixAttention 照樣在各自的 system prompt / toolset 內共享前綴;
  • 相對於為每個 Agent 部署獨立模型,可省下 GPU 台數,用相同硬體支撐更多產品線。

推理伺服器設定與壓測腳本範例

1. 簡單 SGLang 推理伺服器設定

假設你使用 Python client 直接呼叫 SGLang:

from sglang.client import SGLangClient

client = SGLangClient("http://localhost:8000")

SYSTEM_PROMPT = """You are a helpful multi-tool agent..."""
TOOLS_DESC = """[tool schemas here]"""

base_prefix = SYSTEM_PROMPT + "\n" + TOOLS_DESC

resp = client.generate(
    model="/models/Qwen2-7B-Instruct",
    prompt=base_prefix + "\nUser: ...\nAssistant:",
    extra_headers={
        "toolset_id": "tools_v1"  # 跟 Config 2 對應
    }
)

print(resp.text)

注意:

  • extra_headers 或 metadata 作為 prefix routing key 很實用;
  • 讓 server 能知道哪些請求理應共享前綴。

2. 簡單壓測腳本(多 session、多工具)

以下是簡化的壓測程式,用來比較 開 / 關 RadixAttention 的 latency:

import time
import asyncio
import httpx

URL = "http://localhost:8000/generate"

SYSTEM = "You are a tool-using agent..."
TOOLS = "[long tool desc]"

async def run_session(client, session_id):
    prompt = f"{SYSTEM}\n{TOOLS}\nUser: hi {session_id}\nAssistant:"
    t0 = time.time()
    resp = await client.post(URL, json={
        "prompt": prompt,
        "extra_headers": {"toolset_id": "tools_v1"}
    })
    dt = time.time() - t0
    return dt

async def main(n=100):
    async with httpx.AsyncClient(timeout=30) as client:
        tasks = [run_session(client, i) for i in range(n)]
        durations = await asyncio.gather(*tasks)
    print("p50:", sorted(durations)[int(0.5*n)])
    print("p95:", sorted(durations)[int(0.95*n)])

if __name__ == "__main__":
    asyncio.run(main())

測試方式:

  1. 關閉 RadixAttention(enabled: false)跑一次,記錄 p50/p95;
  2. 開啟 RadixAttention(使用 Config 2 或 4)再跑一次;
  3. 在前綴長度 > 2k tokens、共用 toolset 的情境下,常見能看到 p50 延遲下降約 40–60%。

建議與注意事項:幾個常見坑

1. 模型支援度與穩定性

  • 並非所有模型 / weight 格式都完全支援 RadixAttention,尤其是 特別修改過 attention 結構的模型;
  • 在導入前,先確認:
  • 官方支援列表(Qwen、Llama 家族通常支援較好);
  • 是否有已知 issue(例如和特定 FlashAttention 版本不兼容);
  • 導入初期要加強 回退策略:Radix 出錯或 OOM 時,自動退回普通 KV cache。

2. 工作負載不適合:收益有限甚至負向

RadixAttention 最適用:

  • 長 system prompt / 工具描述;
  • 多會話共享前綴;
  • 多輪對話需要重用歷史。

不適或收益有限:

  • 單輪、短 prompt 的 inference endpoint;
  • 每個請求的 prompt 都完全不同(例如 ad-hoc code generation、純 RAG 而前綴較短);
  • 超短 context(< 256 tokens),Radix 管理 overhead 可能大於節省量。

3. 成本 vs 延遲 vs 准確率:避免盲目開高配置

  • OOM 風險:
  • prefix pool 太大(prefix_pool_size、max_depth 過高),再配合大 batch,極容易炸 GPU memory;
  • 建議先從較保守的配置開始(如 max_depth=6、prefix_pool_size=4096),再逐步調高。

  • 吞吐 vs 延遲:

  • 高 batch size 能提升吞吐,但 tail latency 會變長;
  • RadixAttention 本身降低了 per-request 計算量,可以考慮 用其中一半收益換掉尾延遲,而不是全部拿來堆吞吐。

  • 准確率 / 行為一致性:

  • 在理論上 RadixAttention 不應改變模型輸出,但實作上若 prefix chunking / alignment 寫錯,可能導致 off-by-one bug;
  • 上線前務必做 回歸測試:相同 prompt,在開/關 Radix 時輸出應一致(或數據上差異可接受)。

4. 監控與回滾

部署 RadixAttention 時,務必加上:

  • 前綴重用率指標:例如每 batch 平均共享 token 數;
  • GPU memory 利用率與 OOM 次數;
  • 延遲分佈(p50 / p90 / p99)。

若發現:

  • 重用率低(比如平均只共享 < 10% tokens),
  • 或 tail latency 反而變高,

那就表示你的 workload 不適合,或 prefix 分組策略不對,需要調整甚至關閉。


總結:什麼專案值得優先導入 RadixAttention?

如果你的專案符合以下 3 點,非常值得先試 SGLang RadixAttention:

  1. System prompt + 工具描述 > 1k tokens,且所有請求共用;
  2. 同一 Agent 多 session / 多租戶跑在同一模型實例;
  3. 延遲敏感(需要 TTFT < 500ms、整體 latency < 2–3s)。

在這些情境下,實務上很容易看到 延遲砍半、成本下降 20–40% 的效果,而且只需調整 SGLang 的推理配置,不必改模型、不必改大部分上層業務邏輯。

對於正要把 Agent 往產線推的團隊,這是一個相對低風險、但高回報的優化點,值得早期就納入架構設計。


🚀 你現在可以做的事

  • 在現有 SGLang 伺服器上,先套用文中的 Config 1 或 Config 2 測試延遲變化
  • 為你的 Agent 標註 toolset_id / doc_set_hash,實作 prefix 分組並觀察前綴重用率
  • 撰寫回歸與壓測腳本,比較開關 RadixAttention 時的 p50/p95 延遲與成本差異

留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *