ARTICLE DETAIL

资讯详情

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

从零拆解RAG知识获取管道:AI Agent的必备基础

从零拆解RAG知识获取管道:AI Agent的必备基础 走进 AI Agent 这个系列写到第四篇前面把 Agent 的意图识别、工具调用、记忆管理都过了一遍。这一篇聊一个特别容易被低估的模块知识获取管道说人话就是RAG 基础。RAG 的全称是Retrieval-Augmented Generation检索增强生成它在 Agent 里的作用一句话就能讲清——模型记不住的知识由外部管道负责找回再把找回的片段交给模型组织成答案。能不能让 Agent 在不重训的前提下快速获得某个领域、某个系统甚至某个人私有知识就看这条管道搭得好不好。这一篇适合两类人一类是刚开始接触 AI Agent想知道 RAG 到底在整套系统里起什么作用另一类是自己已经搭过简单 Agent但发现回答经常一本正经地编打算用外部知识库解决这个问题。我会从零开始拆管道讲清楚每个环节在设计时的取舍再给出一个可以直接改来用的最小示例。1. 为什么AI Agent必须补上“知识获取管道”1.1 光靠模型内部知识Agent回答不了的三类问题很多刚接触 Agent 的人会有一个错觉模型这么强什么都知道直接问不就行了实际一测就露馅。第一类是私有知识问题。公司内部的规章制度、产品线的历史决策、某个系统的接口文档这些内容根本不在模型训练数据里。第二类是实时信息问题。模型训练有截止日期今天的最新数据、刚发布的版本变更、对方刚发来的附件内容模型不可能知道。第三类是需要溯源的问题。客服场景里问“你根据什么这么回答”模型如果只是在参数里翻记忆没法给出可验证的来源。这三个问题不是模型能力不够而是模型的天花板决定的。把知识塞进参数成本高、更新慢、无法验证这也是为什么纯粹靠微调做知识注入越来越不划算。RAG 的思路换了一个方向知识不放进模型放在外面用到的时候现取。这种方式的优势很明显知识更新只需要改外部数据模型本身一动不动回答还能附上原文出处。1.2 RAG是一条管道不是一个插件我在跟人聊 RAG 的时候发现很多新手会把它当成一个“插件”好像装个库、调个接口就完事了。实际上 RAG 是一条完整的数据管道从原始文档到最终答案中间要经历加载、切分、向量化、存储、检索、重排、生成好几个环节。把它理解成管道有两个实际好处。第一每个环节都能单独优化。比如检索结果不准你得先判断是切分粒度的问题还是向量模型选型的问题还是 top-k 参数不合理。如果当成黑盒插件出了问题根本无从下手。第二每个环节都能单独替换。文档解析器可以换向量库可以换召回策略可以换生成模型也可以换。管道的价值就在于各环节解耦哪个不行换哪个。把 RAG 放进 Agent 架构里看它其实是 Agent 的知识记忆的外部延伸。Agent 本身负责思考、规划、调用工具RAG 负责在思考之前或思考过程中提供参考资料。这也是为什么这一篇叫“知识获取管道”——它支撑的是 Agent 最核心的推理基础。2. 一条完整RAG管道的四个关键环节2.1 环节一文档加载与切分管道第一步是把知识源变成可检索的片段。这一环节最常见的错误是直接拿整篇文档去向量化。大模型上下文有长度限制向量检索的匹配粒度也不适合整篇文档所以必须切分。切分策略里有两个关键参数chunk size块大小和overlap重叠长度。chunk size 决定每个片段包含多少字符或 tokenoverlap 决定相邻片段之间保留多少重叠内容。为什么不直接切完就行因为一句话可能在中间被拦腰截断语义就碎了。加 overlap 是为了让同一个知识点在两段中至少完整出现一次。我自己的经验是通用文档从 500 到 800 字符开始试代码文档从 200 到 400 行开始试Markdown 文档优先按标题结构切。这里推荐用递归字符切分器它先按段落切段落太长再按句子切句子还太长再按字符切比固定长度切分聪明得多。切分完成后顺手把来源、页码、标题这类元数据一并存下来后面做引用溯源就靠它们。2.2 环节二向量化与知识入库切好的片段要转成向量才能被检索。这里核心是选 embedding 模型。embedding 模型把文本映射成一个向量语义相近的文本在向量空间里距离近。选型时主要看三个维度向量维度、语言支持、对比效果。维度高信息更丰富但存储和计算成本也高不支持中文的模型直接不能用效果需要拿自己的数据对比不能只看榜单。向量化之后要把结果存进向量数据库。市面上的方案很多FAISS 适合本地轻量场景Chroma 适合开发原型pgvector 适合已经用了 PostgreSQL 的团队Milvus 适合大规模生产集群。我建议第一次搭 RAG 先用 FAISS 或 Chroma原因很简单把精力放在管道的逻辑上而不是运维上。向量数据库本质是个“按相似度查最近邻”的存储选哪个都要注意索引类型。FAISS 里常用的 IVF 索引适合数据量大但允许一点精度损耗的场景数据量小的时候暴力精确检索反而更好。向量库适合场景部署方式上手难度FAISS本地原型、中等数据量嵌入式低Chroma快速验证、轻量应用嵌入式很低pgvector已有 PostgreSQL 的团队随库部署中Milvus大规模生产、高并发独立集群高Elasticsearch需要全文检索混合独立集群中高这个阶段还有一个易忽略的点知识更新。入库不是一次性的事文档改了一版旧向量还在库里检索时就会带出过期内容。所以在设计时建议给每条向量记录来源文档 ID 和更新时间更新时先删旧再写新。2.3 环节三检索召回与重排检索环节决定从库里捞回哪些片段。最朴素的做法是向量相似度 top-k问题在于只做向量检索关键词完全匹配的场景反而吃亏。比如文档里写的是“张三”用户问的是“Zhang San”向量相似度可能不如关键词命中直观。更稳的做法是混合检索向量检索和关键词检索各跑一遍再把结果合并去重。检索完通常还要加一步重排Rerank。向量召回的目的是“别漏”重排的目的是“别错”。重排模型把召回的候选片段和原始问题拼在一起逐对打分选最匹配的那几个。这一步能显著提升答案质量代价是多一次模型调用延迟会增加几十毫秒到几百毫秒。生产环境我一般建议把重排放在后端前端用户无感知质量提升却是实打实的。top-k 取多少也很讲究。取少了可能漏掉关键信息取多了会把不相关的内容塞进上下文干扰模型判断。我常用的起点是召回 20 条、重排后取前 5 条投入生成。这个参数后面要根据效果调整别迷信默认值。2.4 环节四生成阶段的上下文组装检索到的片段要送进大模型怎么组装决定了答案质量。这里面有两个问题一是上下文超长二是prompt 引导不足。上下文超长时不是把所有片段全塞进去就完事。模型对长上下文的注意力会分散中间位置的内容容易被忽略这种现象业内俗称“lost in the middle”。所以要控制送进去的片段数量把最相关的放最前面或最后面。这里可以做的事情还包括对片段做相关性打分截断低于阈值的宁可不用对重复内容做去重避免同一个知识点反复出现。prompt 层面系统提示词里至少要写清楚三件事回答只依据提供的资料资料不足时直接说明不知道回答尽量附带片段来源。特别是最后一条既方便用户验证也能让模型少一点自由发挥的欲望。组装顺序我习惯按来源分组而不是按相似度排序这样模型在组织答案时更容易把同一文档的信息糅在一起而不是东一句西一句。2.5 最小可运行示例用代码把管道串起来文字讲再多不如一段能跑的代码直观。下面这个示例基于 LangChain 0.1.x实现一个最简 RAG 管道读文档、切分、向量化、检索、问答。from langchain.document_loaders import TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.embeddings import OpenAIEmbeddings from langchain.vectorstores import FAISS from langchain.chat_models import ChatOpenAI from langchain.chains import RetrievalQA # 1. 加载本地文档 loader TextLoader(knowledge.txt, encodingutf-8) documents loader.load() # 2. 递归切分块大小500字符重叠50字符 splitter RecursiveCharacterTextSplitter(chunk_size500, chunk_overlap50) docs splitter.split_documents(documents) # 3. 向量化并存入FAISS embeddings OpenAIEmbeddings(modeltext-embedding-3-small) vectorstore FAISS.from_documents(docs, embeddings) # 4. 构建检索问答链 qa RetrievalQA.from_chain_type( llmChatOpenAI(modelgpt-4o-mini, temperature0), chain_typestuff, retrievervectorstore.as_retriever(search_kwargs{k: 5}), ) # 5. 提问 answer qa.run(咱们的产品支持批量导入吗) print(answer)这段代码里有两个细节值得说明。search_kwargs{k: 5}是检索召回条数建议先按 5 起步看结果再调。temperature0是生成参数知识问答场景尽可能不要有随机性答案必须稳定可复现。如果手头没有 OpenAI 的 keyembedding 和 LLM 都可以替换成本地模型比如用HuggingFaceEmbeddings挂一个开源的 embedding 模型再用Ollama跑本地 LLM管道逻辑完全不用动。3. 进阶方向Agentic RAG 让管道学会自己决策3.1 固定管道和自适应检索的区别基础 RAG 有个明显的死板之处无论什么问题都走“向量化 → top-k 召回 → 生成”的流程。用户问“今天天气怎么样”它也要去知识库里捞一圈用户问“根据公司章程报销流程是什么”它也许只需要查某一个文档却把全库检索了一遍。Agentic RAG 的思路是让 Agent 在检索这件事上拥有决策权。具体表现有很多种先判断要不要检索再判断去哪个知识库检索如果第一轮检索结果不够要不要改写问题再查一次多个子问题是不是要分步检索再汇总。这些决策由 Agent 自己完成而不是写死一条管道。我在实际项目中感受最深的是“查询改写”带来的提升。用户问“那个新流程什么时候生效”这句话直接拿去检索效果很差因为“新流程”是个模糊指代。Agent 可以先根据对话历史把它改写成“2025年修订版员工报销流程的生效日期”再去做检索命中率明显上升。基础 RAG 把问题原封不动丢给检索器Agentic RAG 会在中间加一个“翻译层”。3.2 查询改写、路由和多跳检索的落地逻辑做 Agentic RAG 时通常先加三个能力按性价比排序。第一个是路由Routing。给知识库打标签比如协议文档库、产品说明库、历史问答库。Agent 先判断问题属于哪个领域再去对应库检索避免跨库干扰。第二个是查询改写Query Rewriting把口语、指代、多意图的问题转成更精确的检索词。第三个是多跳检索Multi-hop Retrieval一个问题拆成多个子问题每个子问题独立检索再汇总适合“对比 A 方案和 B 方案的适用场景”这类问题。实现上这三种能力不一定都要用复杂框架。路由可以是一个简单分类 prompt查询改写可以让模型先输出改写后的 query 再走检索引擎多跳检索可以让 Agent 在规划阶段输出一个检索计划。只要理解背后的逻辑用什么框架是次要的。如果研究得更深一层还有 GraphRAG、Ontology RAG 这类基于知识图谱的方案适合组织级知识管理但那些是在基础管道跑通之后再考虑的重武器。3.3 把RAG封装成Agent可用的一把工具这一章最后说一个特别实用的经验RAG 在 Agent 架构里应该是一把可调用的工具而不是藏在系统提示词里的背景知识。很多人的做法是把检索结果一股脑塞进 system prompt这样会让 Agent 每次对话都消耗大量上下文而且当问题不需要外部知识时反而干扰了模型判断。正确的做法是定义成一个工具函数比如search_knowledge_base(query: str) - list[dict]Agent 在需要时主动调用。这样做有至少三个好处。第一上下文只在必要时消耗第二Agent 的推理过程变成可观测的“先查资料再回答”第三这个工具可以和代码执行、API 请求等工具并列构成真正的工具生态。如果你在研究 skill 或者 function calling记住这个设计原则知识获取应该像拧开水龙头一样随用随取而不是让水流一直开着。4. 怎样评估RAG是否真的好用4.1 hit rate、MRR、忠实度指标要怎么读RAG 管道搭完最怕的感觉是“好像行又好像不太行”。要摆脱这种主观判断得有评估指标。最基础的指标是hit rate命中率。它的意思是在测试集里目标答案所在的文档片段有没有被检索出来。假设有 100 个问题每个问题预先知道正确答案在哪个文档块里跑完检索后检查前 k 条召回里有没有包含它包含了几条命中率就是几成。这个指标只看检索环节不看生成效果。第二个常用指标是MRRMean Reciprocal Rank平均倒数排名。它比命中率更严格要求目标片段出现在召回的越靠前越好。计算公式是 1/排名位次比如目标片段排第 1 得 1 分排第 3 得 1/3 分排第 10 得 0.1 分取所有问题平均。同样召回 5 条目标在第一条和最后一条用户体验完全不同MRR 就能把这种差异体现出来。第三个指标更偏端到端叫忠实度faithfulness。它评估生成答案中的每个关键点是否都有检索资料支撑。实际操作中可以逐句检查回答看哪些句子没有出处没有出处的句子占比就是“幻觉率”。如果想用自动化的方式可以让一个更强大的模型去对照检索片段和回答逐条打分成本不高效果也稳定。4.2 手工构造评测集先跑通再跑准建评测集听起来很工程化其实初期可以手工做。拿一批真实用户问题每条配上正确答案所在的文档20 到 50 条就够用。关键在于覆盖度问题要涵盖简单询问、模糊指代、多条件组合、需要溯源四类场景。自己动手标注过一遍你基本能感觉到管道漏在哪。跑评估时先单独测检索再测生成。用同一组问题分别调 chunk size、embedding 模型、top-k 参数记录 hit rate 和 MRR 的变化。生成阶段重点看忠实度。不要一上来就追求指标满分先把流程跑通让 50 条问题中 80% 能得到有出处的答案已经比大多数内部工具强了。5. 实操中反复踩到的坑与排查顺序5.1 四个高频“翻车”现场这几年我前后落地过好几个 RAG 项目踩过的坑基本集中在这四个地方。第一个坑是切分导致语义破碎。典型案例是切分器把“本合同有效期自2024年1月1日起”切到上一段结尾“至2025年12月31日止”切到下一段开头检索时单独命中任何一段都无法获得完整信息。解决思路是切分尽量按语义边界走Markdown 按标题层级切表格按行切代码按函数切同时加大 overlap让语义完整的句子至少完整出现在一个块里。第二个坑是召回设置过紧。有人为了追求精确把 top-k 设为 2结果检索到的两个片段恰好都只覆盖问题的一半模型就只能胡编另一半。检索阶段应该偏“查全”重排阶段偏“查准”。我一般的参数是召回 20、重排后保留 5宁可多召回再做筛选。第三个坑是embedding 模型选错。比如拿通用英文模型处理中文文档相似度分数整体偏低效果自然差。换一个支持中文的向量模型往往能带来比调参更明显的提升。第四个坑是上下文塞太满。检索结果全塞进 prompt模型反而抓不住重点。上下文越长推理越慢准确率也不一定更高。需要通过重排和相关性阈值控制送入生成的片段数量。5.2 排查从哪一步开始避坑速查表遇到 RAG 效果不好我推荐的排查顺序是先看检索再看生成。先拿一个问题去检索器里看召回的前几条如果召回的片段本身就不包含关键信息问题出在索引或检索环节如果召回片段包含了关键信息但生成答案没用上问题出在 prompt 或上下文组装。下面这张速查表可以直接打印贴墙上现象优先排查环节常见解法检索结果牛头不对马嘴切分粒度 / embedding 选型调整 chunk size换支持中文的向量模型答案有幻觉胡编内容上下文组装 / prompt加“仅依据资料回答”约束检查送入上下文的相关性问题变个说法就搜不到查询改写 / 混合检索加入关键词检索对 query 做改写预处理答案不完整只答了一半top-k / overlap增大召回条数加重排环节更新了文档但回答没变知识入库更新策略删除旧向量再入库按来源文档 ID 维护版本相似问题答案不稳定生成参数temperature 调低接近 0每个问题对应一个抓手比瞎调好得多。我把 RAG 项目的调试比喻成修水管先确认进水有没有问题再确认管子通不通最后确认水龙头出不出水。顺序反了容易做无用功。拿问题去检索器里现场看召回结果这个动作应该成为调试时最高频的操作因为生成阶段的黑盒程度比检索阶段高得多能直接在检索阶段解决的问题不要拖到生成阶段去猜。这套 RAG 的管道逻辑本质上不受开发框架限制。我用 LangChain 给你做了示例但同样的流程LlamaIndex 能做Spring AI 配合 Java 生态也能做核心永远是那四个环节加载切分、向量入库、检索重排、生成组装。我个人这几年搭知识管道的体会是别迷恋花哨的架构先把最朴素的管道跑通让检索结果可解释、可观测再一步步往上面加 Agent 决策能力。基础管道稳了Agentic RAG 才有的放矢否则智能决策建立在一个不靠谱的检索地基上结果只会更糟。最后再分享一个小技巧每次你调整完切分参数或者检索策略把前后两次的 hit rate、MRR 记录在一个简单的表格里攒够十几组数据你对自己这套知识库的性格就摸透了。RAG 不是玄学它是可以量化、可以迭代、值得好好打磨的管道工程。
返回列表