《大模型实战指南》—— 面向软件开发者的系统性入门2
第二章 大模型如何工作从 Token 到 Transformer“Transformer 不是魔法而是一套精心设计的信息路由系统。”—— 本书作者 _abab2.1 整体流程概览一条文本的旅程当你向大模型输入一句 “你好今天天气怎么样”它经历了以下步骤[原始文本]↓[Tokenizer 分词] → [你, 好, , 今, 天, 天, 气, 怎, 么, 样, ]↓[Embedding 层] → 每个 token 变成 4096 维向量以 Qwen-7B 为例↓[位置编码Positional Encoding] → 注入“第3个词是‘’”的位置信息↓[多层 Transformer Block] → 重复 32 次Qwen-7B 的层数↓[输出层LM Head] → 预测下一个 token 的概率分布↓[采样策略如 Top-p] → 选择“晴”作为下一个词↓[循环生成] → 拼接“晴”继续预测直到结束✅ 开发者视角整个过程可视为一个 stateful 的函数调用链每一步都可监控、可干预。例如分词后可过滤敏感 token生成中可中断不符合预期的输出位置编码可自定义扩展上下文长度2.2 Tokenizer文本的 “原子化” 处理为什么需要分词神经网络只能处理数字不能直接处理汉字或英文单词。Tokenizer 就是文本到数字 ID 的映射器核心目标是覆盖所有可能的输入最小化 OOV 率平衡 token 数量太少导致语义模糊太多增加计算量主流分词算法对比算法原理示例中文示例英文适用模型开发者关注要点WordPiece贪心合并高频子词“你好” → [你, 好]unhappiness → [un, happi, ness]BERT, ChatGLM中文 OOV 率低适合理解类任务Byte Pair Encoding (BPE)统计合并最常见字节对“天气” → [天, 气]apple → [app, le]GPT, Llama英文压缩率高生成速度快SentencePiece无监督支持跨语言“AI 助手” → [AI, 助, 手]同上支持混合语言T5, Qwen适配多语言场景可自定义词表Qwen 使用基于 BPE 的 SentencePiece其 tokenizer 核心优势开发者需知中文按字切分为主生僻字自动拆分为 UTF-8 字节OOV 率接近 0支持动态扩展词表如添加领域专有名词内置特殊 token如s起始符、符、填充符开发者实操Hugging Facefrom transformers import AutoTokenizer# 加载 Qwen 的 tokenizer需信任远程代码tokenizer AutoTokenizer.from_pretrained(Qwen/Qwen-7B-Chat, trust_remote_codeTrue)# 基础分词与解码inputs 你好世界tokens tokenizer(inputs)print(Token ID 序列:, tokens[input_ids]) # 输出: [151644, 872, 198, 108503, 108504, 32852, 151645]print(Token 文本:, tokenizer.convert_ids_to_tokens(tokens[input_ids])) # 输出: [, 你, 好, , 世, 界, , print(解码还原:, tokenizer.decode(tokens[input_ids])) # 输出: 你好世界# 处理长文本自动截断/填充long_text 这是一段超过模型最大上下文长度的文本...tokens tokenizer(long_text, max_length10, truncationTrue, paddingmax_length)print(截断后长度:, len(tokens[input_ids])) # 输出: 10# 自定义特殊 tokentokenizer.add_special_tokens({additional_special_tokens: [print(新增 token ID:, tokenizer()[input_ids]) # 输出新增 ID⚠️ 关键警告不同模型的 tokenizer 完全不兼容用 Llama 的 tokenizer 处理 Qwen 的输入会导致语义错乱部署时需确保 tokenizer 与模型权重严格匹配建议一起下载2.3 Embedding 与位置编码赋予 token 意义和顺序Embedding 层从 ID 到语义向量核心功能将离散的 token ID 映射为连续的向量如 4096 维学习机制训练过程中语义相近的词如 “猫” 和 “狗”的向量在高维空间中距离更近内存占用Qwen-7B 的 Embedding 层 ≈ 7B × 4096 维 × 4 字节FP16≈ 112MB可忽略不计✅ 开发者优化点量化时 Embedding 层建议保留 FP16INT8 会导致语义损失领域适配时可冻结 Embedding 层减少微调参数位置编码解决 Transformer 的 “顺序失忆症”Transformer 是并行计算架构本身不感知 token 顺序 —— 若没有位置编码“我吃苹果” 和 “苹果吃我” 会被视为相同输入。主流位置编码对比类型原理优势劣势适用场景开发者实操建议正弦 / 余弦编码用不同频率的正余弦函数生成位置向量理论支持无限长度长距离位置关系衰减快早期模型GPT-2不建议用于上下文扩展学习型位置编码位置向量作为可训练参数适配特定任务超出训练长度后性能骤降BERT微调时需同步扩展位置参数RoPE旋转位置编码对向量进行旋转操作编码相对位置支持长上下文外推、计算高效需适配模型架构Llama, Qwen, ChatGLM4推荐优先选择支持 RoPE 的模型RoPE 核心优势开发者必须掌握外推能力训练时用 2K 上下文推理时可扩展到 8K 甚至 32K仅需调整旋转角度相对位置保持编码的是 “词 A 与词 B 相距 k 个位置”而非绝对位置更符合语言逻辑显存友好无需存储位置参数实时计算生成工程实践扩展上下文长度如 8K → 32K以 Qwen-7B 为例扩展上下文到 32K需修改 RoPE 旋转系数from transformers import AutoModelForCausalLMmodel AutoModelForCausalLM.from_pretrained (Qwen/Qwen-7B-Chat,trust_remote_codeTrue,rope_scaling{type: linear, factor: 4.0} # 8K ×4 32K)tokenizer.pad_token tokenizer.eos_token # 确保填充 token 正确2.4 Transformer Block大模型的“计算单元”每个 Transformer 层Decoder 层大模型生成核心包含两个核心子模块 归一化/残差连接结构如下输入 X → LayerNorm → 多头自注意力 → 残差连接 → LayerNorm → FFN → 残差连接 → 输出1多头注意力机制Multi-Head Self-Attention“Attention is All You Need” —— 2017 年那篇改变世界的论文直观理解每个词会“关注”句子中其他词的重要性例如- 句子“猫追老鼠因为它饿了”中“它”会重点关注“猫”- 句子“苹果的价格比香蕉贵”中“贵”会关注“苹果”和“香蕉”数学简化开发者友好版忽略缩放和 dropoutdef multi_head_attention(X, num_heads, d_model):# X: [batch_size, seq_len, d_model] 输入向量d_k d_model // num_heads # 每个头的维度# 1. 线性变换得到 Q, K, VW_q torch.randn(d_model, d_model) # 可学习权重W_k torch.randn(d_model, d_model)W_v torch.randn(d_model, d_model)Q X W_q # [batch_size, seq_len, d_model]K X W_kV X W_v# 2. 分割为多个头并行计算Q Q.reshape(-1, seq_len, num_heads, d_k).transpose(1, 2) # [batch, heads, seq_len, d_k]K K.reshape(-1, seq_len, num_heads, d_k).transpose(1, 2)V V.reshape(-1, seq_len, num_heads, d_k).transpose(1, 2)# 3. 计算注意力分数相似度scores Q K.transpose(-2, -1) / math.sqrt(d_k) # [batch, heads, seq_len, seq_len]attn_weights torch.softmax(scores, dim-1) # 归一化# 4. 加权求和得到输出output attn_weights V # [batch, heads, seq_len, d_k]output output.transpose(1, 2).reshape(-1, seq_len, d_model) # 合并头return output多头Multi-Head的核心价值不同头关注不同关系有的头关注语法主谓宾有的头关注语义同义替换有的头关注指代代词指向例如 Qwen-7B 有 16 个头相当于 16 个 “专家” 并行分析文本关系开发者优化点注意力权重可可视化如用 matplotlib 绘制热力图辅助调试语义理解问题对长文本可使用 “稀疏注意力”如 Local Attention减少计算量2前馈神经网络Feed-Forward Network, FFN结构两层线性变换 非线性激活GELUdef ffn(X, d_model4096, d_ff11008):d_ff 通常是 d_model 的 2~4 倍Qwen-7B 用 110084096×2.6875return torch.relu (X W1 b1) W2 b2 # 简化版实际用 GELU作用对注意力输出进行**非线性变换和特征增强**——注意力负责“关联信息”FFN 负责“提炼信息”计算占比FFN 占 Transformer 层计算量的 60%是推理速度优化的重点3残差连接 LayerNorm深层网络的“稳定器”残差连接Residual Connectionoutput X sublayer(X)解决梯度消失问题支持深层网络如 100 层开发者可通过监控残差连接的输出方差判断模型是否训练稳定LayerNorm对每个样本的特征维度归一化mean0, std1加速训练收敛提高模型鲁棒性现代模型多使用“预归一化”输入先归一化而非原始论文的“后归一化”✅ 开发者须知Transformer 层是 GPU 显存和计算的主要消耗者计算量O(seq_len² × d_model)注意力层 O(seq_len × d_model × d_ff)FFN 层显存主要用于存储 Q/K/V 矩阵和中间激活值可通过梯度检查点技术优化2.5 输出层与采样策略决定生成的“质量与多样性”1输出层LM Head作用将 Transformer 输出的高维向量4096 维映射为所有 token 的概率分布结构Linear(d_model, vocab_size) SoftmaxQwen-7B 的 vocab_size151936因此 LM Head 权重矩阵为 4096×151936 ≈ 6.2GBFP16优化技巧权重共享Embedding 层与 LM Head 共享权重减少显存占用2采样策略从概率分布中选 token生成式模型的核心决策点——不同策略会导致输出风格天差地别开发者需根据场景选择策略原理优点缺点适用场景代码示例贪心搜索Greedy每次选概率最高的 token速度快确定性强输出单调易重复简单问答、代码生成next_token torch.argmax(logits, dim-1)束搜索Beam Search保留 top-k 个候选路径最终选最优输出更连贯计算量大k倍多样性差摘要、翻译beam_search(logits, beam_size3)Top-k 采样从概率最高的 k 个 token 中随机选多样性强可能选低概率无意义 token创意写作、对话top_k 50; filtered logits.topk(top_k); next_token torch.multinomial(filtered.softmax(dim-1), 1)Top-p 采样Nucleus从概率和≥p 的最小 token 集合中随机选平衡多样性和合理性需调温度参数大多数生成场景top_p 0.9; sorted_probs torch.sort(logits.softmax(dim-1), descendingTrue); cumsum sorted_probs.cumsum(dim-1); keep cumsum ≤ top_p温度调节Temperature对 logits 除以温度T1 增加多样性T1 增加确定性灵活调整输出风格需手动调参所有场景logits logits / T; next_token torch.multinomial(logits.softmax(dim-1), 1)开发者最佳实践对话场景Top-p (0.9) 温度 (0.7)平衡自然度和可控性代码/逻辑场景贪心搜索或 Top-k (20) 温度 (0.3)保证准确性创意场景Top-p (0.95) 温度 (1.2)增加多样性3生成终止条件必须显式设置否则模型会无限生成def generate(model, tokenizer, prompt, max_new_tokens512, eos_token_id151645):input_ids tokenizer(prompt, return_tensorspt).input_idsfor _ in range(max_new_tokens):logits model(input_ids).logits[:, -1, :]next_token top_p_sampling(logits, top_p0.9)input_ids torch.cat([input_ids, next_token], dim-1)# 终止条件生成 eos token 或达到最大长度if next_token.item() eos_token_id:breakreturn tokenizer.decode(input_ids[0], skip_special_tokensTrue)2.6 自回归生成与 KV Cache效率的核心大模型生成文本采用自回归Autoregressive方式—— 逐词生成直到触发终止条件。但直接计算会有严重性能问题1无缓存的性能瓶颈每次生成新 token 时需重新计算整个输入序列的 Transformer 前向传播生成 L 个 token 的计算量O (L × seq_len² × d_model)seq_len 随生成过程不断增长示例生成 1024 个 token 时总计算量相当于单次处理 1024×(10241)/2 ≈ 50 万 token2KV Cache生成效率的 “革命”核心思想缓存之前 token 的 KKey和 VValue向量避免重复计算原理新 token 只需要与所有历史 token 计算注意力而历史 token 之间的注意力已在之前计算完成性能提升生成 L 个 token 的计算量降至 O (L × seq_len × d_model)速度提升 10~100 倍开发者实操KV Cache 配置# Hugging Face 中启用 KV Cache默认开启model AutoModelForCausalLM.from_pretrained(Qwen/Qwen-7B-Chat,trust_remote_codeTrue,use_cacheTrue # 启用 KV Cache)# 监控 KV Cache 显存占用def get_kv_cache_memory(model, seq_len, batch_size1):num_layers model.config.num_hidden_layersd_model model.config.hidden_sizenum_heads model.config.num_attention_headsd_k d_model // num_heads# K 和 V 各占 batch_size × num_layers × seq_len × num_heads × d_k 字节kv_memory batch_size * num_layers * seq_len * num_heads * d_k * 2 # ×2 因为 K 和 Vreturn kv_memory / 1024 / 1024 / 1024 # 转换为 GB# 示例Qwen-7B 生成 8K token 时的 KV Cache 占用print(fKV Cache 显存: {get_kv_cache_memory(model, seq_len8192):.2f} GB) # 输出约 8GB⚠️ KV Cache 注意事项开启后会增加显存占用如 8K 上下文约 8GB但生成速度大幅提升多轮对话中需缓存整个对话历史的 KV 向量避免重新计算动态批处理Dynamic Batching场景下KV Cache 会碎片化需用 vLLM 等引擎优化2.7 上下文长度与内存占用工程化选型的核心依据内存消耗拆解以 Qwen-7B 为例FP16 精度大模型推理时的显存占用 模型权重显存 KV Cache 显存 中间激活显存 框架开销组件计算方式8K 上下文32K 上下文开发者优化建议模型权重参数量 × 2 字节FP167B × 2B 14GB14GB不变用 INT8 量化可降至 7GBINT4 降至 3.5GBKV Cache前文公式~8GB~32GB用分组量化如 GPTQ或限制上下文长度中间激活seq_len × d_model × 2 字节 × 层数~2GB~8GB启用梯度检查点牺牲速度换显存框架开销固定开销~2GB~2GB用 TensorRT-LLM 等优化框架减少开销总显存求和~26GB~56GB8K 场景用 32GB GPU32K 场景用 80GB GPU上下文长度的工程化权衡上下文长度适用场景硬件要求推理速度开发者决策要点2K~8K短对话、单轮问答、代码生成消费级 GPU16GB~32GB快TPOT 大多数场景的默认选择平衡成本和体验16K~32K长文档分析、多轮对话、法律合同解读企业级 GPU40GB~80GB中TPOT 0ms需开启 RoPE 外推用 vLLM 优化 KV Cache64K~128K书籍摘要、论文解读、超长代码调试多卡 GPU80GB×2慢TPOT 50ms仅必要场景使用需结合稀疏注意力优化✅ 核心结论8K 是当前平衡能力、成本和速度的 “甜点”除非有明确的长文本需求否则不建议盲目追求超长上下文。本章小结大模型的核心流程文本→Tokenizer→Embedding→位置编码→Transformer→LM Head→采样→生成每一步都可工程化干预。Tokenizer 是 “输入入口”不同模型不兼容需匹配权重使用Qwen 的 SentencePiece 适配多语言场景。位置编码决定上下文能力RoPE 支持外推是扩展上下文长度的关键开发者可通过rope_scaling配置。Transformer Block 是 “计算核心”注意力负责关联信息FFN 负责提炼特征残差连接 LayerNorm 保证稳定。生成效率的关键KV Cache 减少重复计算采样策略决定输出质量自回归循环控制生成流程。内存占用的核心模型权重可量化优化 KV Cache与上下文长度正相关8K 上下文是工程化首选。开发者落地建议先掌握基础流程分词→生成再优化细节采样策略、KV Cache用 Qwen-7B 作为入门实践模型文档全、生态成熟遇到显存不足优先量化模型INT8再限制上下文长度最后考虑多卡部署