
说实话我第一次看到production-agentic-rag-course这个项目标题时第一反应是又有人在炒概念了。但跟着把 RAG检索增强生成从 Demo 推到生产环境之后我才明白这个标题有多精准。传统 RAG 你搭个玩具很容易装个向量库、写两三行检索代码、丢给大模型就能跑通可一旦要面对真实业务数据、多轮交互、复杂查询和线上流量整套方案就开始卡住。所谓“生产级”不是把代码写得好看而是要在检索策略、Agent 编排、知识组织、可观测性和评估机制上全部重新设计。这篇内容是我在自己项目里落地production-agentic-rag-course时的完整总结核心围绕三个问题传统 RAG 的瓶颈到底在哪Agentic RAG 怎么解决这些瓶颈以及在实际工程里该怎么一步步搭出来。适合正在做知识库、智能客服、内部文档问答或者 Agent 应用的技术负责人、后端工程师和独立开发者尤其适合那些已经跑通原型、但在生产环境里反复吃瘪的人。1. 项目概览production-agentic-rag-course 到底在解决什么问题1.1 传统 RAG 在生产环境中的真实瓶颈传统 RAG 的流程看起来很简单把文档切成小块做向量化存进向量数据库用户提问时检索相似内容拼到 Prompt 里交给大模型生成回答。但我在实际生产项目里吃够了亏问题集中在几个地方。第一是切块带来的天然割裂。文档里的信息往往分散在不同段落比如“这个接口的鉴权方式”和“这个接口的限流规则”可能分别写在文档的不同章节。简单向量检索通常只会召回最像的那一段不会主动把多个相关段落拼起来。尤其当问题本身是复合的、需要多步推理时单次检索基本就是在赌命。第二是强依赖 Embedding 的相似度判断。向量相似不等于语义正确尤其很多专业名词、缩写、版本号向量模型根本不认识。比如用户问“新老版本的数据迁移需要注意什么”如果你的语料里写的是 V1 和 V2检索结果可能完全跑偏。生产环境没有那么多标准问答对脏数据、简称、历史描述都是常态。第三是知识更新和维护成本极高。传统 RAG 的知识都在向量库里SSD增删改一遍就要重新切块、重新向量化、重新刷索引。做一个小型知识库可能无所谓但到了几千份文档、每天更新几百条的规模全量重建既浪费钱又容易造成线上检索不一致。还有权限控制的问题。企业知识库经常要按部门、项目组隔离数据传统 RAG 往往是“一把梭”全部向量化检索时不带权限过滤很容易把不该说的内容检索出来。这些问题叠加在一起就会变成热搜里常提到的“RAG瓶颈”Demo 很惊艳上线就翻车。1.2 Agentic RAG 的定位从“检索一次”到“推理循环”Agentic RAG 的解决办法是把原来“检索一次、生成一次”的直线流程改造成一个由大模型驱动的推理循环。大模型不再只是生成器它还承担了任务规划、工具选择、结果判断的职责。我用一个类比来解释传统 RAG 是去图书馆管理员听到你的问题后直接塞给你一本书Agentic RAG 则像一个侦探先拆解你的问题知道自己缺哪块信息然后决定去哪个书架、问哪个专家、甚至交叉验证两个来源是否矛盾最后才给出结论。实际技术实现上Agentic RAG 通常使用类似 ReAct 的循环Agent 根据当前问题决定下一步动作执行动作可能是检索、查知识图谱、调用 API、读取结构化数据拿到结果后再判断是否需要继续检索直到信息足够才生成答案。这套机制特别适合三类场景多跳问题比如“某个客户最近一周的订单里退款率超过多少”、需要混合来源的问题既有文档又有数据库以及需要边回答边自我修正的问题。在生产环境里Agentic RAG 不是要取代普通 RAG而是把普通检索封装成 Agent 的“工具”。这样整个系统变得更灵活也更容易做权限控制、结果校验和过程审计。我个人的经验是普通 RAG 适合“明确知识点的快速问答”Agentic RAG 则面向“需要推理、归纳、对比、跨文档分析”的高难度场景。课程名称里的 production 就是在强调不能停留在概念验证必须考虑线上性能、成本和稳定性。1.3 课程/项目的设计边界这个项目在我的规划里不是一个“手把手写代码的教程”也不是“讲原理的科普”而是一条完整的生产落地路径。我把内容分成四层知识层文档、知识图谱、结构化数据怎么组织检索层向量检索、混合检索、重排怎么配合Agent 层任务规划、工具调用、多轮记忆怎么编排运维层评估、监控、版本管理、权限控制怎么做。它和普通 RAG 教程最大的区别是普通教程通常给你一套固定的检索流程你照着做就行这个课程强调的是“可组装”。不同的业务场景可以替换不同的检索策略、不同的 Agent 编排方案。比如内部 HR 问答系统可能用简单线性 RAG 加一个验收规则就够了而一个跨部门数据分析助手就必须上多轮规划。不要一上来就追复杂要先知道生产环境为什么需要复杂再判断自己需不需要。2. 技术选型向量知识库、知识图谱和结构化数据的搭配2.1 三种知识形态怎么选向量库 vs 知识图谱 vs 关系型表做 Agentic RAG 最核心的技术选型不是选哪个框架而是搞清楚你到底有哪几类知识、分别用什么结构存。我在项目中一直反对“把所有文档全塞进向量库”的偷懒方案因为不同数据天然适合不同的存储方式。这里用一个表直接对照维度向量知识库知识图谱KG关系型表/结构化存储存储结构高维向量 原文 chunk实体-关系-属性图行和列强 schema适合内容非结构化文档、自然语言语义多实体关系、层级体系、事实型网络订单、用户、配置、指标等强结构数据查询方式相似度检索语义召回图遍历、关系推理、SPARQL/CypherSQL 聚合、精确匹配优势实现简单对语义相近查询友好能准确表达多跳关系可解释性强精确、可靠、事务能力强劣势精度有限缺乏逻辑关系构建成本高需要本体设计和实体抽取不适合非结构化内容无法直接语义泛化典型应用制度文档、帮助手册、技术资料人员组织架构、故障依赖链、产品关系图谱订单查询、指标看板、业务规则生产级 Agentic RAG 通常会把三种混着用向量库负责宽泛但不够精确的语义召回知识图谱负责“谁跟谁有关系”的精确关系链关系型表负责可核验的精确事实。比如用户问“某员工在哪个项目组项目的负责人是谁最近项目进度如何”这个问题里“员工-项目-项目负责人”的关系必须从知识图谱拿“最近项目进度”这种自然语言描述可能要从文档里检索。只靠其中一个答案基本都会缺一条腿。2.2 图片/多模态数据怎么放进 RAG 知识库很多人问“RAG 知识库能存图片吗”答案当然能但关键不是“能不能存”而是“怎么让大模型用上图片信息”。我在项目里遇到过不少把截图、流程图、产品设计稿直接塞进知识库的情况如果你只是把图片文件路径存进元数据那它就是个摆设检索到也帮不上忙。实际工作里我会分三类处理。第一类是图片里有大量文字比如操作截图、报表截图先用 OCR 把文字抽出来转成文本或 Markdown 再进向量库这是成本最低的方式。第二类是需要理解视觉语义的图比如产品外观、场景图这类建议接入多模态 Embedding 模型让图片本身参与向量检索如果条件不允许可以先用视觉语言模型对图片生成文字描述再把描述向量化。第三类是图片作为最终答案的一部分比如用户要“导出这个报表的截图”这时知识库里存的是图片文件路径和关联元数据Agent 根据检索结果决定是否有权限返回图片。生产上我强烈建议先做 OCR 和图片转描述不要一开始就上多模态模型因为成本控制不住而且大多数业务图片其实文字比视觉更重要。2.3 Agentic RAG 框架选型框架选型也是很多人纠结的点。目前主流的无外乎三种路线LangChain/LangGraph 生态、LlamaIndex 生态、以及自研编排。我自己的项目用的是 LangGraph原因是它对状态管理和条件分支的表达非常清晰可以很方便地画出“检索→判断→再检索→生成”的状态图。LlamaIndex 对文档索引和各类数据源接入更友好适合偏知识库的场景。如果团队对代码掌控力强甚至可以只用 LLM 回调函数手写一个极简循环把工具函数挂进去几十行代码就能跑。但我必须提醒选框架的优先级不该排在最前面。你首先要确定 Agent 需要哪些工具再考虑每个工具的输入输出格式最后才是用哪个框架把它们串起来。我在项目里的实际经验是框架只是胶水真正决定系统上限的是工具质量和状态设计。如果检索工具本身召回率差Agent 再聪明也没用。另外一定要给 Agent 工具加上明确的描述大模型根据描述决定调用哪个工具描述写得含糊它就会乱来。3. 在 Mac 上从零搭建一套可生产的 Agentic RAG这一节回答很多人关心的“怎么在 Mac 上搭建 RAG 知识库”并把它扩展到 Agent 编排。Mac 作为开发环境完全没问题但生产环境部署时要把服务拆分出来不能把训练、索引、推理都压在笔记本上。我这里给出的是一套从本地跑通再到生产部署的参考路径。3.1 环境准备与依赖安装我自己在 Mac 上用的是 Homebrew 管理基础依赖加上 Conda/Poetry 管理 Python 环境。安装方式不唯一关键是版本别太新尤其是 LangGraph、LangChain 这类更新很快的库最好直接锁定版本。# 以 macOS 为例安装基础工具 brew install python3.11 brew install docker # 创建 Python 虚拟环境 python3.11 -m venv .venv source .venv/bin/activate # 安装核心依赖版本可根据自己项目锁定 pip install langgraph langchain-core qdrant-client pip install openai tiktoken beautifulsoup4 pypdf向量库我比较推荐 Qdrant因为它在 Mac 上用 Docker 跑非常简单同时支持 payload 过滤这对权限控制和元数据筛选很有用。如果只是为了本地快速实验也可以用 Chroma。这里给一个 Docker 启动向量库的方式docker run -p 6333:6333 -p 6334:6334 \ -v $(pwd)/qdrant_storage:/qdrant/storage \ qdrant/qdrant记得数据目录要挂载到本地否则容器一删数据全没。我在这上面吃过亏重建索引等了一个下午。3.2 数据准备、分块和向量化数据质量决定检索上限。我强烈建议数据进来之后先做一次清洗提取正文、去掉页眉页脚、统一编码然后按照文档结构切块。不要无脑按固定长度切最好用 Markdown 标题层级、PDF 章节、或者父子分块策略来切。父块保留更完整上下文子块负责精确检索检索到子块后把父块内容交给大模型。分块大小要根据你的查询粒度来定。短问答主题块可以控制在 300 到 500 token复杂方案文档可以用 800 到 1000 token。这里有个常用的成本估算公式假设一份文档全文 10 万 token按 400 token 分块大约产生 250 个块Embedding 费用基本等于 token 总数乘以单价向量化成本跟分块数量没有直接关系真正影响成本的是总 token 数。但分块数量会影响索引体积和检索延迟块越多向量数量越大ANN 检索压力也越大。from langchain.text_splitter import MarkdownHeaderTextSplitter splitter MarkdownHeaderTextSplitter( headers_to_split_on[(#, H1), (##, H2), (###, H3)] ) chunks splitter.split_text(document_text)Embedding 模型的选择上如果预算有限可以先用开源的 BGE-M3 或 bge-small-zh如果追求效果OpenAI 的 text-embedding-3-small 性价比不错。嵌入之后记得把原文 chunk、来源文件名、章节路径、更新时间作为 payload 存进向量库。这样 Agent 后续可以基于来源过滤、基于时间过滤也能在回答时给出引用。3.3 Agent 编排层实现Agent 层是最像“课程”的部分。我用 LangGraph 做了一个最小的状态机收到用户问题后先做问题分类如果问题需要跨文档对比就启动多路检索如果问题涉及实体关系就调用知识图谱查询最后统一汇总生成答案。下面是一个高度简化的代码思路from langgraph.graph import StateGraph, END class AgentState(TypedDict): question: str retrieved_docs: list kg_results: list answer: str def classify(state): # 调用 LLM 判断问题类型返回 plan return {plan: llm_plan(state[question])} def retrieve_docs(state): # 调用向量库检索工具 return {retrieved_docs: vector_search(state[question])} def query_kg(state): # 调用知识图谱查询工具 return {kg_results: kg_query(state[question])} def generate(state): # 汇总所有结果生成答案 return {answer: llm_generate(state)} graph StateGraph(AgentState) graph.add_node(classify, classify) graph.add_node(retrieve, retrieve_docs) graph.add_node(kg, query_kg) graph.add_node(generate, generate) graph.set_entry_point(classify) graph.add_edge(classify, retrieve) graph.add_edge(retrieve, kg) graph.add_edge(kg, generate) graph.add_edge(generate, END)注意这只是线性版本生产上我会在 classify 之后加一个条件分支如果 Agent 判断检索结果不足以回答就应该重复调用检索工具或者改写问题后再检索。这个过程要设置最大迭代次数通常我限制在 3 轮以内超过就直接进入生成阶段避免模型在循环里反复横跳。工具调用本身要加上超时和错误处理比如知识图谱超时了不能让 Agent 空等而要让它能 catch 异常并降级到向量检索。3.4 从本地服务到生产环境的关键改造在 Mac 上跑通不等于能上线这是 production 课程里含金量最高的部分。第一步是封装 API 服务把 Agent 循环包进后端通常用 FastAPI 提供/query接口请求进入后先做用户身份校验再根据权限注入可访问的数据范围。第二步是缓存对于相同或相似问题可以在向量检索层做语义缓存命中缓存就直接返回能省不少模型调用费。第三步是可观测性Agent 的每一步决策都要留痕至少记录问题原文、每一步的工具名、工具返回摘要、最终答案和置信度方便出问题后回溯。第四步是并发和限流LLM 调用和向量检索都是耗时操作必须做好异步处理和队列防止一个慢查询打满全部资源。我遇到过最典型的生产事故是Agent 在循环里不断调用同一个检索工具把线上 LLM 配额直接打满。后来我在工具层加了两道保护单次 Agent 运行的工具调用次数上限以及全局速率限制。这两个看起来不复杂的开关救了我很多次。4. 生产落地中的常见问题与排查技巧4.1 检索质量差的“三板斧”如果 Agent 回答不好先别怪大模型大概率是检索阶段出了问题。我会按顺序排查三件事。第一看召回内容的相关性是不是真的高。把向量库里的 Top5 结果打印出来肉眼扫一遍如果前三名都不像人话大概率是分块策略或者 Embedding 模型的问题。第二看召回内容是否完整。如果问题需要的答案分散在多个段落就试试父子分块和重排Rerank。重排模型会把向量检索召回的候选重新打分能把很多“相似但不相关”的结果压下去。第三看混合检索有没有做。光靠向量检索关键词命中的情况经常被忽略可以把全文检索BM25和向量检索的结果做融合最后再用重排模型统一排序。这套组合我称之为“可以抄作业的组合拳”向量召回取 Top50BM25 召回取 Top50混在一起去重后给 Rerank 模型最后取 Top5 给大模型。效果通常比单纯 Top5 向量检索高出很多。4.2 上下文爆炸和 Agent 死循环Agent 化之后最让人头疼的问题就是上下文爆炸。多轮检索、多步分析、中间结果全都堆进 Prompt模型窗口再大也会被打满。我在项目里会强制对每步工具返回做裁剪向量库只返回 chunk 的摘要而不是全文知识图谱只返回关键路径上的节点和边调用 API 也只保留必要字段。最终生成阶段拼接的上下文我会设一个 token 上限比如 4000超过的部分必须压缩或者放弃。死循环则更好理解Agent 觉得信息不够反复检索同一个来源生成一堆中间推理却还是拿不到答案。解决办法有三条设置最大迭代次数已经是标配更关键的是在每一步让 Agent 明确“我这一步要解决什么缺口”而不是让它泛泛地说“继续检索”还可以加一个“放弃动作”当模型判断当前问题超出知识范围直接回答不知道而不是硬编答案。生产和 Demo 的区别就在这里Demo 可以允许来回试生产必须在成本和体验之间找平衡。4.3 知识冲突与幻觉控制业务知识库里经常出现新旧文档并存的情况比如薪酬制度更新了但还有一些旧文档没下架。传统 RAG 很可能把新政策当旧政策回答Agentic RAG 会给这个问题多一层防线检索阶段按更新时间过滤把超过有效期的文档直接排除生成阶段要求模型优先引用时间戳最新的资料并在发现来源矛盾时主动说明“存在不同口径”。在 Prompt 里我会明确写一条规则如果你发现多个来源的答案有冲突不要强行选择一个先告诉用户存在冲突再分别列出各自来源。这个行为可以让幻觉率明显下降。另一个实用的技巧是引用溯源。最终答案的每一句关键信息后面都要标注来自哪个 chunk 或哪条知识图谱路径。注意这不是简单把来源 URL 贴出来而是要做成可追踪的引用标识比如[来源1]、[来源2]并且在后端记录来源 ID。一旦线上答案出了问题你可以顺着引用直接定位到是哪份文档、哪个区块导致了大模型生成幻觉。4.4 搭建一套可落地的评估体系评估是生产级课程里最容易被忽略的板块。没有评估体系你根本不知道改动是变好还是变坏。我会先准备一份 100 到 200 条的测试集覆盖三类问题单点事实查询答案必须来自某一文档、多跳关系查询需要连接多个知识片段、以及对抗性问题知识库里没有答案期望模型拒绝回答。然后从三个维度打分评估维度衡量内容用什么方法上下文命中率参考答案是否存在于检索到的上下文里人肉标注或用检索结果自动判断忠实度生成答案是否严格基于检索上下文LLM-as-judge 打分 人工抽验答案相关性生成答案是否回答了原始问题LLM-as-judge 打分 人工抽验用大模型当裁判已经是很常见的做法但要注意别让裁判模型产生偏见比如对超长答案给高分。建议每次评估时固定一个裁判模型版本并抽 20% 结果让人工复核。我在项目里遇到过一个很有意思的情况某个 Prompt 改进让忠实度涨了但答案相关性反而掉了因为模型开始变得保守很多问题都只回“不确定”。这种 trade-off 必须靠评估体系发现否则上线后用户会抱怨答非所问。5. 个人经验总结与扩展建议5.1 再次强调不要跳过基线系统我见过太多团队一上来就想把全套 Agent 编排做出来结果连一个最简单的文档问答基线都跑不通。我自己的习惯是先做一个不需要 Agent 的普通 RAG调好分块和检索把准确率做到一个可接受的基线再在这个基础上逐步引入 Agent每次只增加一项能力比如先加问题改写再加知识图谱工具最后再做多轮循环。每次改动都要用同一套评估集跑分分数不涨就不上线。还有一个很容易被忽略的点权限。生产级系统无论如何要在检索入口做数据权限过滤。向量库每个点point可以挂上部门、可见范围等元数据用户请求进来时把权限条件作为 filter 传进检索从源头把不可见数据隔离掉。这块不做你的 Agent 再智能都会变成安全风险。我甚至建议把权限过滤规则写成一个独立模块任何 Agent 工具都必须申请这个模块的访问能力不允许其他代码直接绕过。5.2 这个课程后续还能怎么扩展这个项目我还计划往几个方向扩展。一是对话记忆目前 Agent 对每一轮问答都接近独立处理但生产用户经常有“接着上一句问”的需求需要把历史会话摘要注入 Agent 状态。二是增量更新现在文档频繁变更时还是走重建索引的路子下一步要按文件级做增量装载和过期标记降低维护成本。三是评测集自动化维护测试集不可能永远不变要把线上用户的坏案例定期回流到测试集里让评估体系跟着业务一起长。最后再说一句我在实际跑这个项目时最大的体会Agentic RAG 真正难的不是让模型“会调工具”而是让整个系统在真实数据、真实用户请求、真实运营压力下还能保持稳定。Demo 里那一套花哨的推理循环到了生产环境里全都要变成可监控、可降级、可解释的工程能力。如果你也正在从普通 RAG 往 Agentic RAG 迁移建议先把本文提到的检索质量、迭代控制、评估体系和权限隔离这四件事做到位再考虑更花哨的功能。过程会很磨人但这条路走完你的系统才算真正“生产级”。