langgraph多智能体

     1.多智能体概述

     1.1为什么要用多智能体

        在后台服务的世界里,单体服务难以扩展、难以维护、缺乏弹性和柔性、难以重用而不能适应复杂的业务需求,所以在生产环境中已经很难看到单体应用的身影了。同样,在智能体的世界里,单智能体因承载太多的逻辑而出现如下问题:

        1)选择工具难。一个大模型如果有太多可用的工具,在选择应该使用的工具时往往表现不佳,甚至做出错误的选择

        2)理解上下文难。经过多轮次不同目的的交互后,上下文混杂了大量各种信息,导致智能体越来越难以理解上下文

        3)扩充维护难。一个智能体承载太多的功能,内聚性自然变差,随着规模变大,扩充新功能、修改BUG等举步维艰

        借鉴微服务的思想,把一个单智能体拆分为多个规模小、功能内聚、易于维护的智能体,langgraph也提供了对于多智能体架构的支持,使用多智能体有如下好处:

        1)模块化。每个智能体都足够简单和内聚,开发、测试和维护工作都更容易完成

        2)专业化。每个智能体在自己的领域都是专家,专家比“杂家”处理问题更高效,从而可以优化整体表现

        3)可控性。开发者可以显式控制智能体之间的交互方式,而不是仅仅依赖function calling进行交互。

     1.2多智能体架构

        设计多智能体的关键智能体之间的交互方式,根据交互方式把智能体架构分成以下五种:

        1)网状架构。所有智能体构成全连接的网络图,每个智能体可以跟任何一个智能体交互,每个智能体可以自主确定下一步调用哪个智能体

        2)监督者架构。有一个智能体承担监督者的角色,监督者可以跟任何一个智能体交互,监督者决定下一步调用哪个智能体

        3)基于工具调用的监督者。属于监督者架构的一种特例。监督者之外的其他智能体全部封装为工具,并绑定到监督者的大模型,监督者基于大模型的工具调用决定下一步调用哪个智能体工具

        4)层次架构。是监督者架构的纵向扩展,每个智能体都是下层智能体的监督者

        5)自定义架构。网状架构、监督者架构和层次架构的综合。每个智能体仅与部分智能体交互,部分智能体作为监督者,有些工作流时固定的

     1.3交接

        在langgraph中,智能体完全等同于langgraph图中的节点,也等同于子图。工作流从一个节点流转到另一个节点称为交接。每个智能体自主执行并决定何时结束,何时交接给下一个节点,交接时需要传递哪些数据。

        在langgraph中使用Command实现智能体之间的交接。在使用langgraph创建工作流系列4:人机回环中使用Command从终端中恢复,在这里Command用于节点之间交接,在一个智能体内部节点之间交接或者在不同智能体之间的交接均由Command实现。

       1.3.1内部交接

        在一个智能体内部节点之间使用Command跳转,则不需要在节点之间用边来连接。

        以下示例是一个简单的两节点图,在node1中使用Command跳转到node2,并且同时更新状态中的值,代码如下:

from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.types import Command
class State(TypedDict):
    v: int
def node1(state: State):
    return Command(
        goto='node2', #goto指定目的节点
        update={'v': state['v'] * 5} #同步更新状态值
    )
    
def node2(state: State):
    return {'v': state['v'] * 2}

"""

    以下创建图时,不需要在node1和node2之间增加边。所以绘制图时,不能正常显示

"""

graph_builder = StateGraph(State)
graph_builder.add_node("node1", node1)
graph_builder.add_node("node2", node2)
graph_builder.add_edge(START, "node1")
graph_builder.add_edge("node2", END)
graph = graph_builder.compile()

       1.3.2跨智能体交接

        从一个智能体跳到另一个智能体使用Command交接时,除了需要指定目标节点外,还需要指定在哪个图内跳转。

        以下示例是一个包括两个子智能体的主智能体,从第一个智能体跳转到第二个智能体,具体代码如下:

from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.types import Command
class State(TypedDict):
    v: int

"""

    构建第一个子智能体,仅有一个节点,从节点内部跳到第二个智能体,并同步更新状态v未原来的5倍

"""
def node1(state: State):
    return Command(
        goto='sub_graph2',
        update={'v': state['v'] * 5},
        graph=Command.PARENT
    )
sub_graph_builder1 = StateGraph(State)
sub_graph_builder1.add_node("node1", node1)
sub_graph_builder1.add_edge(START, "node1")
sub_graph_builder1.add_edge("node1", END)
sub_graph1 = sub_graph_builder1.compile()

#构建第二个智能体,把状态中的v更新为原来的2倍

def node2(state: State):
    return {'v': state['v'] * 2}
sub_graph_builder2 = StateGraph(State)
sub_graph_builder2.add_node("node2", node2)
sub_graph_builder2.add_edge(START, "node2")
sub_graph2 = sub_graph_builder2.compile()

#构建主智能体

graph_builder = StateGraph(State)
graph_builder.add_node("sub_graph1", sub_graph1)
graph_builder.add_node("sub_graph2", sub_graph2)
graph_builder.add_edge(START, "sub_graph1")#先进入sub_graph1智能体
graph = graph_builder.compile()

      2.网状架构多智能体

        如果所有智能体地位平等,没有明确的层级结构,也没有固定的执行顺序,每个智能体有最大的自主权,并且仅根据上下文确定何时跳转到哪个智能体,此时应采用网状多智能体架构。

        有三个智能体,agent1、agent2和agent3,每个智能体都调用大模型根据上下文确定下一步交接的智能体,每个智能体都能够调用其他的两个智能体,具体代码如下:

from typing import Annotated
from typing_extensions import TypedDict

from typing import Literal
from langchain_openai import ChatOpenAI
from langgraph.types import Command
from langgraph.graph import StateGraph, START, END
from langchain.chat_models import init_chat_model

from langgraph.graph.message import add_messages
import os
os.environ["OPENAI_API_KEY"] = "sk-*"

model = init_chat_model(model='qwen-plus', model_provider='openai', base_url='https://dashscope.aliyuncs.com/compatible-mode/v1')

class State(TypedDict):
    messages: Annotated[list, add_messages]

#智能体agent1,跳转目标是agent2或agent3

def agent1(state: State) -> Command[Literal["agent2", "agent3", END]]:
    response = model.invoke(...)

    return Command(
        goto=response["next_agent"],
        update={"messages": [response["content"]]},
    )

#智能体agent2,跳转目标是agent1或agent3

def agent2(state: State) -> Command[Literal["agent1", "agent3", END]]:
    response = model.invoke(...)
    return Command(
        goto=response["next_agent"],
        update={"messages": [response["content"]]},
    )

#智能体agent3,跳转目标是agent1或agent2

def agent3(state: State) -> Command[Literal["agent1", "agent2", END]]:
    response = model.invoke(...)
    return Command(
        goto=response["next_agent"],
        update={"messages": [response["content"]]},
    )

builder = StateGraph(State)
builder.add_node(agent1)
builder.add_node(agent2)
builder.add_node(agent3)

builder.add_edge(START, "agent1")
network = builder.compile()

      3.监督者架构多智能

        在监督者架构中,监督者作为中控,根据上下文确定跳转到智能体1还是智能体2,智能体1和智能体2都要回到监督者,具体代码如下:

from typing import Literal
from langchain_openai import ChatOpenAI
from langgraph.types import Command
from langgraph.graph import StateGraph, MessagesState, START, END
from langchain.chat_models import init_chat_model
import os
os.environ["OPENAI_API_KEY"] = "sk-*"

model = init_chat_model(model='qwen-plus', model_provider='openai', base_url='https://dashscope.aliyuncs.com/compatible-mode/v1')

#监督者

def supervisor(state: MessagesState) -> Command[Literal["agent1", "agent2", END]]:
    response = model.invoke(...)
    return Command(goto=response["next_agent"])

#智能体1,跳回监督者

def agent1(state: MessagesState) -> Command[Literal["supervisor"]]:
    response = model.invoke(...)
    return Command(
        goto="supervisor",
        update={"messages": [response]},
    )

#智能体1,跳回监督者

def agent2(state: MessagesState) -> Command[Literal["supervisor"]]:
    response = model.invoke(...)
    return Command(
        goto="supervisor",
        update={"messages": [response]},
    )

builder = StateGraph(MessagesState)
builder.add_node(supervisor)
builder.add_node(agent1)
builder.add_node(agent2)

builder.add_edge(START, "supervisor")

supervisor = builder.compile()

     4.基于工具调用的监督者架构智能体

        基于工具调用的监督者架构,把除监督者之外的智能体全部封装为工具,示例代码如下:

from typing import Annotated
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from typing_extensions import TypedDict
from langgraph.graph.message import add_messages
import os
os.environ["OPENAI_API_KEY"] = "sk-*"
model = init_chat_model(model='qwen-plus', model_provider='openai', base_url='https://dashscope.aliyuncs.com/compatible-mode/v1')

class State(TypedDict):
    messages: Annotated[list, add_messages]

def agent1(state: State): #智能体1
   response = model.invoke(...)
   return response.content

def agent2(state: State): #智能体2
    response = model.invoke(...)
    return response.content

tools = [agent1, agent2] #把智能体1和智能体2作为工具集 

supervisor = create_react_agent(model, tools) #创建监督者智能体并传入工具集

      5.层次架构智能体

        以下是一个三层架构的智能体,第一层为一个监督者,第二层为两个监督者,第三方为分别隶属于第二层监督着的普通智能体,具体代码如下:

from typing import Annotated
from typing import Literal
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph.types import Command
from typing_extensions import TypedDict
from langgraph.graph.message import add_messages
import os
os.environ["OPENAI_API_KEY"] = "sk-*"
model = init_chat_model(model='qwen-plus', model_provider='openai', base_url='https://dashscope.aliyuncs.com/compatible-mode/v1')

class State(TypedDict):
    messages: Annotated[list, add_messages]

#第二层监督者1

def group_1_supervisor(state: State) -> Command[Literal["group_1_agent_1", "group_1_agent_2", END]]:
    response = model.invoke(...)
    return Command(goto=response["next_agent"])

#受第二层监督者1控制的第三层智能体1

def group_1_agent_1(state: State) -> Command[Literal["group_1_supervisor"]]:
    response = model.invoke(...)
    return Command(goto="group_1_supervisor", update={"messages": [response]})

#受第二层监督者1控制的第三层智能体2

def group_1_agent_2(state: State) -> Command[Literal["group_1_supervisor"]]:
    response = model.invoke(...)
    return Command(goto="group_1_supervisor", update={"messages": [response]})

#构建第一个监督者架构智能体

group_1_builder = StateGraph(State)
group_1_builder.add_node(group_1_supervisor)
group_1_builder.add_node(group_1_agent_1)
group_1_builder.add_node(group_1_agent_2)
group_1_builder.add_edge(START, "group_1_supervisor")
group_1_graph = group_1_builder.compile()

#以下代码构建第二个监督者架构智能体

#第二层监督者2

def group_2_supervisor(state: State) -> Command[Literal["group_2_agent_1", "group_2_agent_2", END]]:
    response = model.invoke(...)
    return Command(goto=response["next_agent"])

#第三方受第二层监督者2控制的智能体1

def group_1_agent_1(state: State) -> Command[Literal["group_2_supervisor"]]:
    response = model.invoke(...)
    return Command(goto="group_2_supervisor", update={"messages": [response]})

#第三方受第二层监督者2控制的智能体2

def group_1_agent_2(state: State) -> Command[Literal["group_2_supervisor"]]:
    response = model.invoke(...)
    return Command(goto="group_2_supervisor", update={"messages": [response]})

#构建第二个监督者架构智能体

group_2_builder = StateGraph(State)
group_2_builder.add_node(group_2_supervisor)
group_2_builder.add_node(group_2_agent_1)
group_2_builder.add_node(group_2_agent_2)
group_2_builder.add_edge(START, "group_2_supervisor")
group_2_graph = group_2_builder.compile()builder = StateGraph(State)

#第一层监督者
def top_level_supervisor(state: State) -> Command[Literal["group_1_graph", "group_2_graph", END]]:
    response = model.invoke(...)
    return Command(goto=response["next_team"])

#以下代码构建层次架构智能体

builder = StateGraph(MessagesState)
builder.add_node(top_level_supervisor)
builder.add_node("group_1_graph", group_1_graph)
builder.add_node("group_2_graph", group_2_graph)
builder.add_edge(START, "top_level_supervisor")
builder.add_edge("group_1_graph", "top_level_supervisor")
builder.add_edge("group_2_graph", "top_level_supervisor")
graph = builder.compile()

      6.自定义架构智能体

        自定义架构智能体是所有多整体架构之集大成者,后面专门文章进行讲解。

        

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值