LangGraph 实战:构建一个可控的 ReAct Agent

ReAct(Reasoning + Acting)是让 Agent 先思考再行动的范式。这篇文章用 LangGraph 实现一个完整的 ReAct Agent,并加入一些生产环境需要的工程细节。 ReAct 的执行流程 用户输入 ↓ 思考(Thought):分析问题,决定下一步 ↓ 行动(Action):选择并调用工具 ↓ 观察(Observation):获取工具结果 ↓ 循环,直到能给出最终答案 ↓ 最终答案 用 LangGraph 实现 from typing import TypedDict, Annotated from langchain_core.messages import BaseMessage, HumanMessage, AIMessage, ToolMessage from langchain_openai import ChatOpenAI from langgraph.graph import StateGraph, END import operator class AgentState(TypedDict): messages: Annotated[list[BaseMessage], operator.add] iteration: int # 防止无限循环 # 初始化 LLM(绑定工具) llm = ChatOpenAI(model="gpt-4o", temperature=0) llm_with_tools = llm.bind_tools(tools) def should_continue(state: AgentState) -> str: """决定下一步走哪条边""" last_message = state["messages"][-1] # 超出最大迭代次数,强制结束 if state["iteration"] >= 10: return "end" # 最后一条消息没有工具调用,说明已经有最终答案了 if not hasattr(last_message, "tool_calls") or not last_message.tool_calls: return "end" return "tools" def call_llm(state: AgentState) -> AgentState: """调用 LLM 节点""" response = llm_with_tools.invoke(state["messages"]) return { "messages": [response], "iteration": state["iteration"] + 1 } def call_tools(state: AgentState) -> AgentState: """执行工具调用节点""" last_message = state["messages"][-1] tool_messages = [] for tool_call in last_message.tool_calls: tool_name = tool_call["name"] tool_args = tool_call["args"] try: result = tool_registry[tool_name].invoke(tool_args) content = str(result) except Exception as e: content = f"工具调用失败:{str(e)}" # 错误不崩溃,反馈给模型 tool_messages.append(ToolMessage( content=content, tool_call_id=tool_call["id"] )) return {"messages": tool_messages} # 构建图 graph = StateGraph(AgentState) graph.add_node("llm", call_llm) graph.add_node("tools", call_tools) graph.set_entry_point("llm") graph.add_conditional_edges("llm", should_continue, {"tools": "tools", "end": END}) graph.add_edge("tools", "llm") # 工具执行完,回到 LLM 节点 agent = graph.compile() 加入 Human-in-the-loop LangGraph 支持在某些步骤暂停,等待人工确认: ...

2024-11-18 · 2 min · Kada Liao

Agent 框架横评:LangGraph vs AutoGen vs CrewAI

2024 年,Agent 框架的竞争进入白热化阶段。我在几个项目里分别用过 LangGraph、AutoGen 和 CrewAI,这篇文章做一个工程视角的横评。 三者定位 框架 核心定位 适合场景 LangGraph 有状态的图执行引擎 需要精确控制流程的复杂 Agent AutoGen Multi-Agent 对话框架 多个 Agent 协作解决问题 CrewAI 角色扮演式 Multi-Agent 任务分工明确的团队协作场景 LangGraph LangGraph 是 LangChain 团队推出的,把 Agent 的执行流程建模成一个有向图。 from langgraph.graph import StateGraph, END from typing import TypedDict class AgentState(TypedDict): messages: list next_step: str def agent_node(state: AgentState): # 调用 LLM 决策下一步 ... return {"next_step": "tool" if needs_tool else "end"} def tool_node(state: AgentState): # 执行工具 ... return {"messages": [...]} graph = StateGraph(AgentState) graph.add_node("agent", agent_node) graph.add_node("tool", tool_node) graph.add_edge("tool", "agent") graph.add_conditional_edges("agent", lambda s: s["next_step"]) 优点:流程完全可控,支持循环、分支、人工介入(human-in-the-loop),适合生产环境。 缺点:上手成本高,要理解图的概念;代码相对冗长。 AutoGen AutoGen 是微软出的,核心是让多个 Agent 通过对话协作: from autogen import AssistantAgent, UserProxyAgent assistant = AssistantAgent( name="助手", llm_config={"model": "gpt-4o"} ) user_proxy = UserProxyAgent( name="用户", human_input_mode="NEVER", # 全自动 code_execution_config={"work_dir": "workspace"} ) user_proxy.initiate_chat( assistant, message="帮我写一个爬虫,抓取 Hacker News 首页" ) 优点:能自动执行代码,适合需要写代码解决问题的场景。 ...

2024-09-10 · 1 min · Kada Liao