别只当API调用侠了!一文带你深入大模型“体内”,看懂推理全流程

张开发
2026/4/3 15:36:30 15 分钟阅读
别只当API调用侠了!一文带你深入大模型“体内”,看懂推理全流程
我把自己写糊涂了每次想到哪里写哪里写着写着就跑偏了概念越来越多…如果让我在面试里先用一句话概括我会这样回答一个 prompt 从输入到输出大体会经历 6 个阶段请求封装、tokenization、推理调度、prefill、decode、结果反解码返回。其核心本质是模型先并行“读懂”整段输入建立上下文状态和 KV cache然后再进入自回归生成循环每次只预测下一个 token。 这种“自回归 不做本次梯度更新”的推理方式正是 GPT 类语言模型的基本范式而 Transformer 则提供了它内部 attention 和前馈网络的计算骨架。一个更通俗的比喻上面的总结非常专业我们也可以用一个更生活化的比喻来解释让它变得更通俗易懂。想象一下你正在向一位博学的图书管理员提问。从你问出问题到他给你答案大致会经历这样一个过程第一阶段快速理解你的问题 (类似 Prefill 阶段)打包问题 (请求封装): 你提问时图书管理员的大脑会自动补充一些背景比如“这位读者需要一个通俗易懂的答案”。拆解关键词 (Tokenization): 他会把你的长问题拆解成一个个核心关键词或短语方便他去检索。问题排队与分组 (推理调度): 想象一下图书馆里有很多读者同时向这位管理员提问。他不会简单地“先来后到”而是有一个智能的“前台接待”。这个“接待”会把所有问题汇集起来看哪些问题可以打包在一起处理批处理/Batching从而让管理员一次性解决大大提高效率。这个管理和安排问题的过程就是 “推理调度”。通读全文、建立联系 (Prefill KV Cache): 最关键的一步来了。他不会马上开口回答而是会一次性、飞快地看完你所有的问题在脑海里形成一个完整的印象。他会立刻抓住所有关键词之间的联系并在心里打好一个“腹稿”或“思维导图”。这个“腹稿”就是所谓的 KV Cache是他的“短期记忆”记录了你问题的核心上下文。这个阶段非常快因为是并行处理的就像一眼扫过整张纸。第二阶段逐字逐句地回答你 (类似 Decode 阶段)开始构思第一句话 (Decode): 有了“腹稿”之后他会基于对你整个问题的理解构思出第一个最合适的词语或短语。边说边想、一字一句 (自回归): 他会一个词一个词地往外说。每说一个新词他都会回头看一眼刚才说的内容和脑海里的“腹稿”确保整个回答是连贯、通顺的。这个“看着前面说出后面”的过程就是 自回归。这就是为什么你看到的 AI 回答像打字机一样一个字一个字地蹦出来。组织成你能听懂的话 (反解码): 他脑子里的概念最终会变成你我能听懂的自然语言。核心总结整个过程分为两大步先是飞快地“读”一次性理解你的整个问题并形成记忆Prefill然后是慢悠悠地“写”一个词一个词地、有逻辑地组织出答案Decode。关于两个关键点他只回答不学习 (不做梯度更新): 在这个回答的过程中图书管理员只是在调用他已有的知识他本身不会因为你的问题而学到新知识或改变自己的知识体系。这叫推理和学习训练是两码事。他的大脑构造 (Transformer): 这位管理员之所以能这么聪明是因为他有一个基于 Transformer 模型的大脑这个大脑特别擅长通过一种叫 Attention 的机制快速判断出你问题中哪些词最重要、关联最紧密。这句话为什么重要因为它先把系统层和模型层分开了也先把prefill和decode分开了。很多人答这道题失分不是因为不会而是因为把所有层次混在一起听起来就没有脉络。补充一个 Prompt 的“人生旅程”图步骤名称 (和比喻)发生什么1 请求封装(写信封)你的问题 (Prompt) 会被系统包装一下加上一些额外的指令比如“你是一个乐于助人的助手”。⬇️2 Tokenization (文本分词)(翻译成密码)完整的问句被切成一个个词或字的“零件”(Token)然后每个“零件”都被翻译成模型能懂的数字 ID。⬇️3⚙️ 推理调度(快递分拣中心)你的请求会和别人的请求一起排队系统会把它们智能地打包Batching好让 GPU 一次性处理更多任务提高效率。⬇️Borders 进入 LLM 大脑核心区 4⚡ Prefill (预填充)(快速通读题目)模型一次性、并行地处理你所有问题的数字 ID瞬间理解你问了什么。这个过程非常快就像你一眼扫过整道题目。 产出关键记忆这个阶段最重要的产物是 KV Cache可以理解为模型读完题目后在脑海里形成的“上下文笔记”。⬇️5✍️ Decode (解码)(逐字动笔回答)模型进入“写作模式”利用刚刚产生的“上下文笔记”(KV Cache)一个字一个字地往外生成回答。每写一个字都会回头参考笔记确保回答连贯通顺。⬇️Borders 离开 LLM 大脑核心区 6 反解码返回(从密码翻译回文字)模型生成的数字 ID 被“翻译”回人类能读懂的文字然后像打字机一样一个一个地显示在你的屏幕上。核心总结Prefill (第 4 步) 像“读”速度很快一次性读懂整个问题。Decode (第 5 步) 像“写”速度相对慢一个字一个字地往外吐。所以你平时感觉 AI 回答第一个字比较慢后面就快了正是因为模型需要先花一点时间完成Prefill读题阶段然后才能开始Decode答题。vLLM 启动后加载模型发生了什么当 vLLM 启动并加载一个模型时它所做的事情远比标准的AutoModel.from_pretrained(...)要复杂得多。其核心目标是对模型进行“魔改”和准备以便适配其独有的 PagedAttention 机制从而实现极致的性能和内存效率。备注PagedAttention 机制深度解析PagedAttention 是 vLLM 的核心创新也是它实现超高吞吐量的关键所在。理解它“做了什么”最好先从它要“解决什么问题”开始。问题传统的 KV Cache 管理方式有什么弊病在 PagedAttention 之前主流的 KV Cache 管理方式是“连续内存分配”。工作方式系统为每一个请求sequence都预先分配一块连续的、大的显存空间用来存放这个请求在生成过程中不断增长的 KV Cache 数据。弊病很明显巨大的内存浪费内部碎片为了防止生成过程中内存不够系统必须按“最大可能长度”如 2048 或 4096来预分配空间哪怕用户请求的实际总长度可能只有 100。这就导致了 90% 以上的预留空间被闲置浪费。严重的内存碎片外部碎片当大量长短不一的请求并发执行时显存会被切割成大大小小的“空洞”。一个长请求结束后它释放的连续空间可能很大但后续如果来的都是短请求就无法有效利用这块大空间导致大块显存被“空置”在那里新请求却因找不到合适的连续空间而无法进入。复杂的共享机制在一些高级采样方法中如并行采样、Beam Search多个候选序列需要共享同一个 Prompt 的 KV Cache。在连续内存模式下实现共享的唯一方法就是“完全复制”这既慢又消耗大量显存。比喻传统方式就像给每个用餐的客人请求都预先分配一个超大的、固定长度的桌子连续内存不管他点几道菜。这导致餐厅GPU空间利用率极低很多空座位无法给新客人用。解决方案PagedAttention 机制做了什么PagedAttention 借鉴了操作系统中经典的“虚拟内存”和“分页”思想彻底改变了 KV Cache 的存储和管理方式。1. 将 KV Cache “分页”存储PagedAttention 不再为每个请求分配连续的内存而是将 KV Cache 存放在一些不连续的、固定大小的内存块Block 或 Page中。物理块池Physical BlocksvLLM 启动时会预先将大量 GPU 显存划分为一个由成千上万个小块组成的“物理内存池”。逻辑块Logical Blocks一个请求生成的 KV Cache 数据流在逻辑上是连续的。块表Block TablePagedAttention 的核心。它为每一个请求维护一个“块表”这个表建立了“逻辑块”到“物理块”的映射关系。例如一个请求的块表可能会记录“我的第 1 个逻辑块存放在物理内存池的第 57 号块第 2 个逻辑块存放在第 1024 号块第 3 个在第 233 号块……”工作流程当模型需要为某个请求生成一个新的 Token 时vLLM 的调度器只需要从物理内存池中取出一个空闲块然后将这个块的地址追加到该请求的块表末尾即可。实现高效的“写时复制”共享Copy-on-Write这是 PagedAttention 最惊艳的功能之一。当需要共享 KV Cache 时例如一个 Prompt 生成多个不同的回答vLLM 不需要复制庞大的 KV Cache 数据本身。它只复制“块表”生成一个新的候选序列时vLLM 只需复制一份原始请求的块表。这样新的候选序列和原始序列的块表在初始阶段会指向完全相同的物理内存块这些块里存着共享 Prompt 的 KV Cache。这个复制成本极低。写时才分配新块当新的候选序列开始生成与原始序列不同的 Token 时vLLM 才会为它分配新的物理块并更新它自己的块表。比喻PagedAttention 就像一个聪明的餐厅老板。他把所有菜品KV Cache都放在后厨标准化的餐盘Block里。客人点餐时他只给客人一个菜单块表上面写着你的菜品在后厨的哪个餐盘。空间利用率高后厨的所有餐盘都可以被灵活使用几乎没有浪费。共享方便如果两桌客人点了同样的前菜老板不需要做两份只需要在他们的菜单上都指向后厨同一个餐盘即可。只有当某一桌开始点不同的主菜时才需要动用新的餐盘。总结PagedAttention 带来的三大好处近乎零的内存浪费通过将内存“化整为零”极大地减少了内外部碎片vLLM 官方声称内存效率可达 96%。灵活强大的采样算法支持通过“块表”的复制可以极低成本地实现并行采样、Beam Search 等复杂算法极大地丰富了模型的输出多样性。极高的吞吐量因为内存效率极高同一个 GPU 上可以同时容纳比其他引擎多得多的请求即更大的批处理大小 Batch Size从而将吞吐量提升一个数量级。PagedAttention 原理图解下图清晰地展示了两个不同请求A 和 B如何通过各自的“块表”类似 HashMap共享和独立使用 GPU 显存中的“物理块”。graph TD subgraph GPU 显存物理块池 P1[物理块 1 (空闲)] P2[物理块 2] P3[物理块 3 (空闲)] P4[物理块 4] P6[物理块 6] P7[物理块 7] end subgraph 请求 A idA[块表 Abr/[0] - 块 7br/[1] - 块 2] end subgraph 请求 B idB[块表 Bbr/[0] - 块 7br/[1] - 块 6br/[2] - 块 4] end idA -- 映射 -- P7 idA -- 映射 -- P2 idB -- 映射 -- P7 idB -- 映射 -- P6 idB -- 映射 -- P4深度解析块表究竟存在哪里这是一个非常关键的实现细节它涉及 CPU 和 GPU 的协同工作。块表的“管理和决策”发生在 CPUvLLM 的调度器Scheduler运行在 CPU 上。它像一个“大管家”在 CPU 内存中维护着所有请求的块表状态并进行分配、释放、复制、共享等所有逻辑操作。块表的“最终解释权”和“修改权”归属于 CPU。块表的“读取和执行”发生在 GPUPagedAttention 的计算核心CUDA Kernel运行在 GPU 上。为了进行高速计算它必须能直接访问块表。因此在每个计算迭代开始前CPU 上的调度器会把当前批次所需的块表数据从 CPU 内存拷贝到 GPU 显存中。随后GPU 就可以在自己的高速显存内看着这份“工作指令”块表完成全部的“查找地址 - 读取数据”操作避免了与 CPU 的慢速通信。总结 块表的状态在 CPU 上被动态管理但在每次运算时其数据会被同步到 GPU 显存供计算核心直接使用。整个过程可以分解为以下几个关键阶段阶段一下载与分发模型权重下载模型vLLM 首先会像 Hugging Face Transformers 一样从 Hub 或本地路径下载并加载模型的配置文件config.json和权重文件如.safetensors或.bin文件。如果需要张量并行切分 (Tensor Parallelism)如果你配置了张量并行tensor_parallel_size 1vLLM 会在加载权重时就直接将其“切分”好。详细解释nn.Linear与切分方式这种“先列后行”的切分方式是 Megatron-LM 等框架实现高效张量并行的核心思想。备注切分发生在哪里“切分”这个动作通常不是在 GPU 上发生的而是在 CPU 内存RAM 中。完整的流程是程序先将整个权重张量从硬盘加载到 CPU 内存在 CPU 上将其切分成小块然后才将这些切好的小块分别发送到对应的 GPU 显存上。这样做可以避免任何单个 GPU 因为要加载一个可能比它显存还大的完整权重而崩溃。沿列切分 (Column Parallelism)第一个权重矩阵W1会被垂直沿列切分。每个 GPU 计算Input 一小块W1得到分裂的中间结果。沿行切分 (Row Parallelism)第二个权重矩阵W2会被水平沿行切分。每个 GPU 用上一层分裂的中间结果去乘以一小块W2得到“部分”的最终结果最后所有 GPU 的结果通过一次通信All-Reduce相加得到完整的输出。例如一个标准的nn.Linear层的权重矩阵会被沿列对于行并行或沿行对于列并行切开。这样每个 GPU 只会加载模型权重的一部分。比如一个大的权重矩阵被切成 4 份分别加载到 4 个 GPU 上。这一步是实现模型并行计算的基础。nn.Linear是什么 它是在 PyTorch 等框架中的“线性层”或“全连接层”核心是执行一次矩阵乘法 (output input W^T b)。这里的W就是需要切分的巨大权重矩阵。如何切分 在 Transformer 的前馈网络FFN/MLP Block中通常有两层连续的nn.Linear可以看作Output (Input W1) W2。阶段二模型结构的“魔改” (Kernel Injection)这是 vLLM 与众不同的核心步骤。vLLM 不会直接使用原生 Hugging Face 模型中的Attention或MLP模块因为它自己的 PagedAttention 机制需要特殊的计算方式。加载原始架构vLLM 先在 CPU 上构建出模型的原始架构例如 LlamaForCausalLM。替换关键模块随后vLLM 会遍历模型的每一层用自己高度优化的模块替换掉原始模块。最典型的替换它会找到原始的LlamaAttention模块并将其替换为自己的PagedAttention实现。为什么这么做vLLM 的PagedAttention是用 CUDA/Triton 等底层语言编写的定制化算子Kernel它不像标准 Attention 那样需要连续的 KV Cache 内存。为了让模型能调用这些特殊的算子必须在代码层面进行“注入”或“替换”。同样MLP/FFN 等其他模块也可能被替换为融合了激活函数的高性能版本以减少 GPU Kernel 的启动开销。经过这个阶段模型虽然从外部看还是那个 Llama 模型但其内部的“引擎”——尤其是 Attention 计算部分已经被换成了 vLLM 的独门法宝。阶段三KV Cache 内存池的初始化这是 vLLM 实现高性能内存管理的另一个核心。计算可用内存vLLM 会检测所有 GPU 上的可用显存。创建物理块池 (Physical Block Pool)vLLM 不会等待请求来了再动态分配 KV Cache。相反它会在启动时将可用显存的很大一部分预先分配并组织成一个巨大的“KV Cache 内存池”。避免内存碎片因为块大小固定所以不会产生小的、无法使用的内存碎片。实现 PagedAttention为 PagedAttention 机制提供了可以直接操作的、离散的内存单元。这个内存池被划分为成千上万个固定大小的、不连续的物理块Physical Blocks。你可以把它们想象成操作系统的内存“页”Page。这样做的好处此时vLLM 已经为所有未来可能的请求准备好了一个巨大的、可灵活调度的 KV Cache 存储空间。阶段四引擎与调度器的启动实例化 LLMEngine将“魔改”后的模型、张量并行配置、KV Cache 内存池等所有组件组合在一起创建一个核心的LLMEngine对象。这个引擎是整个推理服务的大脑。初始化调度器 (Scheduler)LLMEngine内部会启动一个调度器。这个调度器的职责是接收新来的推理请求。实现连续批处理 (Continuous Batching) 策略智能地将请求组合成批次。管理逻辑块到物理块的映射即决定哪个请求的哪个 Token 的 KV Cache 应该存到哪个物理内存块中。启动 API 服务最后vLLM 会启动一个 Web 服务器如 FastAPI开放 HTTP 端点等待接收用户的推理请求。总结比喻如果把标准模型加载比作“买来一辆家用车”那么 vLLM 加载模型的过程更像是采购零件 (下载权重)买来顶级跑车的发动机、底盘、车身等所有核心零件。如果搞“多卡并行”就是把零件分发到多个车间。改装引擎 (模型魔改)不用原厂的涡轮和变速箱而是换上自己研发的、配合“氮气加速系统 (PagedAttention)”的定制化超级引擎。建立配件仓库 (初始化KV Cache池)在车库里建一个巨大的、模块化的货架上面放满了成千上万个标准尺寸的零件盒用来存放未来比赛中可能需要的所有备件。组建指挥团队 (启动引擎和调度器)赛车和仓库都准备就绪最后请来一位经验丰富的赛事总监调度器他将负责指挥赛车何时进站、何时加速、如何高效地从仓库取用备件。当这一切完成后vLLM 才真正准备就绪能够以极高的效率处理并发请求。Prompt进入vllm之后第一部分准备阶段 —— 模型“看到”问题之前步骤 1文本到数字的“翻译” (Tokenization)我们在聊天框里看到的是自然语言但模型真正接收到的通常不是这段原始文本本身。在送入模型之前服务层一般会先把 system、user、assistant 等多轮消息按固定模板组织起来再补上一些特殊标记(基于聊天模版)。 随后文本会经过 tokenizer被切成 token 序列基于词表。像 OpenAI 开源的 tiktoken备注tiktoken是 OpenAI 官方开源的高效分词器用于将文本切分为模型可处理的数字 ID 就明确说明它是一个用于模型的 BPE tokenizer。也就是说对模型来说文本首先会被变成一串离散的 token IDs备注Token ID(单数) 指的是词汇表中代表单个Token的唯一数字编号它是一个标量。模型会用这个ID作为“钥匙”来获取其对应的“词向量”。而文中的token IDs(复数) 指的便是代表整段文本的、由多个Token ID组成的 数字序列/列表而不是“句子”本身。这一层很多人容易忽略但它很关键。因为后面所有推理都是建立在 token 序列上的。你输入的是一句中文、一段英文、还是一段代码对模型来说第一步都得先转换成 token IDs。步骤 2推理调度与请求批处理 (Scheduling Batching)在真实的工程系统中一个经过 Tokenize 的请求并不会立刻被送入 GPU 执行。它会先进入一个“调度中心”由推理服务框架如 vLLM进行统一管理这个过程就是推理调度 (Scheduling)。调度的核心目标是提升系统整体的吞吐量和效率而它最重要的手段就是批处理 (Batching)。Batching 指的是将来自不同用户的多个独立请求“打包”成一个批次Batch然后一次性喂给 GPU 进行并行计算。这就像一辆货车GPU一次性运送一整车的货物a batch of requests而不是一次只送一个包裹a single request极大地提高了运输效率。在现代推理系统中通常采用更先进的 Continuous Batching (连续批处理)。这是一种动态策略调度器不必等待批次里的所有请求都生成完毕而是当任何一个请求完成后就立刻将其从批次中移除并动态地将新等待的请求补充进来从而减少 GPU 的空闲时间进一步降低延迟。所以从系统视角看这一步是专门为了“压榨”GPU性能而设计的优化层。它的意义在于模型推理不是单个请求的“裸跑”而是由推理引擎通过高效的调度和批处理对大量并发请求进行统一组织和优化。备注vLLM 如何实现高效调度和批处理vLLM 的高效正来源于其独特的调度和批处理机制它与 PagedAttention 密不可分。传统静态批处理Static Batching的弊端在 vLLM 之前普遍做法是将 N 个请求打包将所有请求填充Padding到与最长请求一致的长度然后整个批次一起计算直到所有请求都完成才能结束。这导致了大量的显存和时间浪费即 GPU “空转”。vLLM 的 Continuous Batching PagedAttentionvLLM 的 连续批处理 是一种迭代式的动态调度其核心工作流程如下循环与检查调度器在一个循环中运行在每个计算步它都会检查“正在运行”的请求队列。单步生成将当前所有正在运行的请求组合成一个动态批次送入 GPU 仅生成一个新 Token。立即释放计算一结束调度器马上检查是否有请求已完成如生成结束符。若有立即将其移出队列并释放其占用的内存块得益于 PagedAttention。动态补充因为有内存被释放调度器会尝试从“等待”队列中立刻加入新的请求到“正在运行”队列从而填补空缺。PagedAttention 是实现这一切的基石它以“块”为单位的非连续内存管理完美解决了传统方式的填充和碎片问题使得在每个步骤动态增删请求成为可能。绝佳比喻玩俄罗斯方块静态批处理像新手玩俄罗斯方块一次必须凑齐一行才能放下中间全是空隙填充浪费效率低下。vLLM像顶级玩家所有方块都由 1x1 的小方块构成PagedAttention内存块可以紧密堆叠。一旦某一行填满请求完成瞬间消除内存释放新的方块新请求立即落下填补空间使游戏区域GPU始终保持高密度、高速运转。第二部分核心阶段 (一) —— “读懂问题”的 Prefill步骤 3数字 ID 到语义向量 (Embedding)真正进入 LLM 后第一步不是“开始回答”而是把 token IDs 映射成高维向量。这一步叫 embedding lookup。每个 token 都会查一张巨大的 embedding 表得到自己的向量表示。到这时模型才真正进入连续空间的数值计算。Transformer 的基础论文《Attention Is All You Need》所定义的就是这样一种基于 attention 的序列建模方式。不过只有 token 向量还不够因为模型还得知道“谁在前、谁在后”。早期 Transformer 使用位置编码后来很多大模型会用 RoPERotary Position Embedding。RoPE 的核心价值是把位置信息融入 attention 计算中让模型在处理 token 时同时保留相对位置信息。步骤 4真正的核心计算 (Transformer Block)这是这道题最核心の部分。如果面试官说“越详细越好”你就必须把 Transformer Block 讲清楚。一个典型的 decoder-only LLM每一层大体都会做两件事●第一Self-Attention●第二FFN / MLP前馈网络中间再配合残差连接和归一化。Transformer 论文给出的主体结构就是这样。你可以把它想成●attention 负责“读群聊”●FFN 负责“自己想一想、整理一下”Self-Attention 在干什么可以把它理解成当前位置的 token要去看上下文里哪些 token 最相关。模型会把当前隐藏状态投影成 Query、Key、Value 三组向量然后通过 Query 和所有 Key 的相似度算出注意力权重再对 Value 做加权求和。Transformer 论文把它定义为 Scaled Dot-Product Attention。对于生成式语言模型还有一个必须强调的点causal mask。也就是当前位置只能看见自己和前面的 token不能偷看未来。这一点决定了模型天然是自回归生成的它永远只能基于已有上下文去预测下一个 token。GPT-3 论文里所讨论的 few-shot/in-context learning本质上也是建立在这种自回归预测机制之上的。关于 Q、K、V可以简单这样理解Q 我现在想找什么K 每个词身上贴的“索引标签”V 每个词真正携带、可被取走的信息。最通俗的比喻是“图书馆检索”你现在脑子里有一个问题这就是 QQuery书架上每本书卡片上的主题标签是 KKey书里真正的内容是 VValue。系统先拿你的问题 Q 去和所有标签 K 比一比看看“像不像、相关不相关”相关度高的那些书它们的内容 V 就会被更多地取出来最后合成当前这一步该看的信息。Transformer 论文对 attention 的定义本质上就是“一个 query 对一组 key-value 对做匹配输出是 values 的加权和”。FFN 又在干什么如果说 attention 负责“从上下文搬运信息”那么 FFN 更像是“对当前位置做进一步加工”。它不会跨位置交互而是对每个 token 的表示单独做非线性变换把特征进一步提纯和增强。Transformer 论文把它称为 position-wise feed-forward network。所以一个 Transformer Block 可以粗略理解成先决定我该关注上下文里的谁再把取回来的信息做一轮更深的特征变换注意在整个流程中prefill 和 decode 阶段都要做 self-attention 和 FFN。但要分清楚“都要做”不等于“做法完全一样”。●Prefill 把整段 prompt 一次性送进去。 这时每一层都会对这批 token 做 masked self-attention然后再过 FFN。因为整段 prompt 一开始就都已知所以这一步可以在单个请求内部并行处理很多 token。Hugging Face 对 prefill 的描述也是prefill 会处理整段输入并建立 KV cache。●Decode 开始一个 token 一个 token 往后生成。 这时每生成一个新 token它仍然要在每一层里经过一次 self-attention一次 FFNdecode 不是把旧 token 全部再跑一遍 attention 和 FFN。有了 KV cache 后旧 token 的 K/V 会被缓存起来新 token 到来时只需要为这个新 token 计算当前层需要的表示再和历史 K/V 做注意力计算然后继续过 FFN。Hugging Face 官方缓存文档明确说了后续生成时只传入尚未处理的新 token并把 key/value 写入和读取自 cache。FFN 就是 Transformer 每层里、紧跟在 self-attention 后面的前馈网络本质上是对每个 token 单独做的 MLP 加工。在标准 LLM 里prefill 和 decode 两个阶段都要经过 self-attention 和 FFN区别只是 prefill 处理整段已知 tokendecode 只处理当前新 token并复用历史 KV cache步骤 5并行处理一次读懂 (Prefill)很多人会误以为模型一进来就开始逐字生成。其实不是。生成前通常会先有一个很重要的阶段Prefill。Prefill 的意思是先把整段 prompt 一次性跑完整个前向过程。在这个阶段模型会为输入中的所有 token 计算各层隐藏状态并且生成后面 decode 要用到的 KV cache。Hugging Face 的缓存文档明确指出KV cache 会把注意力层中之前 token 产生的 key-value 对存下来后续生成时直接复用从而避免重复计算。Prefill 的一个重要特点是它通常可以高度并行。因为整段输入已经完整给定了GPU 能把很多矩阵操作一起做完。所以 prefill 更像“先整体读题”吞吐通常更高。vLLM 文档也明确把 prefill 归类为更偏 compute-bound 的阶段你可以把 prefill 想象成一个正在考试的人prefill 就是他正在读题把题目先读到脑子里填充好上下文然后再开始做答输出 token步骤 6制作高效“备忘录” (KV Cache)这部分是面试里非常加分的点。因为它体现你不只懂“算法”还懂“推理为什么能跑得起来”。如果没有 KV cache那么每生成一个新 token模型都要把整个历史上下文从头再算一遍成本会非常高。而有了 KV cache 后历史 token 在每层 attention 中算出的 K 和 V 都被缓存起来。下一个时间步只需要为新 token 计算新的 Query、Key、Value再用新的 Query 去和历史缓存里的 Key 做匹配即可。Hugging Face 的官方文档把这一点解释得很清楚KV cache 的目标就是消除重复计算加速自回归生成。一句话说明就是●没有 KV cache像每次都重读整篇文章●有 KV cache则像前文已经做好笔记现在只补最后一句。为什么 KV cache 只缓存 K 和 V而不缓存 Q一个东西值不值得缓存不看它“重不重要”而看它“后面还会不会再次被用到”。KV cache 只缓存 K 和 V不缓存 Q不是因为 Q 不重要而是因为 Q “只在当前这一步有用一次”而 K、V 会在后面每一步继续被反复用到。 这正是 Hugging Face 官方对缓存机制的解释过去 token 的 K 和 V 可以缓存并复用而在推理时只需要“最后一个 token 的 query”来计算当前步的表示。第三部分核心阶段 (二) —— “逐字回答”的 Decode步骤 7循环生成逐字输出 (Decode)当 prefill 完成后模型已经“读懂”了整段输入。接下来系统会取最后一个位置的隐藏状态通过输出层映射成整个词表上的 logits也就是“下一个 token 的打分”。随后再通过 softmax 和解码策略决定下一个 token 输出什么。Transformer 的输出逻辑与 Hugging Face 的生成文档都说明了这一点。下一个 token 是怎么选出来的并不是只有“选概率最大”这一种方式。常见解码策略包括 greedy、sampling、top-k、top-p 等。不同策略会影响文本の稳定性、多样性和创造性。Hugging Face 的生成策略文档对此有系统说明。然后流程进入一个循环●把刚生成的 token 接到上下文后面●复用 KV cache●只为这个新 token 跑一遍前向计算●再得到新的 logits●再生成下一个 token这就是为什么你看到的大模型回答总是一个 token 一个 token 流式地吐出来而不是整段瞬间出现。第四部分常见疑问与总结问为什么“第一个字慢后面快”这也是一个非常像面试 follow-up 的问题。很多候选人知道 prefill 和 decode但解释不清为什么两者速度特征不同。vLLM 的优化文档明确提到prefill 更偏 compute-bounddecode 更偏 memory-bound。原因在于prefill 可以把整段输入并行做大矩阵乘法吃满 GPU 算力而 decode 虽然每步只算一个 token但它强依赖历史 KV cache频繁访问显存并且步骤之间有严格的顺序依赖。这也是为什么工程上会有很多针对推理性能的优化比如●FlashAttention通过 IO-aware 的 attention 计算方式减少显存读写●continuous batching动态调整批次减少 GPU 空转●chunked prefill / Paged Attention改进长上下文和缓存管理效率要注意这些技术优化的是执行效率不是模型的“语义本质”。模型本质上做的事情仍然是基于已有上下文反复预测下一个 token问看起来主要是推理引擎在工作从整个流程上看几乎都是推理引擎在负责所以可以这么理解但要再往前走半步●从“流程编排”角度看LLM 本体确实很被动●从“核心计算与语义生成”角度看LLM 才是全链路里最不可替代的部分。如果把整个链路拆开职责大致是这样的推理引擎 / serving 系统负责接 HTTP 请求、做 tokenization / 输入处理、调度 batching、管理 KV cache、协调 GPU worker、流式返回结果、做一部分采样与系统优化。vLLM 的官方文档甚至把这几层写得很直白最少会有 1 个 API server 负责 HTTP、tokenization 和输入处理1 个 engine core 负责 scheduler 和 KV cache 管理再加上 N 个 GPU worker 负责执行模型前向计算。LLM 模型本体负责对 input_ids 做 embedding经过多层 Transformer block 的 self-attention 和 feed-forward network输出 logits也就是“下一个 token 的分数分布”。Transformer 论文给出的核心结构就是 attention FFNTransformers 文档也明确说 causal language modeling 本质上是在左侧上下文条件下做 next-token prediction而模型输出里的 logits 是对词表中每个 token 的预测分数。所以推理引擎决定“怎么高效地跑”模型决定“到底生成什么”。前者偏“编排与优化”后者偏“语义计算与内容生成”总结一条完整的链路我现在觉得这道题最稳妥的回答方式就是最后收束成一句话一个 LLM 请求的推理过程本质上是先把 prompt 模板化并 token 化经由推理服务调度进入 GPU模型通过 embedding 和多层 Transformer block 并行完成 prefill建立上下文表示和 KV cache随后进入 decode 循环基于历史缓存逐 token 执行注意力、前馈网络和采样直到生成结束再把 token 序列反解码成文本返回。 这条链路同时体现了 Transformer 的计算机制、自回归生成范式以及现代推理系统在 batching、缓存和 attention kernel 上的工程优化这里给大家精心整理了一份全面的AI大模型学习资源包括AI大模型全套学习路线图从入门到实战、精品AI大模型学习书籍手册、视频教程、实战学习、面试题等资料免费分享扫码免费领取全部内容1. 成长路线图学习规划要学习一门新的技术作为新手一定要先学习成长路线图方向不对努力白费。这里我们为新手和想要进一步提升的专业人士准备了一份详细的学习成长路线图和规划。可以说是最科学最系统的学习成长路线。2. 大模型经典PDF书籍书籍和学习文档资料是学习大模型过程中必不可少的我们精选了一系列深入探讨大模型技术的书籍和学习文档它们由领域内的顶尖专家撰写内容全面、深入、详尽为你学习大模型提供坚实的理论基础。书籍含电子版PDF3. 大模型视频教程对于很多自学或者没有基础的同学来说书籍这些纯文字类的学习教材会觉得比较晦涩难以理解因此我们提供了丰富的大模型视频教程以动态、形象的方式展示技术概念帮助你更快、更轻松地掌握核心知识。4. 2026行业报告行业分析主要包括对不同行业的现状、趋势、问题、机会等进行系统地调研和评估以了解哪些行业更适合引入大模型的技术和应用以及在哪些方面可以发挥大模型的优势。5. 大模型项目实战学以致用当你的理论知识积累到一定程度就需要通过项目实战在实际操作中检验和巩固你所学到的知识同时为你找工作和职业发展打下坚实的基础。6. 大模型面试题面试不仅是技术的较量更需要充分的准备。在你已经掌握了大模型技术之后就需要开始准备面试我们将提供精心整理的大模型面试题库涵盖当前面试中可能遇到的各种技术问题让你在面试中游刃有余。7. 资料领取全套内容免费抱走学 AI 不用再找第二份不管你是 0 基础想入门 AI 大模型还是有基础想冲刺大厂、了解行业趋势这份资料都能满足你现在只需按照提示操作就能免费领取扫码免费领取全部内容

更多文章