LLM(如DeepSeek、ChatGPT、LLaMA系列等)的推理本质是自回归生成:从初始输入(如[CLS]
或用户prompt)开始,逐token预测下一个词,直到生成结束符(如[EOS]
)。其核心分为两个阶段:
[CLS]你好
),嵌入为向量x_0
。h_0
。[batch, heads, seq_len, head_dim]
)。此时seq_len=0
,因为尚无历史token。示例:生成首词“今天”时,输入为[CLS]
,初始化后仅计算第一层的h_0
,KV Cache为空。
在LLM推理中,Initialization阶段(初始化阶段)又称“预填充阶段”(Prefill Stage)。这一命名源于其核心功能:为后续的逐token生成预填充(Prefill)KV Cache和初始隐藏状态。
Hugging Face的transformers
库、NVIDIA的FasterTransformer均采用prefill
和generation
区分这两个阶段。例如:
# 伪代码:Hugging Face生成逻辑
outputs = model.prefill(prompt) # 预填充KV Cache(Initialization)
for _ in range(max_new_tokens):
outputs = model.generate_step(outputs) # 解码阶段,逐token生成
场景 | 常用术语 | 含义侧重 |
---|---|---|
学术描述 | Initialization | 强调“初始化隐藏状态和缓存” |
工程实践 | Prefill | 强调“预填充固定长度的输入” |
用户视角 | 输入处理阶段 | 对应“用户输入的prompt处理” |
本质是同一阶段,但“Prefill”更直观反映了其“为生成提前准备历史KV”的工程目标。
t
个token为例):
t-1
步生成的token嵌入x_t
,与前一步隐藏状态拼接,输入Transformer层。Q_t
(因为只关注当前位置)。Q_t
与所有历史Key的相似度(仅需一次矩阵乘法,而非重复全量计算)。seq_len += 1
)。t
个token的概率分布,选择下一词(贪心/采样)。通过“预填充”,避免了每次生成新token时重复计算prompt的KV,这正是LLM实现高效推理的关键优化之一。
缓存历史层的Key/Value,避免重复计算。每个Transformer层维护独立的KV Cache,存储该层所有已生成token的Key/Value向量。
初始化缓存(t=0):
K_cache = []
, V_cache = []
(形状:[num_layers, heads, 0, head_dim]
)。第t步生成(t≥1):
Q_t, K_t, V_t
。K_cache[t_layer] = torch.cat([K_cache[t_layer], K_t], dim=2) # 在seq_len维度追加
V_cache[t_layer] = torch.cat([V_cache[t_layer], V_t], dim=2)
attn_scores = Q_t @ K_cache[t_layer].transpose(-2, -1) # Q_t: [1, heads, 1, d], K_cache: [1, heads, t, d]
attn_probs = softmax(attn_scores / sqrt(d)) @ V_cache[t_layer] # 仅需O(t)计算
循环:重复步骤2,直到生成[EOS]
或达到最大长度。
KV Cache是LLM落地的基石,其设计思想(复用历史计算)贯穿现代推理优化(如FlashAttention、QLoRA),最终实现了从“实验室模型”到“实时对话”的跨越。