RAG准确率从60%到80%:链路优化实战指南
2026/9/8 9:22:05 网站建设 项目流程

RAG 系统的准确率从 60% 拉到 80%,听起来像是某个参数或者某个模型一步到位的事,实际做过的同学应该都清楚,这笔账要算在整个链路上。RAG 不是“向量检索 + 大模型”两个关键词拼在一起就结束了,它牵涉文档解析、切片、Embedding、召回、重排序、提示词组织、输出验证,任何一个环节漏了,准确率都会掉,而且很难通过换模型救回来。

这篇文章主要写给正在做知识库问答、想让 RAG 回答更可靠的程序员。你可以不是算法背景,但要能看日志、改代码、跑评估。这里不吹某个框架,不吹某个模型,只讲我实测后认为从 60% 走向 80% 最值得花时间的几个环节,以及每个环节要用什么标准去判断。

1. 准确率卡在 60%,问题大概率不在大模型身上

先不要上来就换模型。60% 的系统通常有典型症状:简单问题基本能答,复杂问题开始胡说;有时能检索到相关内容,但排在前面的片段不是答案所在;有时大模型回答得很通顺,但引用的来源和答案对不上。

这些现象很容易被误判成“大模型能力不够”,于是有人去换更大的模型、改 temperature、加复杂 prompt。结果准确率可能只涨两三个点,还带来更高延迟和成本。原因是问题根本不在生成阶段,而在召回和排序阶段。

1.1 60% 的典型症状:能说、能找、答不准

我建议先做一个控制变量实验:把正确片段固定拼进 prompt,再让模型回答。如果十有八九能答对,说明生成模型本身没问题,问题在于 RAG 链路没有把正确的上下文送进去。反之,如果固定上下文也答不对,再考虑模型能力和 prompt 设计。

这个实验很快,不用写复杂代码。手动挑 10 条错误 case,把正确答案从文档里复制到 prompt 里,看模型反应。结果能帮你把调优方向从“玄学”变成“确定环节”。

还有一种常见情况:检索返回的片段里其实有正确答案,但被淹没在大量无关内容中。大模型看到的信息越杂,越容易答偏。这也不是模型问题,而是召回排序不准。把这类错误单独标记出来,你会发现 60% 到 80% 的差距,大概率是被“上下文送错了”和“上下文送太杂”这两件事同时拖住。

1.2 先建最小评估集,再谈调优

没有评估集,调优就是空转。60% 到底怎么来的?可能是手工看 20 条结果得出的印象。但 20 条样本太少,问题类型分布不明确,换一个参数可能打断一批旧问题,你根本发现不了。所以第一步不是优化,而是建一个 50 到 100 条的最小评估集。

每条评估样本至少包含这些字段:问题、标准答案、参考来源、问题类型、通过标准。怎么算通过?我的建议是“答案内容正确,并且引用来源确实能支撑答案”才算通过。仅凭“看起来相关”去打分,最后一定失真。

[ { "id": "rag-eval-001", "question": "项目上线前需要准备哪些检查项?", "reference": "网络、权限、日志、备份四项都需要确认", "source": "docs/checklist.md", "type": "单跳", "pass_rule": "答案包含网络、权限、日志、备份四项,并引用对应片段" } ]

上面只是示例格式。真实评估集里还要覆盖几类问题:单跳问题、多跳问题、否定表达、精确数字查询、同义说法、没有答案的越界问题。没有答案的问题尤其重要,因为很多 RAG 系统失败不是答错,而是不该答的时候硬答。

有了评估集之后,每次改动都要跑一遍。记录哪些问题从错变对,哪些从对变错。只有这样才能判断某个改动到底是真提升,还是只是把错误类型换了位置。

2. 文档解析和切块是容易忽略的准确率刺客

很多项目把重心放在检索模型上,忽略了文档解析。文档解析出问题,后面所有环节都会被污染。尤其是 PDF、扫描件、多栏排版,解析结果经常是乱码、断行、表格散架、页眉页脚混入正文。向量化之后,这些噪声进入向量库,检索时就会命中一些“看起来有关,实际没内容”的片段。

如果你发现系统经常答非所问,先别怀疑 Embedding,先把真正进入向量库的文本翻出来看一遍。很多时候你一看就知道,源头就是脏的。

2.1 清洗文档,把噪声挡在进入向量库之前

清洗的目标很简单:让进入向量库的文本尽量接近原始文档的有效信息。常见要做的事包括:

  • 去掉页眉、页脚、页码、目录、导航链接。
  • 把多栏文本按阅读顺序还原,不要左右两栏混在一起。
  • 表格转成结构清晰的 Markdown 表格,而不是一行行碎片。
  • 合并被错误断行的段落,避免一句话被切成三段。
  • 去掉水印、批注、修订痕迹。
  • 检查重复导入,同一个文件不要以多个版本同时存在。

清洗之后,建议抽 2 到 3 页人工看一遍。如果一个人读起来都费劲,那模型和检索器也不会读得更好。不要全量直接入库,先处理一批样本,确认解析质量稳定再继续。

如果文档是扫描件,必须走 OCR。OCR 阶段不要急着全量跑,先抽几页看识别准确率。数值、英文、表格、公式最容易出错,而这些往往就是用户查询时的关键词。OCR 识别错的字段,后续再怎么优化召回都找不回来。

2.2 切块参数要和文档结构匹配

不要只按固定 token 数切块。500、800、1000 只是起步值,不是通用答案。更好的做法是优先按文档结构切:先按章节、标题、段落、列表、表格切,再对过长的块做二次拆分。

切块的核心判断标准是:一个 chunk 能不能独立回答一个问题。比如“这个接口的入参有哪些”,如果能从某个 chunk 里直接找到答案,这个 chunk 就是合格的。如果答案散落在三个 chunk 里,说明切得太碎;如果一个 chunk 里混了十几个无关主题,说明切得太粗。

常见参数可以这样起步:

参数常见范围说明
chunk_size512 到 1024 token单纯按长度切,不能替代结构切分
chunk_overlap50 到 200 token,或 10% 到 20%缓解关键信息刚好被切断的问题
切分单位章节、段落、表格、代码块比固定长度更符合语义边界
适用场景技术文档、制度文档、FAQ、代码库不同文档类型需要不同策略

实际调的时候,不要一上来就把 chunk_size 从 500 改到 1000。先看当前失败 case,判断是“信息丢失”还是“信息太杂”。如果是信息丢失,优先调 overlap 和结构切分;如果是信息太杂,优先缩小 chunk 或继续拆分。

2.3 用召回命中率验证切块质量

切块调得好不好,不能靠生成效果判断,因为生成阶段还会引入其他变量。正确做法是只看召回命中率:用评估集里的问题去检索,看正确答案对应的片段是否出现在 top1、top3 或 top5 里。

几个常见规律:

  • top5 里有正确答案,但 top1 没有:说明切块大体可用,但噪声太多,需要靠重排来解决。
  • 正确答案被切成两半,分别出现在两个 chunk 里:chunk 太小或 overlap 不够。
  • 正确答案在 chunk 中间,头尾全是无关内容:需要按章节或语义段落重新切。
  • 完全检索不到:可能是查询用词和文档表达差异太大,也可能是解析阶段把关键内容弄丢了。

我一般会先抽 20 个问题做切块验证,不直接全量批量调参。20 个问题足够暴露大部分解析和切块问题,而且手检速度快。等这 20 个问题稳定了,再跑完整评估集。

3. 召回优化:向量之外要加混合检索和查询改写

向量检索是 RAG 的默认配置,但默认不代表够。准确率卡在 60% 时,第一嫌疑就是召回丢答案。因为如果正确片段压根没进大模型上下文,prompt 写得再好也没有用。

向量检索擅长“语义相近”,但不擅长“精确命中”。很多生产级知识库里的文档偏偏充满编号、代码、产品名、日期、数量词,这些内容对向量相似度并不友好。所以召回优化不能只盯着 Embedding 模型换。

3.1 为什么向量检索会漏掉该命中的答案

向量检索的基本逻辑是,把问题和文档片段分别编码成向量,然后计算相似度。这个机制对“换一种说法问同一件事”很有效,但对精确匹配不敏感。

举个例子:文档里写“SKU-2024-0917”,用户问“2024 年 9 月 17 日的订单编号”。语义上很接近,但字面差距大,向量检索不一定把这条排在前面。再比如用户问“不包含海外节点”,而文档写的是“国内节点包括北京、上海、广州”,这里带着否定和排除关系,向量相似度往往判断不准。

如果系统只有向量召回,漏召回是必然的。提高 top_k 能稍微缓解,但会把大量无关内容一起带进来,增加后续重排和大模型的负担。正确思路不是只调 top_k,而是增加别的召回通道。

3.2 混合检索怎么加

混合检索的经典组合是“向量召回 + 关键词召回”。向量负责语义相似,关键词负责精确匹配。关键词部分可以用 BM25,也可以用数据库自带的全文索引。

流程大致是这样:

  1. 向量检索返回 top 20 到 50 条。
  2. 关键词检索返回 top 20 到 50 条。
  3. 两路结果合并去重。
  4. 合并后交给重排,再取 top 3 到 5 给大模型。

合并方式不一定要很复杂,先试 RRF,也就是倒排融合。这种方案对分数不敏感,不用费心去对齐向量相似度和 BM25 分数的量纲。

def hybrid_search(query, top_k=20): vector_hits = vector_index.search(embed(query), k=top_k) bm25_hits = bm25_index.search(query, k=top_k) merged = merge_by_rrf(vector_hits, bm25_hits, k=top_k) return merged

这只是示意,真实实现里还要处理出处字段、去重、分数归一化。加上混合检索后,要回评估集看召回命中率。如果命中率明显提升,说明之前丢答案确实是字面匹配问题。如果加了之后检索结果变杂,不要马上回滚,先看重排能不能收住。

3.3 查询改写:把用户原话变成更容易命中的检索语句

用户不会按文档的写法提问。文档里可能写“部署前检查”,用户问“上线之前我要注意什么”。这种差异靠向量能解决一部分,但不够彻底。查询改写的作用,就是把这些口语化、指代化、碎片化的问题,变成更适合检索的语句。

最简单的改写方式不是上大模型,而是做一套规则和同义词表。比如“上线”“发布”“部署”映射到同一组关键词,“薪资”“工资”“薪酬”统一成文档常用词。成本低,效果可控。

再进一步,多轮对话场景要把指代还原。用户先问“这个接口支持并发吗”,再问“超时时间是多少”,第二问的“超时时间”其实是“这个接口的超时时间”。如果不改写,检索时很容易丢掉主语。

复杂一点的方案是用大模型做 Query Rewrite。但有一个前提:必须用评估集验证改写前后的 top5 命中率。如果命中率没有提升,就不要在生产环境开启,因为改写本身会带来额外延迟,还可能把原本正确的查询改歪。

4. 重排序:准确率从“差不多”到“可用”的关键动作

重排往往是被忽略的一环。向量检索结果 top5 中可能有一两条正确,但 top1 不对,直接把这 5 条塞给大模型,模型容易受前几条干扰。给模型更多候选未必提升准确率,反而可能让无关片段干扰答案。

重排的价值,是把正确片段尽量提到最前面。这样大模型看到的主要内容是有效信息,而不是一堆“有点相关但不对”的噪声。

4.1 向量检索返回的分数不能直接当作相关性

向量检索常用双塔结构,问题和文档各自编码成向量,计算快,但对细粒度相关性不敏感。也就是说,向量分数高不代表这个片段真的能回答问题。

重排模型通常把“问题 + 候选片段”拼起来,让模型一起编码计算相关性。这种方式更准,但慢,所以不能拿它去检索全量语料,只能对召回后的候选做二次排序。

判断重排是否有效,要看一个指标:正确答案是否从 top5 被提到了 top1 或 top3。如果重排前后 top3 命中率差不多,说明重排模型没有带来增量,这时不要硬留。

4.2 重排的接入方式和参数

建议先固定候选集大小,再调重排。一般流程是:召回阶段取 20 到 50 条候选,重排后取 top 3 到 5 条进入大模型。

def rerank(query, candidates, top_k=5): scored = [] for doc in candidates: score = reranker.score(query, doc) scored.append((score, doc)) scored.sort(reverse=True) return scored[:top_k]

候选太少,重排提升有限;候选太多,延迟明显增加。如果评估集显示重排后 top1 命中率反而下降,先检查候选里有没有正确答案。候选里没有,说明召回没修好,重排背不了锅。候选里有但被排到了后面,再看是不是候选文本太长、格式被截断,或者重排模型与你的文档类型不匹配。

接入重排后,要重点观察延迟。不要把重排服务和在线检索放在同一个单点服务里,如果并发一高就超时,建议先做结果缓存。相同或相似的查询,短时间内可以直接复用重排结果。

4.3 重排不是越多越好

重排不是万能的。如果你的知识库主要是短问答,比如“XX 功能怎么打开”,向量检索的 top3 命中率已经很高,重排提升不明显。这类场景强行加重排,只会增加延迟和机器成本。

重排更适合长文档、同类文本多、术语复杂的场景。比如制度文档、技术手册、合同条款,文档之间内容相似,向量检索容易把“看起来相关”的片段排到前面。重排可以把真正回答问题的片段选出来。

低配置机器跑重排要谨慎。重排模型比 Embedding 慢很多,尤其用跨编码器时,每条候选都要和查询一起算。可以先只对 top 20 条候选重排,不要贪多。等确认提升明显后,再考虑并发和缓存。

5. 生成环节:提示词、引用和拒答决定准确率的最终形态

召回和重排解决的是“上下文对不对”,生成阶段解决的是“回答可不可信”。如果端到端准确率还没有到 80%,这里通常要改三样东西:提示词边界、引用规则、生成参数。

很多团队把生成阶段当成最后一公里,随便写个 prompt 就上线。结果检索已经做得不错了,最终答案仍然出现编造、答非所问、引用错位。准确率统计时,这些都会被算成失败。

5.1 提示词先把边界写清楚

提示词不需要写得很长,但必须把“怎么答”和“没依据怎么办”写清楚。

你是一个知识库问答助手。请只根据以下资料回答问题。 如果资料中没有足够信息,请回答“资料中没有提到”,不要根据常识编造。 回答时先给出结论,再用[1][2]标注引用。 资料如下:

这段只是通用框架,实际要根据业务调整。如果业务要求必须给答案,那么“拒答”算不算对,要在评估集里提前定义好。最怕的是 prompt 没有边界,模型在资料不足时硬编一个看起来正确的答案,这种情况在准确率评估里非常吃亏。

注意,prompt 不能替代召回。如果资料本身没有相关内容,prompt 再怎么限制,模型还是可能编。所以 prompt 的作用是兜底,让系统在“无答案”时表现稳定,而不是让模型强行扩大知识范围。

5.2 引用和可验证性必须一起做

RAG 和普通问答的区别,在于它应该有来源可查。给每个知识片段编号,让模型在回答中标出引用来源,这样评估时就能区分“答案对但引用错”和“答案对引用也对”。

引用错误是准确率刺客。模型可能回答“支持批量导入 [1]”,但 [1] 里根本没有“批量导入”这几个字。这说明模型在生成时没有严格依据片段,而是在强行解释。只要出现这种问题,那条结果就不能算通过。

实现上可以写一个简单校验脚本:把模型输出的引用编号提取出来,检查对应片段里是否包含答案关键词。这个校验不能完全替代人工,但能快速筛掉一批幻觉回答。评估集里多统计“引用正确率”,你就知道生成阶段到底有没有在瞎编。

5.3 生成参数也要纳入回归

生成参数不要拍脑袋。常见做法是把 temperature 调到 0 到 0.2,减少随机性。max_tokens 不要设得太大,否则模型会顺着话头补充一堆无关内容。

如果业务需要结构化输出,可以让模型先返回 JSON 或 Markdown,再在后端解析。但要注意,结构化输出比较容易出错,尤其是字段名多、嵌套深的时候。先用小样本验证格式稳定性,再接入正式流程。

如果 temperature 已经调到 0,答案仍然不稳定,问题通常不在生成参数,而在上下文和 prompt。这时候不要继续调温度,回头去看召回和重排。

6. 把 60% 拉到 80% 之后,靠什么稳住

很多团队在调优阶段能把准确率提到 80%,上线跑两周又掉回 70%。原因是文档在更新,检索链路在变,评估集却没有跟着升级。准确率提升这件事,一时冲上去不难,难得是稳住。

我自己的习惯是,每个版本改动之前先跑一遍完整评估集,把结果记录下来。先看哪些问题从错变对,再看哪些从对变错。所谓准确率提升,本质上不是每一条都变好,而是错误类型被系统性地减少。

6.1 准确率怎么算,才不会自己骗自己

端到端准确率至少要拆成几个维度看:

指标计算方式说明
召回命中率正确片段是否在召回结果中召回阶段是否丢答案
排序命中率正确片段是否在重排后 top3 中上下文是否有效
答案正确率给定正确上下文后,答案是否可接受生成模型和 prompt 质量
端到端准确率答案正确且引用合理且无编造最终业务口径

端到端准确率最适合对外汇报,但不适合定位问题。只看这个数,出现下降时你不知道改哪里。所以在日常优化中,一定要同时记录几个子指标。60% 到 80% 的提升,更多是召回命中率和排序命中率的提升,而不是大模型能力突变。

6.2 调优顺序:先修链路,再换模型

我建议按这个顺序调:

  1. 建评估集,先跑出当前基线。
  2. 修文档解析和切块,观察召回命中率。
  3. 加混合检索,看召回是否继续提升。
  4. 加重排,看排序命中率是否提升。
  5. 调 prompt 和生成参数,看端到端准确率。
  6. 对失败 case 分类,回到对应环节继续修。

如果一条链路改动后准确率从 75% 涨到 80%,不要急着庆祝,先看是不是评估集太小造成的波动。建议评估集至少 100 条,每次对比时记录准确率和失败类型分布。如果你发现某个改动让准确率从 75% 掉到 72%,也不要立刻回滚,先看失败类型。有时掉的是“无答案但硬答”的错误,换来的是“复杂问题多跳回答”的提升,这可能是业务更需要的。

6.3 位置都到位后,防回归比继续调参更重要

到 80% 以后,常见的回归点有三个。

一是文档更新。新文档格式不同,原有的解析规则和切块策略可能失效。比如之前都是 Markdown 转文本,新文档是图片型 PDF,解析产物完全不一样。每次更新知识库后,至少抽一批新文档检查解析结果。

二是向量库更新。如果要换 Embedding 模型,通常需要全量重新向量化。新旧向量混在一个库里,检索相关性会乱。建议全量重建,或者至少用版本号区分,避免混用。

三是评估集本身过拟合。如果每次调参都盯着同 100 条问题看,很容易针对这些 case 打补丁。更稳妥的做法是留一个平时不看的盲测集,等调参完成后再跑。盲测集的准确率才能反映真实泛化能力。

如果你的系统也停在 60% 附近,我建议不要先折腾模型,先把评估集建立起来,再按文档解析、切块、召回、重排、生成这个顺序过一遍。很多项目的提升,其实只靠这几步就能完成。RAG 调优真正难的不是某一个玄学参数,而是把评估和链路绑定起来,让每次改动都能被测量。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询