向量嵌入

概念

RAG中不可缺少的核心步骤就是向量嵌入Embedding,即将高维的数据文本图像等通过深度学习嵌入模型映射成低维连续数值向量。优势在于让现实中语义上相似的对象,其向量在空间中的距离也更近,度量方法有余弦相似度、点积、欧氏距离等数学方法。

在RAG,将切分的文档块转为向量,存到向量数据库中,将用户的问题也转成向量,再在构建的向量数据库中寻找与问题向量相似度最高的文档块,找到的文档块与原始问题一起送给LLM进行处理。可以说,嵌入模型的质量直接决定了RAG检索召回的准确性和相关性。

技术发展

  • 静态词向量(2013-2014):Word2Vec和Glove生成上下文无关的固定向量,无法解决一词多义问题(如“苹果”在不同语境中向量相同)。
  • 动态词向量(2018):BERT基于Transformer编码器,通过掩码语言模型(MLM)等任务实现上下文相关嵌入,同一词汇在不同语境中生成不同向量。
  • RAG时代需求(2020后):要求嵌入模型具备领域自适应、多粒度/多模态支持及高效检索能力。

在这里插入图片描述

训练原理

当今主流的嵌入模型核心架构通常是bert,通常堆叠多个 Transformer Encoder 层来构建一个深度的双向表示学习网络。

Bert的核心训练任务:

  1. 掩码语言模型 (Masked Language Model, MLM),让模型学习每个词元和其上下文之间关系,掌握深层次语境语义
  2. 下一句预测 (Next Sentence Prediction, NSP),让模型学习句子与句子之间的逻辑关系、连贯性和主题相关性,注:这个其实不好用,现在的大多数与训练模型已经放弃NSP
  3. 度量学习 (Metric Learning),收集正例对和负例对,优化向量空间中的相对距离。
  4. 对比学习 (Contrastive Learning),构建一个三元组(Anchor, Positive, Negative),将向量空间中相似的样本“拉近”,将不相似的样本“推远”。

模型选择

  1. 参考MTEB (Massive Text Embedding Benchmark)网站;
  2. 关注模型在检索任务的排名、模型使用的语言、大小、向量维度、最大Token数、得分和机构、成本等多方面指标;
  3. 根据自己的业务不断迭代优化,确定最佳选择

多模态嵌入

多模态嵌入 (Multimodal Embedding) 是将不同类型的数据(如图像和文本)映射到同一个共享的向量空间。

CLIP模型

OpenAI的CLIP(Contrastive Language-Image Pre-training)是这个领域很有影响力的模型,它采用双编码架构,包含一个图像编码器和一个文本编码器,如图所示
在这里插入图片描述
先通过对比学习训练双编码器,对齐向量空间,再通过图文相似度匹配实现零样本预测。

其他模型:BLIP 系列专注于提升细粒度的图文理解与生成能力,ALIGN 证明了利用海量噪声数据进行大规模训练的有效性。

BGE-M3模型

M3即

  1. 多语言性,支持100多种语言的文本和图像处理;
  2. 多功能性,同时支持密集检索、多向量检索、系数检索;
  3. 多粒度型,从短句到长达8192个token的长文档都可以胜任。

BGE-M3 在架构上采用了基于 XLM-RoBERTa 优化的联合编码器,采用网格嵌入,将图像分割为多个网格单元并独立编码,显著提升了模型对图像局部细节的捕捉能力。

使用案例

环境准备

# 进入 visual_bge 目录
cd code/C3/visual_bge

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

# 返回上级目录
cd ..

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

代码

# 导入操作系统相关模块,用于环境变量配置
import os
# 设置Hugging Face镜像站点,加速模型资源下载(国内访问优化)
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"

# 导入PyTorch深度学习框架,用于张量运算和模型推理
import torch
# 从visualized_bge库中导入Visualized_BGE多模态嵌入模型
from visualized_bge.visual_bge.visual_bge.modeling import Visualized_BGE

# 初始化Visualized_BGE模型
# 参数说明:
# - model_name_bge: 基础文本嵌入模型,这里使用BAAI的bge-base-en-v1.5英文基础模型
# - model_weight: 预训练模型权重文件路径,包含图像和文本的联合嵌入参数
model = Visualized_BGE(
    model_name_bge="BAAI/bge-base-en-v1.5",
    model_weight="../../models/bge/Visualized_base_en_v1.5.pth"
)

# 将模型设置为评估模式
# 评估模式会关闭训练时的随机化操作(如Dropout),确保推理结果稳定可复现
model.eval()

# torch.no_grad()上下文管理器:关闭梯度计算
# 推理阶段无需计算梯度,可减少内存占用并加速计算
with torch.no_grad():
    # 1. 文本编码:将文本转换为向量表示
    # 对"DataWhale开源组的logo"这句话进行编码,得到文本嵌入向量
    text_emb = model.encode(text="datawhale开源组的logo")
    
    # 2. 图像编码:将图像转换为向量表示
    # 对第一张DataWhale图片进行编码,得到图像嵌入向量
    img_emb_1 = model.encode(image="../../data/C3/imgs/datawhale01.png")
    
    # 3. 多模态编码(图文结合):同时输入图像和文本,得到融合后的向量
    # 结合第一张图片和"DataWhale开源组"文本进行编码
    multi_emb_1 = model.encode(
        image="../../data/C3/imgs/datawhale01.png", 
        text="datawhale开源组"
    )
    
    # 对第二张DataWhale图片进行编码
    img_emb_2 = model.encode(image="../../data/C3/imgs/datawhale02.png")
    
    # 结合第二张图片和"DataWhale开源组"文本进行编码
    multi_emb_2 = model.encode(
        image="../../data/C3/imgs/datawhale02.png", 
        text="datawhale开源组"
    )

    # 4. 相似度计算(使用向量点积,值越大表示语义越相似)
    # 计算两张纯图片向量的相似度
    sim1 = img_emb_1 @ img_emb_2.T  # @表示矩阵乘法,.T表示向量转置
    
    # 计算第一张纯图片与第二张图文结合向量的相似度
    sim2 = img_emb_1 @ multi_emb_2.T
    
    # 计算纯文本与第一张图文结合向量的相似度
    sim3 = text_emb @ multi_emb_1.T
    
    # 计算两个图文结合向量的相似度
    sim4 = multi_emb_1 @ multi_emb_2.T

# 打印所有相似度计算结果,验证多模态数据的语义关联
print("===== 相似度计算结果 =====")
print(f"纯图像1 vs 纯图像2: {sim1}")          # 两张图片的相似程度 tensor([[0.8318]])
print(f"纯图像1 vs 图文结合2: {sim2}")       # 图片1与图片2+文本的相似程度  tensor([[0.8291]])
print(f"纯文本 vs 图文结合1: {sim3}")        # 文本与图片1+文本的相似程度 tensor([[0.7627]])
print(f"图文结合1 vs 图文结合2: {sim4}")     # 两种图文组合的相似程度  tensor([[0.9058]])

向量数据库

简介

向量数据库用于存储高维向量,利用索引技术提供相似性搜索和各种过滤查询、范围查询等,企业级向量数据库采用分布式架构增加了扩展能力和容错性,并于主流AI框架结合,简化了开发流程。

向量数据库与传统数据库的主要差异如下:

维度 向量数据库 传统数据库 (RDBMS)
核心数据类型 高维向量 (Embeddings) 结构化数据 (文本、数字、日期)
查询方式 相似性搜索 (ANN) 精确匹配
索引机制 HNSW, IVF, LSH 等 ANN 索引 B-Tree, Hash Index
主要应用场景 AI 应用、RAG、推荐系统、图像/语音识别 业务系统 (ERP, CRM)、金融交易、数据报表
数据规模 轻松应对千亿级向量 通常在千万到亿级行数据,更大规模需复杂分库分表
性能特点 高维数据检索性能极高,计算密集型 结构化数据查询快,高维数据查询性能呈指数级下降
一致性 通常为最终一致性 强一致性 (ACID 事务)

工作原理

在这里插入图片描述

主流数据库

新手选择ChromaDBFAISS ,企业选择 MilvusWeaviate 或云服务 Pinecone

主流向量数据库产品对比表

产品名称 核心定位 架构特性 关键功能 性能表现 适用场景 部署方式 开源情况
Pinecone 企业级托管向量数据库服务 完全托管Serverless架构,存储计算分离,自动扩展与负载均衡 支持混合搜索(稀疏+稠密向量)、实时索引更新、命名空间隔离、多语言SDK、99.95% SLA保障 低延迟搜索(<100ms),支持75亿+向量存储,每日3000万+全局写入 企业级生产环境、高并发业务(如推荐系统、大规模RAG)、无需运维的规模化场景 云端托管(无本地部署选项) 闭源(商业服务)
Milvus 开源分布式向量数据库 全分布式K8s原生架构,支持单机/集群模式,计算存储分离,冷热数据分层 支持GPU加速(NVIDIA CAGRA)、多索引算法(HNSW/IVF/FLAT等)、多租户隔离、实时流更新、Spark/Kafka数据集成 支持十亿级向量检索,数万QPS查询,支持实时数据写入与检索 大规模部署(如生物医药分子搜索、工业级推荐)、高性能要求场景、需自定义开发的开源项目 单机部署(Standalone)、集群部署(K8s/物理机)、云端托管(Zilliz Cloud) 开源(Apache 2.0协议,LF AI & Data基金会托管)
Qdrant 高性能开源向量搜索引擎 Rust开发,轻量级架构,支持内存/磁盘存储,分布式分片与复制 支持稀疏向量混合搜索、向量量化(降97%内存)、Payload精细过滤(geo/数值/文本)、SIMD硬件加速、Async I/O RPS>4000,低延迟检索,支持百万至亿级向量规模 性能敏感型应用(如语义搜索、图像匹配)、高并发中小规模场景、需要轻量部署的业务 本地部署(Docker/二进制)、云端托管(Qdrant Cloud) 开源(Apache 2.0协议)
Weaviate AI集成型开源向量数据库 云原生架构,支持分布式集群,内置模块化设计 支持GraphQL/REST/gRPC API、20+AI模块(OpenAI/Cohere/HuggingFace集成)、多模态数据处理、RAG优化、RBAC权限控制 百万级向量检索毫秒级响应,支持动态扩展与副本容错 AI应用开发(如ChatGPT检索插件、多模态搜索)、快速原型迭代、需GraphQL交互的场景 本地部署(Docker/集群)、云端托管(Weaviate Cloud Services) 开源(BSD-3-Clause协议)
Chroma 轻量级开源向量数据库 本地优先设计,无外部依赖,支持内存/文件持久化 零配置安装、自动嵌入(Sentence Transformers/OpenAI等)、元数据过滤、Regex查询、LangChain/LlamaIndex无缝集成 适合中小规模数据(万至百万级向量),低资源消耗,原型开发快速响应 原型开发、教育培训、小规模应用(如个人RAG、轻量语义搜索)、快速验证业务想法 本地运行(Python pip安装/内存模式)、Docker部署、云端托管(Chroma Cloud) 开源(Apache 2.0协议)

本地存储FAISS案例

FAISS (Facebook AI Similarity Search)可以与langchain结合,适用于中小应用,本质上是一个算法库,它将索引直接保存为本地文件(一个 .faiss 索引文件和一个 .pkl 映射文件),而非运行一个数据库服务。这种方式轻量且高效。

运行代码

# 导入所需的库
# FAISS:用于高效存储和搜索向量的库
from langchain_community.vectorstores import FAISS
# HuggingFaceEmbeddings:用于加载HuggingFace的嵌入模型,将文本转换为向量
from langchain_community.embeddings import HuggingFaceEmbeddings
# Document:LangChain中的文档类,用于包装文本内容
from langchain_core.documents import Document

# 1. 准备示例文本数据和初始化嵌入模型
# 定义一些示例文本,将被转换为向量存储
texts = [
    "张三是法外狂徒",
    "FAISS是一个用于高效相似性搜索和密集向量聚类的库。",
    "LangChain是一个用于开发由语言模型驱动的应用程序的框架。"
]

# 将文本转换为LangChain的Document对象,便于后续处理
# 每个Document对象包含页面内容(page_content)等元数据
docs = [Document(page_content=t) for t in texts]

# 初始化嵌入模型,这里使用中文BGE模型
# model_name指定了要使用的预训练模型
embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5")

# 2. 创建向量存储并保存到本地
# 使用文档和嵌入模型创建FAISS向量存储
# 这一步会将所有文档转换为向量并构建索引
vectorstore = FAISS.from_documents(docs, embeddings)

# 定义本地存储路径
local_faiss_path = "./faiss_index_store"

# 将创建的向量存储保存到本地文件系统
vectorstore.save_local(local_faiss_path)

# 打印保存成功的信息
print(f"FAISS index has been saved to {local_faiss_path}")

# 3. 从本地加载索引并执行相似性查询
# 从本地加载之前保存的FAISS向量存储
# 需要指定相同的嵌入模型,并且允许反序列化(生产环境需谨慎使用)
loaded_vectorstore = FAISS.load_local(
    local_faiss_path,
    embeddings,
    allow_dangerous_deserialization=True
)

# 定义查询文本:想要搜索相关的内容
query = "FAISS是做什么的?"

# 执行相似性搜索,k=1表示返回最相似的1个结果
results = loaded_vectorstore.similarity_search(query, k=1)

# 打印查询结果
print(f"\n查询: '{query}'")
print("相似度最高的文档:")
for doc in results:
    print(f"- {doc.page_content}")

输出

FAISS index has been saved to ./faiss_index_store

查询: 'FAISS是做什么的?'
相似度最高的文档:
- FAISS是一个用于高效相似性搜索和密集向量聚类的库。

索引创建的细节
在这里插入图片描述

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐