跳到主要内容

Embedding 向量化

目的
  1. 理解 Embedding 如何把离散的 token id 变成模型可以计算的向量。
  2. 理解向量如何进入 Transformer 生成 hidden state,并通过 LM Head 转成 logits。
  3. 区分两个概念:LLM 内部的 token embedding,和检索系统中面向整段文本的 text embedding。

在进入大语言模型之前,文本会先被 tokenizer 切分成 token,并且映射到 token id。

但 token id 只是离散编号,本身不表达语义。Embedding 的作用,就是把这些离散编号转换成模型可以计算的连续向量。

概括来讲:

Embedding 是把离散对象映射到连续向量空间的方法。

本篇可以视为 "Token 与概率" 篇中 "处理 Token 的完整流程 - 模型根据 token ids 计算下一个 token 的 logits" 的展开。


1. Token ID 并不直接表达语义

Tokenizer 会把文本切分成 token ,并匹配对应的 token id:

文本: 猫喜欢鱼
Tokens: ["猫", " 喜欢", " 鱼"]
Token Ids: [1357, 2468, 9753]

这些 ID 只是词表中的编号,编号之间的大小关系没有语义。

例如:

猫 = 1357
狗 = 1358
银行 = 1359

这不代表“猫”和“狗”只差 1 就更相似,也不代表“银行”与它们距离接近。token id 只是索引,不是语义表示。


2. Embedding Lookup

把索引跟语义联系起来需要的是 Embedding lookup - 通过 token id 对应一个可学习的向量。

Embedding lookup 可以理解为查表:模型一般会维护一个 embedding 向量矩阵,每个 token id 对应矩阵中的一行(即一个向量)。

token_id -> embedding_matrix[token_id] -> vector

假设词表大小是 50,000,embedding 维度是 4,那么 embedding 矩阵可以想象成:

token idembedding vector
0[0.12, -0.03, 0.44, 0.09]
1[-0.20, 0.31, 0.05, 0.77]
2[0.88, -0.14, 0.10, -0.25]
......
49,999[0.81, 0.24, -0.15, -0.47]

真实模型的 embedding 维度通常远大于 4,可能是 768、2048、4096、8192 或更高。

Embedding lookup 本身不是复杂计算,它更像"按 token id 取出对应向量"。


3. Embedding 矩阵

矩阵的形状

Embedding 矩阵的形状通常是:

vocab_size x hidden_size
  • vocab_size 是词表大小,也就是模型能直接表达多少个 token。词表越大,embedding 矩阵行数越多。
  • hidden_size 是每个 token 向量的维度,它决定了 Transformer 内部每个位置的表示宽度。如果一个模型 hidden size 是 4096,那么每个 token 在进入 Transformer 前,会被表示成一个 4096 维向量。

例如:

参数示例值
vocab_size50,000
hidden_size4096
embedding 矩阵参数量50,000 × 4096 = 204,800,000

这说明 embedding 层本身也会占用大量参数。

矩阵的值

Embedding 矩阵的具体值是通过模型训练得到。

  • 在模型训练开始时,矩阵里的数值通常是随机初始化的。
  • 训练过程中,模型不断做下一个 token 预测:预测错了,就根据 loss 通过反向传播调整参数,embedding 矩阵也会一起被更新。
  • 经过大量训练后,经常在相似上下文中出现、用法接近的 token 的向量会逐渐得到更接近的表示,最终就获得了 Embedding 矩阵。

可以简单理解为:

Embedding 矩阵 : 随机向量 -> 训练中不断调整 -> 学到可用于语言建模的 token 表示

4. 向量空间中的相似性

Embedding 的直觉是:语义或用法相近的对象,在向量空间中应该更接近。

例如,一个训练良好的语义 embedding 空间中:

  • "猫"和"狗"可能更近。
  • "北京"和"上海"可能更近。
  • "显存"和"GPU"可能更近。
  • "合同审查"和"法律条款"可能更近。

而常见相似度度量方式包括:

方法含义
Cosine Similarity 余弦相似度看两个向量方向是否接近
Dot Product 点积/内积看两个向量点积大小
Euclidean Distance 欧式距离看两个向量几何距离

RAG 和向量检索里最常见的是 cosine similarity 或 dot product。

Cosine Similarity 余弦相似度

Cosine similarity 计算两个向量夹角的余弦值。

cosine(a, b) = dot(a, b) / (||a|| * ||b||)

如果两个向量方向很接近,cosine similarity 接近 1;如果方向差异很大,则接近 0 或负数。


5. 输入 Embedding 与位置编码

只把 token 映射成向量还不够。模型还需要知道 token 在序列中的位置。

例如:

狗咬人
人咬狗

这两句话包含相同 token,但顺序不同,含义完全不同。

因此,Transformer 输入通常包含两类信息:

  • token embedding:表示“这个位置是什么 token”。
  • position information:表示“这个 token 在序列中的哪个位置”。

不同模型使用不同位置编码方式,例如绝对位置编码、RoPE、ALiBi 等。它们的共同目标是让模型能够感知顺序和相对位置。

input vector = token embedding + position information

严格来说,RoPE 这类方法不是简单相加,但从直觉上可以理解为:模型输入不仅要知道 token 内容,还要知道 token 位置。


6. Hidden State 与 Token Embedding

Token embedding 是 token 进入模型前的初始表示,Hidden state 是经过 Transformer 层处理后上下文的表示。

概念位置包含内容
Token embedding输入层不包含或几乎不包含上下文
Hidden stateTransformer 中间层 / 输出层包含上下文

同一个 token 在不同句子里,初始 token embedding 是一样的,但经过 Transformer 后的 hidden state 会不同。

例如 token 苹果

我买了一斤苹果。
苹果发布了新芯片。

输入层的 苹果 token embedding 相同,但在第一句中它会更像水果,在第二句中会更像公司。

这个上下文区分主要由 Transformer 层完成,而不是静态 token embedding 本身完成。


7. LM Head

生成模型的核心任务是要预测下一个 token,所以模型要把最后位置的 hidden state 转成对整个词表的 logits。

这个时候就需要一个名为 LM Head 的层。

LM Head 通常是一个线性层,形状大致是:

hidden_size x vocab_size

它把 hidden state 映射到词表空间,为每个 token 产生一个 logit。

很多语言模型会使用 weight tying,也就是让输入 embedding 矩阵和输出 LM Head 共享权重或相关参数。即直觉上,模型既要把 token 映射到向量空间,也要从向量空间映射回 token。


8. Transformer 中的 Token Embedding

在《Token 与概率》篇 处理 token的完整流程 中有一步是:

模型根据 token ids 计算下一个 token 的 logits。

这个过程可以进一步展开为三步:

  1. token ids 通过 Embedding lookup 和 Embedding 矩阵 得到 token embeddings
  2. Transformer 处理这些 embeddings 得到 hidden states
  3. LM head 再把 hidden states 转成 logits。

9. Text Embedding

在 LLM 里,embedding 通常有两种常见含义:

  • 模型内部的 token embedding:把 token id 变成 Transformer 架构模型可以处理的向量。
  • 检索系统里的 text embedding:把文本片段变成语义向量,用于相似度搜索、聚类和推荐等。

两者都叫 embedding,但用途和训练目标不同,不能混为一谈。

即除了生成模型内部的 token embedding,工程中有时说的 embedding 是指 "text embedding 文本语义向量"。

text embedding 会把一段文本映射成一个固定长度向量:

"如何部署 vLLM?" -> [0.013, -0.284, ..., 0.117]

text embedding 通常用于:

  • 语义搜索。
  • RAG 文档召回。
  • 文本聚类。
  • 推荐系统。
  • 去重。
  • 相似问题匹配。
  • 分类和路由。

text embedding 的输出通常是句子级、段落级或文档片段级向量,而不是每个 token 一个向量。


与 Token Embedding 的区别

维度Token embeddingText embedding
所属系统生成模型内部检索、RAG、推荐、聚类系统
输入token id一段文本
输出每个 token 一个向量整段文本一个向量
是否直接给用户用通常不直接使用经常作为 API 输出
训练目标支持语言建模支持语义相似、检索或对比学习
典型用途Transformer 输入向量检索、语义匹配

这两个概念都叫 embedding,但工程上要分清楚。


RAG 中的 Embedding

RAG 系统中,text embedding 常用于召回相关文档。

基本流程:

  1. 文档切分:把文档切成 chunk。
  2. 向量化:用 embedding 模型把每个 chunk 转成向量。
  3. 向量存储:把向量写入向量数据库。
  4. query embedding: 用户提问时,把 query text 也转成向量。
  5. 召回 / 相似度匹配:在向量库中搜索最相似的向量,对应到 chunk。
  6. 生成:把召回内容(即 chunk)放进生成模型作为上下文。

RAG 里的 embedding 不负责生成答案,它负责“找材料”。生成答案仍由 LLM 完成。


为什么 Embedding 检索可能会失败

Embedding 检索很有用,但不是万能的。

常见失败原因:

  1. Chunk 切分不合理:如果 chunk 太短,语义不完整;如果 chunk 太长,向量会混合多个主题,检索不准。

  2. Query 和文档表达不一致:例如用户问"怎么降低首 token 延迟",文档写的是 "TTFT 优化"。如果 embedding 模型没有很好捕捉这层同义关系,可能导致召回失败。

  3. 专有名词和代码符号弱:Embedding 模型对自然语言语义通常更强,但对精确符号、ID、函数名、错误码、版本号可能不如关键词搜索稳定。

  4. 语义相似但任务不匹配:两个文本语义接近,不代表它们能回答同一个问题。例如“vLLM 安装教程”和“vLLM 性能调优”都和 vLLM 相关,但用户问题不同,需要的文档不同。

  5. 向量相似度不等于事实正确:向量库只能召回“相似内容”,不能保证内容是最新、权威、完整或正确的。

因此,实际 RAG 往往会结合 向量检索、关键词检索、metadata filter、rerank、引用和溯源等技术和策略。


Embedding 的维度并非越高越好

更高的 Embedding 维度可以表达更复杂的信息,但也会带来更高的存储和检索计算成本,以及更慢的向量库构建。

选择 embedding 模型或者服务时,除了看维度大小,还要关注:

  • 任务效果: 在你的数据和 query 上召回是否好。
  • 语言覆盖: 中文、英文、代码、专业术语是否适配。
  • 上下文长度: 能否处理你的 chunk 长度。
  • 向量维度: 涉及存储、检索、构建成本。
  • 速度: 批量入库和在线查询延迟。
  • 成本: API 或自部署推理成本。

Embedding 与分类、聚类、去重

Embedding 不只用于 RAG,也常用于分类、聚类、去重等场景。

分类

可以把文本转成 embedding,再用一个简单分类器做意图识别、主题分类、风险分类等。

文本 -> embedding -> classifier -> 类别

聚类

把大量文本转成 embedding 后,可以按向量距离聚类,发现相似问题、重复工单、用户反馈主题或知识库空白。

去重

相似度高的文本可能是重复问题、重复文档或同一事件的不同表述。Embedding 可以作为语义去重的基础。


常见误区

  • Embedding 就等于语义:不完全是。Embedding 是模型学到的表示,通常包含语义信息,但也可能受到训练数据、任务目标、语言分布和模型结构影响。

  • 向量相似就一定相关:不一定。向量相似表示模型认为表达接近,但不保证能回答用户问题,也不保证事实正确。

  • RAG 只要有 embedding 就够:不够。RAG 还需要 chunk、metadata、hybrid search、rerank、上下文压缩、引用、权限和评估等流程和技巧。

  • 生成模型的 token embedding 可以直接拿来做检索:通常不建议。生成模型内部 embedding 的训练目标是语言建模,不一定适合语义检索。工程上一般使用专门训练的 embedding 模型。


小结

Embedding 是连接离散文本和连续计算空间的桥梁。

在 LLM 内部,token embedding 把 token id 变成 Transformer 可以处理的向量;经过 Transformer 多层处理后,模型得到包含上下文的 hidden state,并用 LM Head 得到 logits。

结合之前在 "Token 与概率" 篇中的知识,LLM 模型的生成流程可以抽象为:

  1. 使用 tokenizer 切分文本,并且得到 tokens 和 token ids。
  2. 通过 ebmedding 得到 token embedding ,拼接 position embedding 作为模型输入。
  3. 模型计算得到 hidden state。
  4. LM Head 将 hidden state 转化为 logits。
  5. Softmax 将 logits 表示为概率分布。
  6. 解码和采样 确定 next token。
  7. 将这个 token 追加到输入中并进行下一次循环

在 RAG 和搜索系统中,text embedding 把用户输入和文档片段变成语义向量,系统通过相似度检索找到相关材料并送入模型作为上下文参考。