1、导读

本文学习来源 all-in-rag
个人学习笔记整理总结,有错误或者遗漏希望大家指正

本章主要讨论

  • Embedding 负责把数据变成语义向量
  • Vector Store / Vector DB 负责存储和检索向量
  • Index Optimization 负责让检索结果更准、更完整、更可控

2、Embedding

What

Embedding 是把数据源(文本、图片、音频等)映射成语义向量的过程,输出结果通常是一个 Vector。
也可以理解为:把原始数据映射到一个固定维度、稠密、可计算的数字空间中,每个数据块对应一个向量。

例子:

文本:"RAG是检索增强生成"
→ 向量:[0.12, -0.03, 0.55, ...]  # 高维向量

这些向量捕捉了 语义信息,而不仅仅是字面字符。

Why

  1. 语义搜索
    • 原始文本无法直接比较相似度(字符串相似不等于语义相似)
    • 向量空间里可以用 距离度量(cosine similarity / L2) 找语义最接近的数据
    • cosine similarity 更关注向量方向,L2 更关注空间距离
    • 例子:
      • “苹果是水果” 和 “香蕉也是水果” → 语义接近 → 向量距离近
      • “苹果是水果” 和 “计算机芯片” → 语义不接近 → 向量距离远
  2. 高效检索
    • 向量可以建索引(FAISS / Milvus / Chroma)
    • 支持 Top-K 检索:快速找到最相关的数据块
    • 原始文本无法高效做大规模相似度搜索
  3. 统一处理多模态
    • 文本、图像、音频都可以转向量
    • 但要注意:跨模态检索需要使用已经做过模态对齐的多模态 Embedding 模型
    • 这样才可以在同一个向量空间里进行跨模态检索,并把检索结果提供给后续生成模型使用
    • 例子:文本查询 → 找相关图片 → 用 CLIP embedding

How

  1. 不同模态先做不同预处理:文本通常用 Tokenizer 变成 token,图像/音频会经过对应的视觉或音频编码处理
  2. Embedding 模型神经网络将输入映射成向量
  3. 对文档块向量进行处理,并且存储进向量数据库
  4. 用户查询时,也要用同一个或兼容的 Embedding 模型编码成查询向量
  5. 最后比较查询向量和文档向量的相似度,返回 Top-K 相关数据块

2.1 向量嵌入

核心理解:

  1. Embedding 的本质是语义坐标

    • 每个文本块都会被模型映射成一个固定维度的向量
    • 这个向量可以理解成文本在语义空间里的坐标
    • 语义相近的文本,向量距离更近;语义不相关的文本,向量距离更远
  2. RAG 中的向量嵌入流程

    • 离线阶段:文档 → 切分 Chunk → Embedding 模型编码 → 文档向量 → 存入向量数据库
    • 在线阶段:用户问题 → 同一个 Embedding 模型编码 → 查询向量 → 和文档向量做相似度搜索
    • 检索结果:返回 Top-K 最相似 Chunk,作为上下文交给 LLM
  3. 关键点:文档和问题必须在同一个语义空间

    • 建库时用的 Embedding 模型,查询时也要用同一个或兼容模型
    • 如果文档向量和查询向量不是同一个模型生成的,相似度比较就不可靠

向量相似度:

  • Cosine Similarity:看两个向量方向是否接近,越接近 1 越相似,文本语义检索常用
  • Dot Product:点积,向量归一化后可以近似等价于 cosine similarity
  • Euclidean Distance / L2:看两个向量在空间中的直线距离,距离越小越相似

Embedding 技术发展:

可以理解成:向量表示从“符号匹配”一步步走向“语义理解”。

  1. 稀疏表示

    • 代表:One-hot、Bag of Words、TF-IDF
    • 特点:把词当成离散符号,通常是很长、很稀疏的向量
    • 例子:苹果 = [0, 0, 1, 0, ...],香蕉 = [0, 1, 0, 0, ...]
    • 问题:机器只知道它们是不同词,不知道“苹果”和“香蕉”都属于水果
    • 本质:能做字面统计,但很难理解语义关系
  2. 静态词嵌入

    • 代表:Word2Vec、GloVe
    • 特点:每个词对应一个固定的稠密向量
    • 怎么学:如果两个词经常出现在相似上下文里,模型就认为它们语义接近
    • 优点:开始能表达词语之间的语义关系
    • 问题:不能处理一词多义
    • 例子:“苹果公司”和“吃苹果”里的“苹果”会共享同一个向量
  3. 动态上下文嵌入

    • 代表:BERT、RoBERTa
    • 特点:同一个词在不同上下文中可以得到不同表示
    • 怎么做:Transformer 的 Self-Attention 会让词关注句子里的其他词
    • 例子:
      • “我吃了一个苹果”里的“苹果”会受到“吃了”的影响
      • “苹果公司发布了新手机”里的“苹果”会受到“公司、手机”的影响
    • 解决的问题:让模型不只理解词本身,还理解词所在语境
  4. 面向检索的 Embedding

    • 代表:SBERT、DPR、E5、BGE 等
    • 目标:不只是理解一句话,而是判断“问题”和“文档块”是否匹配
    • 例子:
      • 问题:FAISS 是做什么的?
      • 文档:FAISS 是用于高效相似性搜索和向量聚类的库
    • 如果这两段语义相关,它们的向量就应该更近
    • RAG 里常用的 Embedding 模型,通常是这种专门为检索优化过的向量模型

嵌入模型训练原理:

核心目标:让模型学会把语义相近的内容放近,把语义不相关的内容推远。

  1. 自监督预训练:先学语言理解

    • 不需要人工标注,模型从大量文本中自己学习语言规律

    MLM(Masked Language Model)

    • 随机遮住文本中的部分 token
    • 让模型根据上下文预测被遮住的词
    • 例子:RAG 是 [MASK] 增强生成,模型要预测 [MASK] 是“检索”
    • 作用:学习词和上下文之间的关系

    NSP(Next Sentence Prediction)

    • 判断句子 B 是否是句子 A 的下一句
    • 作用:学习句子之间的连贯性和主题关系
    • 注意:后续很多模型不一定继续使用 NSP,比如 RoBERTa 移除了这个任务
  2. 面向检索的训练:再学匹配关系

    • RAG 更关心的是:用户问题和哪个文档块匹配
    • 训练数据通常是三元组:
      • Anchor:用户问题
      • Positive:正确相关文档
      • Negative:不相关文档

    例子:

    • Anchor:FAISS 是做什么的?
    • Positive:FAISS 是用于相似性搜索和向量聚类的库
    • Negative:Python 是一种编程语言
  3. 度量学习

    • 直接优化向量空间里的距离关系
    • 目标是让相关文本更近,不相关文本更远
    • 重点不是追求绝对相似度,而是优化排序关系
  4. 对比学习

    • 本质还是“拉近正例,推远负例”
    • 训练目标:
      • sim(query, positive) 更高
      • sim(query, negative) 更低
    • 这对 RAG 很关键,因为检索时就是要把正确文档排到前面
  5. Hard Negative(困难负例)

    • 指看起来相关,但不是正确答案的负例
    • 例子:
      • 问题:FAISS 是做什么的?
      • 困难负例:Milvus 是一个向量数据库
    • 它们都和向量检索有关,但答案并不一样
    • 用困难负例训练,可以让模型学会更细粒度地区分“相似但不正确”的内容

RAG 对 Embedding 的要求:

  • 领域适配:法律、医疗、金融等专业场景,通用模型可能不够
  • 多粒度支持:要能处理短句、段落、长文档、代码、表格等
  • 检索效率:向量维度越大,表达能力可能更强,但存储和计算成本也更高
  • 多模态支持:真实知识库可能不只是文本
  • 混合检索能力:向量检索可以理解语义,但关键词精确匹配也很重要

模型选型:

  • 可以先看 MTEB 排行榜,但不能只看总分
  • RAG 场景重点看 Retrieval 任务表现
  • 中文场景要看中文或多语言支持
  • 要关注模型大小、向量维度、最大 token 长度、推理速度、部署成本
  • 最终还是要用自己的业务数据做测试,因为公开榜单不等于真实业务效果

向量嵌入是 RAG 检索的语义基础。它决定了问题和文档能不能在向量空间中正确“相遇”。如果 Embedding 模型理解不好,后面的向量数据库再快也只是快速找错内容。

2.2 多模态嵌入

多模态嵌入解决的是:不同类型的数据如何进入同一个语义空间。

为什么需要多模态嵌入:

  • 现实世界的信息不只有文本,还有图片、音频、视频、表格、截图等
  • 普通文本 Embedding 只能理解文本,不能直接理解图片内容
  • 如果文本向量和图片向量不在同一个空间里,它们之间的相似度没有意义
  • 多模态嵌入的目标就是打破这堵“模态墙”

核心目标:

  • 把文本、图像等不同模态映射到同一个共享向量空间
  • 在这个空间中,语义相关的文本和图片应该距离更近
  • 例子:
    • 文本:“一只奔跑的狗”
    • 图片:一张狗正在奔跑的图片
    • 这两个向量应该接近

关键难点:跨模态对齐

  • 模型要学会哪段文本描述哪张图片
  • 也要学会哪些图文只是表面相关,但语义不匹配
  • 常用技术:Transformer、视觉 Transformer(ViT)、对比学习
  • 本质:让不同模态的数据虽然输入形式不同,但输出向量可以在同一个空间中比较

CLIP 的核心思想:

  1. 双编码器架构

    • 图像编码器:把图片编码成图像向量
    • 文本编码器:把文本编码成文本向量
    • 两个编码器输出到同一个共享向量空间
  2. 对比学习训练

    • 正确的图文对:向量相似度要更高
    • 错误的图文对:向量相似度要更低
    • 本质还是“拉近正例,推远负例”
    • 例子:
      • 图片:一只狗在草地上奔跑
      • 正确文本:一只狗在草地上奔跑 → 拉近
      • 错误文本:一辆红色汽车 → 推远
      • 错误文本:一只猫坐在沙发上 → 推远
  3. 零样本能力

    • CLIP 可以把分类任务转成图文相似度匹配
    • 例子:判断一张图是不是猫
      • 图片向量 vs “a photo of a cat”
      • 图片向量 vs “a photo of a dog”
      • 哪个文本相似度更高,就更可能是哪一类

bge-visualized-m3:

  • 它是在 BGE-M3 文本嵌入模型基础上加入图像能力的多模态模型
  • 目标是让文本和图像可以进入统一向量空间,用于图文检索
  • M3 主要继承自 BGE-M3:
    • Multi-Linguality:多语言能力
    • Multi-Functionality:多功能检索能力,比如密集检索、多向量检索
    • Multi-Granularity:多粒度能力,可以处理短文本到长文档

bge-visualized-m3 的大致流程:

  1. 文本经过 tokenizer,变成文本 token
  2. 图像经过视觉编码器,提取 patch token
  3. 图像 token 被映射到和文本 token 相同维度
  4. 图像 token 和文本 token 一起进入 BGE 的 Transformer 编码器
  5. 最终得到统一的多模态向量表示

应用场景:

  • 以文搜图:输入文字,找相关图片
  • 以图搜图:输入图片,找相似图片
  • 图文组合检索:输入图片加文本,找更精确的结果
  • 多模态 RAG:知识库里有文本、图片、截图、表格等内容时,可以一起检索

多模态嵌入不是简单地“文本也转向量、图片也转向量”,重点是这些向量必须被对齐到同一个语义空间。
只有这样,文本查询和图片内容之间的相似度才有意义。

3、Vector

3.1 向量数据库

向量数据库解决的问题是:Embedding 已经把数据变成向量了,但当向量数量变多以后,怎么快速找到和查询最相似的向量。

为什么需要向量数据库:

  • 原始文本、图片、音频不能直接做大规模语义搜索
  • Embedding 模型把它们变成向量后,就可以计算相似度
  • 但如果有几百万、几千万甚至更多向量,暴力两两计算会很慢
  • 向量数据库通过专门的索引结构,让相似性搜索变快

在 RAG 里,向量数据库扮演的是“外部知识库”的角色:

文档 / 图片 / 表格
→ Embedding 模型编码成向量
→ 向量数据库存储向量和元数据
→ 用户问题也编码成向量
→ 向量数据库返回 Top-K 相关内容
→ LLM 根据这些内容生成答案

向量数据库主要能力:

  1. 高效相似性搜索

    • 根据查询向量,找到最相似的 Top-K 向量
    • 核心是 ANN(Approximate Nearest Neighbor,近似最近邻)检索
    • ANN 不是暴力找绝对最精确结果,而是在速度和召回率之间做平衡
  2. 存储向量和元数据

    • 向量字段:存 Embedding 结果
    • 标量字段:存原始文本、图片路径、标题、类别、时间等
    • 检索时通常是先找到向量,再通过元数据找回原始内容
  3. 支持过滤查询

    • 不只是“找最相似”,还可以加条件
    • 例子:只搜索 2024 年以后的文档,只搜索某个分类下的图片
  4. 支持索引优化

    • 用 HNSW、IVF、PQ、LSH 等索引结构加速检索
    • 不同索引适合不同规模和性能要求
  5. 和 RAG 框架集成

    • LangChain、LlamaIndex 都可以接 FAISS、Milvus、Chroma 等向量存储

向量数据库 vs 传统数据库:

传统数据库更擅长:

  • 精确查询:id = 1
  • 条件过滤:year > 2023
  • 事务、表关系、结构化数据管理

向量数据库更擅长:

  • 相似性搜索
  • 高维向量检索
  • 语义搜索
  • 推荐、RAG、图像检索、多模态检索

两者不是替代关系,而是互补关系:

传统数据库:存业务数据、交易数据、结构化信息
向量数据库:存 Embedding 向量和检索元数据

ANN 的几类常见方法:

  1. 基于树

    • 例子:Annoy 的随机投影树
    • 思路:用树结构不断缩小搜索范围
  2. 基于哈希

    • 例子:LSH
    • 思路:让相似向量更可能落到同一个桶里
  3. 基于图

    • 例子:HNSW
    • 思路:构建邻近图,查询时沿着图快速跳到相似区域
  4. 基于量化

    • 例子:IVF、PQ
    • 思路:通过聚类和压缩降低存储与计算成本

主流向量数据库 / 向量存储:

  • FAISS:本地向量检索库,轻量、高效,适合学习和原型
  • Chroma:轻量级本地向量数据库,适合小项目和快速实验
  • Milvus:生产级开源向量数据库,适合大规模、高性能、多索引场景
  • Qdrant:Rust 实现,性能好,过滤能力强
  • Weaviate:支持 GraphQL 和 AI 模块,集成能力强
  • Pinecone:托管型云向量数据库,少运维,适合生产快速接入

FAISS:

FAISS 全称是 Facebook AI Similarity Search,本质上更像是一个本地向量检索库 / 向量索引库,不是完整的数据库服务。

FAISS 负责:

  • 存储向量索引
  • 构建相似性搜索结构
  • 根据查询向量返回最相似的向量

FAISS 不负责完整数据库能力:

  • 没有独立服务端
  • 没有用户权限系统
  • 不主打分布式和高可用
  • 元数据管理要依赖框架补充

LangChain + FAISS 示例理解:

02_langchain_faiss.py 的流程:

文本列表
→ Document
→ HuggingFaceEmbeddings 编码成向量
→ FAISS.from_documents 建本地向量索引
→ save_local 保存到本地
→ load_local 重新加载
→ similarity_search 查询 Top-K

跑完后生成了两个文件:

faiss_index_store/
  index.faiss
  index.pkl

两个文件的作用:

  • index.faiss:FAISS 的核心向量索引文件,负责相似性搜索
  • index.pkl:LangChain 保存的文档映射和元数据,用来把向量 id 找回原始文本

LlamaIndex 本地索引示例理解:

03_llamaindex_vector.py 的流程:

文本列表
→ LlamaIndex Document
→ HuggingFaceEmbedding 编码
→ VectorStoreIndex 建索引
→ persist 保存到本地 JSON
→ StorageContext 加载
→ load_index_from_storage 恢复索引
→ retriever.retrieve 查询

LlamaIndex 持久化后生成的是更透明的 JSON 文件,例如:

  • docstore.json:保存原始文档 / 节点内容
  • default__vector_store.json:保存向量和向量对应的节点 id
  • index_store.json:保存索引结构信息
  • graph_store.json:图关系信息,简单例子里可能很少

和 FAISS 的区别:

FAISS:核心文件是二进制索引,更偏底层相似性搜索
LlamaIndex:持久化结构更透明,更偏 RAG 数据层和索引管理

3.2 milvus

Milvus 是一个开源的生产级向量数据库,用来做大规模向量相似性搜索。它最早由 Zilliz 发起,现在是 LF AI & Data Foundation 的顶级项目。

和 FAISS 的区别:

FAISS:本地向量检索库,适合学习和原型
Milvus:完整向量数据库服务,适合生产和大规模场景

Milvus 更像传统数据库系统:

  • 有服务端
  • 有 Collection
  • 有 Schema
  • 有索引
  • 有数据持久化
  • 有客户端 SDK
  • 可以用 Attu 可视化

Milvus 核心概念:

  1. Collection

    • 类似关系型数据库里的表
    • 是存储向量和元数据的顶层容器
  2. Entity

    • Collection 里的一条数据
    • 类似表里的一行记录
  3. Field

    • Entity 里的字段
  4. Schema

    • Collection 的结构定义
    • 决定有哪些字段、字段类型、向量维度、主键等
  5. Partition

    • Collection 内部的逻辑分区
    • 可以按业务规则把数据分区,比如年份、类别、租户
    • 查询时只查部分分区,可以缩小搜索范围
  6. Alias

    • Collection 的别名
    • 常用于线上平滑切换

Milvus 索引:

Milvus 的索引是为了加速向量搜索。

常见向量索引:

  1. FLAT

    • 暴力搜索
    • 结果最准确
    • 数据量大时慢
    • 适合小数据、追求 100% 召回
  2. IVF

    • 先把向量聚类成多个桶
    • 查询时只查最可能相关的几个桶
    • 速度更快,但召回率不是绝对 100%
    • 适合大规模通用检索
  3. HNSW

    • 基于图的索引
    • 通过多层邻近图快速找到相似区域
    • 查询速度快,召回率高
    • 内存占用相对大
  4. DiskANN

    • 面向磁盘 / SSD 的大规模索引
    • 适合数据量大到无法完全放入内存的场景

HNSW 参数:

index_params.add_index(
    field_name="vector",
    index_type="HNSW",
    metric_type="COSINE",
    params={"M": 16, "efConstruction": 256}
)

含义:

  • field_name="vector":给 vector 字段建索引
  • index_type="HNSW":使用 HNSW 图索引
  • metric_type="COSINE":用余弦相似度衡量语义接近程度
  • M:图中每个节点的最大连接数,越大可能召回越好,但更占内存
  • efConstruction:建索引时搜索范围,越大索引质量可能越好,但构建更慢

查询时:

search_params={"metric_type": "COSINE", "params": {"ef": 128}}
  • ef:查询时的搜索范围,越大召回可能越高,但查询更慢

Milvus 检索类型:

  1. 基础 ANN Search

    • 输入查询向量
    • 返回最相似的 Top-K Entity
  2. 过滤检索

    • 向量相似度 + 标量字段条件
    • 例子:只查某个分类、某个年份、某个价格范围的数据
  3. 范围检索

    • 不是固定 Top-K,而是返回相似度在某个范围内的数据
  4. 多向量混合检索

    • 同时查多个向量字段
    • 例子:文本向量 + 图片向量 + 稀疏关键词向量
    • 再用 reranker 做结果融合
  5. 分组检索

    • 按某个字段分组,避免结果都来自同一个来源
    • 适合文档检索时控制结果多样性

多模态 Milvus 示例流程:

04_multi_milvus.py 完整跑通的链路:

启动 Milvus Docker 服务
→ 加载 Visualized-BGE 多模态 Embedding 模型
→ 连接 Milvus: http://localhost:19530
→ 创建 Collection: multimodal_demo
→ 定义 Schema: id / vector / image_path
→ 遍历 dragon 图片
→ 每张图片编码成 768 维向量
→ 插入 Milvus
→ 给 vector 字段创建 HNSW + COSINE 索引
→ load_collection 加载到内存
→ 用 query 图片 + 文本“一条龙”编码成查询向量
→ search 返回 Top-5 相似图片
→ 根据 image_path 找回原图
→ 生成 search_result.png

这个过程说明:

Visualized-BGE 负责理解图文语义
Milvus 负责存储向量和路径
HNSW 负责加速相似性搜索
image_path 负责把检索结果映射回原始图片

4、索引优化

索引优化解决的是:基础向量检索已经能用了,但怎么让它查得更准、上下文更完整、范围更可控。

前面普通 RAG 的流程是:

文档切块
→ Chunk 向量化
→ 向量数据库 Top-K 检索
→ 把召回内容交给 LLM

这个流程能跑,但会遇到几个问题:

  • Chunk 太小:检索很准,但上下文不够,LLM 可能答不完整
  • Chunk 太大:上下文够,但里面噪声也多,检索不够精准
  • 知识库太大:全库 Top-K 容易被无关文档干扰
  • 数据有结构:PDF 页码、Markdown 标题、Excel sheet、年份、标签等信息没有被充分利用

所以索引优化的目标不是“再换一个向量库”,而是优化:

怎么切
怎么索引
怎么过滤
怎么扩展上下文
怎么路由到正确数据源

4.1 句子窗口索引

句子窗口索引解决的是:

小块检索准,但上下文不够
大块上下文够,但检索不够准

它的核心思想是:

为检索精确性而索引小块
为生成质量而提供大上下文

也就是:

  • 检索时用“单句”做向量匹配
  • 生成时不用孤立单句,而是把该句前后窗口一起交给 LLM

适合场景:

  • 纯文本
  • 长 PDF
  • 连续性强的文档
  • 段落语义依赖前后文的资料
  • 用户问题往往能命中某一句,但回答需要结合上下文

例如气候报告、论文、说明文档、政策文件等。

流程:

原始文档
→ 按句子切分
→ 每个句子变成一个 TextNode
→ 每个句子单独做向量索引
→ metadata 里保存前后 N 个句子的 window
→ 查询时先命中最相关句子
→ 后处理器把单句替换成 window 上下文
→ LLM 根据窗口上下文生成答案
关键组件:
  1. SentenceWindowNodeParser

    • 把文档切成一句一句
    • 每个句子作为一个 Node
    • 给每个 Node 的 metadata 存入前后窗口
  2. window_size

    • 控制前后取多少句
    • 示例里是 window_size=3
    • 表示命中句子的前 3 句和后 3 句也会作为窗口上下文
  3. window_metadata_key

    • 窗口上下文存在 metadata 的哪个 key 里
    • 示例里是 window_metadata_key="window"
  4. original_text_metadata_key

    • 保存原始单句文本
    • 示例里是 original_text_metadata_key="original_text"
  5. MetadataReplacementPostProcessor

    • 检索出来的是单句 Node
    • 后处理时读取 Node 的 window metadata
    • 用完整窗口替换原来的单句内容
    • 最后交给 LLM 的不是孤立句子,而是一段上下文

一个重要细节:

句子窗口索引不是把整个 window 拿去做 embedding。

它是:

embedding 时:只嵌入单句
生成时:替换成 window 上下文

这样才能同时保证:

  • 检索精确:因为向量对应的是一句话
  • 回答完整:因为 LLM 看到的是前后窗口

和常规分块索引的对比:

常规分块索引:

文档 → 按 chunk_size 切块 → 每个 chunk 做向量索引 → 直接把 chunk 给 LLM

句子窗口索引:

文档 → 按句子切 → 每句做向量索引 → 命中后替换成前后窗口 → 给 LLM

常规索引简单直接,但 chunk 大小不好拿捏。句子窗口索引更细,适合需要“精准定位 + 补上下文”的场景。

4.2 结构化索引 / 元数据索引

结构化索引解决的是另一个问题:

知识库很大,或者数据本身有结构时,不应该全库无差别 Top-K 搜索

如果一个问题只和某个年份、某个章节、某个 sheet、某个文件相关,应该先缩小范围,再做向量检索。

适合场景:

  • PDF:页码、章节、标题、作者、年份
  • Markdown:一级标题、二级标题、文档路径
  • Excel:sheet 名、年份、表格类别
  • 多文档知识库:文件名、数据源、部门、日期、标签
  • 企业知识库:权限、租户、产品线、业务分类

注意:不是说 PDF / Markdown / Excel 只能用结构化索引。
同一个 PDF 也可以做句子窗口索引。关键在于:有没有结构化 metadata 可以利用。

核心思想:

先用 metadata 缩小范围
再在小范围内做向量检索

例子:

问题:请总结 2023 年 Q2 财报中关于 AI 的论述

可以先过滤:

document_type == 财报
year == 2023
quarter == Q2

然后只在这个范围内搜索“AI 的论述”。

这比全库 Top-K 更准,也更快。

Metadata 的作用:

metadata 可以理解为给每个文本块或文档打标签。

常见 metadata:

  • 文件名
  • 页码
  • 章节标题
  • 作者
  • 创建时间
  • 年份
  • sheet 名
  • 分类标签
  • 数据来源

这些信息本身不一定参与向量语义匹配,但可以用于过滤、路由和结果解释。

4.3 递归检索

递归检索是结构化索引的一种更复杂形式。

它解决的是:

数据分散在多个来源里,系统要先判断该去哪里查,再在对应来源中查具体内容

它更像“先路由,再查询”。

递归检索的思想:

用户问题
→ 顶层索引判断该进入哪个子数据源
→ 找到对应的子查询引擎 / 子索引
→ 在子数据源内部继续检索或查询
→ 返回最终答案

我的理解:

句子窗口索引和结构化索引解决的是两个不同问题:

句子窗口索引:解决上下文粒度问题
结构化索引:解决检索范围和数据路由问题

句子窗口索引适合连续文本:

先命中最相关句子,再扩展前后上下文

结构化索引适合有属性、有标签、有来源的数据:

先根据 metadata 定位范围,再在范围内检索

两者不是互斥的。生产 RAG 里完全可以结合:

先用 metadata 过滤到某个文档/章节
再在这个文档/章节内部做句子窗口检索

这样既能控制范围,又能保证上下文完整。

5、总结

5.1 Embedding

Embedding 是 RAG 检索的语义基础。

关键理解:

  • 向量是语义坐标
  • 语义相近,向量距离更近
  • 文档和查询必须使用同一个或兼容的 Embedding 模型
  • 检索模型通常通过对比学习等方式,让 query 和相关文档靠近
  • 多模态 Embedding 的重点是跨模态对齐,不是简单各自转向量

5.2 向量数据库

向量数据库不是理解语义的地方。

它负责:

  • 存向量
  • 存元数据
  • 建索引
  • 做相似性搜索
  • 返回 Top-K

5.3 索引优化

索引优化不是换模型,而是改变“怎么组织知识”。

句子窗口索引:

检索用小粒度单句
生成用大粒度窗口上下文

结构化索引:

先根据 metadata 缩小范围
再做向量检索或问答

递归检索:

先路由到正确数据源
再进入子数据源查询

最终目标都是:

  • 查得准
  • 上下文够
  • 范围可控
  • 噪声更少
  • 结果更适合给 LLM 生成答案

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐