LangGraph 简介
LangGraph 是一个 LangChain 生态的一个支持图的扩展,也是一个构建多代理框架的工具。其核心功能是能够构建和管理状态图,并使大型语言模型(LLM)能够承载这些图。
LangGraph 可以脱离 LangChain 运行哦。
多代理系统是什么意思呢?它具有如下特点:
• 包含多个LLM的复杂代理的系统。
• 每个LLM都可以运行自己的图,
• 并且可以相互通信和共享信息,
• 不同代理能够协同工作的复杂代理系统。
好了,下面我们来开始介绍今天的内容。
首先简单介绍一下图(Graph)。
图简介
看过我《构建个人知识图谱》 系列的对图(Graph)肯定不陌生,我再啰嗦一下图的概念:
图主要是由节点的和边组成,LangGraph 里面的概念更偏向流程图,还有判断和循环的概念。
节点
节点就是代理要执行的函数。
边
边用来连接节点,表示执行完前面的节点执行后面的节点。
判断
条件判断允许代理根据不同的逻辑执行不同的节点或流程。
循环
当节点又指向之前的节点,就形成了一个循环。
下面介绍 LangGraph 里面的核心概念,这些概念和其他的一些代理系统类似、熟悉 LangChain 的同学看起来就更容易了。
State 状态
LangGraph 中的状态用来存储代理执行过程中产生的数据。
一个简单的 State 的Python实现如下所示,仅仅存储系统的对话。
虽然简单到了极致,但是却很有用哦,很多时候我们的代理都不需要复杂的状态管理。
class AgentState(TypedDict):
messages: Annotated[list[AnyMessage], operator.add]
LangGraph 代理类
代理类,就是 Python 里面实现代理功能的类。现在我们用 LangGraph 来编写代理。
可以用 graph = StateGraph(AgentState) 来创建 Graph 对象,使用 Graph 的如下方法来构建图:
•
add_node•
add_conditional_edges•
add_edge•
set_entry_point
先创建一个动作函数:
tool = TavilySearchResults(max_results=4) #increased number of results
构建 Agent 代码如下:
class Agent:
def __init__(self, model, tools, system=""):
self.system = system
graph = StateGraph(AgentState)
graph.add_node("llm", self.call_openai)
graph.add_node("action", self.take_action)
graph.add_conditional_edges(
"llm",
self.exists_action,
{True: "action", False: END}
)
graph.add_edge("action", "llm")
graph.set_entry_point("llm")
self.graph = graph.compile()
self.tools = {t.name: t for t in tools}
self.model = model.bind_tools(tools)
def exists_action(self, state: AgentState):
result = state['messages'][-1]
return len(result.tool_calls) > 0
def call_openai(self, state: AgentState):
messages = state['messages']
if self.system:
messages = [SystemMessage(content=self.system)] + messages
message = self.model.invoke(messages)
return {'messages': [message]}
def take_action(self, state: AgentState):
tool_calls = state['messages'][-1].tool_calls
results = []
for t in tool_calls:
print(f"Calling: {t}")
if not t['name'] in self.tools: # check for bad tool name from LLM
print("
....bad tool name....")
result = "bad tool name, retry" # instruct LLM to retry if bad
else:
result = self.tools[t['name']].invoke(t['args'])
results.append(ToolMessage(tool_call_id=t['id'], name=t['name'], content=str(result)))
print("Back to the model!")
return {'messages': results}
上面代码添加了 LLM 节点来执行函数。
创建代理
现在可以使用上面的代理类快速创建代理机器人:
prompt = """你是一个聪明的研究助理。使用搜索引擎查找信息。\
你可以拨打多个电话(一起或按顺序拨打)。\
只有当你确定你想要什么时才查找信息。\
如果你需要在提出后续问题之前查找一些信息,你可以这样做!
"""
model = ChatOpenAI(model="gpt-3.5-turbo")
abot = Agent(model, [tool], system=prompt)
查看图
我们一直说图,但是讲了半天,图长啥样呢?
可以使用 Python 的工具类快速查看我们刚才构建的代理流程图是什么样。
from IPython.display import Image
Image(abot.graph.get_graph().draw_png())
是不是很简单,除去开始和结束节点,就是大模型和动作节点。
执行代理
具体的执行过程我就不分析了,我们执行代理并直接查看结果。
messages = [HumanMessage(content="What is the weather in sf?")]
result = abot.graph.invoke({"messages": messages})
result['messages'][-1].content
返回的结果如下:
旧金山的当前天气如下:
- 温度:12.2°C (54.0°F)
- 状况:晴朗
- 风速:5.6 英里/小时,风向:西北偏北
- 气压:1013.0 mb
- 湿度:97%
- 能见度:16.0 公里
- 紫外线指数:1.0
如果您需要更多详细信息或历史天气数据,请告诉我!
我们一下询问两个城市的天气试试:
messages = [HumanMessage(content="旧金山和洛杉矶的天气怎么样?")]
result = abot.graph.invoke({"messages": messages})
这次返回的结果简单一些:
“旧金山当前天气为 54.0°F,晴空。风速为 5.6 英里/小时,湿度为 97%。
洛杉矶当前气温为 59.5°F,多云。风速为 4.3 英里/小时,湿度为 90%。”
总结
接上昨天手写 Agent,今天学会了用 StateGraph 来记录节点状态,并构建图,使用 TavilySearch 来进行搜索。
使用框架和工具的好处就是,减少代码量、让代码开起来更加简洁可读。
最后回顾下使用 LangGraph 的过程:
• 创建
graph = StateGraph(),并指定AgentState• 使用 add_* 构建 graph
•
add_node•
add_conditional_edges•
add_edge•
set_entry_point• 调用 Agent() 执行图
Agent 的代码看起来40行有点儿复杂,但是大家可以复用这个, 一般情况下我们都是从简单的示例上修改来满足自己的需求。
--- END ---

