ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

RAG实战指南:为AI Agent打造知识获取管道

RAG实战指南:为AI Agent打造知识获取管道 做 AI Agent 快两年了有个场景我印象特别深用户拿着企业内部一堆散落文档来问——我们的报销制度单笔超过多少需要分管副总审批你让大模型硬答它要么编一个数字要么理直气壮地说我不知道。这真不是模型的锅。模型训练时压根没见过你公司的报销制度它的知识全部封存在参数里来自于遥远的公开语料。想让 Agent 真正能在具体业务里干活你必须给它修一条知识获取管道把外部知识在生成之前送进上下文。这就是 RAGRetrieval-Augmented Generation检索增强生成。这篇是走进 AI Agent系列的第四篇聊的是 AI Agent 知识获取管道最基础也最核心的一块RAG。我会从知识割裂问题讲起把 RAG 的索引、检索、增强、生成四段式流程拆开揉碎然后给出一套可以直接上手的搭建方案和真实代码最后聊聊我从基础 RAG 走向 Agentic RAG 时踩过的坑。适合正在做 Agent 落地、被幻觉和知识更新问题困扰的开发者也适合想系统理解 RAG 原理的产品和技术同学。1. 为什么 Agent 需要一条知识管道预训练知识的天花板1.1 大模型的知识幻觉到底从哪来先看一个很多人忽略的事实大模型不是数据库它是一台概率续写机器。你问它问题它不是在查表而是在根据前文预测下一个最可能的 token。它训练时见过海量文本知识以参数模式的形式存在但这些知识有三个硬伤。第一是时效性。预训练语料是某个时间点之前的数据模型对之后发生的事情一无所知。你问它今年新品发布会延期到几号它只会按训练数据里那个时间点之后的信息瞎编。第二是私有性。企业内部的制度文档、产品手册、客服话术、项目复盘这些数据永远不会进公开语料。模型对它们零认知你硬问它就硬编。第三是准确性。即便是公开知识模型也可能把相似概念混淆把时间、数字、专有名词张冠李戴。这三个硬伤叠加起来就是那条著名的幻觉结论模型在生成——它真的以为自己知道但它不知道它不知道。你让模型回忆一段它从未见过的知识本质上是在逼它写小说。1.2 Agent 的知识来源体系参数记忆、上下文记忆、外部检索把 Agent 比作一个人它的知识来源可以粗分为三层。第一层是大脑记忆也就是模型参数里封存的预训练知识。这个层决定了 Agent 的基础语言能力和通识水平但不可更新、不可定制你没法往里塞公司文档。第二层是工作记忆也就是上下文窗口里临时放入的信息。你可以在每次请求时把相关资料塞进上下文让模型临时读一遍再回答。这个层更新灵活但容量有限塞得太多模型会抓不住重点。第三层是外部资料库也就是文档、数据库、知识图谱、API 等外部存储。这一层容量无限但模型没法直接读需要一条管道去取。RAG 干的事情就是打通第二层和第三层根据用户问题先从外部资料库里检索出最相关的片段再把它们注入到上下文窗口让模型基于临时读过的资料来回答。为什么叫管道因为这条链路是流水线式的文档进来要被切割、编码、存储问题进来要被编码、匹配、排序最终拼装成提示词再送去生成。1.3 RAG 在生产环境里的真实定位很多刚接触 RAG 的人把它当成给模型外接一个数据库这个理解太窄了。在生产环境里RAG 承担的职责其实是Agent 的长期记忆与事实底座。它跟微调是两条完全不同的路线微调是把知识焊进参数成本高、周期长、更新要重新训练RAG 是把知识放在手边改文档只需重建索引秒级生效。我个人的经验判断一个场景该不该上 RAG就两个标准一是知识会不会频繁变化二是答案是否要求可溯源。如果答案要求严谨可查法务、医疗、财务或者知识每周都在变产品方案、活动规则、政策解读那就必须上 RAG微调救不了你。反过来如果只是想让模型的语气更像某个人、输出格式更稳定那微调反而更划算。还有一点值得强调RAG 不是用来消除幻觉的银弹。它能把幻觉从凭空编造降低为依据不足时拒答但如果检索到的资料本身不对模型照样会基于错误资料自信地胡扯。所以 RAG 工程的核心根本不是生成端而是检索端的质量。2. RAG 核心流程拆解索引、检索、增强、生成四段式2.1 文档加载与清洗源头决定终点RAG 管道的第一步是把原始文档读进来。这一步看起来不起眼但数据质量直接决定最终效果。你丢进来的 PDF 如果是扫描件不做 OCR 就直接切分检索出来的全是乱码Word 文档里的页眉页脚、表格跨页、目录页不去清洗就会变成大量噪声片段。我习惯把清洗分三层做。第一层是格式转换把 PDF、Word、HTML 统一转成纯文本或 Markdown保留标题层级和列表结构因为后面切分时这些结构信息非常有用。第二层是噪声过滤去掉页眉、页码、目录、水印、重复的免责声明这些内容切进 chunk 里只会稀释检索的语义密度。第三层是表格和长文处理表格如果转成纯文本会丢失行列关系我会把它们转成 Markdown 表格或按行拆成字段名: 值的形式超过一定长度的正文段落手动按二级标题拆分。这一步我的忠告清洗时间不要省。源头多留一个脏字符下游的 embedding 就多一分噪声检索命中率就低一分。很多团队调了很久的 chunk 参数没效果最后发现是源文档里的页眉把 embedding 向量带偏了。2.2 切分策略chunk size 不是随便拍的文档清洗完就进入切分。切分的目标是把长文档切成语义相对完整、长度适中的片段每个片段叫一个 chunk。为什么必须切因为 embedding 模型有最大输入长度限制而且一个几百页的文档整体编码成一个向量语义早就被稀释成一锅粥检索时根本无法精准定位。切分的核心矛盾是颗粒度。chunk 太小单个片段可能装不下一个完整的知识点检索时上下文残缺chunk 太大片段里包含大量无关内容向量被平均化精确匹配失效。我做中文业务文档时经验值是单个 chunk 控制在 256 到 768 个 token 之间默认 512重叠 64 到 128。重叠的作用是防止知识点恰好被切断让相邻 chunk 互相兜底。切分时优先按 Markdown 标题层级切没有标题结构再按段落和句子边界切实在不行才按固定字符数硬切。这里有个反直觉的点切分粒度要跟你期望用户怎么提问匹配。如果你的知识库是产品使用手册用户问题通常针对某个具体功能的操作步骤chunk 就应该小一点保证一段流程自包含如果你的知识库是深度研究报告用户问题往往概览性更强chunk 可以大一些保证上下文完整。不要盲目抄别人的参数。2.3 Embedding 与向量存储把文字变成可以计算的坐标切分完成后每个 chunk 要经过 embedding 模型转成向量。向量是什么你可以理解成把一段话压扁成一个几百维的坐标语义相近的文字在坐标空间里距离更近。报销单超过五千要副总审批和单笔金额超过五千元需分管副总批准这两句字面完全不同但向量距离很近这就是 embedding 能够支撑语义检索的根本原因。选 embedding 模型时中文业务场景要特别留意三件事。第一是分词覆盖很多英文语料训练出的模型对中文专有名词理解很差领域术语直接被切成碎片第二是领域适配法律的、医疗的、代码的语料差异巨大通用模型在垂直领域经常拉胯第三是输入上限如果选的模型最大输入 512 token那你的 chunk 就不能超过这个值否则会被截断。向量存储选型我按规模分三档几百上千个 chunk 的轻量场景用 FAISS 本地文件就够了零部署成本万级 chunk 的团队协作场景上 Chroma、Qdrant 这类开源库支持过滤和持久化百万级以上的生产场景才需要考虑 Milvus、Elasticsearch 这类分布式方案。很多小项目一开始就上重武器纯属给自己找运维麻烦。2.4 检索与重排命中率才是这条管道的命门检索阶段做的事情是把用户问题也转成一个向量然后在向量库里找距离最近的 K 个 chunk。这个 K 就是 top-k一般取 4 到 10。取太少了上下文不够取多了噪声暴增。但这里有个隐藏问题纯向量检索只看语义不管关键词当你问项目延期三天时如果库里写的是交付周期顺延它可能搜不准反过来当你问一个精确编号或人名时向量检索又容易被相似但错误的片段干扰。所以生产环境我强烈建议采用混合检索向量检索 关键词检索BM25并行召回然后把两路结果合并重排。为什么要关键词检索因为实体、编号、日期这类信息精确匹配远比语义相似可靠。合并之后再用一个重排模型比如 bge-reranker 这类 cross-encoder对候选片段逐对打分把最相关的排到最前。重排阶段计算成本高但只在几十个候选里做完全扛得住。检索质量的度量最常用的指标是召回率recall和命中率hit rate。命中率衡量的是正确答案是否出现在召回的 top-k 里这是 RAG 管道的生命线。如果命中率为零后面生成端再强也白搭因为模型手上根本没有正确答案。2.5 生成增强把检索结果揉进提示词检索拿到相关片段后就要把它们组装进 prompt交给大模型生成答案。这一步看着简单工程细节不少。第一必须给出清晰的指令约束告诉模型只能基于提供的资料回答资料中没有的内容要明确说不知道不能瞎编。第二要保留引用标记比如在每段资料前加 [1]、[2] 编号要求模型在回答末尾附上引用的编号这样答案才能溯源。第三要注意上下文的组装顺序通常把问题放最后资料放前面中间用分隔符隔开避免模型把资料和问题混淆。这里有个容易翻车的细节top-k 排序不等于组装顺序。重排模型给出的最相关片段不一定适合直接放在最前面。有时候更合理的做法是把包含明确答案的片段放最前把补充背景的放在后面让模型先读到核心结论再看到细节展开。这个策略在不同模型上效果差异很大需要实测调优。生成端的另一个关键参数是温度。知识问答场景我把 temperature 调到 0 或接近 0因为我们要的是稳定、忠实的事实回答不是创意写作。温度一高模型就容易在资料基础上自由发挥幻觉率直线上升。3. 手把手搭一条可用的 RAG 管道从方案选型到代码落地3.1 技术选型为什么我选了这个组合很多人一上来就纠结用 LangChain 还是 LlamaIndex其实答案很简单看团队谁在维护。我现在的习惯是小规模验证阶段尽量少用重量级框架直接用 Python 把流程串起来让每一步都透明可控确定效果后再考虑用框架封装。下面这套示例代码围绕四个组件构建FAISS 做向量存储HuggingFace 的 BGE-M3 做 embeddingjieba 分词 BM25 做关键词召回bge-reranker 做重排。选这组是因为全部可以本地免费运行不依赖任何闭源 API对中文支持好适合作为个人项目和内部知识库的起步配置。如果你有条件调用商业 embedding API思路完全一样替换对应模块即可。3.2 索引端文档加工进库索引端代码负责把清洗好的文档转换成向量和倒排索引。先用递归切分把长文档切成 chunk然后逐个编码成向量连同原文和元数据一起写入 FAISS 索引文件。import faiss import numpy as np from sentence_transformers import SentenceTransformer # 模型加载BGE-M3 对中文支持好支持 8192 长度输入 embedder SentenceTransformer(BAAI/bge-m3) def split_document(text, chunk_size512, overlap128): 按字符数滑动窗口切分记录重叠区间 chunks [] start 0 while start len(text): # 优先在句号、换行符处切断避免切碎句子 end min(start chunk_size, len(text)) cut_pos max(text.rfind(。, start, end), text.rfind(\n, start, end)) if cut_pos start chunk_size * 0.5: end cut_pos 1 chunks.append(text[start:end]) start end - overlap return chunks chunks split_document(cleaned_text) embeddings embedder.encode(chunks, normalize_embeddingsTrue) dim embeddings.shape[1] index faiss.IndexFlatIP(dim) # 内积距离配合归一化向量等价于余弦相似度 index.add(embeddings) faiss.write_index(index, kb.index) # 把 chunk 原文和元数据单独持久化留作检索后映射 import json with open(chunks.json, w, encodingutf-8) as f: json.dump([{text: c, source: doc_name, page: page_no} for c in chunks], f, ensure_asciiFalse)这段代码里有两个细节值得说。第一个是 IndexFlatIP配合 normalize 之后的向量使用内积等价于余弦相似度这是 FAISS 里检索效果最稳的配置数据量不大时不需要上 IVF 这类近似索引。第二个是切分的切断点逻辑——我要求切断位置必须落在句子边界附近避免从一句话中间硬切这样保留下来的 chunk 语义完整度会高很多。3.3 检索端混合召回加粗排检索端是整条管道的核心。我的实现是先做向量召回和 BM25 召回各取前 20 条合并去重后交给重排模型精排最后取前 5 条作为生成上下文。import jieba import json from rank_bm25 import BM25Okapi # 加载索引和 chunk 数据 index faiss.read_index(kb.index) with open(chunks.json, encodingutf-8) as f: chunks_data json.load(f) # 构建 BM25 索引jieba 分词处理中文 tokenized_docs [list(jieba.cut(c[text])) for c in chunks_data] bm25 BM25Okapi(tokenized_docs) def hybrid_search(query, top_k20): # 向量召回 q_vec embedder.encode([query], normalize_embeddingsTrue) vec_scores, vec_idx index.search(q_vec, top_k) # 关键词召回 tokenized_query list(jieba.cut(query)) bm25_scores bm25.get_scores(tokenized_query) bm25_idx np.argsort(bm25_scores)[::-1][:top_k] # 合并两路候选加权融合权重可按业务调 candidate_scores {} for i, score in zip(vec_idx[0], vec_scores[0]): candidate_scores[i] candidate_scores.get(i, 0) 0.6 * score for i in bm25_idx: candidate_scores[i] candidate_scores.get(i, 0) 0.4 * 1.0 ranked sorted(candidate_scores.items(), keylambda x: -x[1]) return [chunks_data[i[0]] for i in ranked[:50]] # 重排cross-encoder 逐对打分 from sentence_transformers import CrossEncoder reranker CrossEncoder(BAAI/bge-reranker-v2-m3) def rerank(query, candidates, top_n5): pairs [(query, c[text]) for c in candidates] scores reranker.predict(pairs) sorted_cands [c for _, c in sorted(zip(scores, candidates), reverseTrue)] return sorted_cands[:top_n] candidates hybrid_search(单笔报销超过多少需要副总审批) final_chunks rerank(单笔报销超过多少需要副总审批, candidates) for c in final_chunks: print(c[source], c[text][:80])这里要说明为什么搞向量BM25重排三层而不是只做向量检索。真实业务的问题五花八门纯语义的、带精确编号的、带缩写的、口语化的。单靠向量精确实体容易丢单靠 BM25同义改写完全失灵。两路召回互相补位再用重排把噪声压掉召回率能提升一个明显的档次。代价只是多几十毫秒的延迟对知识问答完全可接受。3.4 生成端带引用的提示词组装最后一步是把重排后的片段变成 prompt交给 LLM 生成带引用的答案。def build_prompt(query, chunks): context_parts [] for idx, c in enumerate(chunks, 1): context_parts.append(f[{idx}] 来源{c[source]}\n{c[text]}) context \n\n.join(context_parts) prompt f你是一个严谨的问答助手。请仅依据下面提供的资料回答问题。 如果资料中没有相关信息请直接回答资料中未找到相关信息不要编造。 资料 {context} 问题{query} 要求 1. 基于资料作答引用编号标注来源格式如 [1]。 2. 回答简洁结论先行必要时补充关键细节。 return prompt # 调用 LLM 生成temperature 设 0 from openai import OpenAI client OpenAI(base_urlhttp://localhost:11434/v1, api_keyollama) resp client.chat.completions.create( modelqwen2.5:14b, messages[{role: user, content: build_prompt(单笔报销超过多少需要副总审批, final_chunks)}], temperature0, ) print(resp.choices[0].message.content)生成端的提示词设计核心原则是把忠实度焊进指令里。我在提示词里明确写了不要编造并要求逐条引用来源这比单纯把资料丢给模型要稳得多。很多 RAG 翻车案例问题不在检索而在 prompt 没约束住模型的发挥欲。4. 检索质量实测命中率、上下文窗口与干扰项4.1 用真实语料跑一次端到端从指标到主观体验代码跑通只是起点真正重要的工作是评估。我用公司内部一套产品文档做了一轮测试总共 126 份文档、约 2 万多个 chunk准备了 80 道覆盖不同业务场景的问答对每道题都标注了答案出自哪份文档的哪个段落。先看硬指标。纯向量检索的 hit5 是 63.75%意味着有大约 36% 的问题正确答案根本没进入前 5生成端再强也答不对。加入 BM25 混合后hit5 提升到 77.5%再加 bge-reranker 重排最终 hit5 到了 85%。这个数据很典型基础 RAG 项目只要把检索链路从单路升级成双路重排命中率就能显著提升。而且 hit5 到 85% 之后再往上提很难瓶颈往往在文档清洗和 chunk 切分这种上游环节而不是检索算法本身。再看主观体验。我找了几道典型的翻车题来做对比。有道题问项目验收流程中甲方确认需要几个工作日纯向量检索召回的第一名是一份合同模板里关于验收条款的解释语义相近但完全是另一件事混合检索把文档里验收确认应在 3 个工作日内完成这一句捞了回来重排后排到了第一位。还有道题问VIP 客户的折扣比例是多少向量检索召回了VIP 客户服务权益清单里关于生日礼遇的段落因为VIP 客户语义相近但 BM25 靠精确匹配把折扣比例相关的段落抬了上来。4.2 三种典型检索失败语义漂移、实体失配、上下文残缺测试过程中我整理了三种最常出现的检索失败模式值得拿出来专门说。第一种叫语义漂移。问产品上线前的安全检查清单有哪些模型召回的片段遍布安全检查上线等词的语义邻居却没有一条真正包含完整清单。语义漂移的原因通常是问题本身包含多个主题词向量被多个语义重心拉扯。应对办法是让问题进入检索前先做一次简单的意图改写——把口语化问题转成更明确的检索式比如线上环境 安全检查 项目 清单。第二种叫实体失配。问题是APM-210 型号的固件升级步骤但文档里写的是性能监控器 APM210一个连字符的差别就导致向量检索完全失效。这种场景 BM25 也不一定有用因为分词后 APM 和 210 会被拆散。我的做法是维护一个业务实体别名表在检索前做规则替换把APM-210映射成文档里的标准写法APM210。这类规则虽然土但在内部知识库里极其有效。第三种叫上下文残缺。答案本身在某一段落里但段落被切得只剩结论没有条件模型读了也没法正确作答。比如文档写特批权限仅限总监及以上且需在系统内留痕切分时把仅限总监及以上切进了前一个 chunk需在系统内留痕进了后一个 chunk检索时只召回前半句回答就有失偏颇。解决思路一是增加重叠长度二是检索后做父子文档补全——命中父级 chunk 后把与其相邻的若干子 chunk 一并带进上下文。4.3 评估集维护命中率之外还要看什么说句得罪人的话很多团队做完 RAG 说效果很好是因为他们就拿三五个问题试了试。真正靠谱的做法是从第一天起就建一个可持续迭代的评估集。评估集分两层。第一层是检索评估每道题标注正确答案所在的 chunk ID跑完检索流水线后统计 hitk。这一层跑得快可以每次改完切分参数、换完 embedding 模型后全量回归。第二层是生成评估要人工或者用更强的大模型去判分看答案是否正确、是否有引用、是否忠实于资料。生成评估慢且贵不需要每次跑一周跑一轮就够了。我要特别提醒一个陷阱只盯着命中率容易自我欺骗。命中率好到 90%可能你的评估题全是简单的文档里一句话能回答的问题真实场景里那些需要跨段落推理、需要多文档合并的问题完全没覆盖。所以评估集要刻意包含三类难题——需要合并多个来源的、包含精确数字和编号的、文档中措辞与问题措辞差异很大的这类题才是检验管道的试金石。5. 从基础 RAG 走向 Agentic RAG知识管道的下一步5.1 基础 RAG 的三层局限基础 RAG 是一问一答一取的固定流程搞明白它的局限才知道往哪个方向进化。第一层局限是无法处理复杂问题拆解。用户问帮我对比 A 产品和 B 产品的售后政策差异基础 RAG 只能做一次检索要么取到 A 要么取到 B很难同时拿到两份完整政策做对比。正确做法是先让 Agent 把问题拆成两个子问题分别检索再汇总对比——这就是查询规划 多次检索的能力。第二层局限是看不到检索的失败。基础 RAG 检索完就直接生成如果没搜到关键资料模型照样硬着头皮答。进阶的 Agent 应该能判断这轮检索质量不行然后改写查询词、换检索策略、或者去调一个外部 API 再试一次。这个自我判断 迭代重试的循环是 Agentic RAG 和基础 RAG 最大的区别。第三层局限是没有工具调用能力。很多知识根本不在文档里而在数据库和 API 后面。用户问我这个季度的订单总额是多少这不是检索文档能解决的需要 Agent 调用 SQL 查询。所以知识获取管道的尽头是把 RAG、数据库查询、工具调用统一在一个 Agent 的编排之下。5.2 多路召回与路由让检索策略跟着问题走从基础走向进阶我建议先做的一件事是检索路由——让系统先判断问题类型再决定走哪条检索路径。我实际在做的路由分这么几条事实型问答走向量BM25重排的标准 RAG带精确编号的问题强制走 BM25 并放宽精确匹配总结归纳型问题走全量文档摘要 分章节抽取的路径数据统计型问题直接路由到 SQL Agent不碰文档。路由本身可以用一个小模型做分类也可以写规则要点是让不同特性的问题流向各自擅长的检索器。这里有个关键词要提Agentic RAG。概念上它指的不是某一种算法而是把 RAG 从固定流程变成Agent 可调用的能力。Agent 根据任务目标自主决定要不要检索、检索几次、检索哪类知识源、检索结果不够时怎么换策略。有人说这是过度包装但我从业两年多的体会是这个能力边界在真实业务里有实打实的价值——尤其面对多跳问题、条件过滤、跨源合并这些复杂场景时固定流程真的顶不住。5.3 Skill 与 RAG 怎么结合我的实践框架结合是今年讨论最多的方向之一我之前在项目里也纠结过知识库检索和 Agent 的 Skill工具技能到底是并列关系还是检索只是众多 Skill 中的一种我的结论是不要把 RAG 做成一个全局的、隐形的背景知识注入器而是把它封装成一个显式的 Skill叫 search_knowledge_base。Agent 在使用时显式调用、传参、拿回结果再决定下一步。这样做的直接好处是可控性和可观测性。你能在日志里看到 Agent 到底检索了什么、检索结果是否被采纳出了问题可以定位到具体环节。而如果让 RAG 隐式地伴随每个请求自动注入上下文被无关资料污染时你甚至不知道是哪次注入导致的跑偏。Skill 和 RAG 结合的另一个场景是检索后动作。比如检索到某篇政策文档后Agent 可以自动触发一个生成摘要的 Skill或者把结果写入工单系统。RAG 从知识获取升级成知识获取 行动触发这才更像 Agent 该有的样子。5.4 进阶方向本体 RAG 与 GraphRAG 解决什么问题最后简单提两个进阶方向不展开但值得知道它们各自解决什么问题。GraphRAG 是这两年很热的做法核心是把文档中的实体和关系抽取出来构建成知识图谱检索时从实体出发沿着关系扩展上下文。典型场景是A 产品用了 B 芯片B 芯片的供应商是 CC 有供货风险这类多跳关系问题纯向量检索很难答好图谱却天然擅长。但 GraphRAG 的代价是构建成本高需要大量的 LLM 抽取和人工校正。本体 RAGOntology RAG则更偏系统约束先定义好领域内的概念体系和关系类型把文档内容对齐到本体上再在这个有结构的框架内做检索。好处是查询意图和文档内容之间存在稳定的语义映射专有名词和概念关系不容易漂移。我在法务和医疗器械这类强领域知识场景试过对术语准确性的提升非常明显但前期本体设计的门槛不低需要领域专家深度参与。6. 我踩过的坑和几个忠告6.1 坑一Embedding 模型选错领域术语全线失配最早做这套管道时我图省事选了一个通用英文 embedding 模型结果中文业务文档的检索效果惨不忍睹。比如文档里写工单、履约、核销问订单怎么处理时向量距离远到几乎没有关联。后来换成对中文和领域词支持更好的 BGE-M3效果立刻上一个台阶。这个教训说明embedding 模型的选择不是能跑就行而是要针对你的语料语言和领域做实测对比。给一个简单的选型方法从你的真实知识库里抽 30 道题分别用两三个候选模型跑一遍 hit5谁高用谁。别看 benchmark 分数那些分数是用公开英文数据集测出来的跟你的中文业务场景关系不大。6.2 坑二Chunk 重叠率过高检索噪声跟着涨我最初为了不让知识点被切断把重叠设得很大300 token 的重叠配 512 的 chunk。结果检索时经常出现一串高度相似的 chunk 占据前几名模型读到的全是重复内容有效信息密度极低。调低重叠并配合父子文档策略后问题才解决。经验值分享一下重叠率控制在 15% 到 25% 之间。如果发现知识点频繁被切断不要盲目加大重叠优先检查切分逻辑是否尊重了标题和段落边界。重叠只是兜底手段不是解决切分不合理的方式。6.3 坑三离线指标漂亮线上问答完全跑偏还有一次我把 hit5 调到 90%信心满满地上线结果真实用户一连串问题答非所问。复盘发现问题出在评估集和真实查询之间的分布差异评估题都来自文档改写措辞规范、结构完整真实用户的问题是口语化的、带错别字的、一半话没说完的。评估集里根本没覆盖这些脏查询。后来我养成了一个习惯每次上线前从线上日志里捞真实用户问题进评估集不预处理原样跑。这个脏查询评估集现在是我判断 RAG 系统能不能抗住线上压力的第一道关卡。6.4 一个让成功率明显提升的小技巧最后分享一个小技巧成本极低但效果很实在检索前对用户问题做一次查询词抽取把问题里的核心实体、限定条件、时间范围单独抽出来拼成一个纯检索式再做检索。比如用户问三月份华南区的退款率超标了吗直接拿整句去检索容易带上了吗超标这类对检索无益的词稀释向量。抽成三月 华南区 退款率 超标再检索命中明显更准。这个操作可以用规则实现也可以丢给一个小模型做。我实测下来很多之前命中不了的问题就是靠这一步救回来的。回过头看这套知识获取管道最深的体会是RAG 没有那么多玄学它就是一条需要认真对待每个环节的流水线。清洗、切分、编码、检索、重排、生成每一环的粗糙都会在下游放大。你把它当系统工程来打磨它就给稳定的收益你把它当玩具跑通就完事它就会在线上用各种匪夷所思的答案教育你。希望这篇基础篇能帮你把地基打好后面我们继续聊 Agentic RAG 和知识图谱方向时你不会被这些基础问题绊住脚。
返回列表