Agent大脑-RAG知识库

什么是RAG?为什么要做优化?

这张图画的是 RAG(检索增强生成) 的完整工作流程,说白了就是 "让 AI 先查资料再回答问题"。我用**"图书馆查资料写作业"**的比喻

一、建图书馆(上方流程,一次性准备工作)

复制代码
文档 → Split 切分 → Chunks 数据块 → Embedding 向量化 → 向量数据库
步骤 例子
文档(PDF、Excel、TXT) 你有一堆公司资料、产品手册、业务文档
Split 切分 把一本厚书撕成一张张小卡片(每张小卡片叫一个 Chunk)。切法有讲究:按固定字数切、按句子切、按段落主题切、按语义相似度切等等(图上方那一堆就是各种切分策略)
Embedding 向量化 给每张卡片拍一张 "语义身份证照"------ 把文字变成一串数字(向量),意思相近的卡片,数字也相近
向量数据库 把所有带身份证的卡片按 "意思相近" 分门别类存进图书馆,方便以后快速找

二、查资料回答(下方流程,用户每次提问时走的路)

复制代码
用户问题 → Embedding 向量化 → 去向量库检索(Retrieval) → 拿到相关片段(result)
                                                              ↓
                                    用户回答 ← LLM 大模型 ← 问题 + 检索到的资料
步骤 例子
用户问题 你问:"我们公司退货政策是什么?"
问题 Embedding 把你的问题也拍一张同样的语义身份证照
Retrieval 检索 拿着问题的身份证,去图书馆里找意思最接近的几张卡片
result 结果 找到了几张相关的资料片段
LLM 大模型 你的问题 + 找到的资料一起塞给 AI,让它 "参考这些资料,组织成通顺的话回答我"
Response 回答 AI 给出基于公司真实资料的回答

三、右边写的是这个 "朴素版 RAG" 的毛病

图右边列了 Naive RAG(朴素 RAG) 的三大痛点:

  1. 检索效率低、结果不准 ------ 找卡片找得慢,还经常找错
  2. 用户问题太抽象 / 概念模糊 ------ 你问得太笼统,AI 不知道该找哪张卡片
  3. 生成质量差、不忠于原文事实 ------ AI 拿着资料还瞎编,或者答非所问

1.索引优化

1.1摘要索引

正常思维:

直接把庞大的数据文档,然后直接切分导入一个向量数据库。但是检索时问题百出

摘要索引思想:

把庞大的数据文档,然后直接切分成Chunk,但是通过大模型把每一个Chunk的摘要(Summrary)提取出来。类似于存储当前原始文档块的核心思想。在把摘要存储的向量数据库(Embedding Model)中。

对比之前普通 Naive‑RAG:普通是把原始 chunk 文本做向量入库 ;摘要索引是给每个块先写摘要,拿摘要去做向量检索

建库阶段(预处理)

plaintext

复制代码
原始Document文档
    ↓切分
Chunk‑1、Chunk‑2、Chunk‑3(原始原文片段)
    ↓每个chunk交给大模型生成简短摘要
Summary‑1、Summary‑2、Summary‑3(每一块的浓缩简短概括)

👉两件存储:
1. **摘要Summary**:送去Embedding模型,转为向量,存入向量数据库Vector Store(用来做检索匹配)
2. **原始Chunk原文**:存到 DocumentStore 文档仓库,保存完整原文,不做向量

通俗比喻:

一本厚书,把每一页(Chunk)写一张内容小纸条摘要 (Summary)

  • 把所有小纸条拿去做向量,放到向量库,用来搜索。
  • 整本完整的书(原始 Chunk)另外放柜子 DocumentStore 保存。

用户提问查询阶段

  1. 用户问题 → 向量化,去向量库 Vector Store 检索,匹配的是【各个 chunk 的摘要向量】(不是原文!图中标注 1:检索文档段摘要)
  2. 向量库找到最匹配的摘要条目,拿到这个摘要对应的编号
  3. 根据编号,去DocumentStore柜子里,把对应的完整原始 Chunk 原文取出来(图中标注 2:召回原文档段)
  4. 原始完整原文塞进 Prompt,交给 LLM 去生成回答。

为什么要这么干?优点

  1. 摘要文字很短,去除冗余废话,语义更聚焦。用户问题容易匹配上,解决普通 RAG:原文 chunk 噪音多、检索不准的问题。

比如一大段代码 + 说明文字,原文噪音大;LLM 提炼摘要,只保留核心含义,向量匹配更准。

缺点(坑)

  1. 预处理成本高:每个 chunk 都要调用大模型生成摘要,耗 token、耗时间。
  2. 如果摘要写歪、漏关键信息 → 检索直接就找不到对应原文,摘要错全流程错。
  3. 检索拿到的是摘要,但是传给大模型回答依然用原始完整 chunk,不是摘要,不能拿摘要去回答,摘要只是 "搜索钥匙"。

和普通 Naive‑RAG 对比

普通 RAG 摘要索引 RAG
原始 chunk 直接 embedding 入库 chunk 先 LLM 生成摘要,摘要 embedding 入库
检索直接返回原始 chunk 检索匹配摘要,再通过摘要索引找回原始 chunk
适合短句、干净文本 适合长、噪音大、复杂文档

一句话总结: 摘要相当于 "目录小纸条",拿小纸条去搜索;搜到之后,再翻开真正的原文书页来回答用户。小纸条只用来搜,回答不用小纸条。

1.2假设性问题索引

通俗讲:拿文档块,让大模型猜 "用户会问什么问题",用猜出来的问题建向量库,不是拿原文建库

一、建库预处理流程(离线)

plaintext

复制代码
原始Document文档
    ↓切分
Chunk‑1、Chunk‑2、Chunk‑3 原始文本片段
    ↓送入LLM
让大模型阅读这一段文字,自动生成N个用户可能会问的假设问题 Question‑1、Question‑2...Question‑n
👉 两件存储:
1. 这些【生成出来的假设问题】拿去做Embedding,向量存入Vector Store向量库(检索用)
2. 原始的Chunk原文保存到 Documents Store,不做向量,只存原文,保留映射关系:假设问题 ↔ 对应原始chunk

Chunk 原文:DeepSeek公司成立于2023年7月17日 LLM 读完,自动生成一堆假设问题:

  • DeepSeek 公司什么时候成立?
  • DeepSeek 成立日期是?
  • 深度求索公司创立时间?

把上面这一堆问题做向量入库,而不是把 "DeepSeek 公司成立于 2023 年 7 月 17 日" 这句话入库。 原始的那段文字另外存起来。

二、用户线上查询流程

  1. 用户输入真实问题,做 Embedding 向量
  2. 去向量库,和一堆预先生成的假设问题向量做相似度匹配
  3. 找到相似度最高的那条假设问题,通过映射关系,取出它绑定的原始 Chunk 原文
  4. 将原始 chunk + 用户问题一起丢给 LLM,生成最终回答

为什么要这么做?解决什么痛点

普通 RAG 痛点:用户提问是问句,文档 chunk 是陈述句,句式不一样,向量相似度容易匹配不上

用户问:DeepSeek什么时候成立? 原文 chunk 是陈述句:DeepSeek公司成立于2023年7月17日 陈述句 vs 问句,文本句式差异大,向量容易算出来相似度低,检索漏召回。

这个方案的妙招: 向量库里存的全部都是问句!用户输入也是问句,句式对齐,向量更容易匹配上,召回率提升。

缺点(现实坑)

  1. 成本高:每一个 chunk 都调用 LLM 批量造问题,消耗大量 token,文档多的时候预处理很慢。
  2. LLM 会瞎编问题:生成出来的假设问题,有可能和原文无关,造成错误映射。
  3. 向量库体积膨胀:1 个 chunk 生成 5 个问题,向量库数量直接翻 5 倍,占用存储、检索速度变慢。

1.3元数据索引

前面几种:靠文本语义向量 找内容; 元数据索引:一部分条件走标签 / 属性过滤(类似数据库 where 条件),一部分走语义向量搜索,两者结合检索。

什么是元数据 metadata

每一段 Chunk 除了正文文本,额外带上一堆标签信息: {"author":"bar", "category":"报告", "time":"2026‑08", "source":"文档A"} 这些不属于正文内容,是描述文档的属性,就叫元数据

流程图完整流程(Self‑querying 自查询)

用户原始问题:What did bar say about foo(作者 bar 对于 foo 说了哪些内容)

  1. Query constructor(查询构造器,交给 LLM 处理) LLM 分析人类自然语言问题,自动拆成两部分:
  • 语义搜索关键词:foo → 用来做向量语义检索
  • 元数据过滤条件:eq("author","bar") 等价于 SQL where author = 'bar'

LLM 把人话,翻译成【向量搜索词 + 元数据过滤条件】

  1. 组装查询指令 search:"foo", where:{"author":"bar"}

  2. 送入 Vector Store 向量库执行 先过滤元数据:只保留 author=bar 的文档块,在过滤后的子集里面,再做向量语义相似度检索。

不是全库比对向量,先筛标签,再算向量,缩小搜索范围,减少噪音。

现实例子

文档库里面几百份文档,每条 chunk 附带元数据:{作者,部门,年份,文件类型}

用户提问:"2025 年研发部写的关于机器人机械臂的方案是什么?"

  • LLM 拆解: ①语义搜索词:机器人机械臂方案(向量匹配正文) ②元数据过滤条件:year=2025,department=研发部
  • 向量库先过滤:只留下 2025、研发部的 chunk,再在这批里面做语义检索。

✅优点

  1. 过滤掉大量无关文档,提升检索准确度,减少无关内容混入 Prompt。
  2. 区分「属性条件」和「文本语义」,适合多来源、多分类的知识库。
  3. 元数据过滤速度很快,不需要计算向量相似度,类似数据库查询。

❌缺点

  1. 入库阶段必须给每一条 chunk 补全元数据标签,没有标签就无法过滤。
  2. 依赖 LLM 解析用户问题生成 filter 条件,LLM 容易生成错误的过滤字段,导致查不到数据。
  3. 如果用户问题里面没有属性条件,就退化成普通向量检索。

2.查询优化

2.1查询优化-Enrich完善问题

多轮追问补全意图(RAG 前置对话补全流程)

普通 RAG 拿到用户一句话直接检索;这个流程是:大模型先判断用户提问信息够不够,信息缺就主动反问用户,循环收集信息,参数齐全之后,才去做 RAG 检索、输出答案。

完整流程图拆解

  1. 用户输入原始问题,交给 LLM 思考

LLM 思考三件事: ①这个问题信息完整吗? ②能不能直接拿去检索? ③我还缺哪些信息?

  1. 分支判断
  • 分支 A:信息完整充足 LLM 总结、重写用户的完整问题 → 进入 RAG 检索 → 生成答案返回给用户。

  • 分支 B:信息不完整,缺少关键参数 把缺失点整理成自然语言,向用户发起询问:

"你说的 XX,请问是指哪一个?还需要你补充 XX 信息" 用户看到提问,回复补充信息;回到最开头,形成循环。 循环 N 轮,直到参数全部补齐。

例子(机械臂场景)

知识库里面存机械臂操作文档。

用户输入:帮我抓取物体。

LLM 思考:信息不全!缺少:抓取哪个物体?目标坐标?夹持力度? → 反问用户:"请问抓取哪个物体?目标位置是多少?需要多大夹持力?"

用户回复补充:"抓取方块,坐标 x=0.3,y=0.2,力度 30N" 现在信息完整,LLM 整理完整问题,走 RAG 检索文档,输出操作方案。

现实价值(解决什么痛点)

普通 RAG 坑:用户说半句话,信息残缺,直接检索,召回一堆无关文档,答案错误。 这套机制就是:不强行猜用户意图,缺参数就主动问,多轮对话补齐条件再检索。

缺点

  1. 增加交互轮次,用户不能一次拿到结果;
  2. 需要维护对话上下文历史,LLM 要记住前面几轮的对话;
  3. 如果用户一直不给关键信息,会无限循环追问,需要设置最大循环次数上限。

2.2查询优化-Multi-Query多路召回

流程通俗拆解

plaintext

复制代码
原始用户问题
    ↓【问题改写】LLM生成多个不同表达方式的子问题
→ 用户问题1、用户问题2、用户问题3(同一个含义,换不同说法)
    ↓每一个子问题分别做【信息抽取】,各自独立去向量库检索
→ 拿到多组检索结果,做结果合并去重
    ↓把合并后的全部文档块送入LLM
生成最终答案

举例子

用户原始问题:机械臂怎么降低抖动?

LLM 做问题改写,一次性输出 3 个变体:

  1. 机械臂运行抖动如何处理
  2. 机械臂关节振动抑制方法
  3. 怎么减少机械臂运动过程震荡

三个问题分别向量化,分别检索向量库

  • 问题 1 可能命中 A 文档
  • 问题 2 可能命中 B 文档
  • 问题 3 可能命中 C 文档

把 A/B/C 全部收集、去重,合并成一份上下文,再交给大模型回答。

解决什么痛点

普通 RAG:只用用户原始一句话去检索。 用户提问表达方式,和文档里面的措辞不一样,向量相似度低,相关文档漏召回

用户说:"机械臂抖动怎么解决" 文档写:"关节振动抑制方案" 字面不一样,语义一样,直接检索很容易匹配不到。

✅多路改写:生成多种问法,多方向检索,把不同措辞的相关文档全部捞回来,提升召回率。

缺点

  1. 多次向量检索,耗时翻倍,生成 N 个问题就要执行 N 次检索;
  2. 检索结果会变多,很多冗余文档,必须做去重、过滤,不然上下文 token 暴涨;
  3. LLM 改写出来的子问题有可能跑偏,引入无关检索结果。

2.3查询优化-Decomposiyion问题分解

和上一节**多路问题改写 (Multi‑Query)**容易混淆:

  • Multi‑Query:同一个意思,换多种说法,语义等价,只是措辞改写。
  • Decomposition 问题分解:把一个复杂大问题,拆成多个逻辑独立的子问题,子问题之间有依赖关系

有两种执行模式:串行执行、并行执行

1、并行执行(下面那张图)

流程:

  1. 用户复杂大问题 → LLM 做问题分解,拆成 3 个独立子问题 1/2/3
  2. 三个子问题互不依赖,可以同时跑:每个子问题分别做检索、分别生成子答案
  3. 收集全部子答案,交给 LLM 做汇总融合,输出最终完整答案

示例 用户问题:机械臂型号A,最大负载多少?重复定位精度多少?供电电压是多少? 拆出 3 个子问题,三者互不依赖,并行分别检索,拿到三份结果,最后合并输出。

2、串行执行(上面那张图)

子问题有先后依赖,后一个子问题需要前一个子问题的结果作为输入,不能一起跑。

  1. 原始大问题拆解为子问题 1、子问题 2、子问题 3
  2. 先跑子问题 1:检索 + 生成子答案 1 3. 把子答案 1,塞到子问题 2 的 prompt 里面,再跑子问题 2,得到子答案 2 4. 把子答案 2 传入子问题 3,执行子问题 3
  3. 全部跑完,汇总得到最终答案

机械臂例子 用户提问:使用A机械臂,抓取方块,计算从起点到目标点的安全运动轨迹,并且给出避障参数。

  • 子问题 1:查询 A 机械臂运动学参数(得到关节限位、最大速度)
  • 子问题 2:依赖子问题 1 输出的参数,检索轨迹规划方案
  • 子问题 3:依赖子问题 2 轨迹结果,查询对应的避障配置参数 必须一步一步串行,后面任务要拿前面的输出。

✅优点

  1. 对付复杂复合型问题,大问题直接检索很难召回全部信息;拆成小问题,每个子问题针对性检索,效果更好。
  2. 串行适合有逻辑依赖的链式推理;并行适合互不相关的多查询,可以并发提速。

❌缺点

  1. 拆解出来子问题多,多次调用 RAG,token、耗时上升;
  2. 串行模式总耗时会累加;
  3. 如果前面子问题检索出错,错误会向后传递扩散(串行风险尤其大);
  4. LLM 拆解子问题可能拆错,漏关键点。

3.1Rerank重排序-RPF

两套 / 多套不同检索器返回的文档列表做融合重排序 。 典型组合:关键词检索(BM25) + 向量相似度检索

BM25 擅长字面关键词匹配;向量检索擅长语义匹配;两者各有优缺点,RRF 把两份结果合并,取长补短。

公式

  • \(rank_i(d)\):文档 d,在第 i 个检索器里面的排名,从 1 开始,第 1 名 rank=1,第 2 名 rank=2
  • k:平滑常数,工业界一般取 k=60,避免排名靠前的文档权重爆炸
  • 对同一个文档,在每个检索列表分别算分,全部累加得到总 RRF 分数;总分数越高,文档越优先

示例

两套检索结果

  1. 关键词检索:[doc1, doc2, doc3]
  2. 向量相似度检索:[doc1, doc3, doc4]

1)关键词检索计算(k=60)

  • doc1 rank=1 → \(1/(60+1)=1/61≈0.0164\)
  • doc2 rank=2 → \(1/(60+2)=1/62≈0.0161\)
  • doc3 rank=3 → \(1/(60+3)=1/63≈0.0159\)

2)向量检索计算

  • doc1 rank=1 → \(1/(60+1)=1/61≈0.0164\)
  • doc3 rank=2 → \(1/(60+2)=1/62≈0.0161\)
  • doc4 rank=3 → \(1/(60+3)=1/63≈0.0159\)

3)累加总分数

  • doc1:\(0.0164+0.0164=\boldsymbol{0.0328}\)(两套都排第一,总分最高,排最前面)
  • doc3:\(0.0159+0.0161=\boldsymbol{0.0320}\)
  • doc2:\(0.0161+0=\boldsymbol{0.0161}\)(仅关键词检索出现)
  • doc4:\(0+0.0159=\boldsymbol{0.0159}\)(仅向量检索出现)

✅融合之后最终排序:doc1 > doc3 > doc2 > doc4

核心思想:只要文档在任意检索系统排名靠前,就会拿到较高分数;多个检索器同时命中同一篇文档,分数叠加,优先级最高。

优点

  1. 不需要关心两种检索器原始分数值域,只看排名序号。BM25 分数、向量 cos 相似度数值范围完全不一样,没法直接相加;RRF 只拿排名,天然解决不同检索分数不能直接相加的痛点。
  2. 同时吸收关键词检索、语义向量检索两者优势:既抓字面关键词,又抓语义。
  3. 实现简单,没有复杂调参,k 一般固定 60 即可。

缺点

  1. 需要同时跑多路检索,性能开销变大;
  2. 完全抛弃原始相似度分数,只看位次;如果某一个检索器整体质量很差,依然会干扰融合结果。

工程对应场景(RAG 经典架构)

Hybrid 检索(混合检索)= BM25 关键词检索 + 向量检索 + RRF 倒数排名融合重排。 这是工业 RAG 最常用的标配组合。
💡对比其他重排: RRF:基于排名序号做融合; Cross‑Encoder 交叉编码器:输入文档 + query,模型输出相关性分数,做二次重排序。

一句话记忆:

RRF 倒数排名融合:只看文档在各个检索列表的名次,套公式累加分数,不直接使用原始相似度数值,实现多路检索结果合并。

相关推荐
VALENIAN瓦伦尼安教学设备32 分钟前
设备状态检测振动分析实训台案例分析
大数据·数据库·人工智能·嵌入式硬件·算法
黄俊懿1 小时前
【架构师从入门到进阶】第五章:DNS&CDN&网关优化思路——第十节:网关安全-单向加密
网络·数据库·计算机网络·安全·架构·系统架构·架构师
garmin Chen1 小时前
redis面试题
java·数据库·redis·缓存
小小龙学IT1 小时前
Qt 元对象系统(Meta-Object System)深度解析:从 MOC 到反射式编程
数据库·qt
想带你从多云到转晴2 小时前
MySQL重点梳理
数据库·mysql
胖头鱼的鱼缸(尹海文)2 小时前
胖头鱼的技术专栏-465 数据库能力上移还是下沉:库变弱了,应用就变重了(20260828)
数据库
2601_962181962 小时前
Redis Redis介绍、安装 - Redis客户端
数据库·redis·postman
2601_962062943 小时前
Spring Boot入门——Spring Boot项目的创建
java·数据库·spring boot
冰暮流星3 小时前
mysql之外键约束
数据库·mysql