RAG 与向量数据库是如何工作的:从图书馆比喻到系统架构

RAG 与向量数据库是如何工作的:从图书馆比喻到系统架构

本文也是分 4 个层级,从直觉讲起,一步步走到架构和一点点数学:

  • RAG(Retrieval-Augmented Generation)是什么
  • 向量数据库怎么存、怎么查
  • 检索结果如何合并进 Prompt
  • RAG 在理论上如何刻画为"检索 + 生成"的组合模型

Level 1:非技术直觉版------"图书馆 + 聪明翻译官"

先用一个生活类比:

  • 大语言模型(LLM) :一个很会写的"翻译官",有很多常识和语言能力,但不了解你公司内部的私有文档
  • 向量数据库 :一个超级图书馆 + 语义搜索引擎,可以在成千上万份文档里,翻出最相关的几段内容

当你问一个问题时,RAG 做的事是:

  1. 先把你的问题拿去"图书馆"搜索,找出最相关的几段资料
  2. 再把:
    • 这些资料 + 你的问题
    • 一起交给大模型;
  3. 大模型一边看"资料",一边组织语言给你答案。

一句话理解:
RAG = 先查资料,再参考资料来回答问题。


Level 2:工程师视角------一条完整的 RAG 流水线

这一层从"写代码的角度"走一遍典型 RAG 流程。

Step 1:预处理 & 向量化(离线阶段)

对你的知识库文档做预处理,一般包含三步:

  1. 切块(chunking)

    • 将长文档拆成较小的段落(比如每段 200~500 字)。
    • 每个 chunk 会被当成一条"可检索单元"。
  2. 向量化(embedding)

    • 使用 embedding 模型将每个 chunk 映射到一个向量:
      chunki  ⟶  vi∈Rd \text{chunk}_i \;\longrightarrow\; \mathbf{v}_i \in \mathbb{R}^d chunki⟶vi∈Rd
    • 这个向量可以理解为:这段文本在语义空间中的坐标
  3. 存入向量数据库

    • 向量库中记录的通常包括:
      • 向量 vi\mathbf{v}_ivi
      • 原始文本内容
      • 元数据:来源文件、页码、更新时间、标签等

Step 2:用户提问 → 向量检索 Top-k

当用户提一个问题 q 时:

  1. 对问题做 embedding:

    q  ⟶  vq q \;\longrightarrow\; \mathbf{v}_q q⟶vq

  2. 向量检索:在向量数据库中查找与 vq\mathbf{v}_qvq 最相似的向量

    伪代码示例:

    复制代码
    v_q = embed(query)
    results = vector_db.search(v_q, top_k = k)
    • 相似度常用:
      • 余弦相似度(cosine similarity)
      • L2 距离(欧氏距离)
      • 内积(inner product)
  3. 返回结果通常包含:

    • 文本片段(chunk 内容)
    • 相似度分数
    • 元数据(标题、文档名、页码等)

这一步就是:在语义空间中找到"最像这个问题"的几个段落。


Step 3:构造 Prompt ------ 合并检索结果 + 问题

拿到检索出的 Top-k chunks 后,需要构造一个完整的 Prompt 喂给 LLM,例如:

你是一个知识库问答助手。

下面是与问题相关的资料片段(可能存在冗余或冲突):

片段1 - 来自文件 A 第 3 页

...

片段2 - 来自文件 B 第 10 页

...

片段3 - 来自文件 A 第 4 页

...

请严格依据以上资料回答下列问题,如资料中没有答案,请说明"资料不足":

问题:{用户的问题}

实践中通常还会:

  • 合并相邻的 chunk(减少上下文碎片)
  • 去重、去明显重复的信息
  • 按相关度排序,限制总 token 长度

Step 4:LLM 带着"参考资料"生成回答

最后,把构造好的 Prompt 发给大模型:

复制代码
   answer = LLM(prompt_with_context)
  • LLM 在生成时,一边"看"你给的资料,一边利用自身的语言组织能力输出答案。
  • 回答质量取决于:
    • 检索结果是否覆盖了真正需要的信息;
    • Prompt 设计是否清晰、约束是否合理;
    • 模型自身能力。

一个基础版 RAG 系统的主流程可以概括为:

Query → Embedding → Vector Search → Top-k → Prompt 构造 → LLM 生成


Level 3:向量数据库内部的检索机制 & 结果融合策略

这一层更偏"系统 / 算法"视角,关注向量库如何高效检索以及如何优化检索结果。

向量检索:从暴力搜索到近似最近邻(ANN)

假设你有 NNN 条向量,每条是 ddd 维:

  • 暴力搜索(Brute Force)

    对每一条向量 vi\mathbf{v}_ivi 计算一次相似度,复杂度 O(Nd)O(Nd)O(Nd)。

    当 NNN 很大(百万级以上)时,速度会很慢。

  • 向量数据库一般使用 近似最近邻搜索(Approximate Nearest Neighbor, ANN)

    • 图结构:HNSW(Hierarchical Navigable Small World)
    • 基于聚类的倒排索引:IVF
    • 压缩技术:PQ / OPQ(Product Quantization)等

这些方法的目标是:

在可接受的时间和内存下,快速找到"足够接近真实最近邻"的向量,而不追求严格的精确最优。


相似度度量:语义空间中的"距离"

向量库中常见的相似度 / 距离度量:

  • 余弦相似度

    cos(u,v)=u⋅v∥u∥ ∥v∥ \mathrm{cos}(u, v) = \frac{u \cdot v}{\lVert u \rVert \,\lVert v \rVert} cos(u,v)=∥u∥∥v∥u⋅v

  • 欧氏距离(L2)

    ∥u−v∥2 \lVert u - v \rVert_2 ∥u−v∥2

  • 内积(Inner Product) 等。

embedding 模型训练时,会让:

  • 语义相近的文本 → 向量更接近(夹角更小、欧氏距离更小)
  • 语义无关的文本 → 向量更远

因此,向量相似度就可以作为"语义相关度"的近似。


结果融合:不仅仅是"Top-k 拼一块"

实际项目里,你往往会对检索结果做进一步处理:

  1. 重排(Re-ranking)

    • 第一步:用向量库快速找出 Top-50
    • 第二步:用更复杂的模型(如 cross-encoder)对这 50 条进行精细打分,再选 Top-5
      → 兼顾速度和精度。
  2. MMR(Maximal Marginal Relevance)

    • 目标:在保持高相关度的前提下,避免多个 chunk 内容高度重复;
    • 让最终选出的片段既相关又"多样"。
  3. 按元数据过滤 / 加权

    • 只检索某个时间范围(例如最近 1 年);
    • 只检索特定标签(某个项目 / 客户);
    • 权重更高的文档优先展示。

合并进 Prompt:要考虑上下文预算

模型上下文长度是有限的(例如 8k / 32k / 128k tokens),因此需要设计策略:

  • 对每个 chunk 估算 token 数,避免超过上限;
  • 可以按"相关度降序 + 去重"逐个添加,直到接近 token 上限;
  • 按来源分组,例如:

合同文本相关片段

chunk 1\]... \[chunk 2\]... # 邮件记录相关片段 \[chunk 3\]...

这一步看似是"工程细节",但对实际问答效果影响极大。


Level 4:从建模视角看 RAG------"检索 + 生成"的组合模型

最后一层从"理论 / 抽象"角度看 RAG,帮助你对整体形成更高层的理解。

普通 LLM vs RAG:隐式知识 vs 显式知识

  • 普通 LLM:

    • 训练阶段读过海量语料;

    • 最终把这些知识"压缩"到了参数 θ\thetaθ 里(隐式知识);

    • 推理时执行:

      y∼pθ(y∣x) y \sim p_\theta(y \mid x) y∼pθ(y∣x)

      完全不访问外部知识库。

  • RAG 模型:

    • 知识放在一个外部库 DDD 中(文档、数据库等);

    • 推理时,会先根据 query 做一次检索,得到上下文 C(q,D)C(q, D)C(q,D),再生成:

      y∼pθ(y∣q,C(q,D)) y \sim p_\theta(y \mid q, C(q, D)) y∼pθ(y∣q,C(q,D))

这样做的好处:

  • 可以随时更新知识库,而不用改模型参数;
  • 可以把隐私 / 最新信息放在库里,由权限、访问控制来管理;
  • 易于审计模型"依据了哪些资料"给出结论。

RAG 中的"检索器"和"生成器"

将 RAG 抽象成两个组件:

  1. 检索器(Retriever)

    C(q,D)=Retrieve(q;D) C(q, D) = \mathrm{Retrieve}(q; D) C(q,D)=Retrieve(q;D)

    • 输入:query qqq 和文档库 DDD
    • 输出:一组与 qqq 相关的文档片段(可以是集合、加权集合等)
  2. 生成器(Generator)

    y∼pθ(y∣q,C(q,D)) y \sim p_\theta(y \mid q, C(q, D)) y∼pθ(y∣q,C(q,D))

在高级用法中,检索器本身也是可学习的:

例如用强化学习或梯度信号,训练检索器让"被选出的文档集合"对最终任务(准确回答、任务成功率)最有帮助。


向量数据库 = 一个高效实现"近似 argmax"的系统

本质上,向量检索就是在做:

Retrieve(q;D)=arg⁡max⁡d∈Dsim(f(q),f(d)) \mathrm{Retrieve}(q; D) = \arg\max_{d \in D} \mathrm{sim}\bigl(f(q), f(d)\bigr) Retrieve(q;D)=argd∈Dmaxsim(f(q),f(d))

其中:

  • f(⋅)f(\cdot)f(⋅):将文本映射到向量的 embedding 模型;
  • sim\mathrm{sim}sim:相似度函数(余弦、内积、负 L2 等)。

向量数据库的作用就是:

在 NNN 很大时,依靠精心设计的数据结构(HNSW、IVF、PQ 等),
高效近似地求解这个最大化问题


多轮 / Agent 化:RAG 的进阶形态

在复杂应用中,RAG 还可以继续进化,例如:

  1. 多轮迭代检索(Iterative RAG)

    • 第一次检索给出初步结果;
    • LLM 读完后发现"不够",自动生成新的子问题再检索;
    • 重复多轮,逐步聚焦到真正需要的资料。
  2. 工具化 / Agent 化

    • 模型不只"被动接受"检索结果,而是能:
      • 决定何时发起检索;
      • 决定从哪个知识源检索(合同库、邮件库、代码库等);
      • 决定使用什么过滤条件;
    • 每一次检索结果都作为新一轮思考的上下文。

小结

  • RAG 的核心思想: 把知识存放在外部可更新的库中,模型推理时先检索、再生成
  • 向量数据库 提供了在"语义空间"中高效搜索相关文本片段的能力,是 RAG 的基础设施。
  • 从流程上看:
    文档切块 → 向量化 → 入库 → Query 向量化 → 相似度检索 → 合并结果进 Prompt → LLM 生成
  • 从建模上看:
    RAG 是一个显式的 "检索器 + 生成器" 组合模型,
    可以让模型在不改参数的情况下,使用最新、私有、可控的知识。
相关推荐
爬山算法1 小时前
Redis(160)Redis的安全问题如何解决?
数据库·redis·安全
可可苏饼干1 小时前
MySQL 索引
运维·数据库·学习·mysql
落日漫游1 小时前
Redis集群与MySQL的对比
数据库·redis·mysql
我是海浪1 小时前
DB2数据库:批量导入(Import)导出(Export)加载(Load)
数据库
霸王大陆1 小时前
《零基础学PHP:从入门到实战》教程-模块七:MySQL 数据库基础-4
数据库·mysql·php
i小白1 小时前
Sql Server 大批量数据迁移
服务器·数据库
Leon-Ning Liu1 小时前
【系列实验一】Oracle 19c RAC 安装(4个节点)
数据库·oracle
xuanloyer1 小时前
oracle从入门到精通--oracle体系结构
数据库·oracle
生产队队长1 小时前
Database:Linux环境中的Oracle修改密码
linux·数据库·oracle