Skip to content

Transformer 与 Embedding

🎯 学习目标

  • 理解 Transformer 的 Encoder、Decoder 与 Attention 在 LLM 中的角色
  • 掌握 Token、Tokenization 与 Embedding 的含义及工程影响
  • 理解 Context Window(上下文窗口)如何限制 Prompt 设计
  • 能估算 Token 用量并据此设计文档切分与成本预算

引言

调用 LLM API 时,你发送的是 messagesprompt 字符串;模型内部处理的却是 Token ID 序列。同样一段中文,不同模型的 Token 数可能相差近一倍——这直接影响账单、延迟和能塞进多少 RAG 文档。如果不理解 Token 与 Context Window(上下文窗口),很容易做出「Prompt 超长被截断」「检索塞满上下文却没有留给回答的空间」等隐蔽错误。

本节从 Transformer 架构直觉讲起,说明 GPT 类 Decoder 为何成为 LLM 主流;然后深入 Tokenization(分词/标记化)Embedding,最后落到工程师最关心的:窗口、成本、切分策略。你不需要手推注意力公式,但需要知道「上下文是有限共享资源」——System Prompt、对话历史、检索片段、工具返回和用户输入,都在抢同一个 Token 预算。

章节正文

第 1 步:Transformer 架构直觉:Attention 与三种变体

Transformer 的核心是 Self-Attention(自注意力):序列中每个位置都可以「关注」其他位置,权重由内容动态计算。相比 RNN 逐步传递隐状态,Attention 在训练时可并行、在推理时能直接访问 distant context。

常见三种结构:

类型代表特点
Encoder-onlyBERT双向看全文,适合理解、Embedding
Decoder-onlyGPT、Llama、Qwen只看左侧,自回归生成,LLM 主流
Encoder-DecoderT5、早期翻译模型编码输入、解码输出,seq2seq

ChatGPT 类产品底层是 Decoder-only:生成第 t 个 Token 时,只能使用 t 之前的 Token(causal mask)。这保证了生成时不需要「偷看」未来,也与「预测下一个词」训练目标一致。

Multi-Head Attention(多头注意力) 可理解为多组并行 Attention,捕获不同关系(语法、指代、主题等)。层数堆叠(12、32、80 层…)形成「深度」,参数量与 Hidden Size 共同决定模型容量。应用层只需知道:更深更宽通常更强,也更贵、更慢;选型时在能力、成本、延迟间权衡,而非盲目追最大模型。

第 2 步:Token 与 Tokenization:不是「一个字」那么简单

Token 是模型词表(vocabulary)中的最小单元,对应一个整数 ID。Tokenization 把 UTF-8 文本切分为 Token 序列。英文常用 BPE(Byte Pair Encoding) 子词切分:「unhappiness」可能变成 unhappiness;中文因字频与词表设计,可能一字一 Token,也可能常见词组合并。

为什么要在意 Token 数?

  1. API 计费:多数厂商按 input tokens + output tokens 计价
  2. 上下文上限:超过 max context length 会被拒绝或截断
  3. 延迟:prefill(处理输入)与 decode(生成输出)时间都随 Token 数增长

估算技巧:OpenAI 提供 tiktoken;国内模型常文档给出「1 汉字 ≈ 1–2 Token」经验值。上线前应对典型请求用官方 tokenizer 或 API 返回的 usage 字段做实测,不要只靠字符数心算。

示例:同一句「大语言模型很有趣」在 GPT-4 与某开源中文模型下 Token 数可能不同——跨模型对比成本时必须分别测

第 3 步:Embedding:从 Token 到向量

模型收到 Token ID 后,第一步是通过 Embedding 矩阵 查表得到向量,再加上 Positional Encoding(位置编码) 注入顺序信息,然后送入多层 Transformer。

Token Embedding 是模型内部可学习的表示;你在外部调用的 Embedding API(如 text-embedding-3-small、BGE-M3)则是另一个(通常较小的)Encoder 模型,把整段文本映射为一个固定维度向量(如 768、1536 维),供 向量检索 使用。

二者联系:都表达「语义几何」;区别:LLM 内部 Embedding 随生成任务联合训练;外部 Embedding 模型专为相似度检索优化。RAG 切分(chunk) 的长度应适配 Embedding 模型的有效长度(通常 512–8192 Token),而不是 LLM 的 128K——检索器「看不清」的 chunk,LLM 再长也救不回来。

实践建议:chunk 大小、overlap(重叠)、Embedding 模型 max length、LLM context 四者一起设计(第 4.4 节展开)。

第 4 步:Context Window:有限共享资源

Context Window(上下文窗口) 是模型单次 forward 能处理的 Token 上限。GPT-3.5 曾以 4K/16K 为主,现在主流商用模型常见 32K、128K,部分宣称 1M——但标称窗口 ≠ 任意长度都同样快同样准,超长上下文往往 prefill 更慢、中间信息更易「迷失」(lost in the middle 现象)。

一次 Chat 请求的典型 Token 占用:

[System Prompt] + [历史对话] + [RAG 检索片段] + [工具 JSON 结果] + [用户当前输入] + [预留输出空间]

若窗口 8K,输出预留 1K,则输入侧实际可用约 7K。错误做法:检索 top-20 文档全文塞入,挤爆窗口,模型无空间推理。正确做法:控制检索条数与每段长度,必要时对历史做 摘要压缩

长文档场景策略:切分 + 检索(RAG)、Map-Reduce 摘要渐进式阅读 Agent,而不是单次全量粘贴。

第 5 步:工程清单:Token 意识贯穿上线全流程

在设计与运维 LLM 应用时,建议固定以下习惯:

设计阶段

  • 定义「典型请求」与「最坏请求」的 Token 分布(P50 / P95)
  • System Prompt 精简约束,避免重复堆叠规则
  • RAG 注入模板明确标注来源,便于调试也便于控制长度

开发阶段

  • 记录每次调用的 usage.prompt_tokensusage.completion_tokens
  • 对超长用户输入做前置截断或摘要,并告知用户

成本阶段

  • 按业务线拆分 Token 用量;输出 Token 往往比输入更贵(视定价而定)
  • 缓存相同 System + 检索结果(若厂商支持 Prompt Caching)

示例心算:某 API 输入 $0.003/1K tokens,输出 $0.015/1K tokens。一次请求 6K 输入 + 1K 输出 ≈ $0.018 + $0.015 = $0.033。日活 1 万次即约 $330/天——Token 意识即成本意识

掌握 Token 与窗口,是 Prompt 工程、RAG、Agent 的共同前提;后续第 2 章会在 API 层教你读取 usage 与控制 max_tokens

动手练习

  1. 选一段 500 字中文业务说明,用目标模型的 tokenizer 或一次试调用统计 Token 数,并与英文字数相当的一段文本对比。
  2. 假设 context=8192,需预留 1024 给输出,System Prompt 占 800,历史对话占 2000:计算 RAG 最多还能注入多少 Token?若单 chunk 平均 400 Token,最多几条?
  3. 画出你计划做的问答产品的「Token 预算饼图」:System / 历史 / RAG / 用户输入 / 输出 五块各占比。
  4. 解释「lost in the middle」对你设计 RAG 引用顺序(把最相关片段放哪里)有什么启示。

常见问题

Q:128K 窗口是不是可以把整本书塞进去?

技术上可能,但 prefill 成本高、延迟大,且模型对中段内容注意力可能下降。长书仍建议 RAG 或分章摘要,除非任务必须全局连贯且预算充足。

Q:Embedding 维数越高越好吗?

不一定。维数影响存储与检索速度。应在检索 benchmark(Recall@K)与资源之间权衡;同一 pipeline 内 query 与 document 必须用同一 Embedding 模型。

Q:中文为什么有时比英文更费 Token?

取决于词表如何构建。若中文多字单 Token,有时更省;若被拆成多个 byte-level token 则更费。以实测为准,不要假设「一个汉字就是一个 Token」。

本节小结

Transformer 以 Attention 实现并行与长程依赖;LLM 多用 Decoder-only 做自回归生成。Token 是计费与窗口的基本单位,Embedding 连接了模型内部表示与外部向量检索。上下文窗口是所有输入与输出共享的硬预算,RAG 切分、历史压缩与 max_tokens 都需在这一约束下设计。