跳转至

多智能代理

如果单个智能代理需要专门处理多个领域或管理许多工具,它可能会遇到困难。为了解决这个问题,你可以将你的智能代理分解成更小的独立智能代理,并将它们组合成一个多智能代理系统

在多智能代理系统中,智能代理需要彼此之间进行通信。它们通过交接来实现 — 这是一个原语,描述了要将控制权交给哪个智能代理以及要发送给该智能代理的有效负载。

两种最流行的多智能代理架构是:

  • 监督者 — 单个智能代理由中央监督智能代理协调。监督者控制所有通信流和任务委派,根据当前上下文和任务需求决定调用哪个智能代理。
  • 集群 — 智能代理根据其专业领域动态地将控制权交给彼此。系统记住最后活动的智能代理,确保在后续交互中,对话从该智能代理恢复。

监督者

Supervisor

使用 langgraph-supervisor 库创建监督者多智能代理系统:

pip install langgraph-supervisor
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
# highlight-next-line
from langgraph_supervisor import create_supervisor

def book_hotel(hotel_name: str):
    """预订酒店"""
    return f"Successfully booked a stay at {hotel_name}."

def book_flight(from_airport: str, to_airport: str):
    """预订航班"""
    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",
    # highlight-next-line
    name="flight_assistant"
)

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

# highlight-next-line
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")

使用 @langchain/langgraph-supervisor 库创建监督者多智能代理系统:

npm install @langchain/langgraph-supervisor
import { ChatOpenAI } from "@langchain/openai";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
// highlight-next-line
import { createSupervisor } from "langgraph-supervisor";

function bookHotel(hotelName: string) {
  /**预订酒店*/
  return `Successfully booked a stay at ${hotelName}.`;
}

function bookFlight(fromAirport: string, toAirport: string) {
  /**预订航班*/
  return `Successfully booked a flight from ${fromAirport} to ${toAirport}.`;
}

const flightAssistant = createReactAgent({
  llm: "openai:gpt-4o",
  tools: [bookFlight],
  stateModifier: "You are a flight booking assistant",
  // highlight-next-line
  name: "flight_assistant",
});

const hotelAssistant = createReactAgent({
  llm: "openai:gpt-4o",
  tools: [bookHotel],
  stateModifier: "You are a hotel booking assistant",
  // highlight-next-line
  name: "hotel_assistant",
});

// highlight-next-line
const supervisor = createSupervisor({
  agents: [flightAssistant, hotelAssistant],
  llm: new ChatOpenAI({ model: "gpt-4o" }),
  systemPrompt:
    "You manage a hotel booking assistant and a " +
    "flight booking assistant. Assign work to them.",
});

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

集群

Swarm

使用 langgraph-swarm 库创建集群多智能代理系统:

pip install langgraph-swarm
from langgraph.prebuilt import create_react_agent
# highlight-next-line
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",
    # highlight-next-line
    tools=[book_flight, transfer_to_hotel_assistant],
    prompt="You are a flight booking assistant",
    # highlight-next-line
    name="flight_assistant"
)
hotel_assistant = create_react_agent(
    model="anthropic:claude-3-5-sonnet-latest",
    # highlight-next-line
    tools=[book_hotel, transfer_to_flight_assistant],
    prompt="You are a hotel booking assistant",
    # highlight-next-line
    name="hotel_assistant"
)

# highlight-next-line
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")

使用 @langchain/langgraph-swarm 库创建集群多智能代理系统:

npm install @langchain/langgraph-swarm
import { createReactAgent } from "@langchain/langgraph/prebuilt";
// highlight-next-line
import { createSwarm, createHandoffTool } from "@langchain/langgraph-swarm";

const transferToHotelAssistant = createHandoffTool({
  agentName: "hotel_assistant",
  description: "Transfer user to the hotel-booking assistant.",
});

const transferToFlightAssistant = createHandoffTool({
  agentName: "flight_assistant",
  description: "Transfer user to the flight-booking assistant.",
});

const flightAssistant = createReactAgent({
  llm: "anthropic:claude-3-5-sonnet-latest",
  // highlight-next-line
  tools: [bookFlight, transferToHotelAssistant],
  stateModifier: "You are a flight booking assistant",
  // highlight-next-line
  name: "flight_assistant",
});

const hotelAssistant = createReactAgent({
  llm: "anthropic:claude-3-5-sonnet-latest",
  // highlight-next-line
  tools: [bookHotel, transferToFlightAssistant],
  stateModifier: "You are a hotel booking assistant",
  // highlight-next-line
  name: "hotel_assistant",
});

// highlight-next-line
const swarm = createSwarm({
  agents: [flightAssistant, hotelAssistant],
  defaultActiveAgent: "flight_assistant",
});

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

交接

多智能代理交互中的一个常见模式是**交接**,其中一个智能代理将控制权_交接_给另一个。交接允许你指定:

  • 目标: 要导航到的目标智能代理
  • 有效负载: 要传递给该智能代理的信息

这由 langgraph-supervisor(监督者交接给单个智能代理)和 langgraph-swarm(单个智能代理可以交接给其他智能代理)使用。

要使用 create_react_agent 实现交接,你需要:

  1. 创建一个可以将控制权转移到不同智能代理的特殊工具

    def transfer_to_bob():
        """转移到 bob。"""
        return Command(
            # 要去的智能代理(节点)的名称
            # highlight-next-line
            goto="bob",
            # 发送给智能代理的数据
            # highlight-next-line
            update={"messages": [...]},
            # 向 LangGraph 指示我们需要导航到
            # 父图中的智能代理节点
            # highlight-next-line
            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)
        ...
    )
    

这由 @langchain/langgraph-supervisor(监督者交接给单个智能代理)和 @langchain/langgraph-swarm(单个智能代理可以交接给其他智能代理)使用。

要使用 createReactAgent 实现交接,你需要:

  1. 创建一个可以将控制权转移到不同智能代理的特殊工具

    function transferToBob() {
      /**转移到 bob。*/
      return new Command({
        // 要去的智能代理(节点)的名称
        // highlight-next-line
        goto: "bob",
        // 发送给智能代理的数据
        // highlight-next-line
        update: { messages: [...] },
        // 向 LangGraph 指示我们需要导航到
        // 父图中的智能代理节点
        // highlight-next-line
        graph: Command.PARENT,
      });
    }
    
  2. 创建可以访问交接工具的单个智能代理:

    const flightAssistant = createReactAgent({
      ..., tools: [bookFlight, transferToHotelAssistant]
    });
    const hotelAssistant = createReactAgent({
      ..., tools: [bookHotel, transferToFlightAssistant]
    });
    
  3. 定义包含单个智能代理作为节点的父图:

    import { StateGraph, MessagesZodState } from "@langchain/langgraph";
    const multiAgentGraph = new StateGraph(MessagesZodState)
      .addNode("flight_assistant", flightAssistant)
      .addNode("hotel_assistant", hotelAssistant)
      // ...
    

将所有这些放在一起,以下是如何实现一个具有两个智能代理的简单多智能代理系统 — 航班预订助手和酒店预订助手:

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(
        # highlight-next-line
        state: Annotated[MessagesState, InjectedState], # (1)!
        # highlight-next-line
        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)!
            # highlight-next-line
            goto=agent_name,  # (3)!
            # highlight-next-line
            update={"messages": state["messages"] + [tool_message]},  # (4)!
            # highlight-next-line
            graph=Command.PARENT,  # (5)!
        )
    return 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.",
)

# 简单的智能代理工具
def book_hotel(hotel_name: str):
    """预订酒店"""
    return f"Successfully booked a stay at {hotel_name}."

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

# 定义智能代理
flight_assistant = create_react_agent(
    model="anthropic:claude-3-5-sonnet-latest",
    # highlight-next-line
    tools=[book_flight, transfer_to_hotel_assistant],
    prompt="You are a flight booking assistant",
    # highlight-next-line
    name="flight_assistant"
)
hotel_assistant = create_react_agent(
    model="anthropic:claude-3-5-sonnet-latest",
    # highlight-next-line
    tools=[book_hotel, transfer_to_flight_assistant],
    prompt="You are a hotel booking assistant",
    # highlight-next-line
    name="hotel_assistant"
)

# 定义多智能代理图
multi_agent_graph = (
    StateGraph(MessagesState)
    .add_node(flight_assistant)
    .add_node(hotel_assistant)
    .add_edge(START, "flight_assistant")
    .compile()
)

# 运行多智能代理图
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 指示我们需要导航到**父级**多智能代理图中的智能代理节点。
import { tool } from "@langchain/core/tools";
import { ChatAnthropic } from "@langchain/anthropic";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import {
  StateGraph,
  START,
  MessagesZodState,
  Command,
} from "@langchain/langgraph";
import { z } from "zod";

function createHandoffTool({
  agentName,
  description,
}: {
  agentName: string;
  description?: string;
}) {
  const name = `transfer_to_${agentName}`;
  const toolDescription = description || `Transfer to ${agentName}`;

  return tool(
    async (_, config) => {
      const toolMessage = {
        role: "tool" as const,
        content: `Successfully transferred to ${agentName}`,
        name: name,
        tool_call_id: config.toolCall?.id!,
      };
      return new Command({
        // (2)!
        // highlight-next-line
        goto: agentName, // (3)!
        // highlight-next-line
        update: { messages: [toolMessage] }, // (4)!
        // highlight-next-line
        graph: Command.PARENT, // (5)!
      });
    },
    {
      name,
      description: toolDescription,
      schema: z.object({}),
    }
  );
}

// 交接
const transferToHotelAssistant = createHandoffTool({
  agentName: "hotel_assistant",
  description: "Transfer user to the hotel-booking assistant.",
});

const transferToFlightAssistant = createHandoffTool({
  agentName: "flight_assistant",
  description: "Transfer user to the flight-booking assistant.",
});

// 简单的智能代理工具
const bookHotel = tool(
  async ({ hotelName }) => {
    /**预订酒店*/
    return `Successfully booked a stay at ${hotelName}.`;
  },
  {
    name: "book_hotel",
    description: "Book a hotel",
    schema: z.object({
      hotelName: z.string().describe("Name of the hotel to book"),
    }),
  }
);

const bookFlight = tool(
  async ({ fromAirport, toAirport }) => {
    /**预订航班*/
    return `Successfully booked a flight from ${fromAirport} to ${toAirport}.`;
  },
  {
    name: "book_flight",
    description: "Book a flight",
    schema: z.object({
      fromAirport: z.string().describe("Departure airport code"),
      toAirport: z.string().describe("Arrival airport code"),
    }),
  }
);

// 定义智能代理
const flightAssistant = createReactAgent({
  llm: new ChatAnthropic({ model: "anthropic:claude-3-5-sonnet-latest" }),
  // highlight-next-line
  tools: [bookFlight, transferToHotelAssistant],
  stateModifier: "You are a flight booking assistant",
  // highlight-next-line
  name: "flight_assistant",
});

const hotelAssistant = createReactAgent({
  llm: new ChatAnthropic({ model: "anthropic:claude-3-5-sonnet-latest" }),
  // highlight-next-line
  tools: [bookHotel, transferToFlightAssistant],
  stateModifier: "You are a hotel booking assistant",
  // highlight-next-line
  name: "hotel_assistant",
});

// 定义多智能代理图
const multiAgentGraph = new StateGraph(MessagesZodState)
  .addNode("flight_assistant", flightAssistant)
  .addNode("hotel_assistant", hotelAssistant)
  .addEdge(START, "flight_assistant")
  .compile();

// 运行多智能代理图
for await (const chunk of multiAgentGraph.stream({
  messages: [
    {
      role: "user",
      content: "book a flight from BOS to JFK and a stay at McKittrick Hotel",
    },
  ],
})) {
  console.log(chunk);
  console.log("\n");
}
  1. 访问智能代理的状态
  2. Command 原语允许将状态更新和节点转换指定为单个操作,使其对实现交接很有用。
  3. 要交接到的智能代理或节点的名称。
  4. 获取智能代理的消息并将它们**添加**到父级的**状态**中作为交接的一部分。下一个智能代理将看到父状态。
  5. 向 LangGraph 指示我们需要导航到**父级**多智能代理图中的智能代理节点。

Note

此交接实现假设:

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

查看 LangGraph 监督者集群文档,了解如何自定义交接。

查看 LangGraph 监督者集群文档,了解如何自定义交接。