【RAG 3/3】做 RAG 最重要的不是模型,而是检索质量
前两篇分别讲了第 1 篇RAG 是什么有哪些现成应用可以体验 第 2 篇自己搭建 RAG系统如何从简单到复杂逐步升级这一篇讲最关键的部分RAG 为什么效果差怎么定位问题怎么验证它真的变好了很多人做 RAG第一反应是回答不好是不是模型不够强 换个更大的模型试试 换 GPT-4、Claude、Qwen-Max 会不会好一点但实际做下来会发现很多 RAG 问题不是生成模型的问题而是检索链路的问题。更直接地说RAG 的上限通常不是由大模型决定而是由检索质量决定。因为 RAG 的基本流程是用户提问 → 系统检索资料 → 把资料交给大模型 → 大模型基于资料回答如果第二步资料找错了后面的模型再强也是在错误资料上生成答案。所以这篇文章的核心观点是RAG 做得好不好不能只看答案流畅不流畅而要看正确资料有没有被找出来答案有没有忠实于资料。一、为什么说 RAG 的核心不是模型而是检索质量RAG 和普通大模型问答最大的区别是普通问答模型直接回答 RAG 问答先找资料再基于资料回答所以 RAG 的质量至少由两部分决定检索质量 生成质量但很多时候真正卡住系统效果的是前者。比如用户问会员开通后可以退款吗如果系统检索到了正确资料会员开通后 7 天内未使用权益可以申请退款。那即使用一个中等能力的模型也大概率能回答会员开通后 7 天内且未使用权益可以申请退款。但如果系统检索到的是会员权益包括专属客服、优惠券、积分加倍。那大模型再强也很难准确回答退款规则。它可能会说资料中没有明确提到退款规则。也可能开始猜通常会员服务开通后可能不支持退款建议联系客服确认。这不是模型不会说话而是系统没有把正确资料交给它。所以 RAG 的基本判断逻辑是资料找对了模型才有可能答对。 资料找错了模型回答再流畅也没意义。二、RAG 效果差常见不是一个问题而是一条链路的问题一个 RAG 系统大概可以拆成用户问题 → 查询理解 → 检索 → 重排序 → 上下文拼接 → 模型生成 → 引用来源所以答案错了不一定是最后一步错了。可能是用户问题没理解对 检索 query 不合适 文档切片不合理 Embedding 不适合 关键词没命中 正确片段没有进入 Top-K Rerank 排序错误 上下文放太多噪声 模型没有忠实于资料回答 资料本身过时或冲突所以排查 RAG不能只看最终答案。应该从链路前面往后看。最简单的排查顺序是第一步看检索结果有没有正确资料 第二步看正确资料排在第几位 第三步看最终上下文里有没有正确资料 第四步看模型有没有基于资料回答 第五步看答案有没有引用正确来源如果第一步就错了后面基本不用看。三、检索质量不是从向量数据库开始而是从理解用户问题开始很多人以为检索质量主要取决于向量数据库。这个理解不够准确。向量数据库只是执行检索的组件。真正的检索质量从用户问题进入系统的那一刻就开始了。因为用户的原始问题不一定适合直接拿去搜。比如用户问刚买会员后悔了还能退吗文档里写的是会员开通后 7 天内未使用权益可申请退款。用户表达是刚买 后悔 还能退吗文档表达是会员开通 7 天内 未使用权益 申请退款两者语义接近但表面表达不同。如果直接拿用户原话去检索可能能搜到也可能搜不到。更稳的方式是先把用户问题改写成会员开通后退款规则 会员未使用权益退款条件这就是 Query Rewrite。所以有一句话很重要RAG 的检索不是从向量数据库开始的而是从理解用户问题开始的。LlamaIndex 文档中也把 Query Transformations 作为高级检索优化能力它可以把一个 query 转换成另一个 query也可以执行多步查询转换。四、为什么用户原始问题不一定适合检索因为用户问题和文档切片之间经常存在“表达错位”。也就是用户怎么问 ≠ 文档怎么写常见有几类情况。1. 用户说口语文档写规则用户问刚买就后悔了钱还能回来吗文档写会员开通后 7 天内未使用权益可申请退款。系统应该理解用户想问的是会员退款规则。更适合检索的 query 是会员退款规则 会员开通后退款条件 会员未使用权益退款2. 用户问现象文档写原因用户问为什么我登录一直失败文档可能写账号连续输入错误密码 5 次后将被锁定 30 分钟。用户没有说“账号锁定”。但系统应该理解登录失败可能和账号锁定、密码错误、验证码异常、网络异常有关。所以检索 query 可以扩展成登录失败原因 账号锁定规则 密码错误次数限制 验证码异常3. 用户问目标文档写步骤用户问我怎么把项目跑起来文档可能写本地开发环境配置 数据库初始化 启动后端服务 启动前端项目用户没有说“开发环境”“启动服务”“数据库初始化”。但系统要理解用户想找项目本地运行步骤。更适合检索本地启动步骤 开发环境配置 项目运行说明 README 启动服务4. 用户问题太短必须依赖上下文用户问这个怎么开这句话本身几乎没法检索。它可能是开通会员 开启配置 启动服务 打开页面 开通权限这时候必须结合上下文、页面位置、上一轮对话、用户当前操作来判断意图。5. 用户问题涉及多个可能原因用户问为什么用户收不到通知这可能涉及用户通知权限 短信服务配置 消息队列积压 推送模板审核 第三方服务异常 系统定时任务失败这类问题通常不是一个 query 能解决的。需要生成多个检索 query分别查不同方向。五、Query Rewrite把“用户怎么问”转换成“系统怎么搜”Query Rewrite 的作用是把用户原始问题改写成更适合检索系统理解的查询。比如原始问题刚买会员后悔了还能退吗 改写 query会员开通后退款规则是什么这一步不是为了改变用户意思而是为了让检索更容易命中文档。可以理解成用户语言 → 检索语言一个简单 Prompt 可以这样写请把用户问题改写成适合知识库检索的查询语句。 要求 1. 不要改变用户原意 2. 保留关键实体 3. 使用更正式、清晰的表达 4. 只输出改写后的 query 用户问题刚买会员后悔了还能退吗输出会员开通后退款规则和退款条件这一步很有用但不能滥用。如果用户问题本来就很清楚会员退款规则是什么直接检索就可以。强行改写可能反而偏离原意。所以更稳的做法是保留原始 query 同时加入改写 query 一起检索例如原始 query刚买会员后悔了还能退吗 改写 query会员开通后退款规则 扩展 query会员未使用权益退款条件这样即使改写不完美也不至于完全丢掉用户原话。六、Query Expansion一个问题扩展成多个检索方向Query Rewrite 是把问题改得更清晰。Query Expansion 是把一个问题扩展成多个相关查询。比如用户问为什么用户收不到通知系统可以扩展成用户通知权限设置 短信服务配置 消息推送失败原因 消息队列积压 模板审核失败 第三方短信服务异常这适合问题可能有多个原因 答案分散在多个文档 用户没有提供足够关键词 单次检索容易漏掉关键信息Query Expansion 的本质是不要只从一个角度搜而是从多个可能角度召回资料。但也要控制数量。如果扩展太多会带来噪声。比如扩展出 20 个 query检索回来一堆不相关内容模型反而更难回答。所以一般要配合Top-K 控制 去重 Rerank metadata filter七、Multi-Query Retrieval多 query 检索后合并结果Multi-Query Retrieval 可以理解成 Query Expansion 的工程化版本。流程是用户问题 → 生成多个 query → 每个 query 分别检索 → 合并候选片段 → 去重 → Rerank → 选择最终上下文适合复杂问题。比如我的消息为什么发不出去可以拆成多个 query消息发送失败原因 消息队列异常 用户通知权限 短信网关配置 发送失败重试机制 模板审核失败然后分别检索。这种方式可以提升召回率。但问题是成本更高噪声也更多。所以 Multi-Query 不是默认一定要开而是适合问题开放 知识分散 单次检索经常漏 业务允许多查几次LlamaIndex 的 Query Transform Cookbook 也展示了通过 LLM 和 Prompt 生成多个搜索 query 的做法。八、Self-Query把自然语言转成结构化检索条件有些问题不是单纯语义检索还包含过滤条件。比如用户问找一下 2024 年后更新的支付相关文档。这句话里面有两个部分语义查询支付相关文档 过滤条件更新时间 2024-01-01系统可以解析成{query:支付相关文档,filters:{updated_at:2024-01-01,category:payment}}这就是 Self-Query 或结构化 query extraction 的思路。它适合文档有 metadata 需要按时间过滤 需要按版本过滤 需要按部门过滤 需要按权限过滤 需要按产品线过滤例如找最新版退款规则 查支付团队的接口文档 只看 2025 年后的政策 找当前用户有权限访问的合同这类问题不能只靠向量相似度。必须结合结构化过滤。九、HyDE先生成假设答案再拿它去检索HyDE 是一个很有意思的方法。它的全称是Hypothetical Document Embeddings它的思路不是直接拿问题去检索而是用户问题 → 大模型先生成一个假设性答案或文档 → 用这个假设文档去做 embedding 检索 → 从真实文档库里找相似内容HyDE 论文由 Luyu Gao、Xueguang Ma、Jimmy Lin、Jamie Callan 提出。论文指出在没有相关性标注的 zero-shot dense retrieval 场景下可以先让大模型根据 query 生成一个 hypothetical document再用这个文档的 embedding 去检索真实语料。为什么这样有用因为答案往往比问题更接近文档表达。比如用户问刚买会员后悔了还能退吗模型先生成一个假设答案会员开通后在一定期限内若未使用权益可以申请退款。这个假设答案里有会员开通 期限 未使用权益 申请退款这些词更接近文档原文。再拿它去检索可能更容易找到正确片段。但 HyDE 也有风险。因为假设答案可能包含错误细节。所以 HyDE 适合用于“检索”不应该直接把假设答案当最终答案。最终答案仍然要基于真实检索到的资料生成。十、Agentic RAG让模型参与检索决策基础 RAG 是固定流程用户问题 → 检索 → 生成答案Agentic RAG 更像动态流程用户问题 → 判断是否需要检索 → 判断检索哪个知识库 → 生成检索 query → 检索资料 → 判断资料是否足够 → 不够则继续检索或追问用户 → 最后回答它让模型参与决策我要不要检索 检索哪个知识库 用什么 query 检索 检索结果够不够 要不要继续查 要不要追问用户适合复杂任务比如分析项目为什么启动失败 根据多个文档生成方案 综合不同版本资料 查询多个知识库 结合工具执行任务但它也更复杂。因为你要控制循环次数 成本 检索范围 权限 停止条件 错误处理所以 Agentic RAG 不是一开始就要做。先把普通 RAG 做稳再引入动态检索。十一、RAG 常见问题怎么定位当用户说这个回答不对。不要直接换模型。先按链路排查。1. 先看检索结果有没有正确片段这是第一步。用户问会员开通后可以退款吗你要看检索 Top-K 里有没有会员开通后 7 天内未使用权益可以申请退款。如果没有问题在检索前半段。可能是query 不适合检索 文档切片不合理 embedding 不适合 关键词没有命中 metadata 过滤错了 正确文档没有入库这时换大模型没用。因为正确资料根本没给到模型。2. 再看正确片段排在第几位如果正确片段在 Top-20 里但不在 Top-5 里说明召回有了但排序不够好。这时可以考虑加 Rerank 调 Top-K 改 hybrid search 权重 优化 query rewrite问题不是“找不到”而是“没排到前面”。3. 再看最终上下文里有没有正确资料有些系统检索到了正确片段但最终拼接上下文时被丢掉了。比如检索 Top-20 有正确片段 Rerank 后没进 Top-5 或者上下文长度限制把它截掉了这时要查Rerank 结果 上下文拼接策略 去重策略 最大上下文长度 片段排序方式4. 再看模型有没有基于资料回答如果正确资料已经放进上下文但模型还是答错问题才可能在生成阶段。可能原因Prompt 没要求基于资料回答 上下文太多噪声 资料之间有冲突 模型能力不够 模型没有拒答策略 引用来源没有约束这时可以优化Prompt 上下文格式 引用要求 拒答策略 更强模型5. 最后看引用来源是否正确如果答案看起来对但引用错了也不合格。比如答案说会员 7 天内可以退款。但引用来源是会员权益说明而不是会员退款规则这说明系统的引用追踪有问题。RAG 不只是要答对还要能证明自己为什么这么答。十二、一套简单的 RAG 排查流程可以记住这个流程答案错了 ↓ 检索结果里有没有正确资料 ↓ 没有 → 查 query、切片、embedding、metadata、入库 ↓ 有但排名靠后 → 查 rerank、hybrid search、Top-K ↓ 有并进入上下文 → 查 prompt、上下文噪声、模型生成 ↓ 答案对但引用错 → 查来源追踪和 chunk 映射一句话先查检索再查生成。不要一上来就换模型。十三、RAG 怎么评测RAG 评测不能只看最终答案。应该分层评测检索评测 生成评测 端到端评测Ragas 文档中也把 RAG 指标分成 faithfulness、answer relevance、context precision、context recall 等多个维度。TruLens 的 RAG Triad 也强调三项核心评估context relevance、groundedness、answer relevance。这说明业内评测 RAG不是只问“答案好不好”而是拆开看上下文是否相关 答案是否基于上下文 答案是否回答了用户问题十四、第一层检索评测检索评测回答的问题是正确资料有没有被找出来常见指标包括RecallK PrecisionK MRR NDCG Context Recall Context Precision不用一开始就被指标吓到。先理解它们在问什么。1. RecallK正确片段有没有进入前 K 个结果比如用户问题会员开通后可以退款吗正确片段是会员开通后 7 天内未使用权益可以申请退款。如果系统检索 Top-5 里包含这个片段那么 Recall5 命中。如果 Top-5 里没有但 Top-20 里有说明召回还行但前排排序不够好。RecallK 关心的是有没有找出来2. PrecisionK前 K 个结果里有多少是真的相关如果 Top-5 里1 个真正相关 4 个无关Precision 就比较低。PrecisionK 关心的是找出来的东西干不干净3. MRR正确答案排得靠不靠前MRR 关注第一个正确结果出现的位置。如果正确片段排第 1很好。如果排第 9就说明用户问题虽然能找到答案但排序不好。4. NDCG相关性排序是否合理NDCG 更适合有多个相关结果并且相关程度不同的情况。比如片段 A直接回答问题 片段 B部分相关 片段 C背景介绍好的检索应该把 A 排前面B 次之C 后面。5. Context Recall / Context PrecisionRagas 的 Context Precision 衡量 retriever 是否能把相关 chunk 排在不相关 chunk 前面Context Recall 则关注 retrieved context 是否覆盖回答所需信息。可以简单理解Context Recall该找的有没有找全 Context Precision找出来的是否足够相关并且排序靠前十五、第二层生成评测生成评测回答的问题是模型有没有基于资料回答常见指标包括Answer Relevance Faithfulness Groundedness Hallucination Rate 引用准确率1. Answer Relevance答案有没有回答用户问题用户问会员开通后可以退款吗模型回答会员权益包括优惠券、专属客服和积分加倍。这个答案可能来自资料但没有回答退款问题。Answer Relevance 低。2. Faithfulness答案是否忠实于检索上下文Ragas 文档把 Faithfulness 定义为回答与 retrieved context 的事实一致性分数越高表示回答越能被上下文支持。比如资料只写会员开通后 7 天内未使用权益可申请退款。模型回答会员开通后 30 天内可以无条件退款。这就是不忠实。它编造了资料里没有的30 天 无条件Faithfulness 低。3. Groundedness答案是否有依据Groundedness 和 Faithfulness 接近关注答案中的说法是否能被上下文支撑。如果答案里每个关键结论都能找到来源Groundedness 高。如果答案里有很多“看起来合理但资料没说”的内容Groundedness 低。TruLens 的 RAG Triad 就把 groundedness 作为三大评估之一用来判断回答是否基于上下文。4. 引用准确率RAG 最好返回引用来源。但引用也可能错。比如答案说退款规则却引用了会员权益说明。这时答案可能看起来对但来源不对。引用准确率关注答案里的每个关键结论 是否引用了正确文档 是否引用了正确段落十六、第三层端到端评测端到端评测回答的问题是用户最终看到的答案能不能用它不只看检索也不只看生成而是看完整链路。包括答案是否正确 答案是否完整 答案是否有引用 资料不足时是否拒答 是否使用了最新资料 是否遵守权限 用户是否满意比如用户问会员开通后可以退款吗一个合格答案应该满足说明退款条件 说明不可退款情况 引用退款规则来源 不编造额外政策 如果资料不足明确说资料不足端到端评测更接近真实用户体验。但定位问题时仍然要拆回检索和生成两层。十七、怎么构建 RAG 测试集没有测试集就没有优化。你只能凭感觉说好像变好了 好像检索准了 好像回答更自然了这不够工程化。一个 RAG 测试集至少应该包含用户问题 标准答案 正确资料片段 期望引用来源 不可接受错误可以用 JSON 表示{question:会员开通后可以退款吗,expected_answer:会员开通后 7 天内且未使用权益可以退款。,golden_context:[refund_policy_v2.md#section-3],must_not_include:[无条件退款,30 天内退款,联系客服即可全额退款]}其中最重要的是golden_context也就是正确答案应该来自哪些资料片段。因为只有知道正确资料在哪里才能评测检索有没有找对。十八、测试集应该覆盖哪些问题不要只放标准问题。要覆盖真实用户会问的各种表达。1. 标准问题会员退款规则是什么用于测试基础检索。2. 口语化问题刚买会员后悔了还能退吗用于测试 Query Rewrite 和语义检索。3. 模糊问题这个能退吗用于测试上下文理解和追问能力。4. 现象类问题为什么我一直登录失败用于测试系统能否从现象找到原因文档。5. 多跳问题如果我是年度会员已经用过一次权益还能不能退款可能需要同时检索会员类型 权益使用规则 退款规则6. 资料不存在问题公司今年营收是多少如果资料里没有系统应该拒答。用于测试幻觉控制。7. 过期资料问题最新退款规则是什么测试系统会不会检索旧版本文档。8. 冲突资料问题会员退款期限到底是 7 天还是 15 天测试系统能否处理多版本或冲突资料。9. 权限问题今年奖金方案是什么测试系统会不会泄露用户无权限资料。十九、怎么验证 Query Rewrite 是否真的有效不要凭感觉说 Query Rewrite 有用。应该测。方法很简单。准备一批测试问题尤其是口语化、模糊、现象类问题。然后分别跑两套流程A原始 query 直接检索 B原始 query query rewrite 检索比较RecallK 是否提升 正确片段排名是否提前 无关片段是否增多 最终答案是否更准确 成本是否可接受 延迟是否可接受如果 Query Rewrite 提高了 RecallK但引入大量噪声也不一定值得。如果它只是让答案看起来更自然但正确片段命中率没提升也不是真提升。所以判断标准是Query Rewrite 有没有让正确资料更容易被检索出来。二十、怎么验证 Rerank 是否有效同样不要凭感觉。准备同一批问题。对比A只用向量检索 Top-K B向量检索 Top-20 Rerank 取 Top-5看正确片段是否排得更靠前 Context Precision 是否提升 最终答案是否更忠实 延迟是否增加太多 成本是否可接受如果正确片段本来就在 Top-1Rerank 可能提升不明显。如果正确片段经常在 Top-10但进不了最终上下文Rerank 就很有价值。二十一、怎么验证切片策略是否有效对比不同切片策略。比如A固定 500 字切片 B按标题切片 C按段落切片 overlap DParent-Child Chunk看正确片段是否更容易召回 召回片段是否语义完整 模型回答是否更少遗漏条件 上下文噪声是否变少不要只看 chunk 数量。切片的目标不是切得多也不是切得均匀而是让检索出来的片段既相关又包含完整语义。二十二、怎么验证 Embedding 是否适合不同 embedding 模型效果差异很大。尤其在中文 代码 专业术语 法律 医疗 客服口语 多语言场景中。可以用同一批测试集对比OpenAI embedding BGE embedding Qwen embedding Jina embedding 其他本地 embedding看RecallK 正确片段排名 专业术语召回 中文口语问题召回 成本 速度 是否支持本地部署不要只看模型榜单。要看你的业务数据。二十三、RAG 优化的正确顺序不要一上来就改一堆东西。推荐顺序第一步先建立测试集 第二步看当前系统的检索结果 第三步确认正确片段是否进入 Top-K 第四步优化文档解析和切片 第五步优化 query rewrite / hybrid search 第六步加入 rerank 第七步优化 prompt 和拒答策略 第八步再考虑换更强模型也就是说先定位问题 再改系统 最后才换模型如果没有测试集优化就是玄学。二十四、一个实用的 RAG 调试表可以用下面这张表来排查。现象可能原因优先排查答案完全错没检索到正确资料Top-K 检索结果答案缺少关键条件chunk 切片不完整切片策略答案引用错来源来源映射错误chunk 与文档映射问口语问题答不好query 表达不适合检索Query Rewrite错误码、接口名查不到纯向量检索不适合精确匹配Hybrid Search正确片段在 Top-10 但没进上下文排序不准Rerank答案编造资料没有的内容Prompt / 忠实度不足Faithfulness / 拒答策略新规则没生效检索到旧版本metadata / 版本管理不该看的资料被回答权限过滤缺失权限 metadata二十五、RAG 评测工具怎么选可以简单分层。1. Ragas适合评估 RAG 指标比如Faithfulness Answer Relevance Context Precision Context RecallRagas 文档中列出了这些指标用于评估回答是否忠实、答案是否相关、上下文是否精准和召回是否充分。2. DeepEval更像 LLM 应用测试框架。适合把 RAG 评测写进测试代码。比如每次改切片策略、换 embedding、改 prompt 后自动跑测试。3. TruLens适合用 RAG Triad 思路观察Context Relevance Groundedness Answer Relevance这三个指标分别对应检索上下文是否相关 答案是否基于上下文 答案是否回答了问题TruLens 官方把这三者称为 RAG Triad。4. Phoenix / LangSmith / Langfuse更偏线上观测和调试。适合记录用户问题 检索结果 上下文 模型回答 调用成本 耗时 失败案例当系统上线后这类工具比离线评测更重要。二十六、最终总结RAG 做不好很多时候不是模型不会回答而是系统没有把正确资料交给模型。所以这篇的核心结论是做 RAG 最重要的不是模型而是检索质量。检索质量又不是只由向量数据库决定。它来自整条链路用户问题理解 → Query Rewrite → Query Expansion → 文档切片 → Embedding → Hybrid Search → Rerank → Metadata Filter → 上下文拼接真正工程化的 RAG必须能回答几个问题正确资料有没有被找出来 正确资料排在第几位 最终上下文里有没有正确资料 模型有没有基于资料回答 答案有没有引用正确来源 资料不足时有没有拒答所以 RAG 不能只看最终答案流畅不流畅。要分层评测检索评测正确资料有没有找出来 生成评测模型有没有忠实于资料 端到端评测最终答案是否对用户有用最后用一句话总结整个 RAG 系列RAG 的本质不是把文档塞给大模型而是把正确资料在正确时间交给模型并且能证明答案来自这些资料。