RAG 中的向量嵌入和多模态嵌入

本文主要介绍 RAG 中的嵌入模型。

RAG 中的向量嵌入和多模态嵌入

第一节 向量嵌入

一、向量嵌入基础

1.1 基础概念

1.1.1 什么是 Embedding

向量嵌入(Embedding)是一种将真实世界中复杂、高维的数据对象(如文本、图像、音频、视频等)转换为数学上易于处理的、低维、稠密的连续数值向量的技术。

想象一下,我们将每一个词、每一段话、每一张图片都放在一个巨大的多维空间里,并给它一个独一无二的坐标。这个坐标就是一个向量,它“嵌入”了原始数据的所有关键信息。这个过程,就是 Embedding。

  • 数据对象:任何信息,如文本“你好世界”,或一张猫的图片。
  • Embedding 模型:一个深度学习模型,负责接收数据对象并进行转换。
  • 输出向量:一个固定长度的一维数组,例如 [0.16, 0.29, -0.88, ...]。这个向量的维度(长度)通常在几百到几千之间。

Embedding 过程示意图

1.1.2 向量空间的语义表示

Embedding 的真正意义在于,它产生的向量不是随机数值的堆砌,而是对数据语义的数学编码。

  • 核心原则:在 Embedding 构建的向量空间中,语义上相似的对象,其对应的向量在空间中的距离会更近;而语义上不相关的对象,它们的向量距离会更远。
  • 关键度量:我们通常使用以下数学方法来衡量向量间的“距离”或“相似度”:
    • 余弦相似度 (Cosine Similarity) :计算两个向量夹角的余弦值。值越接近 1,代表方向越一致,语义越相似。这是最常用的度量方式。
    • 点积 (Dot Product) :计算两个向量的乘积和。在向量归一化后,点积等价于余弦相似度。
    • 欧氏距离 (Euclidean Distance) :计算两个向量在空间中的直线距离。距离越小,语义越相似。

1.2 Embedding 在 RAG 中的作用

在RAG流程中,Embedding 扮演着无可替代的重要角色。

1.2.1 语义检索的基础

RAG 的“检索”环节通常以基于 Embedding 的语义搜索为核心。通用流程如下: (1)离线索引构建:将知识库内文档切分后,使用 Embedding 模型将每个文档块(Chunk)转换为向量,存入专门的向量数据库中。

(2)在线查询检索:当用户提出问题时,使用同一个 Embedding 模型将用户的问题也转换为一个向量。

(3)相似度计算:在向量数据库中,计算“问题向量”与所有“文档块向量”的相似度。

(4)召回上下文:选取相似度最高的 Top-K 个文档块,作为补充的上下文信息,与原始问题一同送给大语言模型(LLM)生成最终答案。

1.2.2 决定检索质量的关键

Embedding 的质量直接决定了 RAG 检索召回内容的准确性与相关性。一个优秀的 Embedding 模型能够精准捕捉问题和文档之间的深层语义联系,即使用户的提问和原文的表述不完全一致。反之,一个劣质的 Embedding 模型可能会因为无法理解语义而召回不相关或错误的信息,从而“污染”提供给 LLM 的上下文,导致最终生成的答案质量低下。

二、Embedding 技术发展

Embedding 技术的发展与自然语言处理(NLP)的进步紧密相连,尤其是在 RAG 框架出现后,对嵌入技术提出了新的要求。其演进路径大致可分为以下几个关键阶段。

2.1 静态词嵌入:上下文无关的表示

  • 代表模型:Word2Vec (2013), GloVe (2014)
  • 主要原理:为词汇表中的每个单词生成一个固定的、与上下文无关的向量。例如,Word2Vec 通过 Skip-gram 和 CBOW 架构,利用局部上下文窗口学习词向量,并验证了向量运算的语义能力(如 国王 - 男人 + 女人 ≈ 王后)。GloVe 则融合了全局词-词共现矩阵的统计信息。
  • 局限性:无法处理一词多义问题。在“苹果公司发布了新手机”和“我吃了一个苹果”中,“苹果”的词向量是完全相同的,这限制了其在复杂语境下的语义表达能力。

2.2 动态上下文嵌入

2017年,Transformer 架构的诞生带来了自注意力机制(Self-Attention),它允许模型在生成一个词的向量时,动态地考虑句子中所有其他词的影响。基于此,2018年 BERT 模型利用 Transformer 的编码器,通过掩码语言模型(MLM)等自监督任务进行预训练,生成了深度上下文相关的嵌入。同一个词在不同语境中会生成不同的向量,这有效解决了静态嵌入的一词多义难题。

2.3 RAG 对嵌入技术的新要求

在开篇我们就提到了 RAG 框架的提出1,是为了解决大型语言模型 知识固化(内部知识难以更新)和 幻觉(生成的内容可能不符合事实且无法溯源)的问题。它通过“检索-生成”范式,动态地为 LLM 注入外部知识。这一过程的核心是 语义检索,很大程度上依赖于高质量的向量嵌入。

后续 RAG 的兴起对嵌入技术提出了更高、更具体的要求:

  • 领域自适应能力:通用的嵌入模型在专业领域(如法律、医疗)往往表现不佳,这就要求嵌入模型具备领域自适应的能力,能够通过微调或使用指令(如 INSTRUCTOR 模型)来适应特定领域的术语和语义。
  • 多粒度与多模态支持:RAG 系统需要处理的不仅仅是短句,还可能包括长文档、代码,甚至是图像和表格。这就要求嵌入模型能够处理不同长度和类型的输入数据。
  • 检索效率与混合检索:嵌入向量的维度和模型大小直接影响存储成本和检索速度。同时,为了结合语义相似性(密集检索)和关键词匹配(稀疏检索)的优点,支持混合检索的嵌入模型(如 BGE-M3)应运而生,在某些任务中成为提升召回率的关键。

三、嵌入模型训练原理

了解了嵌入模型的发展,我们来简单探究一下当前主流的嵌入模型(通常是基于 BERT 的变体)是如何通过训练获得强大的语义理解能力的。

现代嵌入模型的核心通常是 Transformer 的编码器(Encoder)部分,BERT 就是其中的典型代表。它通过堆叠多个 Transformer Encoder 层来构建一个深度的双向表示学习网络。

3.1 主要训练任务

BERT 的成功很大程度上归功于 自监督学习 策略,它允许模型从海量的、无标注的文本数据中学习知识。

任务一:掩码语言模型 (Masked Language Model, MLM)
  • 过程
    • 随机地将输入句子中 15% 的词元(Token)替换为一个特殊的 [MASK] 标记。
    • 让模型去预测这些被遮盖住的原始词元是什么。
  • 目标:通过这个任务,模型被迫学习每个词元与其上下文之间的关系,从而掌握深层次的语境语义。
任务二:下一句预测 (Next Sentence Prediction, NSP)
  • 过程
    • 构造训练样本,每个样本包含两个句子 A 和 B。
    • 其中 50% 的样本,B 是 A 的真实下一句(IsNext);另外 50% 的样本,B 是从语料库中随机抽取的句子(NotNext)。
    • 让模型判断 B 是否是 A 的下一句。
  • 目标:这个任务让模型学习句子与句子之间的逻辑关系、连贯性和主题相关性。
  • 重要说明:后续的研究(如 RoBERTa)发现2,NSP 任务可能过于简单,甚至会损害模型性能。因此,许多现代的预训练模型(如 RoBERTa、SBERT)在预训练阶段移除了 NSP。

更多细节可查看 BERT 架构及应用

3.2 效果增强策略

虽然 MLM 和 NSP 赋予了模型强大的基础语义理解能力,但为了在检索任务中表现更佳,现代嵌入模型通常会引入更具针对性的训练策略。

  • 度量学习 (Metric Learning)

    • 思想:直接以“相似度”作为优化目标。
    • 方法:收集大量相关的文本对(例如,(问题,答案)、(新闻标题,正文))。训练的目标是优化向量空间中的相对距离:让“正例对”的向量表示在空间中被“拉近”,而“负例对”的向量表示被“推远”。关键在于优化排序关系,而非追求绝对的相似度值(如 1 或 0),因为过度追求极端值可能导致模型过拟合。
  • 对比学习 (Contrastive Learning)

    • 思想:在向量空间中,将相似的样本“拉近”,将不相似的样本“推远”。
    • 方法:构建一个三元组(Anchor, Positive, Negative)。其中,Anchor 和 Positive 是相关的(例如,同一个问题的两种不同问法),Anchor 和 Negative 是不相关的。训练的目标是让 distance(Anchor, Positive) 尽可能小,同时让 distance(Anchor, Negative) 尽可能大。

四、嵌入模型选型指南

理论已经了解,那么该如何选择最适合你项目的嵌入模型?

4.1 从 MTEB 排行榜开始

MTEB (Massive Text Embedding Benchmark) 是一个由 Hugging Face 维护的、全面的文本嵌入模型评测基准。它涵盖了分类、聚类、检索、排序等多种任务,并提供了公开的排行榜,为评估和选择嵌入模型提供了重要的参考依据。

MTEB 排行榜

下面这张图是网站中的模型评估图像,直观地展示了在选择开源嵌入模型时需要权衡的四个核心维度:

  • 横轴 - 模型参数量 (Number of Parameters) :代表了模型的大小。通常,参数量越大的模型(越靠右),其潜在能力越强,但对计算资源的要求也越高。
  • 纵轴 - 平均任务得分 (Mean Task Score) :代表了模型的综合性能。这个分数是模型在分类、聚类、检索等一系列标准 NLP 任务上的平均表现。分数越高(越靠上),说明模型的通用语义理解能力越强。
  • 气泡大小 - 嵌入维度 (Embedding Size) :代表了模型输出向量的维度。气泡越大,维度越高,理论上能编码更丰富的语义细节,但同时也会占用更多的存储和计算资源。
  • 气泡颜色 - 最大处理长度 (Max Tokens) :代表了模型能处理的文本长度上限。颜色越深,表示模型能处理的 Token 数量越多,对长文本的适应性越好。

MTEB 排行榜多维度评估示意图

MTEB 榜单可以帮助我们快速筛选掉大量不合适的模型。但需要注意,榜单上的得分是在通用数据集上评测的,可能无法完全反映模型在你特定业务场景下的表现。

4.2 关键评估维度

在查看榜单时,除了分数,还需要关注以下几个关键维度:

  • 任务 (Task) :对于 RAG 应用,需要重点关注模型在 Retrieval (检索) 任务下的排名。
  • 语言 (Language) :模型是否支持你的业务数据所使用的语言?对于中文 RAG,应选择明确支持中文或多语言的模型。
  • 模型大小 (Size) :模型越大,通常性能越好,但对硬件(显存)的要求也越高,推理速度也越慢。需要根据你的部署环境和性能要求来权衡。
  • 维度 (Dimensions) :向量维度越高,能编码的信息越丰富,但也会占用更多的存储空间和计算资源。
  • 最大 Token 数 (Max Tokens) :这决定了模型能处理的文本长度上限。这个参数是你设计文本分块(Chunking)策略时必须考虑的重要依据,块大小不应超过此限制。
  • 得分与机构 (Score & Publisher) :结合模型的得分排名和其发布机构的声誉进行初步筛选。知名机构发布的模型通常质量更有保障。
  • 成本 (Cost) :如果是使用 API 服务的模型,需要考虑其调用成本;如果是自部署开源模型,则需要评估其对硬件资源的消耗(如显存、内存)以及带来的运维成本。

4.3 迭代测试与优化

不要只依赖公开榜单做最终决定。

(1)确定基线 (Baseline) :根据上述维度,选择几个符合要求的模型作为你的初始基准模型。

(2)构建私有评测集 :根据真实业务数据,手动创建一批高质量的评测样本,每个样本包含一个典型用户问题和它对应的标准答案(或最相关的文档块)。

(3)迭代优化

  • 使用基线模型在你的私有评测集上运行,评估其召回的准确率和相关性。

  • 如果效果不理想,可以尝试更换模型,或者调整 RAG 流程的其他环节(如文本分块策略)。

  • 通过几轮的对比测试和迭代优化,最终选出在你的特定场景下表现最佳的那个“心仪”模型。

第二节 多模态嵌入

现代 AI 的一项重要突破,是将简单的词向量发展成了能统一理解图文、音视频的复杂系统。这一发展建立在注意力机制、Transformer 架构和对比学习等关键技术之上,它们解决了在共享向量空间中对齐不同数据模态的核心挑战。其发展环环相扣:Word2Vec 为 BERT 的上下文理解铺路,而 BERT 又为 CLIP 等模型的跨模态能力奠定了基础。

一、为什么需要多模态嵌入?

前面的章节介绍了如何为文本创建向量嵌入。然而,仅有文本的世界是不完整的。现实世界的信息是多模态的,包含图像、音频、视频等。传统的文本嵌入无法理解“那张有红色汽车的图片”这样的查询,因为文本向量和图像向量处于相互隔离的空间,存在一堵“模态墙”。

多模态嵌入 (Multimodal Embedding) 的目标正是为了打破这堵墙。其目的是将不同类型的数据(如图像和文本)映射到同一个共享的向量空间。在这个统一的空间里,一段描述“一只奔跑的狗”的文字,其向量会非常接近一张真实小狗奔跑的图片向量。

实现这一目标的关键,在于解决 跨模态对齐 (Cross-modal Alignment) 的挑战。以对比学习、视觉 Transformer (ViT) 等技术为代表的突破,让模型能够学习到不同模态数据之间的语义关联,最终催生了像 CLIP 这样的模型。

二、CLIP 模型浅析

在图文多模态领域,OpenAI 的 CLIP (Contrastive Language-Image Pre-training) 是一个很有影响力的模型,它为多模态嵌入定义了一个有效的范式。

CLIP 的架构清晰简洁。它采用双编码器架构 (Dual-Encoder Architecture),包含一个图像编码器和一个文本编码器,分别将图像和文本映射到同一个共享的向量空间中。

CLIP Architecture 图:CLIP 的工作流程。(1) 通过对比学习训练双编码器,对齐图文向量空间。(2)和(3) 展示了如何利用该空间,通过图文相似度匹配实现零样本预测。

为了让这两个编码器学会“对齐”不同模态的语义,CLIP 在训练时采用了对比学习 (Contrastive Learning) 策略。在处理一批图文数据时,模型的目标是:最大化正确图文对的向量相似度,同时最小化所有错误配对的相似度。通过这种“拉近正例,推远负例”的方式,模型从海量数据中学会了将语义相关的图像和文本在向量空间中拉近。

这种大规模的对比学习赋予了 CLIP 有效的零样本(Zero-shot)识别能力。它能将一个传统的分类任务,转化为一个“图文检索”问题——例如,要判断一张图片是不是猫,只需计算图片向量与“a photo of a cat”文本向量的相似度即可。这使得 CLIP 无需针对特定任务进行微调,就能实现对视觉概念的泛化理解。

三、常用多模态嵌入模型(以bge-visualized-m3为例)

虽然 CLIP 为图文预训练提供了重要基础,但多模态领域的研究迅速发展,涌现了许多针对不同目标和场景进行优化的模型。例如,BLIP 系列专注于提升细粒度的图文理解与生成能力,而 ALIGN 则证明了利用海量噪声数据进行大规模训练的有效性。

在众多优秀的模型中,由北京智源人工智能研究院(BAAI)开发的 bge-visualized-m3(Visualized-BGE 的 M3 版本) 是一个很有代表性的现代多模态嵌入模型。它是在 BGE-M3(文本嵌入底座)的基础上引入图像能力而来,体现了当前技术向“更统一、更全面”发展的趋势。

bge-visualized-m3 的核心特性也可以概括为“M3”(主要继承自其文本底座 BGE-M3):

  • 多语言性 (Multi-Linguality):支持超过 100 种语言的文本表示,可用于跨语言的图文检索(文本侧)。
  • 多功能性 (Multi-Functionality):在文本检索场景下,可按需求使用密集检索(Dense Retrieval)、多向量检索(Multi-Vector Retrieval)和稀疏检索(Sparse Retrieval)等不同范式。
  • 多粒度性 (Multi-Granularity):文本侧可处理从短句到长达 8192 个 token 的长文档,覆盖更广泛的应用需求。

在技术架构上,bge-visualized-m3 会先用视觉编码器提取图像的 patch token,再将其映射到与文本同维度的“图像 token”,与文本 token 一起送入 BGE 的 Transformer 编码器进行联合建模,最终得到可用于图文检索的统一向量表示。

四、代码示例

4.1 环境准备

步骤1:安装 visual_bge 模块

1
2
3
4
5
6
7
8
# 进入 visual_bge 目录
cd code/C3/visual_bge

# 安装 visual_bge 模块及其依赖
pip install -e .

# 返回上级目录
cd ..

步骤2:下载模型权重

1
2
# 运行模型下载脚本
python download_model.py

模型下载脚本会自动检查 ../../models/bge/ 目录下是否存在模型文件,如果不存在则从 Hugging Face 镜像站下载。

4.2 基础示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import os
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
import torch
from visual_bge.visual_bge.modeling import Visualized_BGE

model = Visualized_BGE(model_name_bge="BAAI/bge-base-en-v1.5",
                      model_weight="../../models/bge/Visualized_base_en_v1.5.pth")
model.eval()

with torch.no_grad():
    text_emb = model.encode(text="datawhale开源组织的logo")
    img_emb_1 = model.encode(image="../../data/C3/imgs/datawhale01.png")
    multi_emb_1 = model.encode(image="../../data/C3/imgs/datawhale01.png", text="datawhale开源组织的logo")
    img_emb_2 = model.encode(image="../../data/C3/imgs/datawhale02.png")
    multi_emb_2 = model.encode(image="../../data/C3/imgs/datawhale02.png", text="datawhale开源组织的logo")

# 计算相似度
sim_1 = img_emb_1 @ img_emb_2.T
sim_2 = img_emb_1 @ multi_emb_1.T
sim_3 = text_emb @ multi_emb_1.T
sim_4 = multi_emb_1 @ multi_emb_2.T

print("=== 相似度计算结果 ===")
print(f"纯图像 vs 纯图像: {sim_1}")
print(f"图文结合1 vs 纯图像: {sim_2}")
print(f"图文结合1 vs 纯文本: {sim_3}")
print(f"图文结合1 vs 图文结合2: {sim_4}")

代码解读:

  • 模型架构: Visualized_BGE 是通过将图像token嵌入集成到BGE文本嵌入框架中构建的通用多模态嵌入模型,具备处理超越纯文本的多模态数据的灵活性。
  • 模型参数:
    • model_name_bge: 指定底层BGE文本嵌入模型,继承其强大的文本表示能力。
    • model_weight: Visual BGE的预训练权重文件,包含视觉编码器参数。
  • 多模态编码能力: Visual BGE提供了编码多模态数据的多样性,支持纯文本、纯图像或图文组合的格式:
    • 纯文本编码: 保持原始BGE模型的强大文本嵌入能力。
    • 纯图像编码: 使用基于EVA-CLIP的视觉编码器处理图像。
    • 图文联合编码: 将图像和文本特征融合到统一的向量空间。
  • 应用场景: 主要用于混合模态检索任务,包括多模态知识检索、组合图像检索、多模态查询的知识检索等。
  • 相似度计算: 使用矩阵乘法计算余弦相似度,所有嵌入向量都被标准化到单位长度,确保相似度值在合理范围内。

运行结果:

1
2
3
4
5
=== 相似度计算结果 ===
纯图像 vs 纯图像: tensor([[0.8318]])
图文结合1 vs 纯图像: tensor([[0.8291]])
图文结合1 vs 纯文本: tensor([[0.7627]])
图文结合1 vs 图文结合2: tensor([[0.9058]])

完整代码

练习

尝试把代码中的部分文本替换一下,比如将datawhale开源组织的logo替换为blue whale看看结果有什么不同。

参考文献

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计