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 傳遞資料。
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 看得懂的輸入。
AsyncLLM 的 InputProcessor 會把輸入整理成 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。
Engine Core 收到 request 後,會把它交給 Scheduler,然後在 busy loop 中重複三件事:
Scheduler.schedule()
→ model_executor.execute_model(...)
→ Scheduler.update_from_output(...)
也就是:先決定這一輪誰能跑,再派工作給 GPU,最後根據輸出更新每條 request 的進度。
Engine Core 是控制中心,但它本身不執行 Transformer forward。
Scheduler 維護 waiting 與 running 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。
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。
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、長度上限或取消。
| 元件 | 目前主要位置 | 工作 |
|---|---|---|
| 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 開始。