Thought for 4 seconds | Node | | | ------------------------------------------------ |:------------------------------------------------------- | | 内置虚拟node;分别代表图的入口和终止条件。| `START` `EMD` `graph_builder.add_edge(START, "chatbot")` | | | | | 预构建节点;自动并行执行 LLM 返回的 tool_calls 并生成 ToolMessage。| `tool_node = ToolNode(tools=my_tools)` | | 一整套 **“带工具路由 + ReAct 推理 + 记忆管理”** 的 [[子图、执行器]] | create_react_agent | | 给 LLM 声明可调用工具,配合 ToolNode 使用。| `llm_with_tools = llm.bind_tools(tools)` | ## 一句话先说清 - **`create_react_agent`** 生成的是一整套 **“带工具路由 + ReAct 推理 + 记忆管理”** 的 **子图**/执行器,基本开箱即用。 - **普通 Node**(你自己写的 `def some_node(state): …`)只是图里的 **单个步骤**,要自己决定“读状态、做事、写回状态、跳去哪里”。 --- ## 1 概念层级 |层级|`create_react_agent`|普通 Node| |---|---|---| |**颗粒度**|_子图 / Executor_:内部已包含一系列调用循环|_原子步骤_:一段同步或异步函数| |**职责**|- 解析提示- 让 LLM 想 (Reasoning)- 选工具 & 调用- 处理工具结果- 把动作写回 `AgentState`- 决定继续还是结束|你自己写什么就做什么;常见是:- 调一个 LLM / API / 业务逻辑- 更新 `State` 字段- 返回 `Command(goto=…, update=…)`| |**返回值**|直接产出 `AgentState`(内部自己循环),调用者通常只关心最终 `messages`|必须返回 `Command` 指明:① 下一跳 `goto` ② 要更新哪些状态| |**需要手写的东西**|基本只写 Prompt 模板 + 工具列表;复杂流程全交给框架|Node 函数体 + Prompt(如需要)+ 显式路由逻辑| |**适用场景**|快速拉起“LLM + 多工具”的对话式 Agent;关注业务而非框架细节|对流程有**精细控制**需求,或 Node 逻辑与 ReAct 不匹配(数据库事务、调用外部服务、规则判断等)| --- ## 2 在 Taurus 里的示例对比 ### 2.1 用 `create_react_agent` ```python # agents/agents.py research_agent = create_react_agent( get_llm_by_type("qunar_chat_model"), tools=[tavily_tool, crawl_tool], prompt=lambda state: apply_prompt_template("researcher", state), ) ``` - 你 **不用关心** 工具调用顺序、思考链、错误重试等; - 想用时直接 `research_agent.invoke(state)`,返回最后一步的 `AgentState`。 ### 2.2 手写 Node ```python # graph/nodes.py def planner_node(state: State) -> Command[Literal["supervisor", "__end__"]]: messages = apply_prompt_template("planner", state) stream = llm.stream(messages) # 你自己控制流式 full_response = "".join([c.content for c in stream]) goto = "supervisor" if is_json(full_response) else "__end__" return Command( update={"messages": [AIMessage(content=full_response)]}, goto=goto, ) ``` - 逻辑、异常处理、路由都要你亲自写; - 优势是**完全可控**,想怎样就怎样。 --- ## 3 如何一起用? 在 Taurus 里,你常见两种用法: 1. **把 `create_react_agent` 生成的 Agent 当成“黑盒工具”** 在某个 Node 里简单 `result = research_agent.invoke(state)`,再把结果塞回大的 `State`。 2. **纯手写 Node 组合成大图** 比如 `supervisor_node → planner_node → reporter_node`,每一步都显式 `Command(goto=…)`。 这样可以按需取舍: - **简单搜索 / 抓取** → 用 React‑Agent,省事; - **流程敏感或需要业务判断** → 手写 Node,细节自己把控。 --- ### 小结 - **`create_react_agent`**:像“自动挡”,更高抽象层,帮你把 **ReAct 循环 + 工具调用** 都包了。 - **普通 Node**:像“手动挡”,粒度小,**路由与状态更新全靠你自己**。 - 两者可以在一张图里混用,各做各擅长的事情。