大模型推理全流程与开源架构知识库
本手册整理自大模型底层处理机制、分词原理、MoE 架构及开源生态的深度探讨,旨在建立一个从用户请求到模型输出的完整认知链路。
一、 大模型推理全流程解读(从 API 输入到最终输出)
这是大模型"处理请求"的完整生命周期。我们可以把它拆解为 8 个核心步骤:
第 1 步:API 请求接收与预处理
- 动作 :用户通过 HTTP 接口发送请求。请求体通常是 JSON 格式,包含多轮对话列表(例如
{"messages": [{"role": "user", "content": "你好"}]})以及推理参数(temperature、top_p等)。 - 底层:推理服务网关收到请求后,进行权限校验和负载均衡。
第 2 步:角色提示词格式化(应用 Chat Template)
- 动作 :服务端调用分词器(Tokenizer)的
apply_chat_template方法。将传入的[{"role":"user", "content":"你好"}]对话列表,根据tokenizer_config.json里的 Jinja2 模板 ,拼装成一段连贯的单一字符串。 - 示例结果 :原始 JSON 被转换为类似
<|im_start|>user\n你好<|im_end|>\n<|im_start|>assistant\n的格式。
第 3 步:字节对编码(BPE)与词表查表
- 动作 :对拼装好的字符串进行子词切分,并对照词表(Vocabulary)映射为整数(Token ID)。
- 细节 :
- 包含特殊符号添加:根据配置里的
add_bos_token,在开头强制插入开始标记(如<|begin_of_text|>)。 - 采用贪心最长匹配策略,尽可能合并为词表中已有的长子词。
- 包含特殊符号添加:根据配置里的
第 4 步:序列长度处理(截断与填充)
- 动作 :判断生成的 Token ID 数组长度是否超过
model_max_length。如果超过,则按配置的truncation_side进行截断。 - 批量填充 :如果服务端将多个用户的请求合并成一个 Batch(批次),为了形成规整的矩阵,短句必须补全。根据
padding_side(通常为left),在左侧使用pad_token_id将长度补齐。
第 5 步:张量转换与硬件部署
- 动作 :将整型数组(例如
[1, 3001, 456, ...])转换为 PyTorch 或 TensorFlow 的 Tensor 张量,并通过 CUDA 等接口放入 GPU 显存中。
第 6 步:神经网络核心推理(与 MoE 激活)
- 动作:GPU 开始执行 Transformer 层的前向传播。
- Dense(稠密)模型:每层计算包括注意力机制(Attention)和前馈网络(MLP)。
- MoE(混合专家)模型(重要区别) :
- 在特定层遇到
mlp.router(门控网络),门控计算出每个 Token 应该分配给哪个专家。 - 系统只激活 配置中的 Top-K 个专家子网络进行计算(例如 Top-2),其余专家不参与算力消耗,但权重依然占满显存。
- 输出加权合并结果。
- 在特定层遇到
- 计算结果 :模型最终输出一个概率向量(Logits),表示下一个最可能出现的 Token ID 的分数。
第 7 步:自回归生成与反向查表解码
- 动作 :根据
generation_config.json中的策略(如temperature采样或贪心搜索),从 Logits 中选出一个具体的整数 Token ID。 - 反向查找 :系统拿着这个整数 ID,再次对照词表进行反向查表,将这个 ID 映射回人类可读的文字。
- 循环:将生成的文字拼接到上文的 Token 序列尾部,再送回模型推理(重复步骤 3-6),直到模型生成结束符(EOS Token)或达到最大输出长度。
第 8 步:API 响应返回
- 动作:服务端将累积生成的文本封装成 JSON 格式,或通过 SSE(Server-Sent Events)流式传送给用户,完成一次完整的交互。
二、 核心深度知识:分词器与"查表"的玄机
1. BPE(字节对编码)是如何"学会"切分的?
- 训练阶段(生成词表) :先在语料中统计高频相邻字符对,将它们合并为子词。反复迭代直到达到预设的词表大小(如 Llama 3 的 128k)。最终生成
vocab.json(词表映射)和merges.txt(合并规则)。 - 推理阶段(实际切分) :不重新生成规则,只是拿着已有的词表,采用"贪心最长匹配"原则将输入文本切成子词。
- 切分为子词的优势:解决了传统"整词切分"词表过大、处理生僻字会报错(OOV)的缺陷,同时比"单字切分"能保留更强的语义信息。
2. 为什么"数字计算"中间不查表?
- 输入 :Toke ID →
Embedding 矩阵→ 浮点数向量。 - 中间:纯线性代数和微积分运算(查询不参与计算)。
- 输出 :Logits → 反向查表 → 输出文字。
三、 分词器的专有性(不同模型不可通用)
结论 :BPE 算法是共用的(造字典的方法),但词表和训练规则是每个模型独有的财产。只要词典不一样,Llama 的分词器就不能拿去处理 Qwen 的模型。
- 原因 1 :词表大小和词袋侧重不同。例如 Llama 的英文词表极细致,但遇到中文"人工智能"会被切成 4 个单字;而 Qwen 的中文词表里它是一个完整的 Token。
- 原因 2 :控制符(Special Tokens)不同。Llama 用
<|start_header_id|>,Qwen 用<|im_start|>。混用会导致模型找不到控制符 ID 而崩溃。 - 工程铁律 :
tokenizer_config.json、vocab.json和模型权重文件(.safetensors)必须来自同一个 Hugging Face 仓库的同一个版本,绝对不能交叉混用。
四、 开源大模型仓库内容全解(标准版 + MoE 架构进阶)
一个完整可用的开源大模型仓库(如 Hugging Face)会包含以下五大类。注意:MoE 架构的仓库,其特有组件内嵌于这些文件之中,而非独立外挂!
1. 模型权重文件("大脑")
- 标准模型 :
.safetensors或.bin格式,因体积巨大被切分成model-00001-of-xxxxx.safetensors,并伴随model.safetensors.index.json索引文件。 - MoE 模型内部差异 :在这些权重分片的张量名称里,你可以看到
mlp.router(门控网络)和mlp.experts.0.up_proj到mlp.experts.7.up_proj(多个专家的小模型矩阵)。它们的权重必须全部加载到显存中,但在推理时由门控决定只激活少部分专家参与计算。
2. 配置文件("骨架"与"出厂设置")
config.json(核心骨架) :定义了层数(num_hidden_layers)、维度、激活函数。如果是 MoE 模型,还会增加num_local_experts(专家总数)、num_experts_per_tok(每个 Token 激活几个专家)。generation_config.json(输出策略) :定义了默认的max_length、temperature、top_p和重复惩罚参数。
3. 分词器文件("翻译官"与"字典")
tokenizer_config.json:定义加不加 BOS、填充位置、聊天模板(Jinja2)等。vocab.json/merges.txt:BPE 的对照表和合并规则(或tokenizer.model二进制文件)。
4. 模型运行代码("心脏起搏器")
modeling_*.py/configuration_*.py:定义了 Transformer 和 MoE 前向传播的 PyTorch 底层实现逻辑。
5. 说明文档与法律授权("身份证")
README.md:模型能力、显存要求、局限性。LICENSE:商用授权的关键。Apache 2.0、MIT 可自由商用;Llama 系列有特定的月活用户限制。
五、 工程实践指南(避坑与诀窍)
- 不要手动拼装 :如果你使用
transformers库,务必直接调用tokenizer.apply_chat_template(messages, tokenize=True, add_generation_prompt=True)。框架会自动读取tokenizer_config.json里的模板,一步完成前 4 步,防止自己手写逻辑出错。 - MoE 工程风险警示 :MoE 模型因为全量专家都常驻显存,显存占用极为恐怖;并且推理框架(如 vLLM、DeepSpeed)需要专门的 MoE 通信调度代码,部署前必须确认推理引擎是否适配。
- 量化策略差异 :在对 MoE 模型进行量化(GGUF/GPTQ)时,门控网络(Router)必须保留高精度(通常不量化)。因为门控算错一个数导致选错了专家,模型的输出会产生灾难性崩坏。专家参数则可以放心量化压缩。
- 扩展词表与微调 :如果你想把一个纯英文模型(如 Llama)补全中文能力,必须在微调之前重新训练该模型的分词器 ,并重新初始化 Embedding 层权重,这意味着你必须消耗资源进行额外的"部分预训练",而不是简单的 LoRA 微调就能完成。