首页 / 资讯中心 / 文章详情

RAG进阶指南:AI Agent知识获取管道的设计与落地实践

RAG进阶指南:AI Agent知识获取管道的设计与落地实践 ★ FEATURED ARTICLE
聊到 AI Agent前面几篇我们把 Agent 的基础结构、工具调用、规划能力都过了一遍。这篇我们专门讲 Agent 的“记忆外挂”——知识获取管道也就是 RAG 基础。先纠正一个认知RAG 在最火的那两年被很多人等同于“文档问答机器人”弄个向量库存一堆 PDF用户问一句系统检索几段拼给大模型就算完事。但到了 Agent 时代RAG 的地位完全变了它不再是独立于 Agent 之外的一个功能模块而是 Agent 获取世界知识、私有知识、实时知识的核心管道。一个 Agent 如果在需要查资料、读文档、带规则决策的时候只能靠它训练时的那点记忆那它和一本过期百科全书没有任何区别。这篇文章我会用做实际项目的角度把 RAG 如何内嵌进 Agent 的知识获取流程讲清楚包括管道里每个关键环节的选型逻辑、参数取舍、踩坑记录以及最后如何把整套管道封装成 Agent 的 Tool。不论你是准备给手头的 Java、Python 项目接入知识检索还是在学习 Agent 开发这篇文章都能给你一套可以直接落地的思路。1. 为什么说 RAG 是 Agent 的知识获取管道1.1 Agent 缺的从来不是“思考”而是“带宽”很多人构建 Agent 的第一反应是堆 Prompt把要用的知识全塞进上下文里。这个思路在演示场景下确实有效但业务系统里一碰就碎。你去观察真实的企业级 Agent它面对的文档可能有几万份每份几十页产品的技术手册每天都在更新客服话术每个季度都调整。全量塞 Prompt 既不现实也不是成本问题而是注意力被稀释的问题。大模型的上下文窗口再大它对长文本中间部分的关注度天然低于开头和结尾业内叫 lost in the middle。把文档平铺给模型看似信息都在实际上模型处理起来的效果并不好尤其在复杂推理任务里混入大量无关文本会明显拉低准确率。这就是我说的带宽问题模型处理信息的带宽是有限的Agent 需要的是一个过滤器把“当前任务相关”的知识精准提取出来而不是把整个仓库的信息端到它面前。RAG 恰好就是这个过滤器。它的核心价值不在于让模型“读”文档而在于让模型“只读当前需要的部分”。从这个角度看RAG 和 Agent 的关系不是拼接而是内嵌Agent 决定什么时候去查、查什么、怎么评价查回来的结果RAG 负责把这个问题转化成一次高效的检索。1.2 三条知识注入路线的取舍Prompt、微调、RAG谈到让模型掌握私有知识绕不开三条路直接塞 Prompt、做微调、做 RAG。我见过不少团队在这三个选项里反复挣扎尤其是一些有算法背景的团队一上来就倾向微调觉得那才是“根治”。但从我实际案例看选型逻辑根本不复杂按下面三个维度判断就好。先说微调。微调适合沉淀的是“不可言说的知识”比如行话、语气、特定领域的输出格式、或者一个模型很难在推理中临时组织的思维范式。它把知识融进了权重里响应速度不会变慢但缺点是更新一次成本高而且容易把模型原本的能力冲淡也就是灾难性遗忘。我见过一个团队微调出一个带公司内部术语的模型结果通用写代码的能力明显下降最后不得不混合训练数据重新调。再说 Prompt 注入适合规则型、轻量级的知识像某些操作规范、几条关键准则。这个方式直接但不适合大体量知识而且现在很多 Prompt 注入方案会把文本精简成摘要再塞进 system prompt本质上是把知识压成了指纹损失了大量细节。RAG 在这三类知识里站在中间它适合的是“一张表没法说清、一个模型记不住、但能通过查文档找到答案”的知识比如产品手册细节、某个接口的变更记录、行业规定条文。它最香的地方是更新成本极低文档变了重建索引就行模型本体的权重完全不动。从维护角度讲RAG 才是企业知识长效沉淀的正解。1.3 Agent 场景下 RAG 的特殊形态传统 RAG 的交互模式是“用户发问一句话系统返回一段答案”。Agent 场景下完全不一样Agent 的任务往往由多个步骤组成它可能第一步需要先检索公司内部的知识库第二步拿出检索片段判断下一步该调用哪个工具再下一步带着检索结果去回答用户。也就是说RAG 不仅仅服务于最终答案的生成它在决策的中间环节也在被反复调用。这也是这两年 agentic rag、RAG as a service 被讨论得越来越多的原因。Agent 需要的不再是一个静态的检索接口而是一个可以被编排的、支持多轮查询、能感知上下文、能返回结构化知识片段的管道。比如 LangChain4j、Spring AI 这类框架里已经有人把 RAG 直接封装成 Agent 的 Tool让大模型自己决定什么时候查知识库而不是每次对话都强制执行一次检索。这种形态下的 RAG 要求更高要有明确的输入输出契约方便模型调用要支持过滤条件比如某个产品线、某个时间段还要有意图判断能力能识别“这个问题该不该检索”。这些我们在第五节展开先把基础管道搞清楚。2. RAG 管道各环节拆解与选型2.1 文档解析源头的坑决定后面所有环节的坑很多人搭 RAG 第一个动作就是写 chunking 代码这个顺序是错的。RAG 第一条潜规则垃圾进垃圾出。如果源文档解析得乱七八糟后面分块、向量化、检索做得再好也是白搭。文档解析实际碰到的坑比理论多得多。PDF 分两类一类是文本型 PDF文字可以直接提取另一类是扫描件必须 OCR这个步骤非常容易翻车尤其有表格、页眉页脚、多栏排版的内容。Word 文档要考虑样式层级Excel 要考虑行列语义PPT 要考虑标题与正文的关系。我见过一个项目文档里有个关键的金额数字被拆成了两行解析出来变成两个不完整的数字后续检索即使命中也答错了排查了大半天才发现是解析层的坑。实操建议很简单别把解析当成“附加项”把它当成管道的第一道数据处理工序。每引入一种新格式都要人工抽样检查解析结果尤其注意表格内容有没有被拆碎语义是否还完整页眉页脚、页码等重复内容是否被过滤多栏文本的阅读顺序是否正确扫描件 OCR 后的错别字对检索关键词的影响有多大。如果你处理的是网页、Markdown、技术文档这类半结构化内容解析难度会低一些但还是得做标题树提取。因为后面的分块策略强烈依赖文档结构没有结构信息所有文本就像一锅粥chunking 再聪明也只能靠窗口滑动硬切。2.2 分块策略chunk size 与 overlap 的取舍分块是整个 RAG 管道里最容易被低估的一环。不少初学者的做法是固定一个 chunk_size比如 500 个 token然后按窗口滑动。这个做法能用但效果往往一般因为真实文档里语义边界和固定窗口格格不入。我总结了一个分层分块的心得在实际项目中比纯固定窗口效果稳得多第一优先是按文档语义结构切比如 Markdown 的标题层级、Word 的段落大纲、PDF 的章节。一个标题下的内容尽量作为一个完整块这样语义聚拢性好第二优先是看语言边界一个代码示例、一条完整 SQL、一段独立的表格说明都应该作为独立块保留最后才是按 token 窗口兜底在特别长的无结构文本里用 300 到 500 token 的窗口切overlap 设在 50 到 100 token 之间。overlap 的作用是防止语义被切点在中间截断比如一句话跨了两个 chunk检索的时候如果只命中后半段语境就丢了。但 overlap 不是越大越好它会让相邻块之间的重复信息变多检索结果容易出现大量相似内容反而稀释了有效信息。分块参数没有绝对最优行业里推荐的做法是拿一批有代表性的 query 做测试对比不同 chunk_size 的命中率。不要凭感觉调参让数据说话。至于具体调到多少取决于你的文档类型和模型embedding能力后面实操部分我会给一套完整测试方法。2.3 Embedding 与向量库选型分完块之后要做的就是把每个块向量化。选 embedding 模型的核心标准不是排行榜刷分多高而是在你的领域文本上表现如何。通用模型对技术术语、行业黑话的编码往往不够精准比如“RBAC”和“权限模型”在不同语境下的语义相似度通用模型可能判断得不够准。建议先拿一批有代表性的 query到你的文档库里跑一个召回测试比较几个候选模型的表现。嵌入维度也是一个考量点维度越高向量化存储占用越大但语义表达通常更细。不过很多场景下用 768 维还是 1536 维差距并不明显真正拉开差距的是模型在垂直领域的实战表现。向量库选型要考虑的维度有检索质量、写入吞吐、过滤能力、生态兼容。我自己的经验如果项目已经用了 PostgreSQL直接上 pgvector少一个组件很多企业项目默认选它运维成本低如果对检索性能要求较高、查询模式偏复杂比如要做混合检索、要频繁更新文档Milvus 或 Qdrant 这类专用向量库更合适如果只是个人项目或快速原型Chroma、FAISS 都够用先跑通逻辑最重要。有一点特别想提醒很多人只关注向量库的“相似度检索”忽略了它的过滤能力。实际上业务系统里时间范围、产品线、文档类别这些过滤条件往往比 Top-k 检索对结果的影响还大。建议选型时就把 filter 支持程度列进关键评估项不然后面每次想要定向检索都得把全量数据拉出来再过滤效率会非常低。2.4 检索与重排为什么召回 top20 比 top5 更稳检索环节有个反直觉的规律先多召回再精排比单纯追求一次性命中 top5 更可靠。原因很简单向量相似度只是语义层面的粗筛它找到“相关主题”的能力不错但找到“真正能回答问题的那一段”的能力有限。把召回范围扩大到 top20再通过重排模型对“问题-段落”做精细打分往往能把真正有用的一段排到前面。重排模型的英文 reranker常见的有 bge-reranker 系列、Cohere 的 rerank 接口以及一些开源 Cross-Encoder 类模型。它们做的事本质上是一次“更聪明的匹配判断”不仅看语义相似还会看两个文本之间是否有直接的问答关系。这个环节通常能把命中率提升 10 到 20 个百分点代价是多一次模型调用增加了毫秒级的延迟。所以流程上我建议把“检索”和“生成”之间加一道重排。这一步在传统 RAG 教程里经常被跳过但工程化落地之后体感差距非常明显。另外检索时建议同时保留关键词匹配和向量匹配关键词保证精确术语能命中向量保证语义泛化能兜底两者融合后再重排是当前比较稳的组合。3. 实操从零搭一个能被 Agent 调用的 RAG3.1 最小可用的数据管道下面我们动手。假设我们要给 Agent 接一套内部知识库管道文档格式是 Markdown 为主、少量 PDF。先写一套最小可用的数据管道用 Python 演示思路可以平移到 Java 或 Go。# ingest.py - 数据管道核心流程 import os from langchain.text_splitter import MarkdownHeaderTextSplitter from langchain.embeddings import HuggingFaceEmbeddings from langchain.vectorstores import Milvus # 1. 加载文档 with open(docs/company_manual.md, r, encodingutf-8) as f: content f.read() # 2. 按标题结构分块 headers_to_split_on [ (#, H1), (##, H2), (###, H3), ] splitter MarkdownHeaderTextSplitter(headers_to_split_on) chunks splitter.split_text(content) print(f生成 {len(chunks)} 个文本块) # 3. 对每个文本块添加元数据 for i, chunk in enumerate(chunks): chunk.metadata[source] company_manual.md chunk.metadata[chunk_index] i # 4. 向量化并写入向量库 embeddings HuggingFaceEmbeddings(model_nameBAAI/bge-m3) vector_store Milvus.from_documents( documentschunks, embeddingembeddings, collection_namecompany_manual, connection_args{host: localhost, port: 19530}, ) print(索引构建完成)这是最基础的一版几行代码就能跑。但我建议你在生产环境里把它扩展成三个环节独立跑解析层、分块层、索引层各做各的事方便单独更新或排查问题。解析和分块是两个最容易引起定位困难的环节一旦检索结果不准从头排查时解析和分块日志要能单独输出。我习惯在每个异步任务里加一个 trace_id从文档加载一路带到 chunk 写入后面调问题才能追根溯源。3.2 检索接口与 rerank 实现管道建好之后Agent 需要的是一个干净的检索接口而不是直接暴露向量库访问。这个接口应当接受一个 query返回一组片段。我们在这加一道重排逻辑# retriever.py - 检索与重排 from langchain.vectorstores import Milvus from langchain.embeddings import HuggingFaceEmbeddings from sentence_transformers import CrossEncoder embeddings HuggingFaceEmbeddings(model_nameBAAI/bge-m3) vector_store Milvus(embeddingsembeddings, collection_namecompany_manual) # 重排模型初始化一次复用 reranker CrossEncoder(BAAI/bge-reranker-base) def search(query: str, top_k: int 20) - list[dict]: # 1. 向量召回 top20 raw_results vector_store.similarity_search_with_score( query, ktop_k ) # 2. 对召回结果做重排打分 pairs [(query, doc.page_content) for doc, _ in raw_results] scores reranker.predict(pairs) # 3. 按重排分数取前5作为输出 ranked sorted( zip(raw_results, scores), keylambda x: x[1], reverseTrue )[:5] return [ { content: doc.page_content, score: float(score), source: doc.metadata.get(source, ), page: doc.metadata.get(chunk_index, 0), } for (doc, _), score in ranked ]这个接口已经具备可以被 Agent 调用的雏形输入一个字符串 query输出一段带来源和分数的结构体。注意返回结果里必须带 source因为 Agent 需要把答案和证据挂在一起否则用户问“你怎么知道的”系统变成无源之水这在很多业务场景是不可接受的。召回参数 top_k20 不是随手写的。我在多个场景跑过top10 和 top20 的差距在复杂问答里尤其明显top20 给重排器提供了更充分的候选池。top30 以上收益递减反而增加重排调用耗时。这个值你可以用自己的一套测试集去验证不同领域可能有差异。3.3 把 RAG 封装成 Agent 的 Tool管道就绪下一步要让 Agent 用起来。最自然的方式是把检索封装成一个 Tool让模型在 Need 时调用而不是每次都硬插上下文。下面是封装 Tool 的示例以 LangChain 的 Tool 接口为例# agent_tool.py - 把检索封装为 Agent 工具 from langchain.tools import tool from retriever import search tool def knowledge_search(query: str, category: str ) - str: 从公司内部知识库中检索信息。 参数说明: - query: 用户想查询的问题关键词建议使用原始问题直接传入。 - category: 可选的类别过滤如产品手册、技术规范、客服话术。 返回: 与查询相关的知识片段列表包含内容、来源和匹配分数。 results search(query, top_k20) # 如果有类别要求在返回前做一次过滤 if category: results [r for r in results if r.get(source, ).startswith(category)] if not results: return 未检索到相关内容请尝试换一种表达方式。 # 拼接成模型容易理解的文本结构 output [] for idx, item in enumerate(results): output.append( f[{idx}] (来源: {item[source]}, 相关度: {item[score]:.3f})n f{item[content]} ) return n.join(output)这里有一个容易踩的坑Tool 描述一定要写清楚参数含义因为模型是在“读描述”来决定怎么传参的。如果你的 query 参数描述写得模糊模型可能自作主张提取关键词再传结果检索效果反而不如直接传原句好。实测下来让模型直接传入原始用户问题检索效果通常最好因为 RAG 管道的向量检索对自然语言表达比“精简关键词”更友好。Agent 拿到检索结果后下一步是判断这个结果够不够回答用户。这块有两种处理方式一是让模型直接把检索片段作为事实依据组织答案这是最基本的 Retrieval-augmented Generation二是让模型再走一步推理看要不要二次检索补充细节这就进入 agentic rag 的范畴了。第五部分会展开。4. 常见问题与排查实录4.1 检索命中率不理想问题可能出在哪命中率是 RAG 项目最让人头疼的指标。我整理了一份排查顺序按下面顺序查基本能覆盖绝大多数问题第一看 query 和文档的匹配度如果用户的提问方式和文档表达方式差异太大比如文档写“报销单审批流程”用户问“我填完单子多久能通过”向量检索很可能召回不够直接。这类问题需要靠改写查询词或加同义扩展解决。第二看分块是否切碎了关键内容有时候答案其实是完整的只是被切到了不同块里每个块都只讲了一半。解决办法是查一次召回结果里相邻块如果发现答案确实分散说明分块策略要调整。第三看 embedding 模型对领域词的支持用一批术语 query 单独测如果涉及专有名词的命中率明显偏低就要考虑换更强的领域 embedding 模型或加词典。第四看向量库的归一化问题不同向量库对相似度得分的处理方式不同有的返回的是内积有的是余弦值如果比较得分时混用不同度量容易误判。实际项目中我见过 40% 以上命中率问题出在分块上不是 embedding。所以排查时别急着换模型先拿命中的片段人工看一眼往往就明白问题了。4.2 元数据过滤被忽略的精度利器很多 RAG 实现把检索做成纯粹的“全局语义搜索”结果一搜全库最相近的内容全出来了。但真实业务里知识库往往有极强的结构比如“某产品线的手册”和“另一产品线的手册”用词非常接近单靠向量相似度很难区分。解决办法是为每个 chunk 打上丰富的元数据并在检索时强制过滤。常见的元数据字段有来源文件名、文档版本号、发布日期、所属部门、产品线、文档类型。有了这些字段Agent 查询时就可以带上过滤条件比如“只查 V2 版本的接口说明”准确率会大幅提升。我自己做项目的经验是每次写索引时都把元数据当作一等公民设计宁可冗余也别偷懒。因为后续所有检索优化都依赖这些标签想补的时候往往得重建全量索引成本非常高。4.3 成本与延迟的平衡RAG 管道的延迟大头通常不在向量检索而在重排模型调用和 LLM 生成。向量检索一般能做到十几毫秒到几十毫秒重排需要几百毫秒如果还有大模型回答案整体延迟就看生成长度了。针对这个我有几个实操心得重排虽然增加延迟但不要轻易省。如果实在要省可以把重排模型换成更小的变体或者对较短的候选集做重排比如召回 top10 再重排相比 top20 能省近一半时间。缓存可以大幅压低重复查询的延迟。同一种问法短时间内频繁出现时直接在缓存层返回结果。企业场景里用户体验提升非常明显。对实时性要求极高的 Agent 动作比如需要秒级响应去调工具可以考虑把检索结果预先缓存到 Agent 的上下文里而不是实时查库。控制输入到 LLM 的片段长度。每段返回 200 到 300 token 足够太长反而降低答案精准度。另外Embedding 模型如果用的是在线 API延迟和费用都不好控制。批量写入索引的时候建议用本地或内网部署的模型不然后台建索引时带宽被占住线上检索也会一起卡壳。5. 从 RAG 到 Agentic RAG下一站怎么走5.1 多轮检索和路由Agent 什么时候该查什么时候不该查聊完基础管道最后说说走向生产环境的 Agent 化改造。传统的单轮 RAG 是“问一下查一次”但真实使用中用户经常说一句话包含多个问题或者问题本身依赖上下文。比如用户先问“报销流程是什么”接着又问“要多久”。第二个问题在纯 RAG 里很容易查偏。Agent 化的 RAG 需要把多轮对话的信息汇总成完整的检索单元再决定是否需要检索这个环节业内叫 query rewriting 或 query routing。我推荐的做法是让 Agent 先做一次意图分类判断当前问题是否需要检索两个原因导致 Agent 倾向去查要么内部知识里明确有要么用户提问的实体词和知识库里的术语高度匹配反之闲聊、通用常识、或者前一轮已经检索过的内容可以直接靠模型记忆回答不触发检索。这个判断本身就是一个函数调用问题。可以让模型决定调不调 knowledge_search 工具这在 LangChain 的 Agent 框架里天然支持。之前封装 Tool 那段代码里Agent 会依据问题判断是否调用这已经算是最简版的 Agentic RAG 雏形了。5.2 结构化知识图谱与 RAG 结合传统 RAG 处理非结构化文本很顺手但碰到强关系、多跳逻辑的时候就吃力了。比如“A 产品的 B 缺陷影响了哪些同样用了 B 模块的其他产品”这类问题纯向量检索很难答好。社区这两年在热的方向是 ontology rag、graphrag把实体和关系抽出来构造成知识图谱Agent 可以通过图谱的路径查多跳关系也可以把图谱检索和向量检索混合使用。实现上通常分两步先做离线图谱抽取用到 LLM 或专门的 NER 模型把文档里的实体、属性、关系抽出来存入图数据库在线阶段根据用户问题决定走“向量通道”“图谱通道”还是“混合通道”。这块复杂度不低但对企业级 Agent 的价值很大尤其是产品检索、故障排查这类高精度场景。不过我的建议是别急着上图谱。如果业务的核心问题都能通过单跳检索解决图谱投入产出比很低。等你能明确说出哪类问题是因为“跨文档的知识碎片化”而答不对再考虑引入图谱效果会明显很多。5.3 RAG as a Service把管道服务化随着 Agent 产品越来越多RAG 本身也在被抽象成一种服务。这波趋势在 Spring AI、AgentScope 这类框架里变得尤其明显。原因很简单知识库的构建和检索实际上是一种很通用的能力不该每个 Agent 重复造轮子。如果你要做成服务核心要考虑三件事缺一不可多租户数据隔离不同业务线之间的知识不能混要在向量库里做 collection 隔离或元数据隔离灵活的 Schema 定义不同知识库有不同的元数据需求服务应支持动态注册字段版本管理与灰度发布索引和检索算法升级时不能一把梭要能快速回滚。这个方向做扎实了其实就变成一个内部的知识中台后端所有业务 Agent 都能复用价值会远远超过一个个独立的知识库。写到最后这套管道从零到能跑通我反复验证下来的核心感受是RAG 的瓶颈从来不在模型多强而在管道设计得是否贴近真实业务。先吃透文档结构和查询模式再选工具和调参效果往往比盲目堆新技术要好得多。希望这篇能给你搭出自己的知识获取管道带来一些可落地的参考。
阅读完成 · 觉得有帮助?
咨询建站