大数跨境
0
0

LangGraph 基于图实现的多代理框架(1)

LangGraph 基于图实现的多代理框架(1) 数翼
2024-06-24
0
导读:今天介绍 LangGraph 的概念,以及如何使用 LangGraph 框架来构建一个简单的 AI 代理。
今天介绍 LangGraph 的概念,以及如何使用 LangGraph 框架来构建一个简单的 AI 代理。

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
Tavily 搜索 Tavily 是一个可以执行互联网搜索的服务,区别于百度、谷歌等网页服务,他可以被接口调用,还能指定很多参数。免费用户每个月有  1000 次的免费配额哦。

构建 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 ---


【声明】内容源于网络
0
0
数翼
专注 AIGC 人工智能知识传播和实践
内容 228
粉丝 0
数翼 专注 AIGC 人工智能知识传播和实践
总阅读29
粉丝0
内容228