关于大模型(4)基本概念
4.1 Token、分词与逆分词——模型不认识“文字”,只认识编号
人类输入的是自然语言(汉字、英文、标点、空格),但大模型只能处理数字张量。所有文本进入模型前,必须经过**分词器(Tokenizer)**完成转换:文本 → Token片段 → 整型Token ID。模型全程只根据 Token ID 计算,完全不认识原始文字。
Token 定义:模型语义处理的最小基本单元,不可再拆分。
纠正新手模糊认知:
- 英文/数字:多为词根、词缀拆分,一个长单词会被拆为多个 Token(例如 ChatGPT → Chat、GPT);
- 中文:绝大多数情况下单字对应一个 Token,极少多字合并;
- 标点、空格、换行、特殊符号全部独立占用 Token,会实打实消耗上下文长度。
分词器核心工作流程:
- 分词(Tokenize):原始文本切割为模型预定义的子词片段 → 查表映射为唯一整型ID;
- 逆分词(Detokenize):模型输出的Token ID序列 → 拼接还原为人类可读文本。
这里有个坑:每一个模型必须配套专属分词器与专属词表(Vocab)。LLaMA 使用 SentencePiece、GPT 系列使用 BPE、GLM/Qwen 有自定义词表。绝对不能跨模型混用分词器,否则Token ID完全错乱,语义彻底崩坏,模型生成乱码、胡说八道。
词表大小与推理性能的强关联(重点补强)
词表大小(Vocab Size)直接决定最后一层 LM Head 的计算量与显存开销:
- LLaMA2:32000 词表;
- Qwen:151643 超大词表;
- GPT-4 级模型:十万级超大词表。
词表越大,LM Head 矩阵乘法维度越高,单Token推理延迟越高、显存占用越大。这也是 Qwen 推理同参数下比 LLaMA 略慢的核心原因之一。工业界会通过词表裁剪、动态Vocab、LM Head优化提速。
4.2 词嵌入与模型权重——模型的知识是怎么存储的
Token ID 只是一个纯数字编号(如 1234、5678),没有任何语义信息,无法直接参与矩阵运算。模型需要把离散的整型 ID 映射为连续、稠密、携带语义的浮点向量,这个过程就是词嵌入(Embedding)。
1. 嵌入层(Embedding Layer)本质
嵌入层就是一张巨大的可学习参数表:[vocab_size, hidden_dim]。
以 LLaMA-7B 举例:Vocab=32000,Hidden_dim=4096,嵌入层参数总量 = 32000 × 4096 ≈ 1.3亿参数。查表逻辑:输入Token ID直接索引对应向量,作为模型首层输入。语义知识的底层基础全部存储在嵌入向量中。
2. 模型权重(Weight)完整定义
模型权重指训练完成后全部冻结的可学习参数集合,推理阶段全程固定、不更新、不训练。包含:
- Embedding 嵌入权重;
- 每一层Transformer的 Q/K/V 投影权重、输出投影权重;
- FFN 两层/三层门控权重(SwiGLU);
- RMSNorm/LayerNorm 的缩放与偏置参数;
- 最终 LM Head 输出权重。
显存占用硬核结论:
LLaMA-7B 共70亿参数:FP16=2字节/参数,权重体积≈14GB;INT8=1字节≈7GB;INT4=0.5字节≈3.5GB。权重精度直接决定模型底显存占用,这是量化优化的根基。
推理全过程总结:
固定权重 + 动态输入Token向量迭代计算 → 每步输出新Token概率分布。所有推理优化(量化、算子融合、KV Cache、分页注意力)本质都是:更省显存、更少访存、更少冗余计算。
4.3 LM Head 与 Logits——模型生成的最后一关
经过多层Transformer计算后,模型得到当前时刻的隐藏层特征向量[B, D],这个向量是语义特征,不能直接输出文字。
LM Head 精准作用:通过一次线性变换,将隐藏维度 D 映射到词表维度 Vocab,得到原始分数 Logits。
Logits = Hidden × W_head
Logits 是无界实数(可正可负),不满足概率性质,无法直接采样。必须经过Softmax归一化,将值域压缩到 [0,1] 且总和为1,得到Token概率分布。
为什么要Softmax?
不是“为了好看”,是因为自回归采样算法必须基于合法概率分布(TopK/TopP/Temperature全部依赖概率权重)。
权重绑定(Weight Tying)工程优化
大量开源模型(LLaMA、Qwen)做了Embedding与LM Head权重共享:因为两者形状完全一致[Vocab, Hidden_dim]。收益:节省大量参数与显存、减少冗余计算、提升收敛与推理速度。这也是大模型轻量化的经典基础优化。
推理延迟真相:超长词表模型,LM Head + Softmax 会成为新的性能瓶颈,很多人以为注意力最慢,大词表模型最后一层开销占比极高。
4.4 自回归生成原理——Prefill与Decode的本质差异
1. 原始未优化逻辑
“原始未优化逻辑在数学上等价于**‘每次重写整本历史书’**。它每一步都要把变长的上下文塞进巨大的方阵注意力中,导致总计算量随输出长度呈立方级增长。这使得生成 128 个 Token 或许尚可忍受,但当生成长度达到 2048 时,计算量爆炸会直接导致延迟失控和显存溢出——因此,任何落地的 LLM 系统都必须引入 KV Cache 来打破这一僵局。”
2. 工业真实推理双阶段
阶段一:Prefill 预填充阶段(输入Prompt阶段)
一次性输入完整Prompt序列,全局并行计算,一次性算出所有位置的 KV 并缓存。
特点:计算量大、访存密集、并行度极高、速度快;
作用:生成第一个新Token,同时建好KV Cache缓存。阶段二:Decode 逐Token解码阶段(循环生成阶段)
后续每一步只输入最新一个Token,复用 Prefill 阶段的全部历史 KV Cache,不需要重算过往上下文。
特点:计算量极小、迭代频繁、访存瓶颈极强,是线上推理耗时、成本、显存占用的绝对主力。
结论
- 没有KV Cache:推理计算量是O(L²),完全不可用;
- 有KV Cache:PrefillO(L²),DecodeO(L)。
所有大模型推理优化,本质都是:优化Prefill并行效率 + 极致压低Decode单步延迟与显存开销。
所有针对 Decode 的优化(量化、PagedAttention、算子融合),本质上都是在“以时间换空间”或“以计算换搬运”
自回归逻辑:
Prefill:一次性读完问题、建好缓存;
Decode:每次只算一个新字、拼在后面、循环迭代、直到结束。
4.5 推理停止条件——生产级多维度终止策略
模型自回归生成是无限循环过程,必须设置多层级、兜底式停止条件,否则会无限生成、耗尽显存、触发接口超时、造成线上事故。
1. 核心终止条件:EOS 结束符(逻辑终止)
训练阶段,模型学习到在语义完整、语句结束时输出<eos>或</s>等特殊 Token。推理时一旦采样到 EOS,应立即终止生成,并在后处理中剔除该 Token 再返回用户。
存在问题:模型在长文本、乱序 Prompt、低质量输入等场景下经常失效不输出 EOS,表现为语义已完整但模型仍在继续“硬编”。因此仅靠 EOS 完全不可靠,必须叠加硬限制。
2. 硬兜底终止:max_new_tokens(长度限制)
限制模型最多生成多少个新Token,与输入Prompt长度无关。生产环境必须强制配置,是防止无限生成的第一道安全锁。
# Hugging Face / vLLM 标准用法max_new_tokens=512# 绝对不能省略3. 业务自定义停止词(Stop Words)
针对结构化输出场景(JSON、代码、对话回合),可自定义终止字符串,例如:
} # JSON 对象结束 ### # 章节分隔 </s> # 显式终止标记 <|user|> # 对话中下一轮开始引擎会实时匹配当前输出后缀,命中即截断终止,大幅提升结构化任务准确率,避免模型“画蛇添足”。
4. 生产环境(工程规则)
- 最大总长度限制:必须同时限制 Prompt 长度和生成长度,否则两者叠加可能触发 OOM:
max_seq_len=8192# 模型支持的最大序列长度max_prompt_len=4096# 截断过长的用户输入max_new_tokens=2048# 预留一半空间给输出- 特殊控制Token过滤:对话模型中的系统 Token(如
<|user|>、<|assistant|>、<|system|>、PAD等)属于通信协议内部标记,推理后处理必须过滤,绝对不能返回给用户。 - 重复惩罚终止:模型易陷入“复读机”状态(如“我是我是是的是的”),生产中通常配置:
| 机制 | 类型 | 说明 |
|---|---|---|
repetition_penalty | 软约束 | 修改 Logits 概率分布,压低重复 Token 的采样概率,不终止生成 |
| 循环检测(硬截断) | 硬约束 | 检测到连续重复 N 次相同的 Token 序列(如连续 3 次相同的 10 个 Token),强行终止,属于兜底物理防护 |
5.绝对物理超时(Timeout)
以上所有策略均基于 Token 逻辑,当模型陷入 GPU 卡死或无限循环(不产生新 Token)时,逻辑层失效,必须靠物理熔断:
# FastAPI / Uvicorn 层timeout=120# 秒,强制终止该请求的 CUDA 内核6.显存水位熔断
在请求准入层实施 Admission Control,预估 KV Cache + 激活值 + 权重总和,若超过显存阈值(如 90%),直接拒绝新请求,防止 OOM 拖垮整个进程:
ifrequired_kv_cache_mem+allocated>total_gpu_mem*0.9:raiseResourceExhausted("GPU memory insufficient, reject request")7.各条件执行优先级(工程红线)
在代码执行流中,停止条件的触发顺序严格分层:
最高优先级(物理层) │ ├── 显存 OOM(系统强制中止,不可控) │ ├── 物理时钟超时(GPU Kernel 熔断) │ ▼ 次高优先级(引擎层) │ ├── max_new_tokens 计数器归零 ← 第一道逻辑闸门 │ ├── 匹配 stop_strings(业务停止词) │ ▼ 最低优先级(模型层) │ └── 采样到 EOS(优雅语义终止,最理想情况)关键事实:
max_new_tokens的优先级高于EOS。若max_new_tokens=128,模型在第 50 步输出 EOS → 优雅终止;若一直不输出 EOS → 计数达 128 时硬性截断,绝不超 1 个 Token。
8.完整防护体系架构图
┌─────────────────────────────────────────────────────────────────┐ │ 用户请求准入层 │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 显存水位检查(Admission Control)→ 拒绝或排队 │ │ │ └─────────────────────────────────────────────────────────┘ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 总长度限制:截断 Prompt 到 max_prompt_len │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ 自回归生成循环 │ │ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 每步解码 → 采样 Logits │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ │ ┌───────────┴───────────┐ │ │ ▼ ▼ │ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │ │ 命中 EOS? │ │ 达到 max_new_tokens│ │ │ │ → 优雅终止 │ │ → 硬截断 │ │ │ └─────────────────────┘ └─────────────────────┘ │ │ │ │ │ │ └───────────┬───────────┘ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 停止词匹配:检查输出后缀是否匹配 stop_strings │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ │ ┌───────────┴───────────┐ │ │ ▼ ▼ │ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │ │ 重复循环检测 │ │ 物理时钟超时 │ │ │ │ → 强行终止 │ │ → 熔断终止 │ │ │ └─────────────────────┘ └─────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ 后处理输出层 │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 1. 剔除 EOS Token │ │ │ │ 2. 过滤 <|user|>、<|assistant|>、PAD 等系统 Token │ │ │ │ 3. 剔除 stop_strings 匹配的后缀部分 │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘核心总结
| 层级 | 策略 | 作用 |
|---|---|---|
| 逻辑层 | EOS 结束符 | 语义完整时优雅终止,最理想情况 |
| 引擎层 | max_new_tokens | 防止无限生成的第一道安全锁 |
| 业务层 | 自定义停止词 | 结构化输出的精准截断 |
| 规则层 | 重复检测 / 特殊 Token 过滤 | 后处理保障输出干净度 |
| 系统层 | 物理超时 / 显存水位熔断 | 最终兜底,防止服务雪崩 |
总结:EOS 做优雅终止,max_tokens 做硬兜底,stop_words 做业务定制,Timeout + 显存熔断做物理防护,后处理做干净输出——五层保障才是线上可用的推理服务。
本章总结
- 模型只认Token ID,分词器、词表、模型三者必须严格配套;
- 嵌入层把数字ID转为语义向量,权重是模型全部静态知识;
- Logits是原始分数,Softmax生成概率分布,词表大小直接影响推理速度;
- 真实推理分为 Prefill(并行、算全局)/ Decode(迭代、访存瓶颈)两个阶段,KV Cache彻底改写计算复杂度;
- 生产级推理必须多层停止条件兜底,不能依赖模型自发EOS。
