RAG为什么经常答错:切分、召回、重排、引用和数据新鲜度
-
RAG 经常答错,不是因为 RAG 这个方向错了,而是因为很多系统只做了“把文档塞进向量库,再把相似片段塞给大模型”这一小段。真正的 RAG 是一条证据链:原始数据要被正确解析,文档要被合理切分,查询要被理解和改写,候选片段要被召回,结果要被重排,证据要被压缩和组织,模型要基于证据回答,引用要能回到原文,数据还要持续更新。任何一个环节松动,最后都会表现为“模型胡说”。
很多用户看到 RAG 答错时,会第一时间怀疑大模型不够强。模型当然重要,但 RAG 的错误通常更像供应链问题。模型拿到的片段不相关,它会被带偏;片段相关但缺少上下文,它会误读;片段重复又冲突,它会随机挑一边;片段过期,它会认真回答旧事实;引用没有绑定原文,它会生成看似可信的假出处;召回漏掉关键证据,再强的模型也无法凭空补齐。RAG 的可靠性,取决于证据如何进入模型,而不只取决于模型本身。
RAG 最初的研究目标,是把参数化记忆和外部非参数记忆结合起来,缓解大模型知识更新和出处追踪问题。Lewis 等人在 2020 年的 RAG 论文里讨论了用检索到的 Wikipedia 段落辅助生成,核心价值是让模型可以访问显式知识并提供 provenance。这个想法进入产品之后,被简化成了向量搜索加提示词拼接。简化可以让原型快速跑起来,但也埋下了生产失败的根。
本文按一条真实 RAG 链路展开:先讲为什么切分会毁掉语义,再讲召回为什么经常漏,接着讲重排为什么是质量闸门,然后讲引用为什么不能靠模型自由生成,最后讲数据新鲜度为什么决定长期可信。目标不是堆术语,而是让读者看清:RAG 答错时,应该从哪里排查,怎么设计一个更可靠的系统。
一、RAG不是“搜索一下再回答”
普通搜索系统的目标是把相关文档排到前面,用户自己阅读和判断。RAG 的目标更复杂:系统要把外部资料转换成模型可用的证据,并让模型生成一个可直接使用的答案。中间多了一层生成,风险就变多。搜索结果里有十条,用户可以看到差异;RAG 把十条压成一段回答,错误可能被流畅语言掩盖。
搜索系统可以容忍结果列表里有几个不相关页面,因为用户会跳过。RAG 不一定能容忍。只要无关片段被放进上下文,模型就可能把它当成证据。尤其是当无关片段文字更具体、数字更多、措辞更肯定时,模型可能优先采用它。相似不等于正确,语义相近不等于回答问题。
RAG 也不是长上下文的廉价替代。有人以为模型上下文变长后,可以把整个文档都塞进去,不需要检索。问题是长上下文模型并不总能均匀使用全部输入。Lost in the Middle 研究发现,相关信息位置会显著影响模型表现,开头和结尾的信息更容易被利用,中间信息可能被忽视。长窗口扩大了可输入内容,不等于消除了信息组织问题。
RAG 的理想状态,是把“最少但足够”的证据送到模型面前。证据太少,模型缺事实;证据太多,模型被噪声淹没;证据太碎,模型误读;证据太旧,模型过时;证据无来源,模型无法引用;证据无结构,模型难以比较。好的 RAG 系统是证据工程,不是文本搬运。
二、第一类失败:原始文档解析已经坏了
很多 RAG 项目从切分开始讨论,却忽略了切分之前的解析。PDF、Word、网页、扫描件、PPT、表格、图片、代码仓库、邮件、工单、数据库导出,格式都不一样。解析器如果把页眉页脚混进正文,把两栏排版读成错序,把表格行列打散,把脚注插到段落中间,把图片 OCR 识别错,后面的 embedding 再先进也只能索引坏文本。
企业文档尤其容易出问题。合同里一个“除外”被断到下一页,模型可能读成相反意思;制度文件里的表格如果丢了列名,金额和条件就失去关系;产品手册如果把章节编号和正文拆开,检索时可能只召回孤立句子;代码文档如果把函数签名和说明分离,模型会错用参数。RAG 的很多幻觉,根源不是生成,而是入库文本已经失真。
解析失败还有一种隐蔽形态:元数据丢失。文档标题、版本号、生效日期、部门、页面、章节、URL、权限、语言、产品线、地区,这些信息对回答很关键。如果只保存纯文本,模型就不知道这段话来自哪个版本,也不知道它是不是适用于当前用户。后来即使召回到了文字,也无法判断优先级。
生产级 RAG 应该把解析质量当成第一道验收。入库前要抽样查看原文和解析文本是否一致,尤其是表格、列表、图片、页眉页脚、脚注、跨页段落、代码块和中文标点。不要只看“文件已上传成功”。上传成功只是存储成功,不代表知识可用。
更好的做法是保留多层表示。原始文件要保留,解析后的 Markdown 或结构化文本要保留,页面坐标或章节锚点要保留,表格最好保留行列结构,图片要保留 OCR 结果和原图引用。这样生成引用时,系统才能回到原文,而不是只能引用一段脱离来源的纯文本。
三、第二类失败:切分把完整意思切碎了
切分是 RAG 的核心难题之一。大文档必须切成小块,才能被检索和放进模型上下文。但每一刀都可能损坏语义。切太短,片段缺少上下文;切太长,召回粒度变粗,噪声变多;重叠太少,跨段信息断裂;重叠太多,结果重复,浪费 token;按固定字符切,可能把一句话、一个表格、一个代码函数或一个条款拆开。
LangChain 文档建议多数场景从 RecursiveCharacterTextSplitter 这类递归切分开始,因为它尝试优先保留段落、句子等自然结构。LlamaIndex 的 SentenceSplitter 也强调尽量保持句子和段落完整,减少块尾出现半句话。它们背后的原则很朴素:切分应该尊重文本结构,而不是只追求固定长度。
合同、制度和技术文档不适合只按字符数切。合同条款有编号、主条款、子条款、例外条件和定义引用。技术文档有标题层级、步骤、参数、返回值和示例。代码仓库有文件、类、函数、注释和测试。表格有表头、单位、行列关系。切分策略应根据文档类型变化。统一用 1000 字加 200 字重叠,能跑原型,但很难长期稳定。
切分失败常见表现是“召回到了相关片段,但答案仍然错”。比如用户问某政策适用条件,召回片段只有结论句,没有上文限定;用户问某 API 参数,召回片段只有参数说明,没有函数名;用户问某费用标准,召回片段只有数字,没有地区和日期;用户问某合同责任,召回片段只有义务,没有免责条款。模型看到局部事实,就会做局部回答。
解决切分问题,不能只调 chunk_size。要先定义“一个可回答证据单元”是什么。对 FAQ,一个问答对就是自然单元;对制度,一条完整条款加标题路径是单元;对代码,一个函数或类加必要注释是单元;对表格,一行记录加表头和单位是单元;对会议纪要,一个议题加决议和负责人是单元。切分不是数学均分,而是业务结构识别。
有些系统会使用父子块。小块用于召回,大块用于生成。先用更细粒度片段找到相关位置,再把所属章节、父段落或相邻窗口送给模型。这能同时兼顾召回精度和上下文完整性。对长文档问答,父子块往往比单一粒度更稳。
还有一种做法是给每个 chunk 增加上下文说明。Anthropic 的 Contextual Retrieval 技术博客提出,在嵌入前用模型为每个片段补充它在原文中的上下文,使孤立片段在检索时更容易被正确理解。官方示例显示,contextual embeddings、contextual BM25 和 reranking 组合可以显著降低检索失败。这个思路说明,切分后不能假设片段仍然自解释。
四、第三类失败:只用向量召回,漏掉关键词和精确条件
向量召回擅长语义相似,但不擅长所有问题。用户问“报销单据超过 30 天还能提交吗”,语义搜索可能找到“报销流程说明”;用户问“API 返回 429 怎么处理”,向量搜索可能找到“错误码说明”;用户问“GLM-4.5-Air-FP8 需要几张 H100”,向量搜索可能找到“GLM-4.5 推理配置”。但如果问题里有精确数字、型号、错误码、条款编号、人名、产品名、日期、版本号,关键词匹配往往更可靠。
纯向量召回容易漏掉稀有词。企业知识库里有大量内部术语、缩写、项目代号、SKU、错误码和专有名词。embedding 模型未必理解这些词的业务含义,甚至可能把它们当噪声。关键词搜索虽然老,但对精确匹配非常重要。生产 RAG 往往需要混合召回:向量召回找语义相关,BM25 或关键词找精确匹配,再合并候选。
召回还会被用户问题写法影响。用户问“这个钱什么时候打”,系统要知道“钱”可能指报销、补贴、退款、付款、工资或合同款。用户问“上次那个配置能不能跑”,系统要结合会话历史。用户问“这个政策还有效吗”,系统要把有效期、版本和发布部门放进查询。直接把用户原话拿去向量搜索,常常不够。
查询改写可以改善召回,但也会引入风险。模型可以把口语问题改写成规范查询,也可以生成多个子查询覆盖不同表达。比如“RAG 答错为什么”可以拆成“chunking failure”“retrieval recall failure”“reranking”“citation hallucination”“data freshness”。但查询改写必须保留用户意图,不能擅自加条件。生产系统最好保留原查询和改写查询的召回结果,避免改写错了导致完全偏航。
召回的 top_k 也不是越大越好。top_k 太小,容易漏证据;top_k 太大,后续重排和生成被噪声影响。更合理的方式是先多路召回较宽候选,再通过重排压缩到较少高质量证据。比如向量召回 30 条、关键词召回 30 条、元数据过滤后合并去重,再用 reranker 选前 5 到 10 条进入答案生成。不同业务需要实测,不要照搬固定值。
召回还必须考虑权限和过滤。用户不该看到的文档,即使语义相关,也不能进入上下文。地区、部门、产品线、客户等级、生效日期、文档状态都可能是过滤条件。很多 RAG 错误不是“没搜到”,而是“搜到了不该搜的旧文档、测试文档、草稿文档或别的部门文档”。检索前过滤和检索后过滤都要设计。
五、第四类失败:没有重排,模型被相似噪声带偏
召回负责找候选,重排负责精挑细选。很多 RAG 原型省略重排,直接把向量相似度最高的几个片段塞给模型。这在小知识库里可能能用,一旦文档规模变大、相似内容变多、用户问题更复杂,就会明显掉质量。相似度最高的片段未必最能回答问题。
Cohere 的 Rerank 文档把 rerank 描述为给定 query 和 documents 后,把文档按语义相关性重新排序。重排模型通常会同时看查询和文档,做更细粒度匹配。相比 embedding 先把文本压成向量再比距离,reranker 能更直接判断“这段是否回答这个问题”。对复杂问题、半结构化文档、多语言和相似条款,重排尤其重要。
重排可以解决几类常见问题。第一,召回到了同主题但不回答问题的段落,重排可以把真正含答案的段落提到前面。第二,多个版本文档都相似,重排配合元数据可以优先新版本。第三,用户问题包含多个条件,重排能更好识别同时满足条件的片段。第四,召回结果里有重复摘要和正文,重排能保留更有证据价值的原文。
但重排也不是万能。reranker 的输入长度有限,太长的 chunk 会被截断;候选里没有正确证据,重排无法凭空创造;元数据不进重排输入,模型就不知道版本和来源;重排目标如果只看相关性,不看新鲜度和权限,仍会选出错误片段。重排应该和过滤、去重、版本优先级一起工作。
重排后的证据还要做组织。不要把 top 片段按相似度简单拼接。更好的组织方式是按来源分组、按章节顺序排列、把同一文档相邻片段合并、把冲突证据标出、把最新版本放前面、把引用编号固定。模型看到有序证据,比看到一堆相似片段更容易回答正确。
重排还要服务成本。把 30 个候选全部塞给大模型,既贵又容易乱。reranker 可以让生成模型只读高信号证据,减少上下文长度、降低延迟、减少 lost-in-the-middle 风险。RAG 系统里,花一点成本在重排上,往往比花更多成本换更大生成模型更划算。
六、第五类失败:引用是生成出来的,不是绑定出来的
很多 RAG 系统最危险的地方,是让大模型自己写引用。模型生成“根据文档 3”“见第 12 页”“来源:某政策”这类文字,看起来很可信,但如果引用没有和检索片段、原文位置、版本和 URL 绑定,它就只是另一段生成文本。用户以为有出处,实际出处可能不存在或不支持结论。
可靠引用应该由系统生成,而不是由模型自由发挥。检索阶段每个 chunk 都要带 source_id、document_id、title、version、page、section、url、start_offset、end_offset 等元数据。生成答案时,模型可以选择引用哪些证据编号,但最终展示的链接和出处应由系统根据编号渲染。模型不应该手写 URL,也不应该编造页码。
引用还要满足“可追溯到原文”。用户点击引用后,应该看到对应原文段落或页面,而不是只看到同一文档首页。如果答案说“试用期为三个月”,引用应定位到包含这句话和适用条件的条款。如果只跳到一份 80 页 PDF,用户仍然无法验证。生产 RAG 的引用体验应该像证据高亮,而不是参考文献装饰。
引用和答案之间还要做一致性检查。答案里的每个关键事实,最好都能对应一个或多个证据。数字、日期、条件、否定、例外、责任主体尤其需要引用。没有证据支撑的句子,要么删除,要么标注“资料中未找到”。很多 RAG 错误来自模型把证据外的常识、旧知识或推测混进答案。
引用粒度也要控制。引用太粗,无法验证;引用太碎,用户看不懂。一个答案段落通常引用一到三个证据比较合适。多个证据支持同一个结论时,要明确它们的关系:是互相补充,还是不同版本,还是存在冲突。遇到冲突证据,系统不应假装一致,而应说明“资料中存在版本差异”并优先显示生效版本。
还有一种常见失败是引用正确但结论错误。模型引用了相关段落,却误读了条件。比如原文说“除非经审批,否则不得报销”,模型回答“可以报销”;原文说“2025 年 1 月 1 日后签署的合同适用”,模型忽略日期;原文表格里金额按地区不同,模型取错列。引用只能证明模型看过资料,不能自动证明推理正确。因此高风险场景需要答案校验或人工复核。
七、第六类失败:数据新鲜度被忽略
RAG 的一个承诺是知识可更新,但很多系统上线后并没有真正更新。文档上传一次,向量库长期不重建;网页改了,索引没变;政策过期,旧版本仍被召回;文件删除了,chunk 还在;权限变更了,索引没有同步;产品价格更新了,缓存仍返回旧答案。结果用户看到的是“带引用的过期回答”。
数据新鲜度不是简单的定时全量重建。生产系统需要知道每份文档的生命周期:创建、审核、发布、生效、过期、替换、撤回、删除。每个 chunk 应继承文档状态和版本。检索时应默认排除草稿、废止、过期、无权限和低可信来源。若用户明确询问历史版本,系统才检索旧资料。
增量更新要处理删除和替换。很多系统只会追加新文档,不会清理旧 chunk。文档标题一样、版本不同,向量库里同时存在多份,召回时它们都很相似。模型可能把旧政策和新政策混在一起。正确做法是给文档稳定 ID 和版本 ID,新版本发布时标记旧版本状态,必要时删除旧 chunk 或降低优先级。
新鲜度还包括外部实时数据。库存、订单、工单状态、汇率、价格、排班、服务状态、法律法规,不能只靠离线知识库。RAG 应该和工具调用结合:静态知识走文档检索,动态事实走 API 或数据库。用户问“我的订单到哪了”,检索帮助理解流程,真正状态必须查订单系统。把动态事实写进向量库,会很快过期。
时间表达也要规范。用户问“现在还能申请吗”,系统需要知道当前日期、政策生效期和用户所在地区。答案里要说具体日期,而不是只说“目前”。索引和生成都要带时间意识。否则模型可能引用一份旧公告回答“可以”,却没有注意申请截止日期已经过去。
新鲜度还需要监控。可以建立过期文档召回率、旧版本命中率、无效引用点击率、答案时间冲突率等指标。每次用户点踩或人工纠错时,要能追溯是文档没更新、索引没更新、过滤失败、重排错误还是模型误读。没有这些指标,RAG 会随着知识库增长逐渐变差,而团队只会感觉“最近模型不太行”。
八、第七类失败:把长上下文当成保险箱
模型上下文越来越长,很多团队开始减少检索设计,直接把更多内容塞进去。这种做法在小规模演示中有效,但在生产里会遇到成本、延迟和注意力分配问题。长上下文不是保险箱,不能保证放进去的每条信息都会被正确使用。
Lost in the Middle 的发现对 RAG 很重要。相关证据位置会影响模型使用效果,尤其在多文档问答和 key-value retrieval 中,信息在中间时表现可能下降。RAG 如果把大量召回片段无序拼接,关键证据可能被埋在上下文中间。此时模型答错,不是因为证据没给,而是证据没有被有效呈现。
长上下文还会放大冲突。假设系统把新旧政策、FAQ、用户历史、工具结果、相似案例都塞进去,模型会面对多个相互矛盾的事实。没有优先级规则,它可能选择更靠近开头或结尾的内容,或者选择措辞更明确的旧内容。上下文越长,越需要排序、分组和冲突处理。
长上下文成本也很高。输入 token 多会增加 prefill 延迟和费用,自建服务还会占用 KV Cache,降低并发。为了避免一次漏召回而每次塞 50 页资料,通常不是好设计。更好的做法是先用检索和重排定位证据,再给模型足够但不冗余的上下文。长上下文可以作为复杂问题的升级手段,而不是默认策略。
如果确实需要长上下文,应设计证据布局。把任务说明、用户问题、最关键证据、冲突说明、引用规则和输出格式放在清晰位置。相同来源的片段按原文顺序排列,多个来源按优先级排列。不要把几十段候选直接拼接成“资料如下”。模型不是人类搜索结果阅读器,它需要结构化输入。
九、第八类失败:评测只看最终答案,不看中间证据
RAG 评测如果只看最终回答,很难定位问题。答案错了,可能是解析错、切分错、召回漏、重排错、引用错、生成错、数据旧,也可能是问题本身无答案。把所有错误都归给模型,会导致错误修复方向混乱。
更好的评测要分层。第一层是解析评测:原文和入库文本是否一致,表格、标题、页码、章节、图片是否保留。第二层是切分评测:一个问题需要的完整证据是否在同一块或可通过父子块恢复。第三层是召回评测:正确证据是否进入候选集。第四层是重排评测:正确证据是否排在前几名。第五层是生成评测:给定正确证据时模型是否能答对。第六层是引用评测:答案引用是否支持结论。
召回评测要建立标准答案和标准证据。比如一个问题对应哪份文档、哪个章节、哪几段原文。然后计算 recall@k、MRR、nDCG 等指标。很多团队没有证据标注,只靠人工看答案,这样很难知道是否该调 embedding、chunk、reranker 还是 prompt。
生成评测也不能只看口感。要检查事实正确、条件完整、引用准确、是否承认不知道、是否遗漏例外、是否混用旧版本。对严肃业务,答案应该分事实项打分。一个回答语气很好但漏掉免责条件,应该判失败。
评测集要持续更新。新文档、新产品、新政策、新失败案例都应进入评测。RAG 系统越用越复杂,老评测集会失效。用户真实问题是最好的来源,但需要脱敏、归类和证据标注。每次改切分、换 embedding、换 reranker、换生成模型,都要跑同一套评测,避免某项提升掩盖另一项退化。
还要做负样本评测。不是所有问题都有答案。用户问知识库里不存在的信息,系统应该说找不到,而不是编一个。负样本包括无资料问题、权限外问题、过期政策问题、条件不足问题、相似但不同问题。RAG 的可信度,很大一部分来自会拒绝。
十、第九类失败:提示词补丁掩盖了系统问题
RAG 答错后,很多团队习惯在提示词里加一句“请严格根据资料回答”。这句话有用,但很有限。如果召回片段错了,模型会严格根据错资料回答;如果资料互相冲突,模型不知道严格根据哪一条;如果引用没绑定,模型会严格生成看似规范的假引用;如果数据过期,模型会严格使用过期信息。
提示词可以约束生成风格,不能替代证据治理。真正有效的提示词应该配合系统结构:证据编号明确,来源和日期可见,冲突资料被标注,输出格式清晰,缺证据时允许回答不知道,引用只能使用给定编号。提示词越清楚,模型越容易遵守;上下文越混乱,提示词越容易失效。
不要把所有规则都塞进一个巨大系统提示词。RAG 上下文里已经有文档、证据、用户问题和输出要求,如果再加几十条重复规则,模型更容易分心。生产提示词应短而有层次:角色、任务、证据使用规则、引用规则、拒答规则、输出结构。业务规则应该来自可检索资料或结构化配置,而不是藏在提示词里。
提示词还要避免让模型“必须回答”。很多系统为了用户体验,要求模型给出完整答案。这会鼓励幻觉。更好的要求是:如果证据不足,说明缺少哪些信息;如果资料冲突,列出冲突;如果问题超出范围,建议用户提供文档或联系对应部门。可信系统不怕说不知道,怕的是假装知道。
十一、第十类失败:把RAG和Agent混在一起却没有边界
现在很多系统把 RAG 接进 Agent,让模型自己决定搜什么、读什么、调用什么工具。这个方向很有价值,但也会放大不确定性。一个普通 RAG 至少检索路径可控;Agentic RAG 如果没有边界,模型可能反复搜索、改写错查询、忽略高质量证据、使用过期工具结果,甚至把网页噪声混进企业知识库。
Agentic RAG 需要明确职责。检索工具负责找证据,数据库工具负责查实时状态,计算工具负责算数,生成模型负责解释和组织。模型可以规划,但不能绕过权限、版本和引用规则。每个工具返回结果时,应带来源、时间、置信度和错误状态。模型不应该把工具报错当成事实。
Agentic RAG 还要有停止条件。用户问一个政策问题,不需要模型搜索十轮。若前两轮已经找到高置信证据,就应该回答;若多轮仍找不到,应说明未找到。没有停止条件的系统会增加延迟和成本,还可能在后续搜索中找到低质量噪声,把原本正确的答案带偏。
多工具场景更需要证据合并。比如用户问“我这个订单是否还能退款”,系统可能需要检索退款政策、查询订单状态、查询商品类型和检查时间。最终答案必须说明哪些结论来自政策,哪些来自订单系统。静态规则和动态状态不能混成一团。否则用户无法判断答案依据。
十二、如何排查一次RAG答错
遇到 RAG 答错,不要先改 prompt。第一步,拿到用户原问题、最终答案、引用和所有进入模型的上下文。没有这些日志,排查只能猜。第二步,查看正确答案需要哪些原文证据。第三步,检查这些证据是否在知识库里,是否解析正确,是否有权限,是否是最新版本。
第四步,看切分。正确证据是否被切碎,关键条件是否和结论分离,表格是否丢表头,标题路径是否保留。第五步,看召回。正确 chunk 是否进入候选 top_k;如果没有,试关键词、混合召回、查询改写和元数据过滤。第六步,看重排。正确候选是否被 reranker 排到前面;如果没排上,检查 chunk 太长、输入缺元数据、问题改写错误或 reranker 不适合语言。
第七步,看证据组织。正确证据是否进入生成上下文,是否被放在容易利用的位置,是否和冲突旧资料混在一起。第八步,看生成。给模型只提供正确证据,它是否还能答错;如果仍错,才重点考虑换模型、改提示词或增加校验。第九步,看引用。答案里的引用是否真实支持结论,点击能否回到原文。
这个流程看似麻烦,但它能避免盲目优化。很多时候问题在第二步就暴露:正确文档根本没入库。或者第五步发现:正确证据在候选第 40 名,top_k 设成 5。或者第七步发现:旧版本放在新版本前面。只有分层排查,才能知道该修哪里。
十三、一个更可靠的RAG架构
可靠 RAG 的第一层是数据治理。文档进入系统时,要记录来源、作者、部门、版本、生效期、权限、语言、类型和更新时间。解析后要有质量检查,低质量解析不能直接入库。文档状态变化要同步到索引,删除和过期要真的生效。
第二层是结构化切分。按文档类型选择切分器,保留标题路径、页码、表头、代码结构、列表层级和前后关系。必要时使用父子块、多粒度索引和上下文增强。切分结果要可视化,让运营或知识管理员能看到系统到底把文档切成了什么。
第三层是混合召回。向量召回、关键词召回、元数据过滤、同义词扩展、查询改写和会话上下文共同工作。召回候选要去重、按权限过滤、按版本过滤。对精确问题,关键词和元数据权重要提高;对语义问题,向量权重可以提高。
第四层是重排和证据压缩。用 reranker 从候选里挑高质量证据,再按来源、版本和章节组织。对太长的证据,做面向问题的压缩,但压缩结果仍要保留原文引用。不要把摘要当成唯一证据,摘要可能丢条件。
第五层是受约束生成。模型只能基于给定证据回答,引用只能使用证据编号。输出结构要适合用户:先给结论,再给依据,再给限制和下一步。没有证据时要明确说明。遇到冲突时要展示冲突,而不是强行合并。
第六层是验证和反馈。答案生成后检查引用是否存在、引用是否被使用、关键事实是否有证据、是否使用过期文档。用户反馈和人工纠错要回流到评测集。系统每次改动都要跑分层评测,而不是只看一两个演示问题。
十四、给不同团队的落地建议
个人开发者做 RAG,先不要追复杂框架。用少量高质量文档,手工检查解析和切分,建立十几个真实问题和标准证据。先做到每个答案都能引用原文,再考虑多路召回和重排。不要一开始就上传几千份 PDF,然后靠模型解决所有混乱。
创业团队做产品,重点是可观测和评测。每次回答都要能回放:用户问题、召回候选、重排结果、进入模型的证据、最终答案和引用。没有回放,就无法修用户投诉。评测集要覆盖主要客户场景,尤其是失败案例。
企业内部知识库,重点是权限、版本和新鲜度。企业资料不是公开网页,谁能看什么很重要。政策和流程经常更新,旧版本必须管理。知识管理员需要看到入库状态、解析质量、过期提醒和用户低分问题。RAG 不只是技术系统,也是知识运营系统。
高风险行业,重点是拒答和复核。医疗、法律、金融、人事、合规等场景不能把 RAG 答案当成最终裁决。系统应给依据、限制和建议复核路径。没有足够证据时宁可不答。引用必须能回原文,关键结论最好有二次校验。
开发工具和代码知识库,重点是结构。代码不能按普通文本切分。文件路径、函数、类、接口、测试、README、issue、commit 信息都应保留。用户问错误栈时,关键词和符号匹配非常关键。生成代码建议时,要引用具体文件和函数,而不是泛泛解释。
十五、结论:RAG可靠性来自证据链,不来自一句“严格根据资料”
RAG 经常答错,是因为很多系统只完成了最容易演示的部分,却跳过了最难生产化的部分。切分没有保语义,召回没有保覆盖,重排没有保相关,引用没有保可追溯,数据没有保新鲜,评测没有保定位。最后模型只能在混乱证据里生成一个看似流畅的答案。
好的 RAG 不追求把所有资料塞给模型,而是把正确证据以正确顺序、正确粒度、正确来源送给模型。它会知道哪些资料过期,哪些资料冲突,哪些问题无答案,哪些结论需要引用。它不是让模型替你读一堆乱文档,而是建立一套证据加工和验证系统。
当 RAG 答错时,最有效的态度不是“换个更强模型试试”,而是沿证据链往回查:原文是否正确,切分是否完整,召回是否命中,重排是否选对,引用是否绑定,数据是否最新,模型是否误读。只有这样,RAG 才能从演示功能变成可信产品能力。
十六、RAG质量指标应该怎么设
RAG 上线后,最怕只有一个笼统的“满意度”。满意度有价值,但它太晚、太粗,也不一定能解释问题。用户点踩可能是答案错,也可能是语气差、太长、没给操作步骤、引用打不开或等待太久。要让 RAG 可维护,必须把指标拆到链路层。
解析层可以看解析成功率、低质量页面比例、表格保留率、OCR 置信度、空文本文件比例、重复页眉页脚比例。切分层可以看平均块长、过短块比例、过长块比例、标题路径缺失率、表格块完整率、父子块关联率。召回层可以看 recall@k、关键词命中率、向量召回覆盖率、正确文档进入候选比例。重排层可以看正确证据进入 top3 或 top5 的比例。
生成层指标要看事实正确率、引用支持率、无答案拒答率、格式成功率、答案长度、人工修改率。引用层要看可点击率、原文定位成功率、引用与结论一致率。新鲜度层要看过期文档命中率、旧版本命中率、删除文档残留率和索引延迟。性能层要看首字延迟、总耗时、检索耗时、重排耗时、生成耗时和超时率。
这些指标不需要一天全部建完,但至少要有回放能力。每个错误答案都应该能看到检索候选、重排顺序、进入模型的上下文和最终引用。没有回放,所有指标都是表面数字。RAG 是证据链系统,监控也必须沿证据链设计。
十七、知识运营比模型调参更长期
很多团队把 RAG 当成工程项目,做完上传、检索、问答就结束。真实情况是,RAG 更像知识运营系统。文档每天会变,组织结构会变,权限会变,用户问题会变。没有人负责知识质量,系统会越来越脏。模型能力再强,也无法长期弥补知识库失管。
知识运营至少包括四件事。第一,入口治理。哪些文档能入库,谁审核,草稿能不能被检索,扫描件是否需要人工校对。第二,版本治理。新旧版本如何关联,废止文档如何处理,历史版本什么时候可查。第三,反馈治理。用户点踩后谁处理,错误样本如何归类,是否需要更新文档、调整切分还是修生成。第四,质量巡检。定期抽查高频文档、高风险文档和低分问题。
很多 RAG 错误其实是组织流程问题。客服知识库里新政策已经发布,但知识管理员没入库;产品价格改了,但旧 FAQ 还在;法务更新了合同模板,但销售仍然上传旧版;权限组调整了,但索引没同步。这些问题不是改 prompt 能解决的。RAG 想可靠,必须有人对知识生命周期负责。
知识运营还要面向最终用户。用户不关心向量库、embedding 和 reranker,他只关心答案是否能解决问题。界面应展示清晰结论、来源、更新时间和下一步操作,不要暴露内部字段和调试术语。引用打不开、来源标题混乱、更新时间缺失,都会削弱信任。RAG 产品的可信度,一半来自答案,一半来自证据呈现。
十八、几个典型错误模式
第一种模式是“相似条款误命中”。用户问请假制度,系统召回加班制度,因为两者都出现“审批”“部门负责人”“三个工作日”。模型据此回答,语气很确定。解决办法是加强元数据过滤、条款标题权重、关键词召回和重排,让同主题但不同制度的片段被区分开。
第二种模式是“旧版本压过新版本”。新政策和旧政策文字大部分相同,向量相似度都高,旧版本因为内容更长或出现更多关键词排在前面。模型引用旧版本回答。解决办法是版本状态过滤、生效日期排序、旧版降权和冲突提示。知识库里允许保留历史版本,但默认回答当前版本。
第三种模式是“表格失去表头”。原文表格里有地区、等级、金额和适用时间,解析后每行只剩数字。用户问某地区标准,模型召回数字却不知道列含义,于是取错值。解决办法是表格结构化入库,把每行记录和表头、单位、标题绑定,必要时用数据库查询而不是普通文本检索。
第四种模式是“多跳问题只召回一跳”。用户问某员工是否符合补贴条件,系统需要同时查员工地区、入职时间、政策条件和例外条款。普通 RAG 只召回政策结论,没有查员工状态。模型给出一般性回答。解决办法是区分静态知识和动态数据,让 RAG 与工具调用协同,并在答案里分清依据来源。
第五种模式是“摘要覆盖原文”。系统为了省 token,先把文档摘要入库。摘要里漏掉例外条件,用户问到边界情况时,模型只能根据摘要回答。解决办法是摘要可以作为导航,但不能替代原文证据。最终回答高风险问题时,仍要引用原文片段。
第六种模式是“负样本被强答”。知识库没有答案,召回系统找了几个相近片段,模型为了满足用户给出推测。解决办法是设置证据阈值、拒答策略和负样本评测。没有足够证据时,正确答案就是说明未找到,并告诉用户需要补充什么资料。
第七种模式是“引用编号漂移”。模型回答第一段引用了资料 2,但系统渲染时资料排序变化,页面显示成资料 1。用户点击后发现不支持结论。解决办法是引用编号由系统固定,生成前后保持稳定,用不可变 evidence_id 绑定,不让模型或前端重排破坏映射。
十九、从原型到生产的路线
第一阶段,做小而准。选择一个明确知识域,清洗几十到几百份高质量文档,建立真实问题集和标准证据。先让系统在这个小范围内答准,而不是追求全公司文档都能问。小范围答不准,扩大规模只会放大混乱。
第二阶段,加回放和评测。把每次问答的中间结果存下来,建立人工标注流程。用户反馈进入错误库,错误库反过来扩充评测。每次改 chunk、embedding、reranker、prompt、模型,都要跑同一套问题。没有评测的迭代,容易把旧问题修好又引入新问题。
第三阶段,加混合召回和重排。当文档规模扩大后,单一向量召回通常不够。加入关键词、元数据、查询改写、reranker 和去重。此时要重点观察召回覆盖和重排质量,而不是只看最终答案。检索质量提升后,生成模型往往不需要盲目变大。
第四阶段,加权限、版本和新鲜度。只要进入企业生产,这三件事就不能拖。权限错误是安全问题,版本错误是可信问题,新鲜度错误是业务问题。索引系统要和文档系统或业务系统建立同步,不要依赖人工偶尔重建。
第五阶段,加高风险保护。对涉及钱、合同、合规、人事、医疗、法律的问题,系统应该提高证据阈值,给出限制说明,必要时要求人工复核。RAG 可以大幅提高效率,但不应把高风险判断伪装成全自动权威结论。
走完这些阶段,RAG 才更接近生产级能力。它不再是一个“接上向量库的大模型”,而是一个围绕证据、版本、权限、引用和反馈持续运行的系统。
参考资料
- Patrick Lewis 等:Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks,https://arxiv.org/abs/2005.11401
- NeurIPS 2020:Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks,https://papers.nips.cc/paper/2020/hash/6b493230205f780e1bc26945df7481e5-Abstract.html
- Nelson F. Liu 等:Lost in the Middle: How Language Models Use Long Contexts,https://arxiv.org/abs/2307.03172
- Anthropic:Enhancing RAG with contextual retrieval,https://platform.claude.com/cookbook/capabilities-contextual-embeddings-guide
- LangChain:Text splitters,https://docs.langchain.com/oss/python/integrations/splitters/index
- LlamaIndex:SentenceSplitter,https://docs.llamaindex.ai/en/stable/api_reference/node_parsers/sentence_splitter/
- Cohere:An Overview of Cohere's Rerank Model,https://docs.cohere.com/docs/rerank-overview
- Cohere:Rerank,https://cohere.com/rerank
- OpenAI:Retrieval API guide,https://platform.openai.com/docs/guides/retrieval