LangGraph vs LangChain:该用哪个构建 Agent
LangChain 的痛点:为什么需要 LangGraph LangChain 最初设计目标是链式调用 LLM——prompt → model → output parser 串成一条链。这在简单的 Q&A 和 RAG 场景下足够用,但当你要构建真正的 Agent时,问题就来了: 痛点 具体表现 链是线性的 Agent 需要循环、条件分支、回退,Chain 只能直线走 状态管理粗糙 Memory 机制简陋,复杂状态需手动管理,多步推理容易丢上下文 没有检查点 长流程中途失败,无法从断点恢复,只能从头来 Human-in-the-loop 困难 链执行中无法暂停等待人类输入 AgentExecutor 黑盒 封装太重,调试困难,自定义控制流代价高 LangChain 的 AgentExecutor 本质上是一个 while 循环 + tool 调用,你无法精确控制每一步的行为。当你需要"如果工具返回 X 则走分支 A,否则走分支 B"这种逻辑时,AgentExecutor 就力不从心了。 LangGraph 的核心思路:把 Agent 当图来建模 LangGraph 的设计哲学很简单:Agent 的执行流程是一张有向图。 节点(Node):每个节点是一个函数,接收状态,返回更新后的状态 边(Edge):连接节点的有向边,可以是固定的或条件性的 状态(State):一个共享的 TypedDict 或 dataclass,在节点间流转 from langgraph.graph import StateGraph, END from typing import TypedDict, Annotated from langgraph.graph.message import add_messages class AgentState(TypedDict): messages: Annotated[list, add_messages] tool_results: list def call_model(state: AgentState): response = llm.invoke(state["messages"]) return {"messages": [response]} def should_use_tool(state: AgentState) -> str: last_msg = state["messages"][-1] if last_msg.tool_calls: return "tools" return END # 构建图 graph = StateGraph(AgentState) graph.add_node("agent", call_model) graph.add_node("tools", tool_node) graph.set_entry_point("agent") graph.add_conditional_edges("agent", should_use_tool) graph.add_edge("tools", "agent") # 工具执行完回到 agent app = graph.compile() 这段代码实现了一个标准的 ReAct Agent,但控制流完全透明。你能看到每一步在做什么,为什么走这个分支。 ...