⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议。
跳转到正文

I2:向量数据库与 RAG

Easy Data x AI 课程 · 产业应用篇 · 第 2 节

本节定位

本节聚焦向量数据库与 RAG 的原理、工程选择和评测方法。D2 已带你完成切分、向量化和混合搜索,D3 已展示 Agentic RAG 的完整代码;本节回答这些实践背后的“为什么”。

学习目标

完成本节后,你将能够:

  1. 解释 Embedding 如何把非结构化内容转换为可比较的向量;
  2. 根据数据与模型特征选择余弦相似度、点积或欧氏距离;
  3. 说明 KNN、ANN、HNSW、IVF 和量化索引的核心权衡;
  4. 设计包含正文、向量、来源、权限和业务字段的 RAG 数据模型;
  5. 区分向量召回、关键词召回、标量过滤、融合与重排的职责;
  6. 使用 Recall@K、MRR、nDCG、延迟和成本评估检索系统;
  7. 判断场景更适合专用向量数据库,还是在现有数据库中扩展向量能力。

1. 从“不可比较”到“可计算”

传统数据库擅长处理有明确类型和结构的数据。数字可以比较大小,日期可以计算区间,字符串可以精确匹配,关系表可以连接与聚合。

但图片、音频、视频和自然语言文档本身没有天然的“相似度运算”:

  • 两张图片的二进制差异很大,不代表画面内容不相似;
  • “如何重置数据库密码”和“忘记口令后怎样恢复访问”几乎没有共同词,却可能表达同一个意图;
  • 一段音频即使经过压缩或改变采样率,人仍然可能认为它们内容相同。

结构化、半结构化与非结构化数据的分类,以及常见存储方式

Embedding 模型改变了这一点。它把文本、图片、音频等对象转换为固定维度的数值向量,使“内容是否相似”近似转化为“向量在高维空间中是否接近”。

text
原始内容 → Embedding 模型 → 高维向量 → 距离/相似度计算

大模型和嵌入模型将多模态数据转换为数据库可处理的数据表示

这并不意味着向量理解了内容的全部含义。更准确地说,向量是模型依据训练目标提取的一组潜在特征表示。

2. Embedding:语义的数值表示

一个 4 维向量可以写作:

x=[0.12,0.31,0.87,0.05]

生产中的文本向量通常有数百到数千个维度。每个维度一般没有稳定、可供人类直接解释的名称,但整个向量共同编码了模型认为重要的特征。

用毛长和体型两个维度直观展示对象在向量空间中的位置与距离

2.1 同一空间是比较的前提

只有由兼容模型、相同版本和相同编码方式生成的向量,距离才通常具有可比性。以下做法会破坏检索:

  • 文档使用模型 A,查询使用模型 B;
  • 模型升级后只重算新数据,没有重算历史数据;
  • 模型要求区分 query 与 document 输入,却对两者使用同一种提示格式;
  • 文本预处理、截断或归一化规则在写入与查询阶段不一致;
  • 向量维度与索引定义不匹配。

因此,向量旁边至少应记录:

字段作用
embedding_model标识模型或逻辑模型名
embedding_version支持升级、回滚和重建
embedding_dim防止维度不一致
content_hash判断原文是否变化、是否需要重算
embedded_at追踪生成时间和数据新鲜度

2.2 向量不是事实本身

向量适合做候选召回,却不适合作为唯一证据:

  • 它不可直接还原为完整原文;
  • 距离分数不是事实正确性的概率;
  • 相似内容可能已经过期或无权访问;
  • 模型可能没有学习到业务中的关键区分。

因此,RAG 应同时保存原文、来源、版本、权限和结构化元数据。向量负责“找到候选”,原文负责“提供证据”。

3. 距离与相似度:到底在比较什么?

选择距离函数不能只看数据库支持什么,还要与 Embedding 模型的训练方式匹配。常见的三种度量是欧氏距离、余弦相似度和点积。

3.1 欧氏距离(L2)

dL2(x,y)=i=1n(xiyi)2

L2 衡量两个点的绝对空间距离,值越小越相似。它既受方向影响,也受向量长度影响,适合关注绝对数值差异,或模型明确以 L2 距离训练和评测的场景。

3.2 余弦相似度

cos(x,y)=xyx2y2

余弦相似度关注方向,弱化向量长度。结果通常位于 [1,1],值越大越相似。它常用于文本语义检索,因为文本长度或向量模长不一定是我们想比较的信号。

3.3 点积(Inner Product)

IP(x,y)=i=1nxiyi

点积同时受方向和模长影响,值越大通常表示越相似。若向量已经做 L2 归一化,则点积与余弦相似度等价:

x2=y2=1xy=cos(x,y)

3.4 如何选择?

情况优先选择
模型文档明确指定距离函数严格跟随模型说明
向量已归一化,关注方向余弦相似度或点积
向量模长本身含有信息点积或 L2,结合模型定义
比较二值特征汉明距离或 Jaccard 距离
不确定用标注查询集对不同度量做离线评测

分数阈值不能跨模型照搬

“相似度大于 0.8 就算相关”不是通用规律。分数分布会随模型、语料、语言、距离函数和是否归一化而变化,阈值必须用当前业务数据校准。

4. 最近邻搜索:从精确到近似

给定查询向量,在数据集中寻找最相似的 K 个向量,称为 K 近邻搜索(KNN)。

4.1 精确 KNN

最直接的方法是计算查询与每条向量的距离,再取 Top-K:

text
for vector in dataset:
    score = distance(query, vector)
sort scores
return top_k

它结果精确、逻辑简单,但时间开销随数据量和维度增长。对小数据集、严格精确查询或索引尚未建立的场景,暴力扫描仍然是重要基线。

4.2 近似最近邻(ANN)

ANN 索引不再检查所有向量,而是利用图、聚类或量化结构缩小搜索空间,用少量召回损失换取明显的延迟和吞吐收益。

这带来向量检索最核心的三角权衡:

目标含义
召回率近似结果覆盖精确 Top-K 的比例
延迟/吞吐单次查询耗时与单位时间查询量
资源成本内存、磁盘、索引构建与维护成本

不存在在所有数据规模和负载下都最优的索引。选择索引,本质是在业务约束下选择可接受的近似程度。

5. 常见向量索引

5.1 HNSW:在多层小世界图上导航

HNSW(Hierarchical Navigable Small World)把向量组织成多层邻接图:

  1. 上层节点少,用于快速跳到大致区域;
  2. 搜索逐层下降,不断靠近查询向量;
  3. 底层更稠密,用于寻找最终候选。

常见参数及影响:

参数增大后的典型影响
M图连接更多,召回可能提高,但内存和构建成本增加
ef_construction建图搜索更充分,索引质量提高,但构建更慢
ef_search查询候选更多,召回提高,但查询更慢

HNSW 通常适合低延迟、高召回的内存型检索,但图结构会带来明显内存开销,持续写入和删除也需要评估维护成本。

5.2 IVF:先找分区,再搜分区

IVF(Inverted File Index)先把向量聚成若干中心:

  1. 建索引时将向量分配到最近的聚类中心;
  2. 查询时先找到最接近的若干中心;
  3. 只在对应分区中搜索候选。

nlist 表示聚类中心或分区数量,nprobe 表示查询时探测的分区数量。nprobe 越大,扫描范围越广,召回通常越高,延迟也越大。

IVF 适合较大规模、批量构建和内存受限场景,但数据分布变化后可能需要重新训练或重建索引。

5.3 量化:用精度换空间

量化通过更紧凑的表示减少存储和计算开销:

  • 标量量化(SQ):降低每个向量元素的精度;
  • 乘积量化(PQ):把向量切成子空间,用码本近似表示;
  • 二值量化(BQ):将向量压缩为二值表示。

量化适合大规模和内存敏感场景,但会引入额外近似误差。常见做法是用量化索引召回候选,再用原始向量精确重算候选分数。

5.4 索引选择速查

场景可优先评估
小数据集、要求精确暴力扫描 / 精确 KNN
中等规模、低延迟、高召回HNSW
大规模、可批量训练、内存受限IVF
超大规模、存储成本敏感IVF + PQ 或其他量化方案
持续高频写入重点评估增量维护、写入放大和索引可见性

索引名称相同也不代表实现、参数和性能相同。最终仍需在目标硬件与真实数据分布上测试。

6. 向量数据库到底存什么?

一个可用于生产 RAG 的数据对象不应只有 ID 和向量。更合理的数据模型包含四类信息:

类型示例用途
原始证据content、title、source_url生成答案和展示引用
向量embedding语义召回
业务元数据tenant_id、department、status权限与业务过滤
数据治理信息doc_version、chunk_no、content_hash更新、追踪、去重和重建

示意表结构如下,具体类型和索引语法以实际数据库为准:

sql
CREATE TABLE knowledge_chunks (
  chunk_id          BIGINT PRIMARY KEY,
  document_id       BIGINT NOT NULL,
  tenant_id         BIGINT NOT NULL,
  title             VARCHAR(512),
  content           TEXT NOT NULL,
  source_url        VARCHAR(2048),
  status            VARCHAR(32),
  document_version  VARCHAR(64),
  chunk_no          INT,
  content_hash      VARCHAR(128),
  embedding_model   VARCHAR(128),
  embedding_version VARCHAR(64),
  embedding         VECTOR(1024),
  updated_at        TIMESTAMP
);

查询也往往不是“全库找相似”,而是在业务条件内找相似:

sql
SELECT chunk_id, document_id, title, content,
       cosine_distance(embedding, :query_vector) AS distance
FROM knowledge_chunks
WHERE tenant_id = :tenant_id
  AND status = 'published'
ORDER BY distance APPROXIMATE
LIMIT 20;

向量回答“哪些内容与问题接近”,标量字段回答“哪些内容属于当前业务范围且允许访问”。

7. RAG:检索增强生成

RAG(Retrieval-Augmented Generation)在生成答案前,从外部知识库检索证据并放入模型上下文。它主要缓解三类问题:

  • 模型训练数据不包含企业私域知识;
  • 模型知识存在时间截止点,无法自动获取最新事实;
  • 仅依靠模型参数生成,答案难以追踪来源。

RAG 不是简单的“向量数据库 + 大模型”,而是两条相互关联的数据流水线。

7.1 离线入库流水线

text
数据源
  → 解析与清洗
  → 文档切分
  → 元数据与权限补全
  → Embedding
  → 写入正文、向量和索引
  → 质量检查

RAG 离线入库流程:文档切分、生成 Embedding 并写入向量存储

离线流水线需要保证幂等性。相同文档重复处理时,不应产生无法追踪的重复块;文档删除、更新、权限变化和模型升级都应有对应的数据维护策略。

7.2 在线查询流水线

text
用户问题
  → 查询理解或改写
  → 查询向量化
  → 多路候选召回
  → 权限与业务过滤
  → 融合与重排
  → 上下文组装
  → LLM 生成
  → 引用与答案验证

RAG 在线查询流程:问题经过相似性检索取得相关 Chunk,再交给大模型生成答案

如果最终答案错误,需要沿这条链路定位问题,而不是笼统地归因于“大模型效果不好”。

8. Chunking:切分决定可检索的最小单元

长文档不能直接无限量放入模型上下文,也不适合只生成一个覆盖全文的向量。RAG 通常先将文档切成 Chunk。

8.1 Chunk 太大或太小会怎样?

情况主要问题
太小语义不完整、上下文断裂、召回结果碎片化
太大向量主题混杂、相关信息被稀释、占用更多上下文
重叠过少关键语义可能被切在边界两侧
重叠过多索引膨胀、重复召回、上下文浪费

常见策略包括:

  • 按固定 Token 数切分并设置 overlap;
  • 按标题、段落、列表、代码块等文档结构切分;
  • 根据句子间语义变化寻找边界;
  • 使用父子 Chunk:小块负责召回,大块负责返回上下文。

8.2 保留文档结构

Chunk 入库时应保留:

  • 文档与父 Chunk 的标识;
  • 标题路径和章节层级;
  • 页码、段落号或代码行位置;
  • 原始来源与版本;
  • 权限和生效时间;
  • 前后邻接关系。

这样检索命中一个小块后,系统可以扩展相邻内容、恢复父级上下文,并生成可定位的引用。

与 D2 的边界

D2 提供固定切分、语义切分、动态 overlap 和父子 Chunk 的代码示例。本节强调这些策略如何影响召回、上下文质量与数据维护。

9. 纯向量检索为什么不够?

向量检索擅长语义近似,但真实业务还包含它不稳定处理的信号:

  • 错误码、订单号、型号和专有名词;
  • 必须严格满足的租户、权限、时间和状态条件;
  • 用户明确输入的关键词;
  • 最新版本优先、官方来源优先等业务规则。

因此,生产 RAG 通常会组合三类检索:

  1. 向量检索:寻找语义相近内容;
  2. 全文检索:捕捉关键词、短语和稀有词项;
  3. 标量过滤:执行权限、租户、状态、时间等硬约束。

9.1 标量过滤与向量检索的执行顺序

过滤条件的选择率会影响最佳执行方式:

策略过程适用情况风险
过滤后精确计算先过滤,再对剩余向量全量算分过滤后数据很少条件不够严格时延迟高
向量优先再过滤先召回较多候选,再做标量过滤过滤选择率高过滤后可能不足 K 条
过滤下推 ANN将允许集合下推到向量索引多种选择率与复杂权限实现和优化器更复杂

不同过滤选择率下,暴力计算、Bitmap 下推、表达式下推和 ANN 后过滤的执行计划

“先向量 Top-10,再过滤权限”尤其危险:不仅可能不足 10 条,还可能让无权限数据进入中间处理或日志。安全边界应尽可能在检索阶段生效。

9.2 全文与向量结果如何融合?

不同召回器分数的量纲不同,不能轻易直接相加。RRF(Reciprocal Rank Fusion)使用名次进行融合:

RRF(d)=rR1k+r(d)

其中 r(d) 是文档 d 在某个召回列表中的名次,k 是平滑常数。RRF 不要求向量距离与 BM25 分数可直接比较,是实用的融合基线。

若使用加权分数融合,应先校准或归一化各路分数,并通过验证集确定权重。

10. 重排与上下文组装

召回阶段追求“不要漏掉”,重排阶段追求“把真正相关的放到前面”。

10.1 为什么采用两阶段检索?

双编码 Embedding 模型可以分别计算查询和文档向量,文档向量可提前离线生成,因此适合从海量数据中快速召回。

Cross-Encoder 或重排模型通常让查询和候选共同参与计算,判断更细致,却无法为任意查询提前算好结果,成本更高。因此常见做法是:

text
海量数据
  → 低成本召回 50~200 条
  → 重排模型精排
  → 选取 5~20 条进入上下文

候选数量不是越多越好。它会同时影响召回率、重排成本、延迟和最终上下文噪声。

10.2 上下文组装不只是拼接

进入 LLM 前还应处理:

  • 相同文档或相邻 Chunk 去重;
  • 命中子块后扩展父块或邻接块;
  • 按文档、章节或时间恢复合理顺序;
  • 控制每个来源占用的 Token;
  • 保留来源、版本与定位信息;
  • 避免把检索到的文档指令当作系统指令执行。

最后一点属于 Prompt Injection 防护:知识库中的文本是不可信数据,不应拥有改变系统规则或调用工具的权限。

11. 如何评测向量检索与 RAG?

“随机问几个问题看起来不错”不能支撑生产发布。评测至少分为检索层、生成层和系统层。

11.1 构建评测集

每条评测数据可包含:

json
{
  "query": "如何恢复忘记的数据库密码?",
  "relevant_chunk_ids": ["doc-17#chunk-3", "doc-17#chunk-4"],
  "expected_answer": "……",
  "required_sources": ["doc-17"],
  "tenant_id": "tenant-a",
  "tags": ["权限", "改写问题", "版本敏感"]
}

评测集应覆盖高频问题、长尾问题、专有名词、错误码、跨段信息、无答案问题、权限隔离、时间敏感内容和对抗输入。

11.2 检索指标

Recall@K:所有相关文档中,有多少出现在前 K 条结果:

Recall@K=|TopKRelevant||Relevant|

Precision@K:前 K 条结果中,有多少是真正相关:

Precision@K=|TopKRelevant|K

MRR:关注第一个相关结果出现的位置:

MRR=1|Q|qQ1rankq

若相关性有“高度相关、部分相关、不相关”等等级,可以使用 nDCG@K 衡量排序质量。

11.3 生成指标

RAG 的最终答案还应评估:

  • 忠实度:结论是否由检索证据支持;
  • 答案相关性:是否直接回答用户问题;
  • 引用准确性:引用是否真的支持对应陈述;
  • 完整性:关键要点是否遗漏;
  • 拒答能力:没有证据时能否明确说明不知道。

11.4 系统指标

生产系统还需观察:

  • P50、P95、P99 延迟;
  • 查询吞吐和并发稳定性;
  • Embedding 与重排调用成本;
  • 索引构建时间和资源占用;
  • 写入后索引可见延迟;
  • 超时率、降级率与缓存命中率;
  • 不同租户和权限条件下的正确隔离。

性能数字必须带完整上下文

比较产品时至少记录数据集、向量维度、距离函数、索引参数、Recall 目标、并发、读写比例、硬件和数据是否在内存中。脱离这些条件的单个 QPS 或延迟数字没有可比性。

12. 专用向量数据库,还是数据库向量扩展?

业界大致有两条路线:

  1. 专用向量数据库:围绕向量存储、ANN 索引和分布式检索设计;
  2. 在现有数据库中扩展向量能力:把向量检索与原有事务、SQL、全文和标量查询结合。

12.1 选型维度

维度需要回答的问题
数据规模向量数量、维度和增长速度是多少?
查询负载QPS、并发、Top-K、延迟和 Recall 目标是什么?
写入负载批量导入还是持续更新?删除和更新是否频繁?
混合查询是否强依赖 SQL、全文、Join 和复杂过滤?
一致性写入后是否必须立即通过向量索引查询到?
多租户安全权限能否在检索阶段可靠下推?
部署云服务、专有云、本地、边缘还是嵌入式?
团队成本能否承担新增系统的同步、备份和运维?

12.2 什么时候优先评估专用系统?

  • 向量检索本身是核心负载,规模与吞吐非常高;
  • 需要某种专用索引、异构计算或成熟的向量生态;
  • 数据同步和权限治理已有可靠平台承接;
  • 团队能够独立运维额外的分布式系统。

12.3 什么时候优先评估统一数据库?

  • 业务数据与向量、全文和权限过滤紧密耦合;
  • 希望使用 SQL、事务、Join 和既有驱动生态;
  • 数据规模中等,更关注开发与运维复杂度;
  • 需要减少跨系统复制和一致性窗口;
  • 应用希望在嵌入式与服务器形态间迁移。

选择系统之前,先明确工作负载和验收指标;不要先选产品,再为产品寻找场景。

13. 贯穿案例:构建可评测的产品文档助手

假设我们为一个数据库产品构建文档助手,要求:

  • 回答安装、配置、错误码和版本兼容问题;
  • 只返回当前租户有权访问的内容;
  • 优先使用最新发布版本;
  • 答案必须带原文引用;
  • 新文档发布后能够在约定时间内被检索到。

13.1 入库设计

  1. 解析 Markdown、PDF 和网页,保留标题层级与来源位置;
  2. 按章节结构切分,代码块和步骤列表尽量保持完整;
  3. 为 Chunk 补充产品、版本、语言、状态和权限字段;
  4. 使用指定版本的 Embedding 模型生成向量;
  5. 幂等写入原文、向量、元数据与全文索引;
  6. 执行空内容、重复内容、维度和权限字段检查。

13.2 查询设计

面对“4.3 版本报错 OB-1234 怎么办?”:

  1. 保留 OB-1234 作为全文检索的精确词项;
  2. 将完整问题编码为查询向量;
  3. 下推租户权限、产品和版本过滤;
  4. 并行获得全文与向量候选;
  5. 使用 RRF 融合,再由重排模型精排;
  6. 扩展相邻步骤或父级章节;
  7. 将有限证据交给 LLM,并要求逐条引用来源;
  8. 若没有足够证据,返回明确拒答而不是猜测。

13.3 评测设计

为该场景建立至少四组对比:

实验目的
纯向量 vs 纯全文 vs 混合检索验证不同信号的互补性
不同 Chunk 大小与 overlap观察召回和上下文完整性
不同 HNSW ef_search观察 Recall 与延迟曲线
无重排 vs 有重排衡量质量收益是否覆盖成本

发布门槛不能只写“效果更好”,应写成可验证条件,例如:

  • Recall@10 不低于既有版本;
  • 权限测试零越权;
  • P95 检索延迟在预算内;
  • 引用准确率达到目标;
  • 新文档在约定索引可见时间内可检索。

14. 常见误区

误区一:向量数据库保存的是原始图片和文档

向量数据库的核心对象是向量及其元数据。原始大文件常保存在对象存储或文件系统中,数据库保存可检索表示、定位信息和必要正文。

误区二:相似度最高的内容就是正确答案

相似只表示模型空间中的接近程度,不代表内容权威、最新、有权限或能支持答案。

误区三:ANN 越快越好

只看延迟可能以牺牲召回为代价。必须在相同 Recall 目标下比较性能。

误区四:Top-K 越大,RAG 效果越好

过多候选会增加重排成本和上下文噪声,还可能让真正证据被淹没。Top-K 应通过评测确定。

误区五:更换 Embedding 模型只改一行配置

模型变化可能导致维度、向量空间和分数分布变化,通常需要版本化、全量重算、索引重建与回归评测。

误区六:RAG 可以彻底消除幻觉

RAG 提供外部证据,但检索可能漏召回,模型也可能误读或忽略证据。仍需引用、验证、拒答和持续评测。

15. 本节小结

本节可以浓缩为六句话:

  1. Embedding 把非结构化内容变成可进行相似度计算的向量;
  2. 距离函数必须与模型训练方式和向量归一化策略一致;
  3. ANN 用一定召回损失换取可扩展的检索性能;
  4. 生产 RAG 需要向量、全文、标量过滤、融合和重排共同工作;
  5. 检索质量、生成质量、延迟、成本和安全必须分别评测;
  6. 向量数据库选型应由真实工作负载决定,而不是由产品标签决定。

课后行动

选择一个不少于 30 篇文档的小型知识库,完成以下实验:

  1. 建立 20 条带相关文档标注的查询集;
  2. 分别运行纯向量、纯全文和混合检索;
  3. 统计 Recall@5、Recall@10 和 MRR;
  4. 调整一次 Chunk 大小和一次 ANN 查询参数;
  5. 记录质量、P95 延迟与候选数量的变化;
  6. 增加租户或版本过滤,验证结果中没有越权和过期内容;
  7. 输出一页实验结论,说明你会选择的检索链路及理由。

思考题

  1. 为什么同一批向量换一种距离函数后,排序可能完全不同?
  2. 精确 KNN 为什么仍然是 ANN 评测的重要基线?
  3. “先向量检索再做权限过滤”会产生哪些正确性和安全问题?
  4. 为什么 Embedding 模型升级通常需要重建历史向量?
  5. 检索 Recall 提升后,最终答案质量为什么可能没有同步提升?
  6. 你的场景中,专用向量数据库的收益是否足以覆盖新增系统成本?

与其他课程的关系

  • I1《AI 原生数据库基础》:建立统一数据、混合检索和事务能力的全景;
  • D2《AI 应用的数据层》:提供切分、Embedding 和混合搜索代码;
  • D3《Agentic RAG 实战》:将检索能力封装为 Agent 工具并完成评测;
  • I3《SQL × AI》:继续讨论 Embedding、重排和生成函数如何进入 SQL;
  • I8《案例场景和测评构建》:扩展产业案例与系统化测评方法。

参考资料

共建说明

欢迎在课程共建 Issue #91 中补充案例、实验、图示和评测方法。

Built with VitePress | GitHub 仓库