LangGraph 在 GitHub 上:核心概念与上手指南 – wiki基地


深入解析 LangGraph 在 GitHub 上:核心概念与上手指南

随着大型语言模型(LLMs)能力的飞速发展,我们不再满足于简单的问答或单轮交互。构建更复杂、更智能的应用,例如多轮对话智能体(Agent)、需要使用工具并根据工具结果进行决策的工作流,或者需要人机协作的流程,成为了新的需求。传统的线性调用链(如 LangChain 的 Chain)在处理带有状态、循环或复杂条件分支的场景时显得力不从心。

正是在这样的背景下,LangGraph 应运而生。LangGraph 是一个构建在 LangChain Expression Language (LCEL) 之上的库,专门用于创建有状态(stateful)、多角色的(multi-actor)应用,其核心思想是将流程建模为一个有向图(Directed Graph)。它在 GitHub 上开源,为开发者提供了强大的工具来设计和实现复杂的 LLM 工作流。

本文将深入探讨 LangGraph 的核心概念,并提供一份详细的上手指南,帮助你理解并开始使用这个强大的工具。

1. LangGraph 的动机与必要性:为何需要它?

在使用 LLM 构建应用时,我们经常遇到以下场景:

  1. 需要维护状态(State): 应用的后续步骤需要依赖前一步或之前多步的输出或信息。例如,在一个复杂的任务中,智能体需要记住已经执行过的步骤、获取到的信息或当前的决策路径。简单的无状态链无法实现这一点。
  2. 需要条件分支(Conditional Routing): 根据某个步骤的输出结果,决定接下来执行哪个不同的步骤。例如,调用一个工具后,如果结果表示任务完成,则结束;如果需要进一步处理,则调用另一个工具;如果出现错误,则进行错误处理。
  3. 需要循环(Loops): 某些任务可能需要反复执行某个步骤或一组步骤,直到满足特定条件。例如,智能体可能需要反复搜索信息、尝试不同的工具调用,直到找到满意的答案或达到某个限制。
  4. 需要多角色/多智能体协作(Multi-Actor/Multi-Agent Systems): 应用由多个独立的智能体或模块组成,它们需要相互协作、传递信息,并根据其他角色的行为调整自己的行为。
  5. 需要人机协作(Human-in-the-Loop): 在工作流的某个节点需要人工干预、审批或提供信息,然后流程再继续。这要求流程能够暂停、保存状态,并在人工操作完成后恢复。

传统的 Chain 结构擅长处理线性的或树状的(通过并行或简单的分支)流程,但难以优雅地表达和管理状态、复杂的条件跳转和循环。LangGraph 通过引入“图”的概念和内置的状态管理机制,完美地解决了这些问题。它将每一个计算步骤或角色视为图中的“节点”(Node),将流程的走向视为“边”(Edge),并提供了一种机制来在节点之间传递和更新“状态”(State)。

2. LangGraph 的核心概念

理解 LangGraph,需要掌握以下几个核心概念:

2.1 图 (Graph)

图是 LangGraph 的基础结构。它由节点(Nodes)和连接节点的边(Edges)组成。整个应用或工作流被建模为一个有向图,表示了计算和信息流动的可能路径。

2.2 状态 (State)

这是 LangGraph 与传统无状态 Chain 的最大区别。LangGraph 应用维护一个单一的共享状态,这个状态在整个图的执行过程中传递和更新。

  • 表示: 状态通常被定义为一个字典(Dictionary)或一个继承自 TypedDict 的类型。这个状态对象包含所有需要跨节点维护的信息。
  • 更新: 当一个节点执行完毕后,它返回一个对当前状态的“更新”。LangGraph 会将这个更新合并(merge)到全局状态中,而不是简单地替换整个状态。这种合并通常是浅层的字典更新。
  • 作用: 节点通过读取当前状态来获取输入,通过返回状态更新来产生输出,并影响后续节点的执行路径(特别是通过条件边)。

2.3 节点 (Nodes)

节点是图中的基本计算单元。每个节点代表工作流中的一个步骤或一个特定的角色(如一个智能体、一个工具调用、一个决策点、一个数据处理函数)。

  • 类型: 节点可以是简单的 Python 函数,也可以是更复杂的 LangChain Runnable 对象(如 LLM 调用、Tool 调用、其他 Chains 或 Agent)。
  • 输入: 节点的输入是当前的图状态。节点会从状态中提取它需要的数据。
  • 输出: 节点的输出是对图状态的更新(一个字典)。这个更新会被合并到全局状态中,供下一个节点使用。
  • 决策节点: 特殊的节点可能会在执行完成后返回一个字符串或一个特定的枚举值,用来决定接下来通过哪条条件边继续执行。

2.4 边 (Edges)

边定义了图的执行流程,连接不同的节点。

  • 普通边 (Normal Edges): 从一个源节点指向一个目标节点。当源节点执行完毕后,流程无条件地转移到目标节点。
  • 条件边 (Conditional Edges): 从一个源节点指向多个可能的目标节点。源节点执行完成后,需要返回一个“路由键”(通常是字符串),LangGraph 根据这个键选择一个或多个目标节点继续执行。这是实现条件分支和循环的关键。定义条件边需要指定一个谓词函数(或直接使用节点输出作为键),以及一个从路由键到目标节点(或节点列表)的映射。
  • 起始节点 (Entry Point): 定义图执行的起始节点。图的执行总是从这里开始。
  • 结束节点 (End Point): 定义图执行的结束节点。当执行到达一个结束节点时,整个图的执行停止。一个图可以有多个结束节点。可以使用特殊的常量 STARTEND 来指代起始和结束。

2.5 图状态管理器 (Graph State Manager)

LangGraph 内部负责管理图的状态。它接收每个节点的输出(状态更新),并将其合并到当前的全局状态中。

2.6 编译 (Compile)

在定义好图的节点、边和状态结构后,需要调用 compile() 方法来编译图。这个过程会验证图的结构是否合法(例如,是否存在无法到达的节点,条件边映射是否完整等),并生成一个可执行的 Runnable 对象。

2.7 运行 (Invoke/Stream)

编译后的图是一个 Runnable 对象,可以通过 invoke()stream() 方法来执行。

  • invoke(): 执行图直到达到一个结束节点,返回最终的状态。
  • stream(): 以流的方式返回每个节点执行的中间结果或状态更新,直到图执行结束。对于需要实时反馈的应用(如聊天机器人),stream() 非常有用。

2.8 检查点 (Checkpoints – Optional)

LangGraph 支持通过配置检查点来持久化图的状态。这允许你在执行过程中暂停、保存当前状态,稍后从保存的状态恢复执行。这对于长运行流程、需要人工干预或需要从中断中恢复的场景非常重要。

3. 上手指南:构建你的第一个 LangGraph

本节将指导你如何在 GitHub 上找到 LangGraph 项目,并动手构建一个简单的 LangGraph 应用。

3.1 查找 LangGraph 项目

LangGraph 是 LangChain 生态系统的一部分,其代码托管在 GitHub 上。你可以通过搜索 langchain-ai/langgraph 来找到官方仓库。

  • GitHub 仓库地址 (通常是): https://github.com/langchain-ai/langgraph
  • 在仓库中,你可以找到源代码、README 文件、示例 (examplesdocs/how_to)、Issue 跟踪和贡献指南。

3.2 安装 LangGraph

首先,你需要安装 LangGraph 库。确保你的 Python 环境已经设置好。

bash
pip install langgraph langchain langchain_openai # 根据你的需要安装LLM库,这里以OpenAI为例

3.3 构建一个简单的状态图

我们来构建一个简单的图:一个智能体决定是否需要调用工具。

场景: 用户提问,智能体先思考。如果问题需要工具(例如计算器、搜索),则调用工具;如果不需要,则直接生成回答。

状态定义: 我们需要跟踪用户输入、智能体的思考/回答、工具调用结果。

“`python
from typing import TypedDict, Annotated, List
import operator
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import BaseMessage
from langchain_core.messages import HumanMessage, AIMessage

定义状态类型

Annotated 用于类型提示和元数据,这里表示 messages 字段在更新时使用 operator.add 进行合并(列表相加)

class AgentState(TypedDict):
messages: Annotated[List[BaseMessage], operator.add]
# 可以在这里添加其他状态字段,如 tool_output: str = None 等
“`

节点定义:

  1. 智能体节点 (call_llm): 调用 LLM 进行思考或生成回答。
  2. 工具节点 (call_tool): 模拟一个工具调用(这里简化为一个函数)。
  3. 决策节点 (should_use_tool): 根据 LLM 的输出来决定下一步是调用工具还是结束。

“`python

导入 LLM 和工具(示例)

from langchain_openai import ChatOpenAI

from langchain.tools import … # 如果使用实际工具

llm = ChatOpenAI(model=”gpt-4o-mini”, temperature=0)

模拟一个简单的工具调用

def call_tool(state: AgentState):
print(“—调用工具—“)
# 假设我们从状态中获取到需要调用工具的指示和参数
# 这里简化为返回一个固定的工具结果
tool_result = “工具返回:根据你的输入,这是一个模拟结果。”
return {“messages”: [AIMessage(content=tool_result)]}

智能体节点:调用 LLM

def call_llm(state: AgentState):
print(“—调用LLM进行思考/回答—“)
messages = state[‘messages’]
response = llm.invoke(messages)
# LLM的响应本身就是一个AIMessage,我们可以将其添加到状态的messages列表中
return {“messages”: [response]}

决策节点:根据LLM的输出来决定下一步

def should_use_tool(state: AgentState):
print(“—做出决策—“)
last_message = state[‘messages’][-1]
# 简单的决策逻辑:如果LLM的输出中包含“工具”,则认为需要调用工具
if “工具” in last_message.content:
print(“决策:需要使用工具”)
return “continue” # 返回一个字符串,对应条件边的键
else:
print(“决策:不需要使用工具,结束”)
return “end” # 返回另一个字符串,对应条件边的键
“`

构建图:

“`python

1. 初始化 StateGraph

workflow = StateGraph(AgentState)

2. 添加节点

workflow.add_node(“llm”, call_llm)
workflow.add_node(“tool”, call_tool)
workflow.add_node(“decide”, should_use_tool) # 决策节点通常也是一个普通节点,只是它的输出用来决定下一步

3. 设置入口

workflow.set_entry_point(“llm”) # 从llm节点开始

4. 添加边

从llm节点出来,无条件进入决策节点

workflow.add_edge(“llm”, “decide”)

从决策节点出来,根据should_use_tool的返回值添加条件边

返回 “continue” 则去 “tool” 节点

返回 “end” 则到达 END

workflow.add_conditional_edges(
“decide”, # 源节点是 ‘decide’
should_use_tool, # 这里的函数也可以省略,如果 decide 节点直接返回了路由键
# 如果省略,LangGraph会查找decide节点的输出中是否有__next__这样的键,
# 或者直接使用节点的返回值作为键(如果返回值是字符串)
# 为了清晰,这里显式写出用于决策的函数(虽然should_use_tool就是decide节点本身)
# 更常见的做法是,decide节点执行完毕后返回一个字典,其中一个键(如 “next”)的值是路由键。
# 如果decide节点(should_use_tool函数)直接返回字符串 ‘continue’ 或 ‘end’,
# 这里的 predicate 参数可以省略或设置为 None,LangGraph会直接使用返回值作为key。
# 示例中 should_use_tool 直接返回 ‘continue’ 或 ‘end’,所以predicate可以省略或 None
{
“continue”: “tool”, # 如果返回 “continue”,则去 “tool” 节点
“end”: END # 如果返回 “end”,则结束
}
)

从 tool 节点出来,无条件回到 llm 节点(模拟工具结果返回给LLM处理)

注意:这个例子为了演示循环,让工具调用后再回到LLM。

在实际应用中,工具调用后可能会直接结束,或者回到一个解析工具结果的节点,再决定下一步。

简单的例子:工具调用后就结束

workflow.add_edge(“tool”, END)

复杂例子:工具调用后回到llm,让llm根据工具结果生成最终回答

workflow.add_edge(“tool”, “llm”) # 这样就形成了一个循环:llm -> decide -> tool -> llm -> decide -> …

5. 编译图

app = workflow.compile()
“`

3.4 运行图

现在,你可以运行编译好的图了。

“`python

运行第一次:提问一个不需要工具的问题

print(“\n— 运行 1:不需要工具 —“)
initial_state_1 = {“messages”: [HumanMessage(content=”你好,请问天气如何?”)]}
final_state_1 = app.invoke(initial_state_1)
print(“\n最终状态 1:”, final_state_1)

预期流程:llm -> decide -> END

运行第二次:提问一个可能需要工具的问题(根据我们的简陋决策逻辑,包含“工具”二字的问题)

print(“\n— 运行 2:需要工具 (模拟) —“)
initial_state_2 = {“messages”: [HumanMessage(content=”请使用工具计算一下 2+2 等于多少?”)]}

使用 stream 看看每一步的输出

print(“\n流式输出 2:”)
for step_output in app.stream(initial_state_2):
print(“步骤输出:”, step_output)
# 可以检查每个步骤的状态更新,例如 step_output[“llm”] 或 step_output[“tool”]

运行 stream 会打印出每个节点的输出和状态变化

预期流程:llm -> decide (判定continue) -> tool -> llm -> decide (判定end) -> END

“`

运行上面的代码,你需要设置 OPENAI_API_KEY 环境变量,或者在 ChatOpenAI 初始化时传入 api_key 参数。观察输出,你会看到流程是如何根据 should_use_tool 函数的返回值在节点之间跳转的。

3.5 探索更多示例

GitHub 仓库和 LangChain 官方文档是学习 LangGraph 的最佳资源。

  • 官方文档: 查找 LangChain 官方文档中关于 LangGraph 的部分,通常有更详细的概念解释和丰富的示例。
  • GitHub 仓库的 Examples 目录: 许多开源项目都会在仓库中包含示例代码。查找 examples/docs/how_to/ 这样的目录,你可能会找到实现更复杂工作流(如 ReAct Agent、多智能体系统、人机协作)的 LangGraph 示例。通过阅读和运行这些示例,你可以学习如何将 LangGraph 应用于实际场景。

4. LangGraph 的进阶概念与应用场景

掌握了核心概念和基本用法后,可以进一步探索 LangGraph 的高级特性和典型应用:

  • 多智能体系统 (Multi-Agent Systems): 使用 LangGraph 构建由多个智能体组成的协作网络,每个智能体负责特定任务,通过状态和条件边进行交互和决策。
  • ReAct 模式的实现: ReAct (Reasoning and Acting) 模式非常适合用 LangGraph 实现,通过循环:LLM 思考(Reason)-> 决定工具/行动(Act)-> 调用工具 -> 观察结果 -> 回到 LLM 再次思考。
  • 人机协作 (Human-in-the-Loop): 结合检查点,在流程中设置需要人工确认的节点,保存状态,等待人工输入后再恢复执行。
  • 长时间运行流程 (Long-Running Workflows): 利用检查点持久化状态,即使程序中断也可以从上次保存的状态恢复。
  • 错误处理与回退 (Error Handling and Fallbacks): 在图中定义错误处理节点和边,当某个节点失败时,可以跳转到错误处理逻辑。
  • 监控与可视化: LangGraph 可以方便地集成监控工具,追踪图的执行路径和状态变化,有助于调试和优化。有些工具甚至可以根据 LangGraph 定义自动生成可视化图。

5. 从 GitHub 贡献 LangGraph (可选)

如果你对 LangGraph 感兴趣并希望为其发展做出贡献,可以:

  1. 报告 Bug: 在 GitHub Issues 中报告你遇到的问题。
  2. 提交功能请求: 如果你有新的想法或功能建议,可以在 Issues 中提出。
  3. 提交 Pull Request (PR): 如果你修复了 Bug 或实现了新功能,可以提交 PR。在提交前,建议先在 Issues 中讨论你的想法,并遵循项目的贡献指南。
  4. 改进文档和示例: 帮助完善 LangGraph 的文档和示例是非常有价值的贡献。

参与开源项目不仅能提升你的技术能力,也能让你更深入地理解项目的设计和实现。

6. 总结

LangGraph 是构建复杂、有状态、多角色的 LLM 应用的强大框架。它将工作流建模为可执行的图,并提供了一套机制来管理和更新贯穿整个流程的共享状态。通过清晰定义节点、边、状态和条件逻辑,开发者可以构建出高度灵活和智能的应用程序,远超简单的线性调用链所能实现的能力。

通过 GitHub 仓库,你可以访问 LangGraph 的最新代码、学习示例并参与社区。掌握 LangGraph 的核心概念和构建图的流程,是迈向构建高级 LLM 应用的关键一步。鼓励你立即动手实践,从 GitHub 上克隆项目或查看文档中的示例,开始你的 LangGraph 之旅!

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部