跳到主要内容

给 RAG 装上循环:agent 与 LangGraph

这一章讲三件事: agent 到底是什么(答案朴素得让人失望);LangGraph 怎么用「图」 描述并控制这个循环;一次真实运行里,agent 的每一步「想法」长什么样。 这是全书从「管道」跨入「智能体」的枢纽章,也是 Part 3 的开篇。

1. agent 的祛魅:就是一个循环

作者说新手最容易被专家绕晕的就是 agent——大家用抽象话术谈它能干什么,却不说它是什么。 他的祛魅版本一句话:把你已经用熟的 LLM 调用,放进一个循环里,任务完成才退出。 「就这么简单,各位」1

别小看这个循环。单次调用只能一问一答;循环让 LLM 能把大任务拆成小步、 每步之后看结果、再决定下一步——这更接近人类解决复杂问题的方式: 观察、推理、调整,而不是一次性吐出答案2

循环里的 LLM 被叫作 agent 的「大脑」。这个比喻有一个真实世界没有的超能力: 大脑可以随时换——换个更聪明的 LLM,甚至配多个大脑互相校验3

2. LangGraph:把循环画成图

裸写循环很容易失控——早期的 agent 框架常见「失控 agent」:循环退不出来,或者盯着错误的任务打转4。 LangChain 2024 年推出的 LangGraph 把控制流(即程序每一步该走哪里的决策逻辑)显式化成一张图,三个构件5:

构件是什么类比
节点(node)一个处理步骤(调用一次 LLM、跑一个工具)流水线工位
边(edge)固定的下一步走向传送带
条件边(conditional edge)带判断的走向:按状态决定去哪个节点分拣机

为什么值得专门为它造一个框架?LangGraph 补了两件裸循环难做的事: 轻松定义循环(图里画个圈就是循环)和内建持久化——状态的存续与恢复, 这让「多个会话并行」和「关键节点人工介入」成为可能。持久化的完整形态,第 12 章的记忆系统会展开 (补充(不在书里,依据我们的 frontier 书架):LangGraph 的持久化基于 checkpoint 机制, 每个超步末尾批量提交,中断后可从 checkpoint 恢复重放。 依据: shelf=ai-frontier-reference/langgraph#03-persistence-hil.md 事实=LangGraph 通过 checkpoint 数据结构实现持久化、中断与恢复,与原书「内建记忆」的说法对应)。

图还顺手统一了历史:早期的 ReAct 范式(先推理该做什么→执行动作→观察结果→再推理, 循环直到目标达成)今天作为框架已经过时,但它的循环图骨架原样活在 LangGraph 里。 原书给出了 ReAct 的论文坐标:arXiv:2210.036296

3. 工具:给 LLM 的说明书

工具(tool)= agent 可以调用的能力。本章给 agent 配了两个7:

  • web_search:Tavily 搜索(第三方服务),最多返回 4 条结果;
  • retriever_tool:把第 05 章建好的 ensemble 检索器包装成工具,名字起得极长: retrieve_google_environmental_question_answers,描述是「Extensive information about Google environmental efforts from 2023」。

名字为什么要啰嗦?因为工具名和描述是写给 LLM 看的——agent 靠它们推理「现在该用哪个工具」。 写得越清楚,agent 选得越准8。原书还提醒:chat 系模型普遍为工具调用(即模型输出「请帮我调用某工具」的结构化请求)微调过, 非 chat 模型可能根本不会用工具,尤其是复杂工具9

同类工具的打包叫 toolkit(toolkit,3-5 个相关工具的组合,如 GitHub toolkit 含搜 issue、读文件、评论等)10

4. 状态:循环的记事本

AgentState 是 agent 在一次执行中的共享草稿板:用户的提问、工具的输出、LLM 的中间结果, 全在这里。所有节点共享同一个状态对象,且约定只追加、不覆盖——后面的节点能看到前面发生过的一切11

代码上是一个 TypedDict:

class AgentState(TypedDict):
messages: Annotated[Sequence[BaseMessage], add_messages]

add_messages 这个注解就是在告诉 LangGraph「往列表后面接,别覆盖」12。 注意边界:这个状态只活在本轮执行里。跨会话的长期记忆是另一个话题——第 12 章。

5. 主走查:一次完整的 agent 运行

输入: 用户问题「Google 的环保举措有哪些?」(语料库就是那份 Google 环境报告 PDF)。

图的拓扑(组装完成后)13:

┌──────────────────────────────────┐
▼ │
开始 → agent ──┬─(要用工具)→ retrieve ──(相关)→ generate → 结束
│ │
│ └─(不相关)→ improve ──┘
└─(不需要工具)→ 结束

图说:agent 是调度中枢;retrieve 是工具节点;improve 把问题改写后送回 agent 重来。

第一跳: agent 收到问题,输出一条「工具调用」消息——它选了 retrieve_google_environmental_question_answers,参数是 {"query": "Google's environmental initiatives"}。 原始输出里能看到 tool_calls 字段带着调用 id 和 JSON 参数,finish_reasontool_calls ——模型没有直接回答,而是说了「我要用哪个工具」。作者评价:选得对14

第二跳(条件边): 工具返回一批文档。走哪条路?由 score_documents 这个条件边决定15:

  1. 拿一个 Pydantic 模型 scoring(只有一个字段:binary_score,取值 yes/no);
  2. llm.with_structured_output(scoring) 让 LLM 的输出严格落在这个结构里;
  3. 提示词问的是:「这份检索文档与问题相关吗?给 yes 或 no」;
  4. yes → 去 generate(生成回答);no → 去 improve(改写问题)16

这一步就是第 03 章「守护 LLM」思想的变体: again 用第二个 LLM 判断「问题 vs 材料」的相关性, 只是裁决结果从「拒答/放行」变成了「生成/重来」。

不相关分支: improve 节点让 LLM 重新审视原问题——「推断背后的语义意图, 重新表述一个更好的问题」——然后把改写后的问题送回 agent,重新走一遍检索17这就是循环的意义: 一次检索不满意,agent 会自己换一种问法再试,而传统管道一次定生死。

终点: generate 节点用我们熟悉的提示词(「照材料答,答不出就说不知道」)生成最终回答,图走到结束。

观察手段: graph.stream() 把每个节点的输出流式打印出来——你能在终端里看着 agent 「想」:调了哪个工具、打了几分、走了哪条边。作者把这个打印称作 agent 思考过程的可视化18

6. 边界与局限

  • 本章的 agent 只有一个检索工具加一个搜索工具,真实系统的工具数量、嵌套深度都会放大失控风险;
  • score_documents 的「相关/不相关」是二值的,材料「部分相关」时它只能猜一头;
  • 改写问题再检索的循环没有次数上限——生产上要加最大重试数,否则一个永远检索不到的问题会让 agent 转到天荒地老(书里没加,这是留白);
  • 状态只活在一轮之内——轮即一次完整的提问与回答——「记得上周聊过什么」要靠第 12 章起的记忆系统。

7. 可带走的

  1. agent = LLM 调用 + 完成才退出的循环;一切玄学表述都可以还原成这个结构。
  2. 图 = 节点(步骤)+ 边(走向)+ 条件边(决策);把控制流画出来,失控 agent 就现形了。
  3. 工具名与描述是 prompt 的一部分——写给 LLM 的,认真写。
  4. 状态只追加不覆盖,这是多节点协作的记事本纪律。
  5. **「检索结果不相关就改写问题重来」**是循环带给 RAG 的最直接红利。
  6. 结构化输出(with_structured_output)+ 二值判断是给 LLM 当裁判的标准姿势。
  7. graph.stream 是调试 agent 的眼睛——让每一步决策可见。

8. 原文地图

主题原书章原文位置
agent=循环的祛魅定义Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:46(搜「just a loop, folks」)
循环带来的推理与拆解能力Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:59(搜「break tasks down」)
大脑比喻与可换脑Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:80(搜「brain」) · text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:83(搜「swap out their LLM brain」)
LangGraph 2024 推出、AgentExecutor 旧路Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:92(搜「AgentExecutor」)
两大新能力(循环+记忆)Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:99(搜「cyclical graphs」)
失控 agent 与控制流的必要性Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:122(搜「rogue agents」)
ReAct 范式与论文Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:115(搜「reason + act」) · text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:128(搜「2210.03629」)
持久化与 HITLCombining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:125(搜「Persistence」)
工具定义(Tavily+检索器工具)Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:176(搜「TavilySearch」) · text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:207(搜「retrieve_google_environmental_question_answers」)
工具名是给 LLM 的说明书Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:216(搜「more verbose names」)
chat 模型才会用工具Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:227(搜「fine-tuned for tool calling」)
toolkits 定义Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:236(搜「toolkits」)
AgentState 与 add_messagesCombining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:260(搜「AgentState」) · text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:263(搜「add_messages」)
状态只活在本轮Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:267(搜「current agent execution」)
score_documents 条件边Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:339(搜「score_documents」) · text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:359(搜「with_structured_output」)
yes/no 分流Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:435(搜「DOCS RELEVANT」)
improve 改写问题Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:489(搜「Formulate an improved question」)
图组装与编译Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:569(搜「add_node」) · text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:596(搜「set_entry_point」)
第一跳的工具调用输出Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:711(搜「finish_reason」)
stream 打印 agent 想法Combining RAG with the Power of AI Agents and LangGraphtext/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:678(搜「graph.stream」)

Footnotes

  1. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 46 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:46,搜「just a loop, folks」)。

  2. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 59 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:59,搜「break tasks down」)。

  3. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 83 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:83,搜「swap out their LLM brain」)。

  4. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 122 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:122,搜「rogue agents」)。

  5. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 56 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:56,搜「conditional edges」)。

  6. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 109 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:109,搜「going obsolete」)与第 128 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:128,搜「2210.03629」)。

  7. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 173-213 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:176,搜「TavilySearch」;text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:207,搜「retrieve_google_environmental_question_answers」)。

  8. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 216 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:216,搜「more verbose names」)。

  9. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 227 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:227,搜「fine-tuned for tool calling」)。

  10. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 236 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:236,搜「toolkits」)。

  11. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 248-251 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:248,搜「scratchpad」)。

  12. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 263 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:263,搜「add_messages」)。

  13. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 559-633 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:559,搜「StateGraph(AgentState)」;text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:606,搜「tools_condition」;text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:621,搜「add_conditional_edges」)。

  14. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 711 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:711,搜「finish_reason」)。

  15. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 339-348 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:339,搜「score_documents」;text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:348,搜「binary_score」)。

  16. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 434-440 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:435,搜「DOCS RELEVANT」)。

  17. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 481-494 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:489,搜「Formulate an improved question」)。

  18. 出处:「Combining RAG with the Power of AI Agents and LangGraph」第 678 段(text/75-fm-combining-rag-with-the-power-of-ai-agents-and-la.txt:678,搜「graph.stream」)。