跳到内容

多代理

如果单个智能体需要专精于多个领域或管理许多工具,它可能会感到吃力。为了解决这个问题,您可以将您的智能体分解为更小的、独立的智能体,并将它们组合成一个多智能体系统

在多智能体系统中,智能体之间需要相互通信。它们通过交接(handoffs)来实现这一点——这是一种描述将控制权交给哪个智能体以及向该智能体发送什么负载的原始操作。

两种最流行的多智能体架构是

  • 主管(supervisor)—— 各个智能体由一个中央主管智能体协调。主管控制所有的通信流和任务委派,根据当前上下文和任务需求决定调用哪个智能体。
  • 群组(swarm)—— 智能体根据各自的专长动态地将控制权移交给彼此。系统会记住最后一个活跃的智能体,以确保在后续交互中,对话能从该智能体恢复。

主管型

Supervisor

使用 langgraph-supervisor 库来创建一个主管(supervisor)多智能体系统

pip install langgraph-supervisor

API 参考:ChatOpenAI | create_react_agent | create_supervisor

from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from langgraph_supervisor import create_supervisor

def book_hotel(hotel_name: str):
    """Book a hotel"""
    return f"Successfully booked a stay at {hotel_name}."

def book_flight(from_airport: str, to_airport: str):
    """Book a flight"""
    return f"Successfully booked a flight from {from_airport} to {to_airport}."

flight_assistant = create_react_agent(
    model="openai:gpt-4o",
    tools=[book_flight],
    prompt="You are a flight booking assistant",
    name="flight_assistant"
)

hotel_assistant = create_react_agent(
    model="openai:gpt-4o",
    tools=[book_hotel],
    prompt="You are a hotel booking assistant",
    name="hotel_assistant"
)

supervisor = create_supervisor(
    agents=[flight_assistant, hotel_assistant],
    model=ChatOpenAI(model="gpt-4o"),
    prompt=(
        "You manage a hotel booking assistant and a"
        "flight booking assistant. Assign work to them."
    )
).compile()

for chunk in supervisor.stream(
    {
        "messages": [
            {
                "role": "user",
                "content": "book a flight from BOS to JFK and a stay at McKittrick Hotel"
            }
        ]
    }
):
    print(chunk)
    print("\n")

群组(Swarm)

Swarm

使用 langgraph-swarm 库来创建一个群组(swarm)多智能体系统

pip install langgraph-swarm

API 参考:create_react_agent | create_swarm | create_handoff_tool

from langgraph.prebuilt import create_react_agent
from langgraph_swarm import create_swarm, create_handoff_tool

transfer_to_hotel_assistant = create_handoff_tool(
    agent_name="hotel_assistant",
    description="Transfer user to the hotel-booking assistant.",
)
transfer_to_flight_assistant = create_handoff_tool(
    agent_name="flight_assistant",
    description="Transfer user to the flight-booking assistant.",
)

flight_assistant = create_react_agent(
    model="anthropic:claude-3-5-sonnet-latest",
    tools=[book_flight, transfer_to_hotel_assistant],
    prompt="You are a flight booking assistant",
    name="flight_assistant"
)
hotel_assistant = create_react_agent(
    model="anthropic:claude-3-5-sonnet-latest",
    tools=[book_hotel, transfer_to_flight_assistant],
    prompt="You are a hotel booking assistant",
    name="hotel_assistant"
)

swarm = create_swarm(
    agents=[flight_assistant, hotel_assistant],
    default_active_agent="flight_assistant"
).compile()

for chunk in swarm.stream(
    {
        "messages": [
            {
                "role": "user",
                "content": "book a flight from BOS to JFK and a stay at McKittrick Hotel"
            }
        ]
    }
):
    print(chunk)
    print("\n")

交接

在多智能体交互中,一个常见的模式是移交(handoffs),即一个智能体将控制权移交给另一个智能体。移交允许您指定

  • 目的地(destination):要导航到的目标智能体
  • 负载:要传递给该代理的信息

langgraph-supervisor(主管移交给单个智能体)和 langgraph-swarm(单个智能体可以移交给其他智能体)都使用了这个功能。

要使用 create_react_agent 实现移交,您需要

  1. 创建一个能够将控制权转移到不同智能体的特殊工具

    def transfer_to_bob():
        """Transfer to bob."""
        return Command(
            # name of the agent (node) to go to
            goto="bob",
            # data to send to the agent
            update={"messages": [...]},
            # indicate to LangGraph that we need to navigate to
            # agent node in a parent graph
            graph=Command.PARENT,
        )
    
  2. 创建能够访问移交工具的单个智能体

    flight_assistant = create_react_agent(
        ..., tools=[book_flight, transfer_to_hotel_assistant]
    )
    hotel_assistant = create_react_agent(
        ..., tools=[book_hotel, transfer_to_flight_assistant]
    )
    
  3. 定义一个包含各个智能体作为节点的父图

    from langgraph.graph import StateGraph, MessagesState
    multi_agent_graph = (
        StateGraph(MessagesState)
        .add_node(flight_assistant)
        .add_node(hotel_assistant)
        ...
    )
    

综合起来,以下是您如何用两个智能体——一个机票预订助手和一个酒店预订助手——实现一个简单的多智能体系统

API 参考:tool | InjectedToolCallId | create_react_agent | InjectedState | StateGraph | START | Command

from typing import Annotated
from langchain_core.tools import tool, InjectedToolCallId
from langgraph.prebuilt import create_react_agent, InjectedState
from langgraph.graph import StateGraph, START, MessagesState
from langgraph.types import Command

def create_handoff_tool(*, agent_name: str, description: str | None = None):
    name = f"transfer_to_{agent_name}"
    description = description or f"Transfer to {agent_name}"

    @tool(name, description=description)
    def handoff_tool(
        state: Annotated[MessagesState, InjectedState], # (1)!
        tool_call_id: Annotated[str, InjectedToolCallId],
    ) -> Command:
        tool_message = {
            "role": "tool",
            "content": f"Successfully transferred to {agent_name}",
            "name": name,
            "tool_call_id": tool_call_id,
        }
        return Command(  # (2)!
            goto=agent_name,  # (3)!
            update={"messages": state["messages"] + [tool_message]},  # (4)!
            graph=Command.PARENT,  # (5)!
        )
    return handoff_tool

# Handoffs
transfer_to_hotel_assistant = create_handoff_tool(
    agent_name="hotel_assistant",
    description="Transfer user to the hotel-booking assistant.",
)
transfer_to_flight_assistant = create_handoff_tool(
    agent_name="flight_assistant",
    description="Transfer user to the flight-booking assistant.",
)

# Simple agent tools
def book_hotel(hotel_name: str):
    """Book a hotel"""
    return f"Successfully booked a stay at {hotel_name}."

def book_flight(from_airport: str, to_airport: str):
    """Book a flight"""
    return f"Successfully booked a flight from {from_airport} to {to_airport}."

# Define agents
flight_assistant = create_react_agent(
    model="anthropic:claude-3-5-sonnet-latest",
    tools=[book_flight, transfer_to_hotel_assistant],
    prompt="You are a flight booking assistant",
    name="flight_assistant"
)
hotel_assistant = create_react_agent(
    model="anthropic:claude-3-5-sonnet-latest",
    tools=[book_hotel, transfer_to_flight_assistant],
    prompt="You are a hotel booking assistant",
    name="hotel_assistant"
)

# Define multi-agent graph
multi_agent_graph = (
    StateGraph(MessagesState)
    .add_node(flight_assistant)
    .add_node(hotel_assistant)
    .add_edge(START, "flight_assistant")
    .compile()
)

# Run the multi-agent graph
for chunk in multi_agent_graph.stream(
    {
        "messages": [
            {
                "role": "user",
                "content": "book a flight from BOS to JFK and a stay at McKittrick Hotel"
            }
        ]
    }
):
    print(chunk)
    print("\n")
  1. 访问智能体状态
  2. Command 原始操作允许将状态更新和节点转换指定为单个操作,这对于实现交接非常有用。
  3. 要移交到的代理或节点的名称。
  4. 获取智能体的消息并将其添加到父级的状态中,作为交接的一部分。下一个智能体将看到父级状态。
  5. 指示 LangGraph 我们需要导航到父级多代理图中的代理节点。

注意

此交接实现假定

  • 每个智能体接收多智能体系统中(跨所有智能体的)整体消息历史作为其输入
  • 每个智能体将其内部消息历史输出到多智能体系统的整体消息历史中

查看 LangGraph 主管(supervisor)群组(swarm) 的文档,了解如何自定义移交。