如何构建多代理网络(函数式 API)¶
在本操作指南中,我们将演示如何实现一种 多智能体网络 架构,其中每个智能体都可以与其他所有智能体进行通信(多对多连接),并且可以决定下一步调用哪个智能体。我们将使用 功能 API — 每个智能体将被定义为任务,并且智能体之间的交接将在主 entrypoint() 中定义:
API Reference: entrypoint | create_react_agent | tool
from langgraph.func import entrypoint
from langgraph.prebuilt import create_react_agent
from langchain_core.tools import tool
# 定义一个工具以表示意图转交给另一个智能体
@tool(return_direct=True)
def transfer_to_hotel_advisor():
"""请求酒店顾问智能体的帮助。"""
return "成功转接至酒店顾问"
# 定义一个智能体
travel_advisor_tools = [transfer_to_hotel_advisor, ...]
travel_advisor = create_react_agent(model, travel_advisor_tools)
# 定义一个调用智能体的任务
@task
def call_travel_advisor(messages):
response = travel_advisor.invoke({"messages": messages})
return response["messages"]
# 定义多智能体网络工作流
@entrypoint()
def workflow(messages):
call_active_agent = call_travel_advisor
while True:
agent_messages = call_active_agent(messages).result()
messages = messages + agent_messages
call_active_agent = get_next_agent(messages)
return messages
设置¶
首先,让我们安装所需的软件包
import getpass
import os
def _set_env(var: str):
if not os.environ.get(var):
os.environ[var] = getpass.getpass(f"{var}: ")
_set_env("ANTHROPIC_API_KEY")
为 LangGraph 开发设置 LangSmith
注册 LangSmith 可以快速发现并改进你的 LangGraph 项目的问题。LangSmith 允许你使用跟踪数据来调试、测试和监控使用 LangGraph 构建的 LLM 应用 —— 了解更多如何入门的信息,请访问 此处。
旅行社示例¶
在这个示例中,我们将构建一个能够相互交流的旅行助手代理团队。
我们将创建 2 个代理:
travel_advisor
:可以提供旅行目的地推荐。可以向hotel_advisor
寻求帮助。hotel_advisor
:可以提供酒店推荐。可以向travel_advisor
寻求帮助。
这是一个全连接网络——每个代理都可以与其他任何代理进行交流。
首先,让我们创建一些代理将使用的工具:
API Reference: tool
import random
from typing_extensions import Literal
from langchain_core.tools import tool
@tool
def get_travel_recommendations():
"""Get recommendation for travel destinations"""
return random.choice(["aruba", "turks and caicos"])
@tool
def get_hotel_recommendations(location: Literal["aruba", "turks and caicos"]):
"""Get hotel recommendations for a given destination."""
return {
"aruba": [
"The Ritz-Carlton, Aruba (Palm Beach)"
"Bucuti & Tara Beach Resort (Eagle Beach)"
],
"turks and caicos": ["Grace Bay Club", "COMO Parrot Cay"],
}[location]
@tool(return_direct=True)
def transfer_to_hotel_advisor():
"""Ask hotel advisor agent for help."""
return "Successfully transferred to hotel advisor"
@tool(return_direct=True)
def transfer_to_travel_advisor():
"""Ask travel advisor agent for help."""
return "Successfully transferred to travel advisor"
Transfer 工具
你可能已经注意到我们在转移工具中使用了 @tool(return_direct=True)
。这是为了让单个代理(例如 travel_advisor
)在调用这些工具后能够提前退出 ReAct 循环。这是期望的行为,因为我们希望检测到代理调用该工具时,立即将控制权交给另一个代理。
注意:这旨在与预构建的 create_react_agent
一起使用——如果你正在构建自定义代理,请确保手动添加处理标记为 return_direct
的工具提前退出的逻辑。
现在让我们定义我们的代理任务,并将它们组合成一个单一的多代理网络工作流程:
API Reference: AIMessage | ChatAnthropic | create_react_agent | add_messages | entrypoint | task
from langchain_core.messages import AIMessage
from langchain_anthropic import ChatAnthropic
from langgraph.prebuilt import create_react_agent
from langgraph.graph import add_messages
from langgraph.func import entrypoint, task
model = ChatAnthropic(model="claude-3-5-sonnet-latest")
# Define travel advisor ReAct agent
travel_advisor_tools = [
get_travel_recommendations,
transfer_to_hotel_advisor,
]
travel_advisor = create_react_agent(
model,
travel_advisor_tools,
prompt=(
"You are a general travel expert that can recommend travel destinations (e.g. countries, cities, etc). "
"If you need hotel recommendations, ask 'hotel_advisor' for help. "
"You MUST include human-readable response before transferring to another agent."
),
)
@task
def call_travel_advisor(messages):
# You can also add additional logic like changing the input to the agent / output from the agent, etc.
# NOTE: we're invoking the ReAct agent with the full history of messages in the state
response = travel_advisor.invoke({"messages": messages})
return response["messages"]
# Define hotel advisor ReAct agent
hotel_advisor_tools = [get_hotel_recommendations, transfer_to_travel_advisor]
hotel_advisor = create_react_agent(
model,
hotel_advisor_tools,
prompt=(
"You are a hotel expert that can provide hotel recommendations for a given destination. "
"If you need help picking travel destinations, ask 'travel_advisor' for help."
"You MUST include human-readable response before transferring to another agent."
),
)
@task
def call_hotel_advisor(messages):
response = hotel_advisor.invoke({"messages": messages})
return response["messages"]
@entrypoint()
def workflow(messages):
messages = add_messages([], messages)
call_active_agent = call_travel_advisor
while True:
agent_messages = call_active_agent(messages).result()
messages = add_messages(messages, agent_messages)
ai_msg = next(m for m in reversed(agent_messages) if isinstance(m, AIMessage))
if not ai_msg.tool_calls:
break
tool_call = ai_msg.tool_calls[-1]
if tool_call["name"] == "transfer_to_travel_advisor":
call_active_agent = call_travel_advisor
elif tool_call["name"] == "transfer_to_hotel_advisor":
call_active_agent = call_hotel_advisor
else:
raise ValueError(f"Expected transfer tool, got '{tool_call['name']}'")
return messages
最后,让我们定义一个辅助函数来渲染代理的输出:
API Reference: convert_to_messages
from langchain_core.messages import convert_to_messages
def pretty_print_messages(update):
if isinstance(update, tuple):
ns, update = update
# skip parent graph updates in the printouts
if len(ns) == 0:
return
graph_id = ns[-1].split(":")[0]
print(f"Update from subgraph {graph_id}:")
print("\n")
for node_name, node_update in update.items():
print(f"Update from node {node_name}:")
print("\n")
for m in convert_to_messages(node_update["messages"]):
m.pretty_print()
print("\n")
让我们使用与我们原始多智能体系统相同的输入来进行测试:
for chunk in workflow.stream(
[
{
"role": "user",
"content": "i wanna go somewhere warm in the caribbean. pick one destination and give me hotel recommendations",
}
],
subgraphs=True,
):
pretty_print_messages(chunk)
Update from subgraph call_travel_advisor:
Update from node agent:
================================== Ai Message ==================================
[{'text': "I'll help you find a warm Caribbean destination and then get some hotel recommendations for you.\n\nLet me first get some destination recommendations for the Caribbean region.", 'type': 'text'}, {'id': 'toolu_015vT8PkPq1VXvjrDvSpWUwJ', 'input': {}, 'name': 'get_travel_recommendations', 'type': 'tool_use'}]
Tool Calls:
get_travel_recommendations (toolu_015vT8PkPq1VXvjrDvSpWUwJ)
Call ID: toolu_015vT8PkPq1VXvjrDvSpWUwJ
Args:
Update from subgraph call_travel_advisor:
Update from node tools:
================================= Tool Message =================================
Name: get_travel_recommendations
turks and caicos
Update from subgraph call_travel_advisor:
Update from node agent:
================================== Ai Message ==================================
[{'text': "Based on the recommendation, I suggest Turks and Caicos! This beautiful British Overseas Territory is known for its stunning white-sand beaches, crystal-clear turquoise waters, and year-round warm weather. Grace Bay Beach in Providenciales is consistently ranked among the world's best beaches. The islands offer excellent snorkeling, diving, and water sports opportunities, plus a relaxed Caribbean atmosphere.\n\nNow, let me connect you with our hotel advisor to get some specific hotel recommendations for Turks and Caicos.", 'type': 'text'}, {'id': 'toolu_01JY7pNNWFuaWoe9ymxFYiPV', 'input': {}, 'name': 'transfer_to_hotel_advisor', 'type': 'tool_use'}]
Tool Calls:
transfer_to_hotel_advisor (toolu_01JY7pNNWFuaWoe9ymxFYiPV)
Call ID: toolu_01JY7pNNWFuaWoe9ymxFYiPV
Args:
Update from subgraph call_travel_advisor:
Update from node tools:
================================= Tool Message =================================
Name: transfer_to_hotel_advisor
Successfully transferred to hotel advisor
Update from subgraph call_hotel_advisor:
Update from node agent:
================================== Ai Message ==================================
[{'text': 'Let me get some hotel recommendations for Turks and Caicos:', 'type': 'text'}, {'id': 'toolu_0129ELa7jFocn16bowaGNapg', 'input': {'location': 'turks and caicos'}, 'name': 'get_hotel_recommendations', 'type': 'tool_use'}]
Tool Calls:
get_hotel_recommendations (toolu_0129ELa7jFocn16bowaGNapg)
Call ID: toolu_0129ELa7jFocn16bowaGNapg
Args:
location: turks and caicos
Update from subgraph call_hotel_advisor:
Update from node tools:
================================= Tool Message =================================
Name: get_hotel_recommendations
["Grace Bay Club", "COMO Parrot Cay"]
Update from subgraph call_hotel_advisor:
Update from node agent:
================================== Ai Message ==================================
Here are two excellent hotel options in Turks and Caicos:
1. Grace Bay Club: This luxury resort is located on the world-famous Grace Bay Beach. It offers all-oceanfront suites, exceptional dining options, and personalized service. The resort features adult-only and family-friendly sections, making it perfect for any type of traveler.
2. COMO Parrot Cay: This exclusive private island resort offers the ultimate luxury escape. It's known for its pristine beach, world-class spa, and holistic wellness programs. The resort provides an intimate, secluded experience with top-notch amenities and service.
Would you like more specific information about either of these properties or would you like to explore hotels in another destination?
Voila - travel_advisor
选择了一个目的地,然后决定调用 hotel_advisor
以获取更多信息!