
苦猿的大模型日记 · Day18 · Agentic RAG——让模型自己决定查不查、查什么、查几次-帮普通人把AI学进简历系列前言同一个问题普通 RAG 答不上来用户问你们家 X3 和 X5 这两款扫地机哪款更适合养猫的家庭你心里咯噔一下因为这个问题你公司的 RAG 系统答错过三次。普通 RAG 把它当一个 query 走完整条流水线embedding → Milvus 召回 top-3 → bge-reranker 精排 → 拼 prompt → DeepSeek 生成。出来的答案是——X3 续航 120 分钟X5 续航 180 分钟建议根据家庭面积选择。看起来像那么回事。但答错了。它根本没理解养猫这两个字背后藏着什么——防缠绕主刷能不能搞定猫毛、滤网清理频次、噪音会不会吓到猫、有没有避让宠物模式——这些信息散在 5 份不同的文档里一次召回根本捞不全。普通 RAG 是一锤子买卖——查一次、答一次、结束。但真实世界里的复杂问题从来不是一次查询能搞定的。过去两篇我把 RAG 从头跑通了又把召回准确率从 50% 拉到 90%。但有一个根本前提我从来没动过——整条流水线是写死的模型只是被动跑一遍。今天把这个前提拆掉。Agentic RAG 不是新模型是新模式。把检索从代码里硬编码的步骤变成模型可以自己调用的工具——区别不在于模型多强在于谁来做决策。PART 01普通 RAG 的天花板——它只会被动应答很多人召回准确率拉到 90%会觉得我的 RAG 已经无敌了。未必。召回再准也救不了三种问题。硬伤 1只会问一次用户问X3 适合养猫家庭吗——普通 RAG 把这当一个 query 走完一遍就结束。但用户的真实需求是三步先查 X3 规格参数 → 再查猫毛处理能力 → 再对比同价位其他型号值不值。普通 RAG 一步就交卷了剩下两步被压缩进了 LLM 的幻觉补全里。模型不敢说我需要再查一次——它的代码里没有这个出口。硬伤 2不知道自己不知道召回的文档里如果根本没提猫毛处理普通 RAG 还是会硬答——它会从一些边角信息里编出来一个看似合理的答案。它没有我不知道这个出口。GPT-4 也会犯这个错。Claude 也会。DeepSeek 也会。不是模型问题是架构问题——普通 RAG 默认必须给答案模型被逼着编。硬伤 3不会用工具用户问X3 现在多少钱——文档里只有 3 个月前的价格表。普通 RAG 会拿旧价格答而不是去调实时价格 API。它的代码里根本没有调外部 API这一环。一个反直觉判断这三大硬伤靠前面讲的那些召回调优都救不回来。召回再准也救不了该查两次的问题被压缩成一次。也救不了文档里压根没有这个信息。也救不了需要调外部工具。这就是 Agentic RAG 的入口——让模型从被动跑流水线变成主动决定我要不要查、查什么、查完够不够。PART 02核心范式——ReAct 决策环Agentic RAG 听起来很玄剥开外壳就是ReActReasoning Acting—— 2022 年 Google 那篇论文提出来的范式。今天所有 Agent 框架LangGraph、AutoGPT、CrewAI底层全是它。一个完整决策环四步Think思考模型先想这个问题我需要查吗查什么Act行动调用一个工具检索、计算器、外部 APIObserve观察看工具返回了什么Loop循环或结束够答了就答不够就再 Think 一次用一个真实例子走一遍还是那个X3 适合养猫家庭吗。Agent 的完整决策轨迹是这样的——Think 1需要查 X3 的规格和猫相关功能 Act 1调用 rag_search(queryX3 规格 防缠绕 滤网) Observe 1返回 3 个 chunk提到防缠绕但没提滤网清理频次 Think 2滤网清理频次没查到再查一次 Act 2调用 rag_search(queryX3 滤网清理 养宠物) Observe 2返回 1 个 chunk提到每周清理一次 Think 3信息够了可以答了 AnswerX3 配备防缠绕主刷适合养猫家庭滤网建议每周清理一次……这就是 Agentic RAG 跟普通 RAG 最本质的区别——普通 RAG 把这段决策轨迹预先写死在代码里Agentic RAG 让模型自己生成这段轨迹。一个反直觉点很多人以为 ReAct 是循环直到完美所以会无限优化下去。不是。ReAct 是循环直到模型自己判断够了。所以——模型推理能力才是 Agentic RAG 的真正瓶颈不是召回。这就是为什么 DeepSeek-V3、Claude 这种推理强的模型跑 Agentic RAG 效果更好。推理弱的模型可能查一次就草草收尾或者陷入查不够→再查→还是不够的死循环。PART 03实战第一刀——把检索包装成 Tool这一节是全文最重的代码段。用 DeepSeek 的 function callingOpenAI 兼容格式把前面搭好的检索函数包成一个 tool让模型自己决定要不要调。Step 1把检索包成可调用函数复用前面搭好的栈bge-m3 embedding → Milvus 召回 → bge-reranker 重排。把它包成一个干净的函数# tools.py —— 把检索包成 Agent 可调用的工具 from FlagEmbedding import BGEM3FlagModel, FlagReranker embed_model BGEM3FlagModel(BAAI/bge-m3, use_fp16True) reranker FlagReranker(BAAI/bge-reranker-v2-m3, use_fp16True) def rag_search(query: str, top_k: int 5) - str: 在产品知识库里检索相关信息。 Args: query: 检索查询建议具体而非笼统 top_k: 返回的文档数量默认 5 Returns: 匹配到的文档片段按相关性排序 # 标准配方dense 召回 top-50 → 重排 → top-k vec embed_model.encode([query])[0] candidates vectorstore.similarity_search_by_vector(vec, k50) pairs [[query, d.page_content] for d in candidates] scores reranker.compute_score(pairs, normalizeTrue) ranked sorted(zip(candidates, scores), keylambda x: -x[1])[:top_k] return \n\n.join([d.page_content for d, _ in ranked])Step 2给工具写 schemaDeepSeek 的 function calling 跟 OpenAI 一模一样。给工具写个 schema告诉模型这个工具叫什么、什么时候该用、参数长什么样tools [{ type: function, function: { name: rag_search, description: 在产品知识库里检索相关信息。当用户问及具体产品规格、政策、流程时调用。, parameters: { type: object, properties: { query: {type: string, description: 具体的检索查询}, top_k: {type: integer, description: 返回文档数默认 5} }, required: [query] } } }]一个关键工程坑description 写得清楚不清楚直接决定 Agent 会不会调用它。模型决策完全靠 description 来判断该不该用这个工具——写得太笼统检索信息模型会乱调啥问题都先去知识库翻一遍写得太具体只在用户提到 X3 时调用模型会漏调X5 来了就忘了用好的 description 应该回答三个问题这个工具做什么、什么时候该用、什么时候不该用。反直觉点工具数量别贪多。3 个写得清楚的工具 10 个写得模糊的工具。模型在多工具场景下选择准确率会断崖式下降——Anthropic 自己测过工具数从 5 加到 20调用准确率能掉 30 个百分点。别一上来就给 Agent 配 10 个工具。先把 1 个调好。PART 04跑通一个最小 Agentic RAG把 PART 03 的工具接到 DeepSeek 的对话主循环里跑通一个会自己决定查几次的 Agent。完整可运行代码# agent.py —— 最小 Agentic RAG 主循环 from openai import OpenAI import json client OpenAI( api_key你的 DeepSeek API Key, base_urlhttps://api.deepseek.com/v1 ) def agentic_rag(user_query: str, max_turns: int 5) - str: messages [ { role: system, content: ( 你是一个会主动检索知识库的助手。 遇到不确定的事实问题先调用 rag_search 查资料 查到足够信息再回答。如果查不到直接说不知道。 ) }, {role: user, content: user_query} ] for turn in range(max_turns): response client.chat.completions.create( modeldeepseek-chat, messagesmessages, toolstools, tool_choiceauto # 关键让模型自己决定调不调 ) msg response.choices[0].message messages.append(msg) # 模型决定不调工具 → 直接答结束循环 if not msg.tool_calls: return msg.content # 模型决定调工具 → 执行 → 把结果塞回 messages for call in msg.tool_calls: args json.loads(call.function.arguments) result rag_search(**args) messages.append({ role: tool, tool_call_id: call.id, content: result }) return 超过最大轮次强制结束同一个问题两个版本对比用户问我们 X3 扫地机适合养猫家庭吗滤网多久清一次普通 RAG——一次召回 → 答 → 大概率漏掉滤网清理那块因为 query 偏向适合养猫家庭滤网信息排到了 top-10 开外。Agentic RAG上面这个循环——模型自己拆成 2 次检索先查 X3 养猫相关再单独查滤网清理 → 各自召回 → 综合答 → 完整。三个工程坑坑 1延迟是普通 RAG 的 2-5 倍。每次决策都要一次 LLM 调用 可能的检索。别把它当默认方案——按 PART 06 的决策表用。坑 2max_turns必须设上限。不设的话模型可能陷入查不够→再查→还是不够→再查的死循环烧 token 烧到天荒地老。5 轮是经验值绝大多数问题 3 轮内能搞定。坑 3流式输出必须开。Agentic 一轮动辄几秒用户等得没耐心。开 streaming先吐我先查一下 X3 的规格...这种过渡话术体验会好很多。PART 05让 Agent 会反思——Self-RAGPART 04 那个循环能用但有个问题模型拿到检索结果后直接信了。它不会判断这些结果是不是真的回答了问题。如果召回跑偏了模型也跟着跑偏。Self-RAG2023 年 ICLR 那篇就是解这个的——核心思想是让模型输出反思 token[Retrieve][Relevant][No Relevant][Generate]每一步都先判断一下。不用真去训练模型靠 prompt 也能模拟个七八成。反思 prompt追加到 system message每次拿到检索结果后先在内心判断三点 1. 检索结果是否真的回答了用户问题 是 → 继续否 → 改写 query 重查 2. 是否有明显遗漏的关键信息 是 → 补查 3. 信息之间是否冲突 是 → 再查一次确认 不要直接告诉用户你在反思直接决定要不要再调用 rag_search。三种反思触发场景场景 1召回结果跑题。query 太宽返回的 chunk 跟问题无关。反思后改写更具体——比如把X3 适合养猫吗改成X3 防缠绕主刷 猫毛 测试。场景 2召回结果不完整。用户问 A 和 B只查到 A。反思后补查 B。场景 3召回结果冲突。两份文档说法不一致旧版手册说续航 120 分钟新版说 150 分钟。反思后再查一次确认。反直觉点反思不是免费的。每次反思 多一次 LLM 调用 可能的检索。复杂查询的延迟可能直接翻倍。生产环境通常只开召回结果跑题这一种反思——其他场景靠 prompt 让模型自己判断要不要补查就行不用显式反思。不要为了显得智能就把三种反思全开那是给自己挖坑。PART 06何时该上 Agentic RAG这一节最重要。Agentic RAG 不是普通 RAG 的升级版是另一种东西。用错场景反而更糟。决策表场景该用哪个理由用户问退货政策是什么普通 RAG单跳问题一次召回就够Agentic 是浪费用户问X3 比 X5 适合养猫吗Agentic RAG多跳问题需要拆解 多次检索用户问上周销量为啥跌了Agentic 多工具需要查销售库 查事件库 交叉分析用户问今天天气如何直接调 API不需要知识库外部 API 一次搞定客服 FAQ答案明确且单一普通 RAGAgentic 反而引入不确定性复杂业务咨询多约束条件Agentic RAG唯一能搞定的方案三个上线坑坑 1延迟爆炸。Agentic 一轮 1 次 LLM 可能的检索多轮就是数倍延迟。实时聊天场景必须给前端加思考中...动画 流式输出。坑 2token 成本翻 3-10 倍。每次决策、每次反思都要 LLM 调用。生产环境必须监控 token 用量否则账单会让你怀疑人生。一个朋友上了 Agentic RAG 之后月度 API 账单从 800 涨到 6500——他没监控。坑 3可解释性下降。Agentic 决策是黑盒用户问为啥你查了 3 次——你必须保留决策日志方便 debug 和审计。一个收尾判断Agentic RAG 的核心价值不在答得准而在能处理普通 RAG 处理不了的复杂问题。别为了时髦而升级。先问自己一句我的场景真的需要多轮检索吗如果不需要普通 RAG 前面讲的那套调优已经够打了。结尾普通 RAG 像查字典——你问一个词它翻一页。Agentic RAG 像请了个研究员——你问一个问题它会自己决定翻几本书、每本翻到哪一页、翻完够不够、不够再去借一本。RAG 的尽头不是更准的召回而是会自己决定查不查、查几次、查完够不够的 Agent。但 Agent 不是答案是一种新工程。它会让你答得更准也会让你的延迟翻倍、账单翻倍、debug 难度翻倍。值不值得看你的问题复杂到什么程度。下一篇 Day19——当一个 Agent 干不过来时怎么让多个 Agent 分工合作。Multi-Agent 不是堆人数是另一套协作范式。关注苦猿下篇见。互动时间你做过的最复杂的 RAG 场景模型一次查不出来的那种是什么样评论区聊聊我下篇可能就拆它。— END —苦猿 · 帮普通人把 AI 学进简历