这里写目录标题
工具定义
import random
from typing import Annotated, Literal
from langchain_core.tools import tool
from langchain_core.tools.base import InjectedToolCallId
from langgraph.prebuilt import InjectedState
from langgraph.types import Command
@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]
def make_handoff_tool(*, agent_name: str):
"""Create a tool that can return handoff via a Command"""
tool_name = f"transfer_to_{agent_name}"
@tool(tool_name)
def handoff_to_agent(
state: Annotated[dict, InjectedState],
tool_call_id: Annotated[str, InjectedToolCallId],
):
"""Ask another agent for help."""
tool_message = {
"role": "tool",
"content": f"Successfully transferred to {agent_name}",
"name": tool_name,
"tool_call_id": tool_call_id,
}
return Command(
# navigate to another agent node in the PARENT graph
goto=agent_name,
graph=Command.PARENT,
# This is the state update that the agent `agent_name` will see when it is invoked.
# We're passing agent's FULL internal message history AND adding a tool message to make sure
# the resulting chat history is valid.
update={"messages": state["messages"] + [tool_message]},
)
return handoff_to_agent
模型选择
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
temperature=0,
model="GLM-4-PLUS",
openai_api_key="your api key",
openai_api_base="https://open.bigmodel.cn/api/paas/v4/"
)
graph节点函数定义
from langgraph.graph import MessagesState, StateGraph, START
from langgraph.prebuilt import create_react_agent, InjectedState
from langgraph.types import Command, interrupt
from langgraph.checkpoint.memory import MemorySaver
# Define travel advisor tools and ReAct agent
travel_advisor_tools = [
get_travel_recommendations,
make_handoff_tool(agent_name="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."
),
)
def call_travel_advisor(
state: MessagesState,
) -> Command[Literal["hotel_advisor", "human"]]:
# 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(state)
return Command(update=response, goto="human")
# Define hotel advisor tools and ReAct agent
hotel_advisor_tools = [
get_hotel_recommendations,
make_handoff_tool(agent_name="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."
),
)
def call_hotel_advisor(
state: MessagesState,
) -> Command[Literal["travel_advisor", "human"]]:
response = hotel_advisor.invoke(state)
return Command(update=response, goto="human")
def human_node(
state: MessagesState, config
) -> Command[Literal["hotel_advisor", "travel_advisor", "human"]]:
"""A node for collecting user input."""
user_input = input("Ready for user input.")
# identify the last active agent
# (the last active node before returning to human)
langgraph_triggers = config["metadata"]["langgraph_triggers"]
if len(langgraph_triggers) != 1:
raise AssertionError("Expected exactly 1 trigger in human node")
active_agent = langgraph_triggers[0].split(":")[1]
return Command(
update={
"messages": [
{
"role": "human",
"content": user_input,
}
]
},
goto=active_agent,
)
builder = StateGraph(MessagesState)
builder.add_node("travel_advisor", call_travel_advisor)
builder.add_node("hotel_advisor", call_hotel_advisor)
# This adds a node to collect human input, which will route
# back to the active agent.
builder.add_node("human", human_node)
# We'll always start with a general travel advisor.
builder.add_edge(START, "travel_advisor")
checkpointer = MemorySaver()
graph = builder.compile(checkpointer=checkpointer)
Graph可视化
from IPython.display import display, Image
display(Image(graph.get_graph().draw_mermaid_png()))
graph 运行
import uuid
thread_config = {"configurable": {"thread_id": uuid.uuid4()}}
user_input = {
"messages": [
{"role": "user", "content": "i wanna go somewhere warm in the caribbean"}
]
}
for update in graph.stream(
user_input,
config=thread_config,
stream_mode="updates",
):
for node_id, value in update.items():
print(f"{node_id}: {value}")
travel_advisor: {'messages': [HumanMessage(content='i wanna go somewhere warm in the caribbean', additional_kwargs={}, response_metadata={}, id='b7a9d8a8-f569-464a-8942-c98f477b8ce2'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_-9024507181658326780', 'function': {'arguments': '{}', 'name': 'get_travel_recommendations'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 7, 'prompt_tokens': 203, 'total_tokens': 210, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-9ed5c54c-2540-41d2-9704-769075778a98-0', tool_calls=[{'name': 'get_travel_recommendations', 'args': {}, 'id': 'call_-9024507181658326780', 'type': 'tool_call'}], usage_metadata={'input_tokens': 203, 'output_tokens': 7, 'total_tokens': 210, 'input_token_details': {}, 'output_token_details': {}}), ToolMessage(content='turks and caicos', name='get_travel_recommendations', id='9dbe9001-1341-40fd-a431-b391bcfab0d8', tool_call_id='call_-9024507181658326780'), AIMessage(content="For a warm getaway in the Caribbean, I recommend visiting Turks and Caicos. It's known for its beautiful beaches and pleasant climate. Would you like hotel recommendations for Turks and Caicos? If so, I can ask the hotel advisor for assistance.", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 52, 'prompt_tokens': 217, 'total_tokens': 269, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-aed9c540-eb16-4782-8dc2-aae47932df30-0', usage_metadata={'input_tokens': 217, 'output_tokens': 52, 'total_tokens': 269, 'input_token_details': {}, 'output_token_details': {}})]}
human: {'messages': [{'role': 'human', 'content': 'hotel recommendation'}]}
travel_advisor: {'messages': [HumanMessage(content='i wanna go somewhere warm in the caribbean', additional_kwargs={}, response_metadata={}, id='b7a9d8a8-f569-464a-8942-c98f477b8ce2'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_-9024507181658326780', 'function': {'arguments': '{}', 'name': 'get_travel_recommendations'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 7, 'prompt_tokens': 203, 'total_tokens': 210, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-9ed5c54c-2540-41d2-9704-769075778a98-0', tool_calls=[{'name': 'get_travel_recommendations', 'args': {}, 'id': 'call_-9024507181658326780', 'type': 'tool_call'}], usage_metadata={'input_tokens': 203, 'output_tokens': 7, 'total_tokens': 210, 'input_token_details': {}, 'output_token_details': {}}), ToolMessage(content='turks and caicos', name='get_travel_recommendations', id='9dbe9001-1341-40fd-a431-b391bcfab0d8', tool_call_id='call_-9024507181658326780'), AIMessage(content="For a warm getaway in the Caribbean, I recommend visiting Turks and Caicos. It's known for its beautiful beaches and pleasant climate. Would you like hotel recommendations for Turks and Caicos? If so, I can ask the hotel advisor for assistance.", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 52, 'prompt_tokens': 217, 'total_tokens': 269, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-aed9c540-eb16-4782-8dc2-aae47932df30-0', usage_metadata={'input_tokens': 217, 'output_tokens': 52, 'total_tokens': 269, 'input_token_details': {}, 'output_token_details': {}}), HumanMessage(content='hotel recommendation', additional_kwargs={}, response_metadata={}, id='931caa5f-a5c7-4c4c-991a-d7e3843c7aa6'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_-9024511201749198020', 'function': {'arguments': '{}', 'name': 'transfer_to_hotel_advisor'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 9, 'prompt_tokens': 273, 'total_tokens': 282, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-92da714d-1d8c-4a96-b6c8-3b0d2ac916c6-0', tool_calls=[{'name': 'transfer_to_hotel_advisor', 'args': {}, 'id': 'call_-9024511201749198020', 'type': 'tool_call'}], usage_metadata={'input_tokens': 273, 'output_tokens': 9, 'total_tokens': 282, 'input_token_details': {}, 'output_token_details': {}}), {'role': 'tool', 'content': 'Successfully transferred to hotel_advisor', 'name': 'transfer_to_hotel_advisor', 'tool_call_id': 'call_-9024511201749198020'}]}
hotel_advisor: {'messages': [HumanMessage(content='i wanna go somewhere warm in the caribbean', additional_kwargs={}, response_metadata={}, id='b7a9d8a8-f569-464a-8942-c98f477b8ce2'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_-9024507181658326780', 'function': {'arguments': '{}', 'name': 'get_travel_recommendations'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 7, 'prompt_tokens': 203, 'total_tokens': 210, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-9ed5c54c-2540-41d2-9704-769075778a98-0', tool_calls=[{'name': 'get_travel_recommendations', 'args': {}, 'id': 'call_-9024507181658326780', 'type': 'tool_call'}], usage_metadata={'input_tokens': 203, 'output_tokens': 7, 'total_tokens': 210, 'input_token_details': {}, 'output_token_details': {}}), ToolMessage(content='turks and caicos', name='get_travel_recommendations', id='9dbe9001-1341-40fd-a431-b391bcfab0d8', tool_call_id='call_-9024507181658326780'), AIMessage(content="For a warm getaway in the Caribbean, I recommend visiting Turks and Caicos. It's known for its beautiful beaches and pleasant climate. Would you like hotel recommendations for Turks and Caicos? If so, I can ask the hotel advisor for assistance.", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 52, 'prompt_tokens': 217, 'total_tokens': 269, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-aed9c540-eb16-4782-8dc2-aae47932df30-0', usage_metadata={'input_tokens': 217, 'output_tokens': 52, 'total_tokens': 269, 'input_token_details': {}, 'output_token_details': {}}), HumanMessage(content='hotel recommendation', additional_kwargs={}, response_metadata={}, id='931caa5f-a5c7-4c4c-991a-d7e3843c7aa6'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_-9024511201749198020', 'function': {'arguments': '{}', 'name': 'transfer_to_hotel_advisor'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 9, 'prompt_tokens': 273, 'total_tokens': 282, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-92da714d-1d8c-4a96-b6c8-3b0d2ac916c6-0', tool_calls=[{'name': 'transfer_to_hotel_advisor', 'args': {}, 'id': 'call_-9024511201749198020', 'type': 'tool_call'}], usage_metadata={'input_tokens': 273, 'output_tokens': 9, 'total_tokens': 282, 'input_token_details': {}, 'output_token_details': {}}), ToolMessage(content='Successfully transferred to hotel_advisor', name='transfer_to_hotel_advisor', id='ce44c5c6-0fa4-4d7e-9452-60399000e83f', tool_call_id='call_-9024511201749198020'), AIMessage(content="I've transferred your request to the hotel advisor who will provide you with hotel recommendations for Turks and Caicos. They will assist you in finding the perfect accommodation for your warm Caribbean getaway.", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 39, 'prompt_tokens': 334, 'total_tokens': 373, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-08b49c36-2726-4935-bf7e-ed6149d03f00-0', usage_metadata={'input_tokens': 334, 'output_tokens': 39, 'total_tokens': 373, 'input_token_details': {}, 'output_token_details': {}})]}
human: {'messages': [{'role': 'human', 'content': 'Well, give me some hotel recom'}]}
hotel_advisor: {'messages': [HumanMessage(content='i wanna go somewhere warm in the caribbean', additional_kwargs={}, response_metadata={}, id='b7a9d8a8-f569-464a-8942-c98f477b8ce2'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_-9024507181658326780', 'function': {'arguments': '{}', 'name': 'get_travel_recommendations'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 7, 'prompt_tokens': 203, 'total_tokens': 210, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-9ed5c54c-2540-41d2-9704-769075778a98-0', tool_calls=[{'name': 'get_travel_recommendations', 'args': {}, 'id': 'call_-9024507181658326780', 'type': 'tool_call'}], usage_metadata={'input_tokens': 203, 'output_tokens': 7, 'total_tokens': 210, 'input_token_details': {}, 'output_token_details': {}}), ToolMessage(content='turks and caicos', name='get_travel_recommendations', id='9dbe9001-1341-40fd-a431-b391bcfab0d8', tool_call_id='call_-9024507181658326780'), AIMessage(content="For a warm getaway in the Caribbean, I recommend visiting Turks and Caicos. It's known for its beautiful beaches and pleasant climate. Would you like hotel recommendations for Turks and Caicos? If so, I can ask the hotel advisor for assistance.", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 52, 'prompt_tokens': 217, 'total_tokens': 269, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-aed9c540-eb16-4782-8dc2-aae47932df30-0', usage_metadata={'input_tokens': 217, 'output_tokens': 52, 'total_tokens': 269, 'input_token_details': {}, 'output_token_details': {}}), HumanMessage(content='hotel recommendation', additional_kwargs={}, response_metadata={}, id='931caa5f-a5c7-4c4c-991a-d7e3843c7aa6'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_-9024511201749198020', 'function': {'arguments': '{}', 'name': 'transfer_to_hotel_advisor'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 9, 'prompt_tokens': 273, 'total_tokens': 282, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-92da714d-1d8c-4a96-b6c8-3b0d2ac916c6-0', tool_calls=[{'name': 'transfer_to_hotel_advisor', 'args': {}, 'id': 'call_-9024511201749198020', 'type': 'tool_call'}], usage_metadata={'input_tokens': 273, 'output_tokens': 9, 'total_tokens': 282, 'input_token_details': {}, 'output_token_details': {}}), ToolMessage(content='Successfully transferred to hotel_advisor', name='transfer_to_hotel_advisor', id='ce44c5c6-0fa4-4d7e-9452-60399000e83f', tool_call_id='call_-9024511201749198020'), AIMessage(content="I've transferred your request to the hotel advisor who will provide you with hotel recommendations for Turks and Caicos. They will assist you in finding the perfect accommodation for your warm Caribbean getaway.", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 39, 'prompt_tokens': 334, 'total_tokens': 373, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-08b49c36-2726-4935-bf7e-ed6149d03f00-0', usage_metadata={'input_tokens': 334, 'output_tokens': 39, 'total_tokens': 373, 'input_token_details': {}, 'output_token_details': {}}), HumanMessage(content='Well, give me some hotel recom', additional_kwargs={}, response_metadata={}, id='8a6d6e7f-5d26-4c77-aa7c-95485581e7e4'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_-9024517077266482785', 'function': {'arguments': '{"location": "turks and caicos"}', 'name': 'get_hotel_recommendations'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 17, 'prompt_tokens': 382, 'total_tokens': 399, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-b072e101-db1e-4809-b87d-d767df0e9f10-0', tool_calls=[{'name': 'get_hotel_recommendations', 'args': {'location': 'turks and caicos'}, 'id': 'call_-9024517077266482785', 'type': 'tool_call'}], usage_metadata={'input_tokens': 382, 'output_tokens': 17, 'total_tokens': 399, 'input_token_details': {}, 'output_token_details': {}}), ToolMessage(content='["Grace Bay Club", "COMO Parrot Cay"]', name='get_hotel_recommendations', id='45cc7ee3-9d7e-4df5-aacc-914878812d5b', tool_call_id='call_-9024517077266482785'), AIMessage(content='Here are some hotel recommendations for Turks and Caicos:\n\n1. Grace Bay Club\n2. COMO Parrot Cay\n\nThese hotels are known for their excellent amenities and beautiful locations. Enjoy your stay in Turks and Caicos!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 48, 'prompt_tokens': 413, 'total_tokens': 461, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-PLUS', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-76dc546c-5272-48cc-ae1b-63437bf6051f-0', usage_metadata={'input_tokens': 413, 'output_tokens': 48, 'total_tokens': 461, 'input_token_details': {}, 'output_token_details': {}})]}
human: {'messages': [{'role': 'human', 'content': ''}]}
参考链接:https://langchain-ai.github.io/langgraph/how-tos/multi-agent-multi-turn-convo-functional/