iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
Software Development

LLM infra 學習日記系列 第 14

一個 Request 怎麼走進 vLLM?從 API 到下一個 Token

  • 分享至 

  • xImage
  •  

The everything

Client
  │  POST /v1/chat/completions
  ▼
API Server Process
  │  validate、chat template、tokenize、sampling params
  ▼
AsyncLLM / EngineCoreClient
  │  EngineCoreRequest,透過 ZMQ 傳送
  ▼
Engine Core Process
  │  Scheduler + KV Cache Manager
  │  產生 SchedulerOutput
  ▼
Executor → GPU Worker → Model Runner
  │  prepare tensors → model forward → sample token
  ▼
ModelRunnerOutput
  │  更新 request 狀態,再經 ZMQ 回傳
  ▼
OutputProcessor → detokenize → SSE / JSON response

單 GPU 的基本部署至少包含三種角色:API server process、engine core process,以及管理 GPU 的 worker process。它們不是同一個 Python function 一路呼叫到底,而是分工並跨 process 傳遞資料。


1. API Server:把聊天請求變成模型輸入

request 進入 OpenAI-compatible endpoint 後,serving layer 先處理模型以外的工作:

檢查 request 與 model
→ 套用 chat template
→ 將 messages render 成 prompt
→ tokenize
→ 建立 SamplingParams

接著 OpenAIServingChat 呼叫 engine_client.generate(...)

這裡還沒有跑 GPU。API server 的任務是理解 HTTP/OpenAI protocol,並把外部資料轉成 engine 看得懂的輸入。


2. AsyncLLM:連接 API 與 Engine Core

AsyncLLMInputProcessor 會把輸入整理成 EngineCoreRequest,其中包含:

request_id
prompt token IDs
sampling parameters
arrival time / priority
LoRA、multimodal 或其他 request metadata

它同時建立一個 output collector,之後用來接收這條 request 的輸出。

request 再透過 EngineCoreClient 送到獨立的 engine core process。線上 serving 使用這層非同步介面,才能讓 API server 在等待 GPU 時繼續接收其他 requests。


3. Engine Core:持續轉動的控制迴圈

Engine Core 收到 request 後,會把它交給 Scheduler,然後在 busy loop 中重複三件事:

Scheduler.schedule()
→ model_executor.execute_model(...)
→ Scheduler.update_from_output(...)

也就是:先決定這一輪誰能跑,再派工作給 GPU,最後根據輸出更新每條 request 的進度。

Engine Core 是控制中心,但它本身不執行 Transformer forward。


4. Scheduler:這一步要算哪些 tokens?

Scheduler 維護 waitingrunning requests。每個 engine step 都有一個 token budget,它會依序判斷:

request 還有多少 tokens 尚未計算?
這一輪 token budget 還剩多少?
KV Cache 是否有足夠 blocks?
是否需要 chunked prefill、preemption 或 prefix-cache reuse?

確認可執行後,KV Cache Manager 會配置需要的 slots/blocks,Scheduler 再產生 SchedulerOutput

vLLM V1 的重點是 unified scheduling:Scheduler 分配的是「這一步各 request 要計算幾個 tokens」,而不是維護兩套完全分離的 Prefill Scheduler 與 Decode Scheduler。

因此第一次可能排進一批 prompt tokens;prompt 完成後,同一條 request 在後續 steps 通常一次前進一個 token。若 prompt 太長,也能切成多個 chunks。


5. Worker 與 Model Runner:真正進入 GPU

Executor 把 SchedulerOutput 派到 GPU workers。每張 GPU 通常由一個 worker process 管理,每個 worker 內有一個 Model Runner。

Model Runner 負責:

更新 persistent batch state
→ 準備 input tensors、positions、slot mappings、block tables
→ 呼叫 model forward
→ Attention backend 讀寫 KV Cache
→ 計算 logits 並 sample token

最後回傳 ModelRunnerOutput,其中包含 sampled token IDs、logprobs,以及 Scheduler 更新狀態需要的資料。

目前文件中的 vLLM V1 是整體 engine 架構;另外還有 Model Runner V2,代表 worker 內部較新的執行器。兩者層級不同,不要把名字理解成兩套互斥的 serving engine。


6. Token 怎麼回到 Client?

Model output 回到 Engine Core 後,Scheduler 會更新 token 數、檢查 EOS/長度限制,並在 request 完成時釋放 KV blocks。

EngineCoreOutputs 再傳回 API server process:

EngineCoreOutputs
→ OutputProcessor
→ token IDs 轉成文字
→ RequestOutput queue
→ chat completion formatter
→ SSE chunk 或完整 JSON

如果使用 streaming,client 看到一個 token,不代表 request 已走完。它會重新回到 Scheduler,進入下一個 engine step,直到遇到 EOS、stop condition、長度上限或取消。


Source trace 地圖

元件 目前主要位置 工作
API server launcher vllm/entrypoints/launchers/api_server/ HTTP server 與 process 啟動
Chat serving vllm/entrypoints/openai/chat_completion/serving.py render request、呼叫 generate、格式化回應
Async engine vllm/v1/engine/async_llm.py input/output processing 與 Engine Core client
Engine Core vllm/v1/engine/core.py schedule → execute → update 主迴圈
Scheduler vllm/v1/core/sched/scheduler.py token budget、request queue、KV block allocation
Model Runner V2 vllm/v1/worker/gpu/model_runner.py GPU input preparation、forward 與 sampling

舊的 vllm/entrypoints/openai/api_server.py 目前主要是 compatibility shim;讀最新版 source 時,入口應從 entrypoints/launchers 開始。

Reference


上一篇
TurboQuant:把 KV Cache 壓到 3–4 bit,真的會更快嗎?
下一篇
Continuous Batching:Batch 為什麼可以中途換人?
系列文
LLM infra 學習日記19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言