目录
前言
尽管大模型在自然语言处理领域掀起了一场革命,展现出强大的文本生成、理解能力,但它本身存在着显著局限。大模型缺乏对任务流程的精细化管理,难以按照复杂的业务逻辑执行任务,在实际应用场景中,常出现对话连贯性差、任务执行偏离预期等问题。当面对多步骤、长周期的复杂任务时,大模型更显得力不从心。
为了应对大模型的不足,LangChain 应运而生。LangChain 是一套专门为开发基于大语言模型的应用而设计的框架。它通过提供各种工具、组件和接口,帮助开发者将大模型与其他资源和功能整合,构建更具交互性、逻辑性和实用性的 AI 应用。借助 LangChain,开发者可以轻松实现多轮对话管理、工具调用以及上下文感知等功能,在一定程度上解决了大模型应用过程中的痛点。然而,随着 AI 应用场景的不断拓展,LangChain 在灵活性、可视化、复杂流程处理等方面的短板逐渐显现。在此背景下,LangGraph 横空出世,凭借其独特的设计和卓越的性能,为大模型应用开发带来了新的思路与解决方案 。
一、LangGraph是什么?
- LangGraph 是一个基于LangChain构建的扩展库。
- LangGraph 是一个用于构建具有状态和多参与者应用程序的 LLM 库,它允许创建具有循环的图,这在大多数智能体架构中是必需的。
- LangGraph提供了对应用程序流程和状态的细粒度控制,这对于创建可靠的智能体至关重要,并且LangGraph 还内置了包括持久化对话,支持高级的人机交互和记忆功能。
LangGraph是一个专注于构建有状态、多角色应用程序的库,它利用大型语言模型(LLMs)来创建智能体和多智能体工作流。这个框架的核心优势体现在以下几个方面:
- 周期性支持:LangGraph允许开发者定义包含循环的流程,这对于大多数中智能体架构来说至关重要。这种能力使得LangGraph与基于有向无环图(DAG)的解决方案区分开来,因为它能够处理需要重复步骤或反馈循环的复杂任务。
- 高度可控性:LangGraph提供了对应用程序流程和状态的精细控制。这种精细控制对于创建行为可靠、符合预期的智能体至关重要,特别是在处理复杂或敏感的应用场景时。
- 持久性功能:LangGraph内置了持久性功能,这意味着智能体能够跨交互保持上下文和记忆。这对于实现长期任务的一致性和连续性非常关键。持久性还支持高级的人机交互,允许人类输入无缝集成到工作流程中,并使智能体能够通过记忆功能学习和适应。
LangChain虽然能够非常简单方便的实现一个简单应用,但是如果想实现一个复杂的应用还是需要使用LangGraph。
LangGraph是一个python库,用于构建具有状态的,拥有多个参与节点的大模型应用程序,可以创建agent和多agent的工作流。
与其他大型语言模型框架相比,它提供了以下核心优势:可循环的流程、可控性和持久性。
LangGraph允许我们定义一个可循环的流程,也就意味着可以多次执行到某个节点,这对于大多数agent架构至关重要,这使其与基于DAG(有向无环图)的解决方案有所区别。
作为一个非常底层的框架,它提供了对应用程序流程和状态的细粒度控制,通过学习深入,会明白这对于创建可靠的agent至关重要。此外,LangGraph还包括内置的持久性功能,支持高级的人机交互和记忆特性。
1.特点
Cycles and Branching(循环和分支)
功能描述:允许在应用程序中实现循环和条件语句。
应用场景:适用于需要重复执行任务或根据不同条件执行不同操作的场景,如自动化决策流程、复杂业务逻辑处理等。
Persistence(持久性)
功能描述:自动在每个步骤后保存状态,可以在任何点暂停和恢复Graph执行,以支持错误恢复、等。
应用场景:对于需要中断和恢复的长时任务非常有用,例如数据分析任务、需要人工审核的流程等。
Human-in-the-Loop
功能描述:允许中断Graph的执行,以便人工批准或编辑Agent计划的下一步操作。
应用场景:在需要人工监督和干预的场合,如敏感操作审批、复杂决策支持等。
Streaming Support(流支持)
功能描述:支持在节点产生输出时实时流输出(包括Token流)。
应用场景:适用于需要实时数据处理和反馈的场景,如实时数据分析、在线聊天机器人等。
Integration with LangChain and LangSmith(与LangChain和LangSmith集成)
功能描述:LangGraph可以与LangChain和LangSmith无缝集成,但并不强制要求它们。
应用场景:增强LangChain和LangSmith的功能,提供更灵活的应用构建方式,特别是在需要复杂流程控制和状态管理的场合。
LangGraph 以 LangChain 为核心,以图的方式来构建大模型应用。
图(Graph)是数学中的一个基本概念,它由点集合及连接这些点的边集合组成。图主要用于模拟各种实体之间的关系,如网络结构、社会关系、信息流等。以下是图的基本组成部分:
- 节点(Vertex):图中的基本单元,通常用来表示实体。在社交网络中,每个顶点可能代表一个人;在交通网络中,每个顶点可能代表一个城市或一个交通枢纽。
- 边(Edge):连接两个顶点的线,表示顶点之间的关系或连接。边可以有方向(称为有向图),也可以没有方向(称为无向图)。
- 权重(Weight):有时边会被赋予一个数值,称为权重,表示两个顶点之间关系的强度或某种度量,如距离、容量、成本等。
把langgraph理解成一个工作流
基本类型的Graph
二、LangGraph代码实现(部分)
1.最简单的图
StateGraph 是 LangGraph 主要使用的一个类,这是由用户定义的State对象参数化的,它由用户定义的状态对象参数化。
代码如下(示例):
from langgraph.graph import StateGraph,START,END
#定义一个节点函数,接收状态,返回新的状态
def my_node(state):
return {"x":state['x']+1,"y":state["y"]+2}
#创建一个状态图
builder = StateGraph(dict)
#创建节点
builder.add_node('node1',my_node)
#创建边
builder.add_edge(START,'node1')
builder.add_edge("node1",END)
#编译图
graph =builder.compile()
#执行图
print(graph.invoke({"x":1,"y":2}))
简单创建图的步骤:
- 创建保存图的状态的字典
- 创建智能体
- 创建带状态的图
- 添加节点 节点和智能体绑定
- 编译图
- 使用:通过图执行智能体和管理 invoke
from langgraph.graph import START, END, StateGraph
from typing_extensions import TypedDict
# 1.创建保存图的状态的字典
class State(TypedDict):
foo: int
# 2.创建智能体
def my_agent(state):
return {"foo": state["foo"] ** 2}
# 3.创建带状态的图
_builder = StateGraph(State)
# 4.添加节点 节点和智能体绑定
_builder.add_node("node1", my_agent)
_builder.add_edge(START, "node1")
_builder.add_edge("node1", END)
# 5.编译图
_graph = _builder.compile()
# 6.执行图
print(_graph.invoke({"foo": 88}))
2.条件边
条件边的使用
- 创建保存图的状态的字典
- 创建智能体
- 创建条件智能体
- 创建带状态的图
- 创建节点 节点和智能体绑定
- 添加边和条件边
- 编译图
- 使用:通过图执行智能体和管理 invoke
代码如下(示例):
class State(TypedDict):
foo: int
def my_agent01(state):
r = {"foo": state["foo"] ** 2}
print(r)
return r
def cond_edges(state):
if state["foo"]>100:
return END
else:
return "node1"
builder = StateGraph(State)
builder.add_node("node1", my_agent01)
builder.add_edge(START,"node1")
builder.add_conditional_edges("node1", cond_edges, ["node1", END])
graph = builder.compile()
print(graph.invoke({"foo": 9}))
from IPython.display import Image, display
graph.get_graph().draw_mermaid_png(output_file_path="./output/con_edge.png")
3.
消息的追加(规约)
消息操作两种:覆盖、追加
追加消息:场景大模型是需要历史的进行消息推理
状态信息追加步骤
- 创建保存图的状态的字典 foo:Annotated[list[int],add]
- 创建智能体
- 创建带状态的图
- 添加节点 节点和智能体绑定
- 编译图
- 使用:通过图执行智能体和管理 invoke _graph.invoke({"foo":[10]})
代码如下(示例):
from langgraph.graph import StateGraph, START, END
from typing_extensions import TypedDict
from typing import Annotated
from operator import add
from IPython.display import Image,display
class State(TypedDict):
# Annotated的作用是给foo定义为list[int]类型
foo: Annotated[list[int], add]
def agent_01(state):
return{"foo": [state['foo'][0] ** 2]}
builder = StateGraph(State)
builder.add_node("node01", agent_01)
builder.add_edge(START, "node01")
builder.add_edge("node01", END)
graph = builder.compile()
print(graph.invoke({"foo": [23]}))
graph.get_graph().draw_mermaid_png(output_file_path="./output/state_app.png")
from langgraph.graph import StateGraph,START,END
from typing_extensions import TypedDict,List,Dict,Any
from typing import Annotated
from operator import add
# 1.创建保存图的状态的字典
class State(TypedDict):
foo:int
bar:list[str]
def update_state(current_state:State, updates: Dict[str,Any]):
#创建一个新的状态的字典
new_state= current_state.copy()
#更新状态字典中的值
new_state.update(updates)
return new_state
#初始状态
state: State ={"foo":1,"bar":['hi']}
print(state)
#第一个节点返回的更新
node1_update = {"foo":2}
state=update_state(state,node1_update)
print(state)
#第二个节点返回的更新
node2_update ={"bar":['bye']}
state=update_state(state,node2_update)
print(state)
4. MessagesState(图中放的state)
messageState会用追加的方式记录历史信息,聊天中需要历史消息
MessageState实现消息追加的步骤
- 创建保存图的状态的字典 继承MessageState
- 创建智能体 添加 messages字段的value
- 创建带状态的图
- 创建节点 节点和智能体绑定
- 编译图
- 使用:通过图执行智能体和管理 invoke 测试messages字段的value, 如 {"messages":"hello", "foo":10}
from langgraph.graph import StateGraph,START,END
from typing_extensions import TypedDict
from langgraph.graph.message import MessagesState
# 1.创建保存图的状态的字典
class State(MessagesState):
foo:int
# 2.创建智能体
def agent_01(state):
return {"messages":"world", "foo":state['foo'] + 1}
# 3.创建带状态的图
_builder = StateGraph(State)
# 4.创建节点 节点和智能体绑定
_builder.add_node("node_01",agent_01)
_builder.add_edge(START,"node_01")
_builder.add_edge("node_01",END)
# 5.编译图
_graph = _builder.compile()
# 6.使用:通过图执行智能体和管理 invoke
_r = _graph.invoke({"messages":"hello", "foo":10})
print(_r)
5.子图
节点包含另一节点
子图--图包含图步骤
- 创建带子图的状态class 属性foo 规约
- 创建5个智能体代理 01、02、l1、r1、r1
- 构建子图
- 构建主图,追加子图
- 编译生成图和运行
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph,START,END
from operator import add
from IPython.display import display,Image
class State(TypedDict):
foo : Annotated[list[str], add]
def agent_01(state):
return {"foo" : ["n1"]}
def agent_02(state):
return {"foo" : ["l1"]}
def agent_03(state):
return {"foo" : ["r1"]}
def agent_04(state):
return {"foo" : ["r2"]}
_sub_builder = StateGraph(State)
_sub_builder.add_node("node_r1", agent_03)
_sub_builder.add_node("node_r2", agent_04)
_sub_builder.add_edge(START, "node_r1")
_sub_builder.add_edge("node_r1", "node_r2")
_sub_builder.add_edge("node_r2", END)
_builder = StateGraph(State)
_builder.add_node("node_n1", agent_01)
_builder.add_node("node_l1", agent_02)
_builder.add_node("sub_graph", _sub_builder.compile())
_builder.add_edge(START, "node_n1")
_builder.add_edge("node_n1", "sub_graph")
_builder.add_edge("node_n1", "node_l1")
_builder.add_edge("sub_graph", END)
_builder.add_edge("node_l1", END)
_graph = _builder.compile()
result = _graph.invoke({"foo":[]})
print(result)
_graph.get_graph().draw_mermaid_png(output_file_path="./output/5.main_graph.png")
_graph.get_graph(xray=1).draw_mermaid_png(output_file_path="./output/5.main_sub_graph.png")