☰
RAG实战:决定检索质量与生产级落地的六处关键细节
2026/10/5 5:33:17 网站建设 项目流程

先下个结论:RAG 确实烂大街了,但烂的是那条流水线——读取文档、切成块、embedding、扔进向量库、TopK 召回、拼 Prompt 交给大模型。这套东西找个周末跟着教程就能点出来,Dify 拖拽一下、LangChain 写几十行、甚至 ollama 本地拉起一个小 demo,两天内都能跑得冒烟。但真正决定一个 RAG 系统能不能进生产,问十个问题能答对几个,能不能让用户觉得“这玩意儿真的懂我的文档”,全卡在流水线之外那六处细节上。我在帮团队搭本地知识库、调检索精度时,几乎每次都栽在同样的地方,今天把这六处掰开揉碎讲清楚。

1. 为什么流水线突然就不值钱了

1.1 那两天就能点的“标准八步”

先说流水线本身。现在随便点开一篇 RAG 教程,步骤几乎是复读机:加载文档、文本清洗、切 chunk、embedding、存向量库、用户提问后 query 也 embedding、TopK 相似度检索、拼 prompt 给 LLM。每一步都有现成组件,LangChain 的 loaders、RecursiveCharacterTextSplitter、OpenAI embedding、Chroma/FAISS/Milvus、再套一个 LLM 调用,完事。

这套标准八步的含金量低到什么程度呢?我见过有人用 no-code 平台一晚上就搭出一个“智能客服问答机器人”,演示时能对着 PDF 问出几个像模像样的回答。问题在于:demo 能跑,离能用差着十万八千里。一旦你换成真实业务文档——扫描件、多栏排版、表格、术语密集的合同、带版本冲突的制度文件——标准流水线立刻暴露出粗糙的一面。召回不准、答案张冠李戴、模型信誓旦旦地编造不存在的条款,这些事我几乎每天都在不同项目里看到。

1.2 分水岭全在“中庸方案”的取舍里

为什么大家都做一样的流水线,结果差距这么大?因为标准流水线给的是一套中庸方案,它解决了“有没有”的问题,没解决“好不好”的问题。真正的分水岭,是在每个环节里做取舍的能力:解析到什么粒度、chunk 怎么切才不被拆断语义、检索用什么策略才能对付别名和口语化提问、召回的单元怎么二次精选、多个冲突信息摆在 prompt 里怎么让模型不糊涂、上线之后怎么知道改进了还是退化。

这六处,每一个都有一堆可以展开讲的实战细节。你哪怕只把其中两三处做扎实,效果都能拉开不重视这些细节的团队一大截。下面我按实战中踩坑的频次,逐个拆给你看。

2. 第一处:文档解析——召回率死在这里,不是死在向量库

2.1 解析不是“读文字”,而是“拆结构”

很多人以为解析就是把 PDF 的文本抠出来。PDF 这种格式本身就分两种:有文本层的电子版,和扫描件。就算是有文本层,你用 PyPDF2 之类的一顿乱抽,抽出来可能是按页、按行甚至按物理坐标乱序的碎文字。多栏排版的论文、带页眉页脚的制度文件、左边是描述右边是对应数据的表格,纯文本抽出来,语义连一半都保不住。

生活化类比:把一本说明书按物理位置剪成互相不连接的小纸片,再让一个助手读这一堆纸片回答你的问题。他不是不知道内容,而是找不到内容的位置和上下文。文档解析做不好,后面切块、向量化、检索全跟着遭殃。我经常说,RAG 的上限在解析,下限才在模型。

2.2 表格、多栏、扫描件怎么处理才算过关

过了阈值之后,工具选型也很关键。目前实际项目里我比较推荐的方向:能用“布局感知解析”就别用简单文本提取。简单说,解析结果要尽量保留标题层级、段落关系、表格结构、甚至阅读顺序。

表格是最容易翻车的点。你如果直接把表格按换行符切平,每一行的文本单独成块,模型根本看不出“单价 300 元”和“产品 A”之间的关联。比较稳的做法是把表格转成 Markdown 或者 HTML 结构保留。具体用什么工具,我按场景列个表供参考:

场景推荐方案说明
纯文本 PDF、Word、HTMLUnstructured / BeautifulSoup批量清洗、段落重构,能识别标题
复杂 PDF(多栏、表格、公式)MinerU / marker / PyMuPDF 自研输出 Markdown,保留结构信息
扫描件、图片型 PDFPaddleOCR / Tesseract + 布局恢复OCR 后必须做版面重构,不能逐行喂
本地离线优先PyMuPDF + PaddleOCR全本地运行,不依赖外部接口

一个容易忽略的点:解析之后要保留“元素类型”和“层级信息”。这段文字是 h1 标题、是正文、还是表格单元格?这些信息在切块阶段是你的护身符。很多项目解析完只留纯文本,等于把结构信息全扔了,后面想按标题切块都切不了。

2.3 图文边界:文字 RAG 到底能不能存图片

热词里有人问“RAG 知识库能存图片吗”。这个问题要看你怎么定义“存”。如果你把图片塞进文档流当作附件,那当然能存;但如果用户提问“这张图里的拓扑结构是什么样的”,纯文本 RAG 一定答不上来。因为流程里根本没有图像理解这个环节。

现在的实践是分两条路:要么走多模态 embedding + 多模态大模型,图文同时进检索和生成;要么在解析阶段把图片抽出来做 OCR 抽文字,或者让视觉模型先生成图片描述,再把描述作为文本块入库。后面这条成本低、落地快,适合大多数本地知识库场景。别期待一个纯文本流水线能神奇地“看”图,这个预期要提前掐灭。

3. 第二处:切块不是“固定尺寸+重叠”就能交差

3.1 固定 chunk 的隐性成本,用代码示例拆给你看

切块大概是整个流水线里被抄作业抄得最狠的环节。默认配置往往是RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50),然后就不动了。这个配置的问题在于:它对所有文档用同一把尺子,完全不看内容结构。

看个反面例子:

chunk_size = 500 overlap = 50 # 一句安全制度可能 400 字,正好被拦腰截断: # chunk_12: "...严禁在未经审批的情况下..." # chunk_13: "动用公司生产环境配置,违者..."

用户问“未经审批能用生产环境吗”,检索阶段很可能只召回到 chunk_12,模型看到“严禁在未经审批的情况下”,后面接不到“动用生产环境配置……违者”,回答起来模棱两可。这不是模型不行,是切块把关键信息劈成了两半,而且你永远不知道哪一次提问会踩中那个断点。

更麻烦的是语义拆散。一段完整论述被机械切分后,embedding 表达的是“半句话的向量”,和完整观点的向量相似度天然偏低。这就是为什么很多人调了半天模型,召回效果没变化——问题根本不在 embedding 模型,而在喂给它的片段本身就不完整。

3.2 结构化切块、父子分块与“随文档类型变化”的策略

切块策略应该是“先结构后长度”。我现在的习惯是:

  • 优先按文档语义结构切:标题作为自然边界,h1 下的大段落到 h2 再切,表格按行组或自然语义块切,列表按条目组切。保证每个 chunk 是一个尽可能完整的语义单元。
  • 长度只是兜底约束:结构切出来的块太长,再按句子边界、标点边界二次分割;太短,可以把相邻相关小节合并。
  • 善用父子分块(Parent-Child / Small-to-Big):索引用小块提高召回命中率,生成时再把小块映射回它的大块上下文。这招在“检索到但内容偏窄”的场景下非常管用。

举个例子。一个运维手册里有大章节“数据库备份方案”,下面分“全量备份”“增量备份”两节。你按小节各切一块,用户问“备份策略全流程”,单小节可能答不全。用父子分块,检索命中“增量备份”小节,但把“数据库备份方案”整章喂给模型,它就能把上下文补全。

3.3 切块参数速查表

场景推荐策略chunk 大概范围
规章制度、合同条款/章节为边界300-800 字
技术文档、FAQ段落+父子分块200-500 字
表格密集资料按表格结构块切,转 Markdown按行组,100-400 字
网页/Wiki 文本按标题层级切200-600 字
聊天记录/短文本按对话轮次合并切300-600 字

原则只有一条:切之前,先问自己“这句话的答案可能分布在哪些块里”,然后去设计边界。切完之后抽查 20 个 chunk,肉眼看看有没有把同一句话、同一个结论、同一条规则拦腰斩断。

4. 第三处:召回环节——TopK 之外还有语义鸿沟

4.1 向量最相似 ≠ 答案最正确

到了召回阶段,很多人以为向量检索 TopK 返回的就是“最相关的几块”。残酷的现实是:embedding 模型衡量的是向量空间距离,它不是万能的,对简短问句、同义改写、专有名词缩写、中英文混写特别不友好。

典型的失败现场是:知识库里写着“RAG 系统的召回模块基于 HNSW 索引”,用户问“那个用层级导航小世界算法的搜索是啥原理”,向量检索可能召不到那一块,因为“HNSW”和“层级导航小世界”在字面上没一个词重合。再比如企业内部简称:“生产环境”叫“prod”、“客户关系管理”叫“CRM”,文档里全是全称、用户提问全是简称,纯向量检索照样抓瞎。

这个问题在本地知识库场景更严重。本地部署的轻量 embedding 模型(比如常见的 300M、400M 参数模型)对复杂语义的理解能力有限,你得在检索策略上找补,而不是指望换个大模型解决问题。

4.2 查询改写、HyDE 与多路召回

现在比较成熟的做法是把召回做成一个多路体系,而不是单靠一路向量。我建议按下面三步搭:

  1. 查询改写:用户输入的问题,先交给 LLM 做一次改写。一个复杂问题拆成多个子问题,一句话里带简称的补全全称,口语化表述翻译成文档风格。这一步很便宜,但对召回率提升非常明显。

  2. 混合召回:向量检索一路,关键词/BM25 检索一路,然后做结果融合。BM25 对精确词匹配、编号、缩写非常敏感,正好弥补向量检索的短板。现在很多平台内置了这个逻辑,但不少人没开或者没意识到为什么要开。

  3. HyDE 兜底:对“用户问得太抽象、文档写得太具体”的场景,可以让 LLM 先根据问题写一个假想的答案段落,再用这个假想答案去检索原文。假设答案会“说人话”,通常和文档表达方式更接近,能显著提高命中。

多路召回之后再谈排序,这也是我们下一处要讲的重排。别把 TopK 当成终点,那只是海选,不是最终决定。

5. 第四处:Rerank 才是被低估的高性价比投资

5.1 TopK 召回夹带的“看起来相关,实则没用”

多路召回之后,你会拿到比如 50 条候选片段。这里有个很多人没意识到的问题:TopK 不代表 Top 正确。向量相似度高的片段,有可能是同一个意思在不同页面的重复表述,有可能是包含了关键词但语义根本不匹配的段落,还有可能是父子分块里多路命中的冗余信息。

如果你直接把 TopK=5 的结果全塞给大模型,模型面对的是一锅杂烩:有用的内容可能只占一两条,剩下三四条要么干扰、要么重复,模型的注意力被分散,回答自然飘。用户感知到的就是“答非所问”“明明文档里有,为什么它答出来像编的”。

5.2 重排模型怎么选、怎么接入、效果能提升多少

重排的本质,是用一个更精细的模型对海选结果做二次打分。流程是:先用便宜的向量检索/BM25 暴力召回几十条,再用重排模型(Reranker)对 query 和每个候选片段做深度交互匹配,重新排序,最后只取前 3-5 条作为上下文。

重排模型和 embedding 模型的区别,我经常这样解释:embedding 是双塔结构,把 query 和文档分别编码再算余弦相似度,算得快但交互浅;Reranker 是交叉编码器,把 query 和文档拼在一起让模型同时看,算得慢但语义理解深。线上流程里先用双塔粗筛掉 99% 不相关的,再对剩下的做交叉精排,性价比最高。

现在本地也能跑不错的轻量重排模型,比如 BGE-Reranker 系列。实测数据给你参考:我做过一个内部运维文档的知识库,原来纯向量检索命中率大概 65%,加了关键词融合后到 72%,再加 Rerank 精排,最终命中率到了 83%,而生成的答案主观质量也从“经常漏掉关键约束条件”变成“基本能把约束条件列全”。这一个环节投入产出比极高,几乎没有理由不做。

6. 第五处:上下文工程——Prompt 里塞得越多,答案越糊涂

6.1 分块拼接的三大坑:漂移、遮蔽、幻觉

很多人把 RAG 的生成端想得太简单:检索到的 chunk 拼起来丢给模型就行。现实是上下文工程在 RAG 里一样是分水岭。因为多个 chunk 本身可能来自不同章节、撰写时间不同、甚至相互矛盾。

三大常见坑:

  • 上下文漂移:一个 chunk 讲备份方案,另一个讲应急预案,模型在生成时可能把应急预案的内容混进备份方案里。
  • 信息遮蔽:重要的约束条件夹在大量无关细节里,模型抓不住重点,回答变得泛泛而谈。
  • 幻觉放大器:模型发现多个 chunk 里有相似但不一致的说法时,会倾向于编造一个“合理”的统一说法,而不是指出文档本身有冲突。

6.2 打元信息、压缩上下文、冲突消解的实操思路

第一件事,给每个进入上下文的 chunk 打上元信息标签。文件名、章节路径、页码、最后修改时间、文档类型。既要让模型看到,也要把来源写进回答里。我常用的 prompt 片段长这样:

请根据以下参考资料回答用户问题。每条资料用「来源: 文件名/章节/页码」标注。 如果资料之间存在矛盾,请分别列出不同说法,并标注各自来源,不要自行合并。 如果资料中没有足够信息,请直接回答“当前资料中未找到相关内容”,不要推测。 资料如下: - [来源: 备份规范 v3.2 / 第三章 / P14] {chunk_text} - [来源: 应急预案 v1.1 / 附录B / P32] {chunk_text}

第二件事,是“有损压缩”。上下文越长,模型越容易糊涂,这是天然规律。如果你召回了很多条,先让一个轻量 LLM 或者规则把明显无关的过滤掉,再把每条压缩成只保留与问题直接相关的句子。压缩之后,模型对关键信息的抓取率会明显上升。

第三件事,是冲突消解。文档内部出现新旧版本冲突时,别让模型自己裁决。要么按时间新鲜度给新版本更高权重,要么把冲突的几条并列输出,让用户自己看。至少在 prompt 层面要知道:“当资料冲突时,模型必须明示冲突,不能默认选一边”。

7. 第六处:评测闭环——没有指标的 RAG 都是自嗨

7.1 到底要测哪些指标,评测集怎么造

最后一个分水岭,也是最容易被人跳过的一步:评测。很多团队搭完 RAG 就用“看起来还行”交差,结果换了一批文档、改了一下切块参数,效果到底变好还是变坏,谁都说不出个数字。没有评测闭环,后续优化全是拍脑袋。

RAG 的评测至少要覆盖两层:

  • 检索层:召回率(正确答案是否在召回的候选里)、命中位置(MRR,正确答案排第几)。
  • 生成层:答案正确率、忠实度(答案是否都能从参考资料里找到依据,有没有编造)、回答完整性(关键点是否漏掉)。

评测集的构建不必一开始追求海量,质量比数量重要。挑 50-100 条真实高频问题,对每个问题标注标准答案和对应的支持文档片段。如果一个问题能对应多个文档片段,要一并标出来。这一步建议找实际用户或者业务方一起做,否则你标的问题可能根本不是用户会问的问题。

7.2 每次问答留痕,把 badcase 变成参数

光有评测集还不够,线上系统要留痕。每次问答把用户的原始提问、改写后的 query、召回到的 chunk、最终喂给模型的上下文、模型的回答、用户有没有点踩,全部记录下来。这个数据池是你后续迭代最大的资产。

有了留痕之后,碰到一个 badcase 不是只看一眼就完,而是要走一遍诊断链路:是解析阶段丢内容了,还是切块把答案切碎了,是召回没召回到,还是召回对了但重排把它排掉了,或者是上下文冲突把模型带偏了。定位到具体环节再动手改,改完拿评测集回归一遍,看指标是涨是跌。

这是一个循环的工程问题,不是一次性配置问题。我见过太多团队卡在“不知道为什么变好了/变差了”,本质就是没有评测闭环,改什么都像是在黑箱里碰运气。

8. 常见问题和排查技巧实录

8.1 本地 RAG 最常踩的五个坑

把这几年帮别人排查问题的经验汇总一下,下面这些坑在本地知识库场景出现频率最高。

  • 向量维度对不上:换了 embedding 模型但没重建索引,或者代码里写死了上一版模型的维度,数据库查出来一堆空结果。
  • 解析出来一堆乱码:中文 PDF 用了不支持中文编码的解析库,或者扫描件没走 OCR 直接进了切块流程。
  • 切块边界拍脑袋:chunk_size 设为 1000,长句子全被切断,召回率直线下降;或者设成 100,每个 chunk 语义碎片化,模型根本读不出完整意思。
  • TopK 太大:一把梭把 TopK=10 的原文全塞进 prompt,模型被噪音淹没了,答得比 TopK=3 还差。
  • 评测只靠肉眼:改了一个参数之后“感觉变好了”,结果换几个问题又翻车,没有评测数据支撑,反复折腾。

8.2 诊断顺序:从这五步开始排查

如果你的 RAG 回答质量不理想,别上来就换大模型。按照这个顺序排查更快:

  1. 把用户问题拿去直接检索,看 Top10 里有没有正确答案。没有,说明问题在解析、切块或召回策略;有,说明问题在重排或生成上下文。
  2. 检查命中的那块文本是不是完整语义。如果是半截话,回到切块那一节调整。
  3. 检查给模型的那几条里有没有明显不相关的。有,就要加 Rerank 或者降低 TopK。
  4. 检查 prompt 里有没有告诉模型“不知道就说不知道”。没有,幻觉概率会高很多。
  5. 跑到评测集上算一个数字,改之前和改之后对比,而不是靠“感觉”。

这套顺序能解决我遇到过的绝大多数 RAG 落地问题。

9. 这些经验往哪里用:从本地 demo 到生产系统

讲了这么多,你会发现这些分水岭其实不挑框架。你用的是 LangChain、LangChain4j、Dify、还是自己从零写的 Python 脚本,该踩的坑一个都不会少。LangChain4j 这种 Java 生态里所谓 “Easy RAG” 的方案,帮你把流水线封装好了,但如果你不知道文档解析要保结构、不知道重排的必要性,一样会把一堆垃圾上下文喂给模型。

我最近帮朋友调一个 ollama 本地知识库,零基础照着教程搭的,答不上问题就怪模型小。我一看,文本拆解用的还是默认的纯长度切分,PDF 表格被切得稀碎,召回也是单路向量。把解析换成布局感知、切块改成结构优先、加上 BM25 混合召回,同样那个 7B 模型,回答质量立刻不一样了。这说明大模型之外的空间远比你想的要大。

至于 Wiki 和 RAG 的结合、ontology RAG 这类偏进阶的玩法,本质上也是从第一处到第六处某一处的延伸。Wiki 站点解析要处理导航噪音和页面结构,属于文档解析;ontology 要处理实体关系,需要在切块时保留关系三元组、在检索时按关系跳转,属于召回和上下文工程的结合。理解了这六处,这些变体对你来说就不是黑盒,而是同一个框架下不同环节的定制。

最后再分享一个小技巧:你不需要一开始就在所有六处都做到满分。把解析和切块这两个“地基”做好,收益最明显;再加一个重排,效果基本能到可用线;关联评测闭环之后,后续迭代才有方向盘。一次一个环节,每个环节都拿数据说话,你的 RAG 才能真正从“能跑”走到“好用”。

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

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

立即咨询