ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

从传统RAG到Agentic RAG:生产级智能检索架构设计与实践

从传统RAG到Agentic RAG:生产级智能检索架构设计与实践 如果你最近在搭RAG大概率已经发现了一个尴尬的事实demo 里看着还挺聪明的问答机器人一旦塞进生产环境就开始“一本正经地胡说八道”。检索不准确、上下文一长就丢重点、用户问个多跳问题直接崩溃。这些问题的根源往往不是模型不够强而是你把 RAG 设计成了一条“单行道”先检索、再拼接、最后生成。而 production 级别的 agentic RAG恰恰是把这个过程拆开交给一个能自己决定“该不该检索、检索什么、检索不到怎么办”的程序。这篇文章我会从一个老工程师的角度聊聊传统 RAG 的卡点、agentic RAG 的架构逻辑以及从 demo 走到生产环境必须解决的工程问题可观测性、评估、成本和延迟。无论你是后台开发、AI 应用工程师还是正在选型的架构师这里的内容都可以直接拿来当决策参考。1. 先搞清楚问题的根源传统 RAG 的瓶颈1.1 “demo 能跑、上线就崩”的三个典型现场传统 RAG 的经典链路大家都熟用户问题进来embedding 之后去向量库做 top-k 召回然后把召回段落拼进上下文交给 LLM 生成答案。这个流程在 demo 阶段特别容易“看起来不错”因为 demo 里通常只有一份干净的测试文档问题也是预先想好的。一旦上了生产立刻会出现三种让人头大的现场。第一个现场是固定 top-k 截断。用户问“哪个部门负责员工报销政策”你的文档库里有十个段落都跟报销相关但最关键的一条在第六个段里。retriever 老老实实返回 top-5答案段落根本没进去LLM 就只能基于前面几个相关性稍弱的段落开始“合理推测”。你调大 top-k 到 20又发现上下文窗口一下子被几十个不相关段落塞满模型反而被噪声干扰回答质量更差。这个矛盾就是固定检索路径的先天局限。第二个现场是检索为空时模型强行编造。生产环境的用户 query 往往充满专有名词、缩写、内部黑话。向量检索经常返回一堆相似度极低的候选段低于阈值但你又不敢直接截断因为怕漏掉真答案。于是你硬着头皮把低相关度的段落拼进 promptLLM 基于残缺证据开始编造幻觉率直线上升。很多团队把这个问题归结为“模型不行”其实是检索阶段没有做好质量门控。第三个现场是多跳问题完全无解。用户问“A 区域的服务器配置是否满足 B 区域数据库迁移的最低要求”这个问题需要先检索出 A 区域服务器清单再去 B 区域迁移文档里找到最低配置要求最后做对比判断。传统 RAG 只有一次检索机会拿到的信息往往是半成品。你不可能在一条 prompt 里同时解决“找 A”“找 B”“做对比”三个子任务。更致命的是这次检索如果没找对后面没有任何机制可以纠正。1.2 为什么“再优化参数”救不了传统 RAG很多人遇到上述问题后的第一反应是去调参数chunk_size 从 256 调到 512embedding 模型换更大的top_k 从 5 调到 10甚至加一层 reranker。这些优化确实能改善单跳检索的质量但无法从根本上解决问题。原因在于chunk_size、top_k、embedding 模型这些参数调整都建立在同一个前提上预先设定一条固定的检索路径。可用户的复杂 query 是不可预测的路径天然是动态的。你不可能靠提前调参来应对所有可能性。更深层的问题在于链路没有反馈回路。传统 RAG 的检索结果一旦生成就立刻进入生成阶段中间没有任何“这个结果够不够用、要不要再查一次”的判断环节。检索错了生成阶段没有任何机制去纠正。这就像你点餐时照着固定菜单走服务员完全不考虑你的忌口、预算和口味变化agentic RAG 则是让一个懂餐饮的经理面对你的需求先判断你适合哪家店再决定点什么菜如果店关了还能换一家。这里的“判断、决定、换一家”就是 agent 循环的核心价值。你与其花三个月调参不如把决策机制引入架构让系统自己能动态调整检索策略。2. Agentic RAG 的架构设计与核心组件2.1 核心循环从“单次检索”到“计划-行动-观察”Agentic RAG 本质上是把 RAG 从“两步流水线”改造成一个“反馈循环”Reason计划如何回答这个问题Act执行工具调用比如检索、查库、计算Observe观察结果是否足以回答然后重复或者结束。这个循环的经典实现是 ReAct 模式。我见过很多人一说 agent 就往复杂了想其实核心就是一个带终止条件的 while 循环。用伪代码描述一下def agentic_rag(query): state new_agent_state(query) for i in range(max_iterations): decision llm(state.messages, tools) if decision.tool_name final_answer: return decision.output tool_result call_tool(decision.tool_name, decision.arguments) state.messages.append(tool_result) return safe_fallback(state)这个循环看起来简单但里面有两个生产上必须注意的细节。第一个是终止条件必须显式存在。agent 每一步都可以选择调用工具也可以选择直接输出 final_answer。如果 prompt 里没有把这个出口写清楚模型会倾向于“多查一下更保险”导致循环次数无限膨胀。第二个是 max_iterations 一定要设硬上限。我见过不止一次线上事故某个 agent 因为工具返回格式变化卡在同一个工具调用上转圈最后把当月的 LLM 配额烧掉大半。生产环境里循环次数一般设 3 到 5 次超过直接走兜底逻辑。2.2 关键组件拆解Router、Retriever、Tool、Memory理解了循环再看组件就清晰了。一个生产级的 agentic RAG 至少要有四个核心组件。Router 负责决定下一步走哪条检索路径。它不仅仅是“向量库 or 关键词”的二选一在复杂业务里还可以路由到 SQL 数据库、知识图谱、内部 API 网关甚至另一个专用 RAG 系统。Router 的选择直接影响后续所有步骤所以它通常由一个小模型或者分类器来承担成本低、延迟低不要拿大模型来做这种高频决策。Retriever 可以注册多个实例。比如 dense 向量检索负责语义相似sparse 关键词检索负责精确匹配混合检索则把两者结果融合。每个 Retriever 的 top_k 可以作为工具参数动态指定而不是写死。这种灵活性是传统 RAG 给不了的。Tool 是 agent 对外部能力的封装。对 RAG 来说最核心的 tool 是“search_documents”但生产中往往还需要其他 tool比如“lookup_staff_directory”“query_asset_database”。每个工具都要有完整的 function schema包括参数说明、返回结构、示例用法。我后面会专门讲工具描述写不好会带来什么坑。Memory 负责跨步骤保存中间信息。agent 完成多跳任务时必须记住“上一跳找到了 A 区域服务器配置下一跳需要去查 B 区域迁移要求”。Memory 可以用会话上下文实现但更稳妥的做法是维护一个显式的状态对象把每一步的检索结果、工具返回、临时变量都记在里面。这样即使某一跳失败也能从状态中定位问题而不是黑盒一样地重来。下面这张表可以很直观地对比传统 RAG 和 Agentic RAG 的差异维度传统 RAGAgentic RAG回答路径固定一条检索→生成动态多条agent 决策检索次数通常 1 次1 到 N 次按需决定上下文处理所有内容硬拼进 prompt选择性进入上下文并保留中间结果错误恢复无可重试、可换工具、可优雅退出可解释性只能看到检索了什么能看到每一步决策及原因依赖日志设计2.3 为什么说“Agent 不是包一层 LLM API”很多团队以为在 prompt 里写一句“你可以检索知识库”就是 agentic RAG 了。这其实只用了 LLM 的指令跟随能力并没有真正的决策能力。一个真正的 agent 需要的基础设施比这多得多。首先是工具定义。LlamaIndex 或者 OpenAI function calling 里工具需要以结构化 schema 声明参数和返回格式LLM 才能正确选工具。如果你的工具描述只有一句“search(kwargs)”模型完全不知道什么时候该调用、参数该填什么。其次是状态管理。跨步骤的变量、中间结果、已访问工具集合都要被显式管理。我在生产里见过太多 caseagent 第一跳检索到了关键信息第二跳因为状态没有传递又把同样的检索做了一遍。这不是模型蠢是状态设计缺失。第三是错误处理。工具调用失败、返回空、超时这些异常在 demo 里不会发生生产里天天发生。agent 需要能够感知错误并调整计划比如换一个工具、改写 query、或者放弃回答。没有这一层整个 agent 就是空中楼阁。第四是成本控制。agent 每多一次调用就多一次 token 消耗如果架构不限制调用次数和并发账单会让你怀疑人生。打个比方LLM API 只是一个“聪明的大脑”但你要给它手、眼睛和一套流程它才能真正干活。只包一层 API 是没有意义的。3. 生产级部署必须跨过三道坎可观测性、评估、成本3.1 可观测性没有 trace没办法排查 agent“发疯”传统 RAG 的日志很简单query 进来retrieved docs 出去answer 返回结束。Agentic RAG 的日志复杂了一个数量级。每一步的 decision、thought、tool call、result、token usage、耗时都需要被记录下来。如果你还在用 print 或者传统的应用日志来做这件事我劝你尽早换掉。我建议直接接入 OpenTelemetry 语义约定或者用 LangSmith、Langfuse 这类专门的 LLM 可观测平台。可以不用付费版但至少要有一个集中式的 trace 采集和展示系统。每次 agent 执行时至少记录以下几类信息输入 query、每一步的决策内容和原因、工具名、工具参数、工具结果摘要、每一步的 LLM 调用 token 数和耗时、最终答案或错误信息。下面是一个简化的 trace 事件结构你可以按这个思路设计自己的日志 schema{ trace_id: abc123, query: A区域服务器是否满足B区域数据库迁移要求?, steps: [ { step: 1, thought: 需要先获取A区域服务器配置, tool: search_documents, args: {query: A区域服务器配置, top_k: 5}, result: 文档ID 1042, 1055, tokens: 1200, latency_ms: 850 }, { step: 2, thought: 需要获取B区域数据库迁移要求, tool: search_documents, args: {query: B区域数据库迁移, top_k: 5}, result: 文档ID 2033, tokens: 1300, latency_ms: 900 } ], final_answer: A区域服务器配置满足B区域数据库迁移要求 }没有这套 trace当 agent 选错工具时你只能靠猜。有了它你可以回放每一次决策看到模型是怎么一步步走到错误结论的。这在线上故障复盘时特别重要能直接定位是 router 判断错了、工具返回不完整、还是 prompt 引导不到位。3.2 评估体系建设用数据而不是感觉判断 agent 好坏传统 RAG 评估常看召回精度、答案忠实度、答案相关性。这些指标对 agentic RAG 来说远远不够你还要评估“决策质量”。我在实际项目中主要看四个指标简单且易落地。第一个是 Tool Selection Accuracyagent 在每一步是否选对了工具。计算方式正确工具选择次数除以总工具调用次数。这个指标能快速暴露 router 的问题。第二个是 Plan Success Rate整轮任务是否最终成功完成。这里不是只看 final_answer 是否出现还要看答案内容是否正确、过程有没有超步数、有没有死循环。计算方式成功完成任务数除以总任务数。第三个是 Error Recovery Rate当第一次工具调用失败时agent 能否通过换工具、改 query、重试等方式继续完成任务。计算方式恢复的任务数除以遭遇错误的任务数。这个指标很容易被忽略但它恰恰是 agentic RAG 相比传统 RAG 的一大优势所在。第四个是 Cost per Completed Task完成任务的平均 token 消耗和金钱成本。agent 循环会让成本放大 5 到 10 倍这个指标必须持续监控。你可以设置告警线比如单任务平均成本超过某个阈值就触发检查。关于评估集的构建我的建议是不要找几个人拍脑袋写测试用例而是从生产日志里挖真实用户 query。至少覆盖四类 case单跳直答、多跳推理、模糊查询、带幻觉陷阱的查询。所谓幻觉陷阱就是检索结果与答案无关时看 agent 会不会编造。每个 case 要标注好“人类期望的答案”和“期望的工具调用路径”。初期人工核对 20 到 30 个 case稳定后再用 LLM-as-judge 批量跑。3.3 控制成本和延迟agent 循环是会烧钱的一个普通 RAG 调用一般有 2 次 LLM 请求一次 embedding、一次生成。Agentic RAG 可能变成 5 到 15 次 LLM 请求再加上 embedding 和 reranker成本是肉眼可见地往上涨。我实测过几个方案下面这几个办法最有效。第一设置 max_iterations常见值 3 到 5。超过这个数不再让 LLM 继续决策直接走 fallback 回答“无法处理”或“需要升级到人工”。第二早停策略。当观察到的信息已经足够回答问题时要求 agent 必须终止不允许“再看看”。这个可以在 prompt 里写死如果你认为已有信息足以回答必须立刻输出 final_answer。第三并发限制。生产环境一定要对 agent 执行设置最大并发数和超时时间避免突发流量瞬间打爆 LLM 配额。第四缓存策略。检索结果缓存很实用同样的 query 在文档版本没变的情况下直接返回上次检索结果省去重复的向量计算和 LLM 调用。LLM 响应缓存也可以做尤其对无状态子任务比如意图分类结果可以缓存。第五模型分层。Router、工具泛化选择这类高频决策交给小模型来做主生成用大模型。小模型负责决策大模型负责表达成本能降不少效果并不会差。4. 关键实操搭建一个生产可用的 agentic RAG 流水线4.1 工具选型LlamaIndex、LangGraph 还是自研很多团队一上来就纠结框架选型我建议先看场景再选工具。下面这张表是我自己的经验总结方案成熟度控制力上手成本适合场景LlamaIndex中高中低快速上线以 RAG 为主的场景LangGraph中高中高需要复杂状态流、多分支控制的场景自研框架低极高高已有基础设施深度定制团队能力强如果团队刚接触 agent我建议先别自研。用 LangGraph 维护一个状态图把“检索、查库、查 API、生成”这些步骤做成节点每步之间是显式的状态迁移出了问题很好定位。等踩完坑再考虑自己撸一个轻量级的调度器。LlamaIndex 的上手门槛更低但它抽象程度更高出问题时要花不少时间去理解框架内部行为。LangGraph 则更接近编程思维适合工程师团队。4.2 一个可落地的 workflow 示例我用一个实际场景来演示整个流程企业内部“IT 资产与系统运维”知识助手。用户通常问三类问题。第一类单跳问题“我的电脑如何连接打印机”去向量库找文档就行。第二类多跳问题“A 区域服务器是否满足 B 区域数据库迁移要求”需要跨文档对比。第三类结构化查询“上周申请的补充报销到账了吗”需要查 SQL 数据库。针对这三类问题流水线可以这样设计第一步意图分类。用小模型或分类器识别 query 属于 doc_query、structured_query 还是 comparison_query。这个决策只花少量 token速度也快。第二步路由。如果是 doc_query走向量检索如果是 structured_query走 SQL 查表或 API 调用如果是 comparison_query先检索 A 区域再检索 B 区域最后做对比问答。第三步检索执行。采用混合检索向量检索加 BM25 关键词检索然后用 reranker 融合排序。候选集先取 50 条重排后只保留 top_k5。第四步窗口扩展。如果命中的文档被 chunk 切分切断了完整语义可以在命中 chunk 的前后各扩展 1 到 2 个 chunk避免“答案被切断”的经典问题。第五步生成。把检索到的内容作为证据块注入 prompt明确要求 LLM 只基于证据回答并引用文档 ID。第六步自检。用一个便宜的小模型判断答案是否忠于证据如果不忠于重新进入检索循环但最多只允许 2 次。下面是一段简化后的逻辑示意你可以按这个思路去实现自己的版本def run(query): category classify(query) if category comparison_query: plan [retrieve_a, retrieve_b, compare_and_answer] else: plan [retrieve_and_answer] state {query: query} for step in plan: if step.startswith(retrieve): state[evidence] retrieve(query_for_step(step, category)) if step compare_and_answer: state[answer] generate_with_evidence(state[evidence]) state[faithfulness] self_check(state[query], state[evidence], state[answer]) if not state[faithfulness]: state[evidence] retrieve(补充: query) state[answer] generate_with_evidence(state[evidence]) return state[answer]参数选择上我建议生成温度设为 0.1降低臆造概率。每个工具调用设置 15 秒超时。top_k 不要固定成一个值单跳问题 top_k5多跳中每一跳也是 5但累积证据可能会超过上下文窗口超长时要对证据做截断或重排序。这一步的取舍说白了就是答案质量与上下文的平衡。4.3 知识库选型向量库、知识图谱、结构化数据库别混为一谈最近很多人问“RAG 知识库和结构知识库怎么选”甚至有人把三者混为一谈。这里我给出一个比较实用的区分思路。向量库适合非结构化文档比如 FAQ、手册、政策文件、聊天记录。它部署简单语义搜索效果好但无法进行精确条件查询也处理不了实体多跳关系。知识图谱适合强关系型数据比如“A 部门负责人向 B 部门提交申请B 部门负责人批准”这种流程链实体、关系、属性非常清晰。知识图谱的优势在于多跳关系推理但成本也高构建和维护图谱本体需要持续投入生产前一定要评估收益率。如果你的业务没有复杂的实体关系网不要为了赶时髦去建知识图谱。结构化数据库适合有明确字段和聚合查询的数据比如报销单、设备清单、订单状态。用户问“最近 7 天内有多少台设备运行异常”用 SQL 是唯一的正确答案。这时候不要硬套 RAG直接让 agent 用 text-to-sql 去查库。我见过不少团队把报销单 OCR 后塞进向量库结果用户一问“我上月报销总额多少”模型就开始胡编数字典型的选型错误。再说图片和其他非文本数据。RAG 索引的主要是文本。图片通常以图片路径、OCR 文本或描述文本作为 metadata 存进向量库。实际推理时如果确实需要看图片得把图片交给多模态模型不能直接塞进上下文。这一点很多人踩坑以为 RAG 能存图片结果把图片编码成向量后模型根本没法“看到”图片内容。下面这张选型表是我个人的推荐标准数据类型推荐方案何时用非结构化文档向量库政策、手册、FAQ强关系实体知识图谱组织结构、审批链、权限关系明细/聚合数据SQL 数据库订单、设备、报销图片文本多模态模型向量索引图片识别、图文混合问答5. 常见问题与排查技巧实录5.1 问题速查表下面这六个问题是我在多个项目里反复遇到的整理成速查表方便你直接对照排查。现象可能原因排查思路agent 反复调用同一个工具工具返回的内容不满足 agent 判断prompt 未要求基于迭代终止查看 trace 中每轮 thought检查工具返回是否真的包含答案在 prompt 中强制“若无新信息输出 final_answer”检索结果为空时 agent 仍编造缺少空结果处理逻辑在路由前先判断检索结果是否为空为空时要求 agent 明确说“未知”或触发兜底路径让用户补充关键词agent 循环不终止缺少 max_iterations终止条件不明确设置硬性 iteration 上限每个决策 slot 增加 must_terminate 标志位超限时返回“无法处理”多跳问题中途中断第二跳没有将上一跳关键信息作为输入状态管理不完整在 state 中显式保存中间结果并传给下一跳上下文超长证据块累积过多对每一跳检索结果做重排序和截断只保留每跳 top_k3 内容增加 token 预算监测成本飙高每轮都让主模型做所有决策把小模型用于 router缓存重复 query减少重试次数5.2 避坑经验分享独门技巧最后分享几个我自己踩坑总结出来的小技巧。第一个技巧是给 agent 加“不知道”出口。很多人只设计“检索到答案”和“检索不到”两个分支但生产环境必然会遇到“检索到一堆看似相关但实际不相关”的情况。明确告诉 agent在检索结果与问题只有表面相关时允许直接回答“当前知识库无法确认该信息”。不要强迫模型硬答。第二个技巧是自检不要用主模型。我自己试过用同一个大模型既做生成又做自检结果常常出现“完美闭环”它自己生成的内容自己怎么检查都觉得没问题。用一个便宜的小模型或者独立的 prompt 模板做 faithfulness check效果更好成本更低。你只需要让小模型看“证据里有哪些事实、答案里有哪些事实”再比对覆盖程度就够了。第三个技巧是日志里一定要记录每一步的 token 消耗和耗时。别小看这一点agentic RAG 很多问题不是“答案错”而是“成本失控”。不统计每个工具的调用频率你永远不会知道你的 agent 每天把 90% 的 token 烧在重复检索同一个文档上。快捷办法是给每个 trace 加上一个 cost 字段按模型单价自动折算金额。第四个技巧是工具描述要写细。不要只写“search query”这种模糊描述LLM 根本不知道什么时候该用这个工具。要写清参数含义、返回结构、示例 query。比如可以这样写search_documents(query: str, top_k: int)“该工具接收一段自然语言问题返回相关文档片段列表每项包含 document_id 和 text”。一个措辞模糊的工具描述往往就是 agent 选错工具的元凶。你花十分钟把每个工具描述写清楚能节省后面无数个排查黑夜。说句实在话agentic RAG 不是银弹。传统 RAG 在单跳、封闭域问题上依然又稳又便宜你不需要给所有问题都套上 agent。但一旦业务需要多跳推理、动态选择数据源、或者面对大量不清楚的复杂 query把决策权交给 agent 是值得的。我踩过最大的坑是刚开始把所有逻辑都塞进一个大 prompt 里结果 agent 每走一步都在重复思考既费钱又慢。后来把 router、retriever 拆成独立工具只让 agent 决定调用顺序稳定性一下子提升了不少。如果只让我留一条建议那就是先把你最想解决的一个业务场景的 50 条真实 query 攒下来跑一百遍看失败模式再谈架构升级。agentic RAG 的“生产”不是靠理想架构堆出来的是靠一轮轮分析失败案例打磨出来的。
返回列表