RAG知识获取管道全解析:从索引、检索到生成
这个系列写到第四篇了。前面几篇我们聊了 Agent 的整体结构、任务规划、工具调用这次终于轮到所有落地场景里最绕不开的一块知识获取管道也就是大家口中的 RAG 基础。先说说为什么 Agent 非得有这条管道。大模型本身不是数据库它不会知道你公司 ERP 里的产品库存、不会知道你 OA 系统里那条公休假审批流程上周刚改过规则、更不会记得你昨天发在飞书文档里的会议结论。Agent 想干活就得有办法把这些外部知识拿进来RAG 就是目前最主流的那条知识获取管道。这篇我打算把 RAG 的每一环讲透为什么这样设计、每个参数到底在调什么、线上最容易在哪里翻车。适合从 0 到 1 搭 Agent 的人、准备做知识库问答的人、以及试过 RAG 但总觉得回答不靠谱、想系统排查一遍的开发者。1. 为什么 Agent 需要一条知识获取管道1.1 大模型不是数据库参数记忆喂不饱 Agent很多刚接触 Agent 的人会有一个直觉大模型懂得那么多我把问题直接抛给它不就行了这个想法在闲聊场景里没错但一落到真实业务就会露馅。你可以试一下问一个没有接任何外部系统的通用大模型我们公司最新的差旅报销标准是什么它大概率会给你一个看似合理、实际上完全编造的答案。原因很简单这类私域知识从来没有出现在它的训练语料里它只能靠泛化去猜一个最像样的回答。即便某些知识恰好出现在训练语料里模型的参数化记忆也是靠不住的。训练有截止日期知识有版本变更同一个公司里不同部门的制度可能还会互相矛盾。指望靠模型的天生记忆去支撑 Agent 干活就像指望一个再博学的顾问背下你公司所有的制度细节他记不全、也记不牢更不可能主动意识到哪些文件已经作废。知识获取管道要解决的就是让 Agent 在需要的时候能把外部知识准确地翻出来这件事。有人会说那我把所有文档都塞进上下文窗口不就行了现在的模型上下文确实越来越长从 128K 到 1M 的都有但能装下不等于用得好。上下文越长模型对中间段落的注意力就越容易稀释。业界常说的 Lost in the Middle 现象指的就是模型倾向于记住开头和结尾、忘掉中间部分。你把 500 页文档一次性灌进去回答问题时模型反而不知道该信哪一段。更别提成本了——按 token 计费的大模型 API每次请求都携带全部文档几轮对话下来费用会非常难看。所以 RAG 的做法是先把知识切碎、索引好每次只挑最相关的那几段送进模型。这是一种按需取用的思路和人类查资料的习惯是一致的。1.2 在 Agent 的认知架构里知识获取是感知层把 Agent 拆开看通常可以分成感知、规划、行动三块。感知负责理解外部世界的状态规划负责决定下一步做什么行动负责调用工具或输出结果。RAG 在 Agent 里承担的不是一个可有可无的问答插件而是感知层的核心组件。Agent 需要先获取到准确的事实才能做出靠谱的决策和行动。这一步要是错了后面再怎么调 Prompt、怎么优化工具调用都是白费。这里要区分一下 RAG 和普通工具调用的边界。工具调用比如查数据库、调 API适合结构化、更新快、精确匹配的数据比如查订单状态、查库存数量一个 SQL 或者一个 API 请求就搞定了。但企业里大量知识是以非结构化形式存在的产品手册、制度文档、会议纪要、售后工单、PDF 里的表格。这些内容没法用一个 SQL 直接取出来需要语义检索才能找到。RAG 擅长处理的正是这一类说不清具体在哪个字段、但大概在哪些内容里的知识。这也是为什么最近知识割裂这个词频繁出现在 RAG 相关的讨论里。很多公司的知识散落在 ERP、CRM、本地文件、Wiki、聊天记录里彼此之间没有打通。员工想找一个答案得在不同系统间来回切换。RAG 出现之前这种割裂只能靠人工整理RAG 出现之后理论上我们可以把这些异构内容先统一索引到一个语义层上再通过一套问答接口去访问。当然工程上要做到这一步并不轻松后面我会讲到实际落地时的坑。但方向是对的知识获取管道存在的意义就是把分散的知识变成 Agent 可以感知到的统一资源。2. 核心链路拆解索引、检索、生成三件事2.1 索引从原始文档到可搜索的向量RAG 的完整链路可以粗暴地分成三个阶段索引、检索、生成。很多人第一次上手时会把注意力全放在检索和 Prompt 上但索引阶段才是决定整个系统上限的地方。索引做不好后面再怎么调参都是事倍功半。索引阶段的第一件事是解析清洗。输入进来的文档可能是 PDF、Word、Markdown、HTML 甚至扫描件。PDF 是最容易出问题的有些 PDF 是双栏排版直接解析会把左右两栏的文字混在一起有些是扫描件必须 OCR 才能提取文字还有些表格在 PDF 里看起来是规整的解析出来却变成了一堆乱序文本。我的经验是这个环节不能图省事直接用默认解析器。Python 生态里 PyMuPDF、pdfplumber 各有擅长前者速度快后者对表格坐标的还原更精确。Word 文档则要小心页眉页脚、批注这些干扰信息转成纯文本后经常混进不相关内容。清洗的目标只有一个让进入索引的文本尽量干净、忠实于原始内容的阅读顺序。清洗之后是分块。为什么必须分块因为 Embedding 模型是对一段文本编码成一个向量这一段的长度和内容质量直接决定了检索效果。块太小语义信息不完整比如一个报销标准的知识点被拦腰截断成两半块太大向量里混合了太多噪声检索出来的段落虽然相似度高但无法精准定位到用户想要的细节。常用的分块策略大致有三类策略做法适用场景典型参数固定窗口分块按固定 token 数或字符数切可加重叠窗口通用场景实现最简单400 tokenoverlap 50递归结构分块优先按段落、标题层级切切不动再按字符兜底有较强结构化排版的文档按 Markdown 标题层级递归语义分块检测句子/段落之间的语义边界自动聚合成语义完整的块文档结构混乱、话题切换多需要额外模型或规则辅助我给一个可以直接抄的经验值中文业务文档块大小建议落在 300 到 600 个字符之间。这个区间对大多数 Embedding 模型来说既不会因为太短而丢失上下文也不会因为太长而引入噪声。重叠窗口一般取块大小的 10% 到 15%作用是避免切分位置刚好把关键句子劈成两半。固定窗口虽然简单但如果你处理的文档本身有清晰的标题结构强烈建议先按结构分块再对超长段落做固定窗口切割。这样既保留了文档原有的逻辑边界又照顾到了实际长度。分块之后就是向量化。这一步需要一个 Embedding 模型把文本转换成高维向量。常见的选择有 OpenAI 的 text-embedding-3-small、开源的 bge-m3、智谱的 embedding-2 等。中文场景下bge-m3 这类国产模型对中文语义的理解通常更好而且支持 8192 token 的长文本性价比很高。向量维度从几百到几千不等维度越高通常表达能力越强但存储和计算成本也越高。向量距离度量一般用余弦相似度它衡量的是方向差异对向量的绝对大小不敏感和文本语义相似度的直觉最匹配。如果用的向量库支持归一化归一化后余弦相似度和内积是等价的查询效率会更高一些。最后一步是存入向量数据库。小项目用 FAISS 就足够了一个本地索引文件就能跑通如果后续要做多租户、增量更新、权限过滤需要换成 Milvus、Qdrant 这类专业向量数据库如果团队已经重度使用 PostgreSQL可以直接用 pgvector 扩展一条 SQL 把结构化查询和向量检索结合起来。选型时不用盲目追求规模化先看你当前的数据量级和更新频率。几万条知识块以内FAISS 完全扛得住。这里要特别强调元数据的重要性。每个知识块入库时至少带上这些字段文档来源、标题、页码或章节、上传时间、文档版本号。没有元数据你后面做权限过滤、来源引用、按时间排除旧版本的时候会非常痛苦。我见过很多项目第一版不存元数据上线后一发现问题就得把所有文档重新入一遍库代价巨大。2.2 检索不是简单算一下相似度就完事索引建好之后进入检索阶段。基础做法是把用户的问题也编码成向量然后在知识库里找最相似的 K 个块。第一次跑通的时候这个流程没有问题但一旦放到真实场景你会发现很多问题——检索出来的结果经常和你心里预期的不太一样。第一个典型问题是精确匹配失效。用户可能会问FC-3000 这款型号的保修期是多久而知识库里写的是FC-3000 产品保修期为 12 个月。向量检索在语义层面能理解保修期和保修是相关的但如果你问的是FC-3000A、FC3000这类带复杂编号的关键词向量检索经常把这些 token 打散反而找不到精确匹配。解决办法是混合检索向量检索负责语义召回BM25 这类稀疏检索负责精确关键词匹配两者结果合并后再做归一化和去重。具体到工程实现可以简单用向量相似度 * 0.6 BM25 分数归一化 * 0.4这类线性融合或者先分别取 top 50扔给重排模型统一排序。第二个典型问题是检索结果排序不精准。第一轮检索通常用双塔模型文档和查询分别编码成向量然后取相似度。双塔模型的特点是快但精度有限——它对段落级语义的刻画不够细腻。要提升精度需要在第一轮召回之后加一个重排环节。重排用的是交叉编码器把查询和文档拼接在一起喂给模型让模型直接输出两者的相关性分数。这样做更准但速度明显变慢所以只能对候选集做重排比如第一轮召回 top 50 或者 top 100重排后只取前 5 个。我实测过一个场景正确的知识块在第一轮排在 23 位重排之后直接升到第 1 位效果提升非常明显。现在主流的中文重排模型如 bge-reranker-v2-m3对长文本的支持和精度都做得不错值得直接纳入管道。第三个常见问题是用户的问题太简略、缺少上下文。比如在一个多轮对话里用户先问我们公司的年假政策是什么接着又问那新入职的能用吗——如果不做处理直接拿那新入职的能用吗去检索大概率什么都检索不到。解决思路是 Query Rewriting也就是用大模型把用户的当前问题和历史对话合并改写成一个能独立检索的完整问题。实践中可以在检索之前加一个轻量级的改写 Prompt把改写后的 query 用于检索。这一步对多轮 Agent 场景几乎是刚需。此外还有检索规模的取舍。top_k 设得太小容易漏设得太大容易把不相关内容塞进上下文。通用问答场景top_k 取 5 到 8 之间比较合适如果是做文档摘要、归纳总结类任务可以把 top_k 放宽到 15 到 20因为这类任务需要看到足够多的来源信息才能综合判断。相似度阈值也是一个需要根据模型调出来的参数——不同 Embedding 模型的分数分布差异很大有的模型结果普遍在 0.7 以上有的在 0.3 到 0.5 之间徘徊。看到低于某个分数的检索结果时不要直接丢给模型先人工检查一下是不是因为 Embedding 模型不擅长这类内容。切莫直接抄网上的阈值务必自己拿一批真实数据跑一遍分布。2.3 生成给大模型立规矩只许照着资料说话检索完成后最后的生成阶段看起来最简单把检索结果和用户问题拼进 Prompt让模型作答。但恰恰是这个环节最容易出现答得很流畅、细节全是编的的问题。想让模型只许照着资料说话需要在 Prompt 结构、引用约束和维护机制上做文章。一个可靠的生成 Prompt 至少包含四部分系统角色说明、参考资料、用户问题、输出约束。系统角色说明告诉模型你是一个知识库助手只能基于参考资料回答参考资料区按顺序列出检索到的知识块最好标注编号用户问题就是原问题输出约束可以写明如果参考资料中没有明确信息请直接回答不知道不要推测。很多人会忽略输出约束总觉得模型应该知道不能编造。但实际情况是大模型的生成习惯就是顺着说你给它的参考材料有一点关联它就敢顺着往下编。我常用的约束写法是在 Prompt 里加一句回答中必须标注引用的知识块编号例如 [1][2]如果某个事实在参考资料中无法定位到对应编号必须明确说明该信息未在资料中找到。这个约束能帮你实现两个目的一是让模型在生成时心里绷着一根弦别乱发挥二是生成结果出来之后你可以自动校验——如果模型引用了某个编号但该编号的内容里找不到对应事实那答案就有幻觉嫌疑可以直接拦截。生成阶段还需要考虑多结果整合。用户的问题往往不是靠一个知识块就能回答完整的。比如问产品的退货政策是什么知识库里可能有退货时限、退货条件、运费承担三个不同章节的内容。如果只取 top 1 的块答案就会缺胳膊少腿。所以在组装 Prompt 时要把多个相关块都放进去并且明确要求模型综合所有参考资料回答而不是只看第一段。还有一个进阶的设计把生成和检索串成一个循环而不是一次性的检索一次、生成一次。第一轮检索结果如果不满足回答条件可以触发第二轮检索比如换一个关键词、查一下相关的 FAQ 索引或者调用一个结构化的数据库工具。这个思路正是 Agentic RAG 的雏形我在第四部分会展开说。对于基础 RAG 来说先把上面三个阶段的底子打好再考虑循环和规划也不迟。3. 实操搭一个最小可用的知识获取管道3.1 文档进入管道前强烈建议先做清洗先动手的话我建议你在正式搭管道之前先花时间处理输入文档的质量问题。这一步看似不产生代码成果但对最终效果的影响之大怎么强调都不过分。我见过一个项目导入了 200 份 PDF 产品手册检索出来的结果总是不对劲排了一天查不出问题最后发现是每份 PDF 的页脚公司地址都被解析出来了模型总是被这些噪声干扰。清洗一遍之后命中率立刻上去了。清洗要做的事情包括去掉页眉、页脚、水印、跳转链接统一编码格式特别是 PDF 转出来的中英文引号、破折号经常变成乱码表格如果本身承载了强语义信息最好转成 Markdown 表格或者按行组织成自然语言描述而不是简单地把表格中的文字一行行拼出来。多栏文档必须先恢复阅读顺序这一步在 PyMuPDF 里可以通过坐标排序实现也可以直接用一些商业解析库。清洗完成后还需要做一步很多人忽略的内容筛选——不是所有文档都值得进知识库。重复的旧版本、已经被作废的制度文件、只有几个字的占位文档都会成为检索时的干扰项。我的建议是先按文档的访问频率和业务重要性拉一个清单优先处理那些用户最常问、更新最频繁的文档。知识库不是越全越好而是越准越好。3.2 分块与 Embedding 参数怎么定搞定清洗后进入分块和向量化环节。我直接给你一套可以复现的最小参数方案参数推荐值说明分块大小400 到 500 字符中文按中文字符数切比按 token 切好控制重叠窗口50 字符避免关键句子被切分分块策略优先按 Markdown 标题切再按字符兜底保留结构信息Embedding 模型bge-m3 或 text-embedding-3-small中文场景优先 bge-m3向量库小项目 FAISS生产环境 Milvus/pgvector按数据量选型top_k5 到 8边调边看命中情况重排bge-reranker-v2-m3在 top 50 中重排取 top 5我用 Python 的 LangChain 生态给你一个可参考的索引流程核心代码大概长这样from langchain_community.document_loaders import PyPDFLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_community.embeddings import HuggingFaceBgeEmbeddings from langchain_community.vectorstores import FAISS # 1. 加载并清洗文档 loader PyPDFLoader(产品手册.pdf) docs loader.load() docs [d for d in docs if len(d.page_content.strip()) 20] # 过滤空页 # 2. 分块先按结构走超长再切割 splitter RecursiveCharacterTextSplitter( chunk_size450, chunk_overlap50, separators[\n## , \n### , \n\n, \n], ) chunks splitter.split_documents(docs) # 3. 向量化并入库 embeddings HuggingFaceBgeEmbeddings(model_nameBAAI/bge-m3) vectorstore FAISS.from_documents(chunks, embeddings) vectorstore.save_local(faiss_index) # 4. 检索 retriever vectorstore.as_retriever(search_kwargs{k: 10}) retrieved retriever.invoke(这个产品的保修期是多久)跑通这条流程只需要几分钟但它已经把 RAG 的核心链路串起来了。分块后建议你随手抽查几个块看一眼内容是否完整、是否保留了标题信息。元数据字段来源、标题、页码在创建 Document 对象时就要塞进去比如doc.metadata {source: 产品手册.pdf, page: 1}后面检索和引用都要靠它。3.3 检索参数调优与命中率自查管道跑通之后第一件事不是急着接 Agent而是验一遍检索的命中率。很多人的做法是问一两个问题看回答像不像样就认为系统可用了。这是最容易踩的坑。正确做法是建立一个小规模的黄金问答集比如从真实业务里挑 30 到 50 个问题每个问题人工标注一下正确答案应该在哪个知识块或哪份文档里。然后批量跑检索统计正确答案是否出现在检索结果的前 K 个位置里。这个指标就是热词榜上那个 Rag Hit Rate。我建立一个简单的自查表格用户问题正确知识块是否出现在 top 10相似度最高值新品 A 有保修政策吗产品手册-新品A-保修章节是0.82退货需要承担运费吗售后政策-退货条款否0.41差旅能住几星级酒店财务制度-差旅标准-住宿是0.75如果发现某类问题命中率很低不要急着调大 top_k先看检索日志里到底返回了什么。这里我有一个习惯每次检索都把分段内容和分数打印出来人工扫一遍很快就能定位问题是出在分块、Embedding 还是查询词上。很多时候你会发现检索之所以不准不是因为模型不行而是因为知识库里那段正确内容的表达方式和你问法之间差异太大向量模型没能把它们关联起来。这时候可以试试在知识库里给关键内容补充别名和同义表达或者做一层查询改写。3.4 一个能跑通的流水线设计从工程角度我建议把 RAG 管道拆成独立模块而不是写一个大函数。这样做的好处是后续每一步都能单独替换和测试。整个流水线大致分成四层文档接入层负责加载和清洗索引管理层负责分块、向量化、增量和删除检索服务层负责 query 处理、向量召回、重排生成服务层负责 Prompt 组装、调用 LLM、输出引用。def rag_pipeline(user_query: str, history: list[dict], retriever, llm): # 1. 改写 query search_query rewrite_query(user_query, history) # 2. 召回重排 candidates retriever.invoke(search_query, k50) results rerank(search_query, candidates, top_k5) # 3. 组装 Prompt context format_context(results) # 带编号、带元数据 prompt build_rag_prompt(context, user_query) # 4. 生成并校验 answer llm.invoke(prompt) answer verify_citations(answer, results) # 校验引用是否真实 return answer模块化之后你可以在不改动其他环节的情况下把 FAISS 换成 Milvus、把 bge-m3 换成效果更好的模型、把固定窗口分块换成语义分块。我用这套结构跑过很多业务场景最大的体会是前期花一点时间把边界划清楚后期排查问题时能省下好几倍的精力。4. 从基础 RAG 到 Agentic RAG 与知识组织4.1 Agentic RAG让 Agent 自己决定怎么翻资料基础 RAG 的逻辑是收到问题—检索一次—生成回答这个流程对大多数简单问答是够用的。但现实中的问题往往没那么规整用户问的可能是B 客户的退货申请为什么被驳回这个问题既涉及退货政策文档又涉及该客户的订单状态结构化数据还可能涉及客户历史沟通记录聊天记录。一个固定的检索流程很难覆盖这种多源、多步的诉求。Agentic RAG 要解决的问题就是把怎么获取知识这件事本身变成一个决策过程。放在 Agent 的架构里RAG 不是被硬编码在固定流程里而是注册成 Agent 可以调用的工具或者技能。Agent 根据用户的意图决定要不要检索、用哪个知识库检索、检索结果不够时要不要换一种方式继续检索。比如它可以先查 FAQ 知识库发现不够精确再决定调用一个结构化数据查询工具最后综合两部分结果给出回答。工具的描述信息通常决定了 Agent 会不会正确选用它。我自己写 Agent 工具时会在描述里写清楚该工具用于查找非结构化文档中的政策和流程说明不适用于查询订单状态这样 Agent 选错的概率会显著下降。另一个经典的 Agentic RAG 方向是 Self-RAG来自 2023 年底伯克利那篇论文。思路是让大模型在生成回答时不光输出答案还输出一些反思标记比如我检索到的结果是否足够支撑回答这个问题有没有矛盾信息。模型可以训练自己判断检索结果不足就继续检索有矛盾就指出矛盾。实际落地时不需要完全复刻论文里的训练方案用普通的大模型加上合适的 Prompt 也能做出类似的自我检查效果。关键是给模型一个判断依据而不是放任它回答完就结束。社区里已经有一些把 RAG 直接封装成服务的产品形态比如一些 Agent 开发平台推出了 RAG as a Service 的能力底层把文档解析、索引、检索、重排都托管了上层 Agent 只需要调用一个接口。这种趋势对业务方是好事省去了很多工程细节但反过来也意味着如果你不懂底层原理出了问题只能干瞪眼。所以我一直建议就算最终要用人家的托管服务自己也要先把基础 RAG 的每一环亲手跑一遍。4.2 GraphRAG、Ontology RAG 与 LLM Wiki知识组织的新方向近几年 RAG 方向上出现了很多试图解决知识割裂问题的进阶方案。热词榜单里的 GraphRAG、Ontology RAG、LLM Wiki本质上都在做一件事让知识块之间产生结构关联而不是孤零零地躺在向量库里等着被检索。GraphRAG 的思路是先从文档中抽取实体人物、产品、事件、部门和实体间的关系构建出一张知识图谱。它的优势体现在两类问题上一是跨文档的全局性问题比如我们公司过去一年所有产品的退货率趋势如何二是关系推理类问题比如A 产品和 B 产品是否共用同一套售后流程。基础 RAG 很难回答这类问题因为答案分散在大量文档中靠向量相似度可能永远凑不齐所有相关段落。GraphRAG 能顺着图谱里的边把相关内容关联起来。代价也明显抽取实体的计算成本高构建和维护周期长中小项目慎用。Ontology RAG 则是把领域本体概念、属性、关系引入检索过程。比如医疗领域如果本体里定义了高血压和血压的层级关系检索时就能利用这层概念关系做更精准的查询扩展。这类做法适合概念体系严格、专业术语密度高的领域法律、医学、金融都算典型场景。但它的前提是必须先有一份质量不错的本体定义不然概念映射本身的误差会让检索更乱。LLM Wiki 这个方向更有意思核心是用大模型来自动生成、修订和整理知识条目把文档变成持续更新的 Wiki 知识库。比如一个团队的历史决策记录可以用 LLM 定期从会议纪要中总结成结构化条目。这些条目的质量依赖于上游源头的准确性但如果维护得当会显著提升知识库的密度和可检索性。我个人的判断是GraphRAG、Ontology RAG 这些方案适合作为知识组织层的进阶选项而不是每个项目的起手式。先把基础 RAG 的索引、检索、生成做好再评估要不要引入图谱这才是理性的路线。4.3 用 Hit Rate 和忠实度把管道管起来说到评估RAG 项目最容易犯的错误是凭感觉调优。今天觉得回答挺流畅明天换个问题又拉胯了靠肉眼判断很难稳定推进。我强烈建议从第一天起就建立一套量化评估机制哪怕一开始只测 20 个问题。Hit Rate 是最基础的指标公式很简单在测试问题集上正确答案出现在检索结果前 K 位的次数占总问题数的比例。比如 50 个问题答案是 50 个块其中 42 次被检索进 top 10那 hit rate 就是 84%。这个指标适合快速判断索引和检索环节的健康度。但要记住一个原则hit rate 高不代表最终回答好。检索命中了生成阶段照样可能因为 Prompt 组装不好而给出错误答案。所以还要配套评估生成忠实度——也就是让标注员看最终回答判断回答里的每个关键事实是否都能在引用块中找到依据。忠实度可以手动抽样评估也可以用更强的大模型做自动评测让它逐条比对。我用这套方式跑过几个知识库项目印象最深的是有一个项目 hit rate 已经到 95% 了但用户仍然觉得回答不好。后来查出来是重排环节出了问题——重排后的 top 5 里确实有正确答案但生成时被其他噪声块干扰模型最终抽取了错误的信息。这说明检索和生成是强耦合的不能只守着一个指标。多指标联合看才能相对准确地定位问题。5. 常见问题与排查技巧实录5.1 检索结果和问题对不上Hit Rate 老上不去这是我被问得最多的一类问题。典型症状是用户问差旅报销能住什么级别的酒店系统返回了一堆差旅制度开头的文本但真正写了住宿标准的那一段没被检索到。遇到这种情况先别着急换模型按下面的顺序排查。第一检查分块是否损坏了语义完整性。把正确的那段内容找出来看看它在知识库里被切成了什么样。如果一句四星级及以下酒店被拆成了上一块结尾和下一块开头那模型当然检索不准。解决方法是调大 overlap或者针对这类制度文档改成按章节标题切。第二把单路向量检索换成混合检索。差旅标准里星级酒店这些关键词本身就是很强的线索BM25 直接命中可能比向量语义匹配更可靠。第三检查检索阈值是否设置过严或过松。如果正确答案的相似度只有 0.5而你的阈值设了 0.6它直接被过滤掉了。第四如果以上都正常再考虑 query 改写。用户口语化的问法经常包含代词和省略改写之后检索命中率能提升不少。我自己的排查习惯是先写一个脚本把测试问题、检索到的前 20 个块、对应的相似度分数、正确答案所在的块一次性打印出来。肉眼扫一遍这四列问题定位通常很快。这个脚本花半小时写后面每次调优都用它效率高很多。5.2 回答得很流畅但细节是编的这类问题最让人头疼因为表面看检索结果没毛病回答也通顺但仔细核对就发现编译出来的答案里有不存在的细节。原因通常有两个方向生成约束太弱或者检索上下文不够。先查生成约束。如果你的 Prompt 只写了请根据以下资料回答模型很容易放飞自我。我的做法是把约束写成硬性要求回答内容必须完全基于参考资料如果参考资料中没有提到相关内容就明确回复未找到该信息禁止根据其他知识推断。再加上引用编号约束几乎能杜绝凭空编造的情况。再查上下文完整性。用户问的问题如果涉及多个知识维度而检索只给了一个块模型为了回答完整就会用训练记忆去补空缺。解决办法是增大 top_k 或者扩展重排候选集让生成阶段有足够多的上下文可以引用。还有一种情况是检索到了但 Prompt 组装时被截断了。检查一下组装之后的 Prompt看看是否因为长度限制丢掉了关键块。5.3 知识更新了系统却还在答旧内容这也是高频故障而且越到后期越严重。第一版知识库跑通后文档会被不断地修订、替换、作废如果管道只有全量入库的逻辑没有增量更新的机制系统就会持续回答旧版本里的内容。处理思路分三层。第一层是在元数据里增加版本号和更新时间检索时可以根据条件过滤掉旧版本。第二层是做增量更新文档有改动时只重新解析、切片、向量化变更的部分同时将旧版本对应的向量从库里删除。这个删除必须是物理删除只做逻辑标记的话相似度检索依然可能把它们捞出来。第三层是定期做全量校验用文档 hash 对比检测有没有漏掉的变更。我遇到过一种更隐蔽的情况同一份文档在不同系统里有多个副本其中一个更新了另一个没更新索引把两份都收了进去回答的时候模型随机挑了一份。这在知识割裂场景里尤其常见。解决办法是在入库时制定统一的文档 ID 规范以源系统加文档编号作为唯一标识同 ID 的文档入库前先做内容版本对比旧版本一律不索引。别小看这个规范它能避免掉很多后期莫名其妙的错误答案。6. 最后分享一点实操体会RAG 这条知识获取管道做到最后你会发现真正的难点不在某一个环节而在于让整条链路耦合得足够稳。我自己跑了几个知识库项目之后的体会是先把最简单的解析—分块—向量化—检索—生成循环跑通再用 hit rate 和忠实度这类量化指标去驱动调优比一开始就堆 GraphRAG、Agentic RAG 这些进阶方案靠谱得多。很多问题在基础管道里就已经被放大了把基本功补上后面的路会顺畅很多。还有一个小技巧分享给你在调试 RAG 的时候把每一次检索的 query、召回块、最终回答都存在本地日志里按天归档。没有这套日志你遇到线上用户反馈错误答案时基本只能靠猜有了日志你五分钟就能还原出问题出在哪一环。RAG 不是一次性的工程它是一条需要持续维护的管道而这种维护能力才是让 Agent 真正可用和可靠的关键。