
AI Agent 这个东西聊到第四篇终于要碰一块硬骨头了。前几篇我们拆了 Agent 的基本架构、工作流编排、工具调用大家都听得很嗨但真到自己动手搭一个 Agent 的时候十个人里有八个会卡在同一个地方Agent 脑子里那点知识完全不够用。大模型训练完就冻结了最新产品参数不知道、公司内部制度不知道、你那个 Excel 里的报价表更不知道。模型再强也只能是个“没有灵魂的百科全书”背书厉害一问你具体业务就露馅。RAG 干的就是这件事给 Agent 装一根吸管把外部知识精准吸进来再喂给模型。这篇我打算把 RAG 从原理到落地完整讲一遍重点放在“怎么搭”“参数怎么调”和“踩过的坑”上适合正在从 0 到 1 搭 Agent、准备给 Agent 接私域知识库的开发者和技术产品经理。看完你至少能独立跑通一个能用的 RAG 管道并且知道问题出在哪一层。1. 为什么 Agent 离不开 RAG知识管道的核心价值1.1 大模型的三个死穴知识截止、幻觉和私有数据先把话说透大模型不是数据库它是一个概率推理引擎。你今天问它“帮我查一下上季度华东区的销售数据”它能给你编一个 3.5 亿出来编得还像模像样。这不是它坏是它天生就没有这个能力边界。我习惯把大模型的问题归成三类。第一是知识截止模型训练完之后就停止更新了ChatGPT 也好、开源模型也好知识都是某个时间点之前的你跟它聊“最新的 Agent 框架版本”它只能瞎猜。第二是幻觉这一点和第一点是连锁反应不知道的事情它不会说“不知道”而是会顺着你的问题编一个看起来合理的答案高概率一本正经地胡说八道。第三是私有数据完全失忆企业内部的制度文档、项目记录、产品手册、数据库里的订单明细这些从来就不在模型的训练集里面你问什么它都不知道。这三类问题的共同答案只有一个在模型推理之前把需要的外部知识先准备好塞到上下文里让模型“开卷考试”。这就是 RAG 的出发点。1.2 RAG 其实不神秘它就是一个“开卷考”机制很多人一听“检索增强生成”这个术语就头大。别怕我用一个生活场景就能讲明白。你去参加一场开卷考试考试范围是 10 本书。你不会把 10 本书全搬进考场也没那个时间翻你要做的是根据题目判断要去翻哪本书的哪个章节找到相关的那几页然后把答案组织出来。RAG 干的就是这个“先查书、再答题”的流程只不过查书和答题都自动化了。拆开来看RAG 管道的标准动作就三步对海量文档做切块、做向量化存进向量数据库这是离线准备阶段收到用户问题后把问题也向量化到数据库里找出最相关的几个内容片段这是在线检索阶段最后把用户问题和检索到的片段一起塞给大模型让它基于这些片段生成答案这是生成阶段。我在给朋友做本地 ERP 产品的检索方案时就是按这个逻辑搭的。先把几千条产品说明和参数表切块入库用户问“某某模块支持多组织架构吗”系统先去库里捞相关段落再让模型基于捞到的内容作答准确率比直接问模型高了不止一个数量级。这套逻辑可以说适用于一切“模型没学过、但你手上有资料”的问题。1.3 Agent 里为什么必须专门有“知识获取管道”如果把 Agent 比作一个人大模型是他的大脑皮层负责思考推理工具调用是他的手脚负责执行动作那 RAG 就是他的外部记忆系统。Agent 最核心的能力是自主完成任务但“自主”的前提是它得拥有足够的信息来做决策如果信息全靠模型内置知识Agent 就像一个失忆的人见一个任务懵一个。所以在 Agent 架构里知识获取管道不是可选项是必选项。你去看现在主流的 Agent 开发框架LangChain、Spring AI、AgentScope全都把 RAG 作为一等公民内置了。尤其到了 Agentic RAG 的阶段检索本身也不再是固定的三步而是让 Agent 自己决定“什么时候该查”“怎么拆问题去查”“查完了要不要再深挖一轮”知识管道从流水线变成了一个有决策能力的智能体。这个后面详细讲。一句话总结你搭的 Agent 如果跑在裸模型上那它再能调用工具也是个残废。知识获取管道就是 Agent 的“粮道”粮道不通前方打得再热闹也是白搭。2. RAG 核心流程拆解从文档到检索再到生成2.1 离线索引阶段切块、向量化、入库一步都不能省离线阶段的目标是把杂乱的非结构化文档变成计算机能快速检索的结构化索引工作量占整个 RAG 搭建的六成以上却是很多人最容易糊弄过去的部分。第一步是文档加载你手里的资料可能是 PDF、Word、Markdown、HTML甚至是数据库里的文本字段需要先用解析器把它们转成纯文本。这一步看着简单坑却不少扫描版 PDF 直接提取出来的可能是乱码表格解析后可能变成一堆挤在一起的数字。我处理过最头疼的是一堆旧的 Excel 产品报价单格式各种合并单元格常规库解析出来完全没法用最后是先用脚本把每个 sheet 转成结构化的文本块才救回来。第二步是切块。这一步是离线阶段的核心难点切得好不好直接决定检索质量。切得太粗一个 chunk 几千字检索时把一堆不相关内容都塞进上下文模型容易跑偏切得太细语义被切碎检索时找不到完整的信息。通用的经验是优先按语义边界切比如 Markdown 的标题层级、PDF 的段落、代码的函数定义而不是死板地按固定字符数硬切。固定字符数切块适合做基线版本但生产环境基本都要定制切块逻辑。第三步是向量化用 Embedding 模型把每个文本块变成一个高维向量语义相近的文本向量距离也近。这一步的产物是整个系统的检索基础选什么样的 Embedding 模型直接决定了“语义理解”的上限。最后一步是入库把向量和对应的原始文本、元数据来源文档、页码、更新时间等一起写进向量数据库为后续的相似度检索做准备。2.2 在线检索阶段query 处理、相似度计算和重排序用户问一个问题系统需要实时完成检索。很多人以为检索就是把问题向量化、然后查最近邻实际操作下来你会发现直接这么干的效果往往很平庸原因在于用户的问题和文档的表述通常不在一个“频道”上。比如用户问“最近退货率怎么这么高”文档里写的是“商品售后异常波动分析”字面上完全不像向量余弦相似度也不高。这时候就需要对用户的原始 query 做改写或扩展用大模型把问题改写成适合检索的形式“2024 年第三季度各品类退货率统计与异常原因分析”。这一步在 RAG 流程里叫 Query Rewriting推荐大家从第一版就加上检索命中率提升非常明显。检索回来一堆候选片段之后还有一道重要的工序重排序。向量检索的 top-k 结果里有不少是“看着像但实际不太相关”的需要用重排序模型对候选片段做一次精细的匹配度打分把真正有用的信息提到最前面。我的经验是加了重排序之后答案的准确率能提升 20% 到 30%如果你现在没加重排这可能是性价比最高的一个升级。检索阶段还有一个关键参数召回数量 top-k。k 太小相关文档可能被漏掉k 太大塞给模型的片段太多不仅浪费 token还会引入噪声干扰模型判断。这个参数建议多做几组对比实验来确定不要拍脑袋定。2.3 生成阶段上下文组装和 Prompt 约束检索完成之后最后一步是把“用户问题 检索到的文档片段 系统指令”拼成最终的 Prompt交给大模型生成答案。这个阶段的第一个关键是上下文组装顺序。把最相关的片段放前面还是放后面对模型注意力的影响远超你的想象我自己测试下来把最相关的两条放在用户问题紧邻的位置效果最好。第二个关键是明确指令约束在 Prompt 里明确告诉模型只能基于提供的资料回答资料里没有的信息直接说明“未找到相关内容”不要强行编造。这能极大缓解幻觉问题。第二个关键点是实现引用溯源。让模型在回答时标注每句话的来源片段编号比如“根据资料[2]”这样用户能回查原始文档。尤其在 ERP 检索、法律文档问答这类场景溯源几乎是刚需否则模型答错了用户也无从校验。2.4 从零跑通一个最小 RAG可以直接抄的核心代码理论说了这么多不放点代码说不过去。下面是我习惯用的一个最简 RAG 流程用 Python 加 LangChain 框架逻辑清晰适合做脚手架from langchain_community.document_loaders import TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.embeddings import OpenAIEmbeddings from langchain_community.vectorstores import FAISS from langchain.chains import RetrievalQA from langchain_openai import ChatOpenAI # 1. 加载并切块 documents TextLoader(product_manual.txt).load() splitter RecursiveCharacterTextSplitter(chunk_size500, chunk_overlap50) chunks splitter.split_documents(documents) # 2. 向量化并入库 embeddings OpenAIEmbeddings(modeltext-embedding-3-small) vectorstore FAISS.from_documents(chunks, embeddings) # 3. 组装检索问答链 qa RetrievalQA.from_chain_type( llmChatOpenAI(modelgpt-4o-mini), retrievervectorstore.as_retriever(search_kwargs{k: 4}), return_source_documentsTrue, ) # 4. 试试效果 result qa.invoke(这个系统支持多组织架构吗) print(result[result]) for doc in result[source_documents][:2]: print(doc.page_content[:100])几个参数我解释一下。chunk_size500是基础版的块大小后面我会专门讨论这个值怎么调chunk_overlap50是切块时的重叠量目的是避免一句话恰好被拦腰切断丢失语义k4表示每次检索召回 4 个片段这个值可以先按这个跑基线再对比调优。提示想跑通上面的代码先确认环境里有langchain、langchain-openai、langchain-community、faiss-cpu这几个依赖包。用本地 Embedding 模型的话把OpenAIEmbeddings换成HuggingFaceEmbeddings就行。3. 关键选型与参数向量库、Embedding 和切分策略怎么定3.1 向量数据库选型别盲目上重武器向量数据库是 RAG 的存储底座市面上可选的一大堆选错了后面迁移成本很高。我给一个亲测过的选型结论小项目和个人练手用 FAISS 或者 Chroma中等规模上 Milvus 或 Qdrant规模大、要上生产的高可用集群再考虑 Elasticsearch 的向量检索能力。我做本地知识库时先用 FAISS 就足够跑通了几十万条向量检索毫秒级返回完全够用。给你看一个对比表方便做技术选型。方案适合规模部署难度优势注意点FAISS百万级以内低单机库轻量、快、无需独立服务不支持数据增量更新和管理Chroma原型验证低Python 内嵌上手最快支持元数据过滤高并发和生产环境不太行Milvus千万级以上中需部署集群功能全、支持过滤和混合检索运维成本高人力不足慎入Qdrant百万到千万级中单节点即可Rust 写的性能稳API 友好生态没有 Milvus 大Elasticsearch和业务系统耦合中高自带倒排索引适合混合检索纯向量性能不算顶级补充一句如果你的场景里“关键词精确匹配”也很重要比如搜产品型号“A38-B12”那建议优先选支持混合检索向量 关键词 BM25的数据库比如 Qdrant 或 Elasticsearch。具体原因后面讲 Hybrid Search 时细说。3.2 Embedding 模型怎么选维度、成本、语言能力三维平衡Embedding 模型负责把文本变成向量它的质量直接决定了“检索结果像不像那么回事”。我选型时主要看三个维度语言能力、向量维度和调用成本。第一个是语言能力如果你的内容以中文为主优先选中文语料训练过的模型比如 BGE 系列、text-embedding-v3 之类直接用英文模型处理中文语义召回率会明显下滑。我踩过这个坑一开始图省事用了某个通用英文模型结果产品文档里的中文术语检索一塌糊涂换了中文模型之后命中率直接翻倍。第二个是向量维度维度越高代表语义表达能力越强但存储和计算成本也越高。当前主流模型的维度在 768 到 1536 之间个人项目 768 维完全够用不用盲目追求高维。第三个是调用成本是每次向量化都要调 API 付费还是本地部署免费推理。很多开源模型用 GPU 跑效果已经和商业 API 差距不大了如果你的离线索引库有几百万条数据本地化部署能帮你省一大笔钱。3.3 chunk size 和 overlap切分策略是检索质量的隐形决定因素我在 2.1 节说过切块是离线阶段的核心难点这里把参数讲透。chunk size 选的不是“一个值”而是“一个平衡点”。切得小每个片段主题集中、检索精准但可能导致一段完整论述被切断使模型缺少上下文切得大每个片段信息完整但检索结果里噪声更多精确匹配度下降。拿产品文档举例子一段“计费规则”共有 800 字如果你用 300 字去切会被切成两半模型检索到后半段时看不到前面的“适用范围”答案就不完整如果用 800 字去切检索时真正相关的可能只有 200 字剩下 600 字是干扰信息模型容易被带偏。实操建议第一默认从 400 到 600 字起步做基线第二结合你的文档类型调整操作手册类可以切大一点到 800FAQ 类建议切小一点到 300 字以内第三overlap 设成 chunk size 的 10% 到 20%搞定跨块语义第四如果 markdown 标题结构规范优先按标题层级切块再补充切分。所有这些值都应该用测试集验证不要凭感觉。3.4 top-k 和重排序检索参数怎么调才算调明白了top-k 和重排序是检索响应的最后两道闸门。top-k 控制“捞多少”重排序控制“捞上来之后谁排前面”。这两者的关系是先靠 top-k 多捞一些候选比如 20 条然后用重排序模型精挑出最好的 4 到 6 条送给模型。这个组合拳比单纯调大 top-k 效果好得多因为向量距离近的不一定真的相关重排序模型专门干这个精细活。重排序模型的选型可以很直接小项目直接调 API比如 Cohere Rerank中文场景也可以用 bge-reranker 系列本地部署。开销是一次额外推理但换来的准确率提升非常值。我见过太多项目精调 Embedding 参数检索却只取 top-3 直接喂给模型结果效果一直上不去一问才发现没加重排这是典型的缺了关键环节。4. 实操中的坑检索不准、答案不对的排查思路4.1 检索不到相关文档先查切块再查 Query 改写最让人血压升高的场景是问了一个问题检索回来的片段驴唇不对马嘴。这时候千万别急着怪模型你要知道答案在哪个环节丢了。先查切块。如果某个技术概念散落在超大 chunk 里被检索到的概率就很低尝试把切块调小或按标题切。再查 Query 改写。用户问题往往口语化和文档风格差异大即便你加了 Query Rewriting也要看改写质量我调试时发现改写模型温度太高会把原意带偏建议温度调到 0.2 以下。最后查 Embedding 模型语言是否匹配中文内容用中文模型这是最基础的一环。另外有一个调试技巧很实用把检索结果直接打印出来人工看一遍。如果人眼看了觉得这些片段确实相关那说明问题在生成环节如果人眼都看不出来相关性那就回到检索环节排查。这一招能帮你快速定位责任方避免瞎调。4.2 上下文里明明有正确答案模型还是答错这个坑也很常见检索到了正确答案模型却给出了错误答案。这时候问题基本出在生成阶段。第一个问题是上下文过载k 值设得太大把不相关内容也塞进去了模型被噪声干扰。先减小 k 值或者加强重排序只留高置信度片段。第二个问题是 Prompt 约束不到位模型看到资料里没有的内容就自由发挥。我在生成 Prompt 里一定会写死这一句“如果提供的资料中没有明确信息请直接回答‘资料未覆盖该内容’”。第三个问题是信息被拆散答案需要综合多个片段单看每一段都不完整模型拼不出来。这种情况建议用多路检索对问题做多个角度的子查询分别召回后合并再让模型综合回答。排查的时候强烈建议把最终喂给模型的 Prompt 手动看一下。你会惊讶地发现有时候检索到的“相关片段”里真正有用的就一句话其他全是废话。这个视觉检查会让你对系统的真实质量产生最直观的认知比看什么评测指标都有用。4.3 知识库更新增量和版本管理是正经需求RAG 上线之后面临的最大问题不是效果不好而是“知识变了怎么同步”。很多文档系统每天都有更新如果索引库不更新Agent 永远给用户旧答案。我常用的方案有两种。一种是增量建索引使用向量数据库的 upsert 能力按文档 ID 和 chunk ID 做覆盖写入删掉老内容再写入新内容。另一种是定时全量重建适合数据量不大、更新频率低的场景定个凌晨两三点的 cron 任务全量跑一遍。生产环境建议两种结合日常小更新走增量定期大变更比如模板调整、术语体系换了做全量重建。版本管理的思路也值得提一下在元数据里记录每个 chunk 的文档版本号、生效时间Agent 在生成时能识别出“最新版资料”和“旧版资料”避免用过期信息回答问题。这块很多团队会漏掉但物料、报价、政策类场景里版本没控住等于白干。4.4 手脚冰凉排查速查表哪里出问题照着查我把自己踩过加看别人踩过的坑整理成了一张速查表遇到问题直接对着找环节能省半天时间。现象可能环节优先排查项检索结果明显不相关切块 / Embedding / Query打印检索片段人工查看确认是否相关相关片段召回了但还是答错生成 / Overload检查 Prompt 约束和 k 值、重排质量答案陈旧不更新索引 pipeline检查是否有增量更新任务冷门术语搜不到切块 / 词典切块粒度调小加入同义词改写回答质量不稳定模型 / 温度降低温度稳定输出格式检索速度慢向量库 / 索引检查是否建了正确的索引类型这张表要配合一个原则用一次只动一个变量。很多新手排查时同时改切块、改模型、改 k 值最后效果好了也不知道是哪个改动起了作用这样的调试毫无积累。我习惯把每一次实验的配置记录下来版本留痕这样迭代几轮之后你对“什么参数在自己的数据上最有效”会有非常清晰的感觉。5. 从能用迈向好用Agentic RAG 和几个进阶方向5.1 Hybrid Search向量检索 关键词检索双通道如果你做了上面的所有优化仍然发现一些精确词检索有问题那很可能需要 Hybrid Search。向量检索擅长语义相近的召回但面对产品型号、人名、特殊代码这类精确符号向量空间里的相似度可能反而不高。比如用户搜“BUG-1834”如果文档里写的是“缺陷编号 1834”向量检索能匹配上但如果写的是“异常单号 1834-2”语义上又有差异纯向量就不稳定了。Hybrid Search 的做法是同时跑两条线BM25 关键词检索走精确匹配向量检索走语义匹配然后把两边的结果合并、重排序。好处显而易见两条线的短板互为补充。我在产品检索的项目里加上这个之后型号类查询的命中率提升非常明显强烈建议所有搜“编号”“型号”“代码”的场景都上。5.2 Agentic RAG把“查不查、怎么查”交给 Agent 决策传统 RAG 是固定管道来一个问题走一遍检索生成答案结束了。但真实世界里很多问题不是一次检索能解决的。比如用户问“对比一下 A 和 B 两个模块的性能差异”一个合理的检索策略是先分别检索模块 A 的性能相关文档、模块 B 的性能相关文档再检索“性能对比”逻辑的通用知识最后综合回答。这个多路检索、多次决策的过程传统管道做起来非常僵硬Agentic RAG 就是为此设计的。Agentic RAG 的核心思路是把检索工具作为 Agent 可调用的工具之一Agent 根据当前问题自主决定是直接回答、检索一次还是检索多次甚至可以在检索结果出来后判断“信息不足”然后自动改写 query 再搜一轮。这种方式下知识获取管道不再是写死的 if-else而是变成了一个有决策能力的智能体。这也是 Agent 和 RAG 结合的终极形态我看到的不少生产级 Agent 框架比如 Spring AI、LangChain都已经支持这套模式开箱即用。5.3 GraphRAG 和 Ontology RAG用结构知识打通关系推理最后聊聊我在热词里看到频率很高的 GraphRAG 和 Ontology RAG。传统 RAG 把文本切成孤立的块检索时也只看单块内容无法回答“A 和 B 的关系是什么”这类跨文档推理问题。GraphRAG 的思路是先从文档中抽取实体和关系构建知识图谱检索时沿着图结构去扩展上下文把相关的多跳信息都带出来。这对需要关系推理的场景比如企业组织架构变更、产品模块依赖分析效果比纯向量检索好一大截。Ontology RAG 则是先把领域知识建模成本体也就是定义好“类、属性、关系”的规范框架再让检索和推理基于这个结构化的知识骨架进行。它适合知识体系相对稳定、对准确性和可解释性要求很高的领域比如医疗、金融、法律。这两个方向都不算轻量不适合刚上手就当第一版方案但了解它们存在能让你在设计知识管道时预留好扩展空间——很多需求一开始是“全文检索”跑着跑着就会变成“要查关系、要查层次”到时候再重构就费劲了。我在实际项目中的一个体会是RAG 这条路最容易走偏的地方不是技术选型而是对“知识管道”的理解。它不是一个检索组件是一整套从知识生产、加工、存储到消费的闭环体系。文档质量差、信息源头乱后面技术做得再花哨都白搭。所以我的建议是第一步先把基础管道跑通用最少的技术栈验证你的文档质量和信息架构第二步再逐步叠加 Query 改写、重排序、Agentic 决策这些进阶能力。每一轮改进都留好实验记录你会看到系统的效果像滚雪球一样越来越好。