跳转至

第六章:Embedding 原理与技术演进

6.1 Embedding 到底在做什么

可以先记住一句话:把文本映射成一个稠密向量,使得语义相近的文本在向量空间中距离更近。

这句话里有两个关键点,缺一个都不完整:

  1. 稠密:几百到几千维的实数向量,每一维没有独立的可解释含义,语义分布在整个向量上;
  2. 语义相近 → 距离近:这是靠训练目标刻意造出来的性质,不是自动出现的。

第二点是理解 Embedding 的关键。「猫」和「狗」的向量之所以接近,不是因为模型显式存着「它们都属于动物」这条知识,而是因为训练时它们大量出现在相似的上下文中,参数被优化成给出相近的表示。

6.2 为什么 RAG 需要它

关键词检索只能匹配字面。用户问「怎么请年假」,而文档写的是「带薪休假申请流程」——没有一个词重合,关键词检索直接失效。

Embedding 把两者都映射到「休假申请」这个语义区域,从而能匹配上。

这就是 RAG 用向量检索的根本原因:它跨越了「同一个意思的不同说法」这道鸿沟。

但也要提前说明:向量检索并非全面优于关键词检索。精确的产品型号、错误码、人名、专有术语,关键词检索反而更可靠——这是第十一章要展开的内容。

6.3 技术演进:四代

flowchart LR
    G1[第一代<br/>静态词向量] --> G2[第二代<br/>上下文词向量]
    G2 --> G3[第三代<br/>句向量 双塔]
    G3 --> G4[第四代<br/>后期交互 多向量]

按代际看,更容易理解为什么后面的架构会变成这样。

6.3.1 第一代:静态词向量

代表:Word2Vec、GloVe、FastText。

核心思想:一个词的含义由它周围经常出现的词决定。通过预测上下文(或用上下文预测中心词)来学习词向量。

贡献:第一次让「语义相似度」变成可以计算的数值。

致命局限一词一向量,无法处理多义词。

「苹果」在「吃苹果」和「苹果发布会」里是完全不同的意思,但静态词向量给它同一个表示——这个向量是两种含义的妥协平均,对两边都不准。

6.3.2 第二代:上下文相关的词向量

代表:ELMo、BERT。

核心突破同一个词在不同句子里有不同的向量。BERT 通过双向 Transformer 编码整个句子,每个 Token 的表示都依赖于它的具体上下文。

多义词问题就此解决。

这里需要单独区分一个常见误解:

BERT 不能直接用于 RAG 检索。

原因有两个:

第一,原生 BERT 的句向量质量差。 直接取 [CLS] 位置的向量或对所有 Token 向量做平均,得到的句向量在语义相似度任务上表现很差——因为 BERT 的预训练目标(掩码语言建模)根本没有优化句子级的相似度

第二,也是更致命的:交互式架构在检索场景下不可用。

BERT 判断两句话是否相似的标准做法,是把两句话拼在一起送进模型(cross-encoder)。这意味着:

flowchart TB
    subgraph CE[Cross-Encoder 交互式]
        Q1[Query] --> CAT[拼接]
        D1[文档] --> CAT
        CAT --> M1[模型] --> S1[相似度分数]
        N1[必须对每个文档算一次<br/>百万文档 = 百万次推理]
    end

    subgraph BE[Bi-Encoder 双塔]
        Q2[Query] --> ME1[模型] --> V1[Query 向量]
        D2[文档] --> ME2[模型] --> V2[文档向量<br/>离线预先算好]
        V1 --> SIM[向量距离]
        V2 --> SIM
        N2[文档向量离线算好<br/>在线只算 Query]
    end

百万级文档库中,cross-encoder 每次查询要做百万次模型推理,完全不可行。 这就是为什么必须有第三代。

6.3.3 第三代:专门优化的句向量模型(双塔)

代表:Sentence-BERT、SimCSE、BGE、E5、GTE、Qwen3-Embedding。

两个关键改进:

改进一:架构改成双塔(bi-encoder)。 Query 和文档分别独立编码,各自得到一个向量,用向量距离衡量相似度。这样文档向量可以在离线阶段全部算好并建索引,在线只需算一次 Query 向量。

这是让向量检索在工程上可行的决定性一步。

改进二:训练目标改成对比学习。 用「相似句子对」作为正样本、「不相似句子对」作为负样本,直接优化「相似的靠近、不相似的远离」这个目标。

SimCSE 展示了一个非常简洁的做法:同一个句子过两次模型,因为 Dropout 是随机的,会得到两个略有差异的向量,把这一对当作正样本;同一批次里的其他句子作为负样本。不需要人工标注就能大幅提升句向量质量。

这一代是当前 RAG 的标准配置。

代价:双塔的 Query 和文档从未"见面",无法建模细粒度的词级交互,所以精度低于 cross-encoder。

这正是 RAG 采用「双塔粗排 + cross-encoder 精排」两阶段架构的根本原因——用双塔的速度缩小范围,用 cross-encoder 的精度定顺序。第一章 1.5 节的漏斗结构,在这里得到了技术上的解释。

6.3.4 第四代:后期交互与多向量

代表:ColBERT、ColBERTv2、ColPali。

核心思想:在「单向量双塔」和「拼接式 cross-encoder」之间取中间路线。

文档不再压缩成一个向量,而是保留每个 Token 的向量。检索时计算 Query 每个 Token 与文档所有 Token 向量的最大相似度,再求和。

flowchart TB
    A[单向量双塔] -->|精度低 速度快| B[后期交互 多向量]
    B -->|精度接近 速度可接受| C[Cross-Encoder]
    A -.->|文档压成 1 个向量| A1[细粒度信息丢失]
    B -.->|文档保留 N 个向量| B1[存储成本高 N 倍]
    C -.->|Query 文档拼接| C1[无法离线预计算]

优点:保留了词级匹配信息,精度显著高于单向量,同时文档表示仍可离线预计算。

缺点存储开销是单向量的几十倍,且需要专门的索引支持。

第四代的一个重要衍生是把它用到视觉上:直接对文档页面图像做多向量嵌入,绕开 OCR 和版面解析(第三章 3.5 节讨论过)。

6.4 相似度怎么算

度量 说明 备注
余弦相似度 只看方向不看长度 RAG 最常用
点积 同时受方向和模长影响 归一化后与余弦等价
欧氏距离 空间直线距离 归一化后与余弦单调等价

实践要点:多数 Embedding 模型输出的向量已经归一化,此时三者在排序上等价,选哪个不影响结果。但必须与向量库的索引配置保持一致——建库时用点积、查询时用余弦,会得到错误的排序。

6.5 使用时的几个硬性约束

6.5.1 建库和查询必须用同一个模型

不同模型的向量位于不同的语义空间,跨空间计算距离没有任何意义,且不会报错——只会静默地返回一堆不相关结果。

推论:换 Embedding 模型 = 全量重建索引。 这是选型时必须提前考虑的成本。

6.5.2 注意输入长度上限

多数模型有最大输入长度(常见 512 Token),超出部分被静默截断。第四章已经强调过,这里再次提醒:这是最隐蔽的一类 bug。

6.5.3 注意指令前缀

不少现代 Embedding 模型(E5、BGE、Qwen3-Embedding 系列)要求给 Query 加特定前缀(如 query: / 为这个句子生成表示以用于检索相关文章:),而文档不加或加另一个前缀。

不按模型卡的要求加前缀,会明显掉点。 这是实践中极常见的低级错误。

6.5.4 对称与非对称检索是两回事

类型 场景 说明
对称检索 句子 vs 句子 两侧长度和形式相近,如相似问题匹配
非对称检索 短 Query vs 长文档 RAG 的典型场景

RAG 需要的是非对称检索能力。 用在对称任务上训练的模型做 RAG,效果会打折扣——这也是为什么不能只看模型在通用相似度榜单上的分数。

6.6 常见错误

6.6.1 说「BERT 就能做 RAG 检索」

原生 BERT 句向量质量差,且 cross-encoder 架构在大规模检索中不可用。这也是检索架构里最容易混淆的一点。

6.6.2 不知道为什么需要双塔

答不出「文档向量必须能离线预计算」,说明没理解检索的工程约束。

6.6.3 把 Embedding 模型和 Rerank 模型混为一谈

前者是双塔、离线可预计算;后者是 cross-encoder、必须在线成对计算。架构完全不同。

6.6.4 忘记加指令前缀

模型卡明确要求的前缀不加,会明显掉点。

6.6.5 混用不同模型的向量

不报错,但结果全错。

6.6.6 只记模型名不讲演进逻辑

「有 Word2Vec、BERT、BGE」这种罗列没有信息量。要说清每一代解决了上一代的什么问题。

6.7 本章总结

  1. Embedding 把文本映射为稠密向量,让语义相似度可计算;这个性质来自训练目标,不是自动出现的;
  2. 第一代静态词向量解决了「语义可计算」,但一词一向量、无法处理多义
  3. 第二代上下文词向量(BERT)解决了多义问题,但句向量质量差 + cross-encoder 架构无法用于大规模检索
  4. 第三代双塔句向量模型是当前 RAG 标配:架构上可离线预计算,训练上用对比学习直接优化相似度
  5. 第四代后期交互(ColBERT 系)保留 Token 级向量,精度更高但存储成本高几十倍;其视觉版本可绕开文档解析;
  6. 两阶段架构的技术根源:双塔快但粗,cross-encoder 准但慢,所以粗排精排分离;
  7. 硬性约束:同一模型建库查询、注意长度上限、按模型卡加指令前缀、区分对称与非对称检索。

参考资料