导入必要的库和设置工具
首先,我们需要导入一些必要的库,并设置我们的工具。这些工具将用于在Spotify和Apple Music上播放歌曲。
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langgraph.graph import MessagesState, START
from langgraph.prebuilt import ToolNode
from langgraph.graph import END, StateGraph
from langgraph.checkpoint.memory import MemorySaver
接下来,我们定义两个工具函数,一个用于在Spotify上播放歌曲,另一个用于在Apple Music上播放歌曲。
@tool
def play_song_on_spotify(song: str):
"""Play a song on Spotify"""
return f"Successfully played {song} on Spotify!"
@tool
def play_song_on_apple(song: str):
"""Play a song on Apple Music"""
return f"Successfully played {song} on Apple Music!"
然后,我们将这些工具封装在一个ToolNode
中,并设置我们的模型。
tools = [play_song_on_apple, play_song_on_spotify]
tool_node = ToolNode(tools)
model = ChatOpenAI(openai_api_base="https://api.lingyiwanwu.com/v1", openai_api_key="YOUR_API_KEY", model="yi-large-fc")
model = model.bind_tools(tools, parallel_tool_calls=False)
定义工作流和状态图
现在,我们将定义一个工作流,该工作流将包含一个代理节点和一个动作节点。代理节点将调用模型,而动作节点将执行工具函数。
def should_continue(state):
messages = state["messages"]
last_message = messages[-1]
if not last_message.tool_calls:
return "end"
else:
return "continue"
def call_model(state):
messages = state["messages"]
response = model.invoke(messages)
return {"messages": [response]}
workflow = StateGraph(MessagesState)
workflow.add_node("agent", call_model)
workflow.add_node("action", tool_node)
workflow.add_edge(START, "agent")
workflow.add_conditional_edges(
"agent",
should_continue,
{
"continue": "action",
"end": END,
},
)
workflow.add_edge("action", "agent")
memory = MemorySaver()
app = workflow.compile(checkpointer=memory)
我们可以使用draw_mermaid_png
方法来可视化这个状态图。
from IPython.display import Image, display
display(Image(app.get_graph().draw_mermaid_png()))
运行工作流
现在,我们可以运行我们的工作流了。我们首先创建一个HumanMessage
对象,然后将其传递给我们的应用。
from langchain_core.messages import HumanMessage
config = {"configurable": {"thread_id": "1"}}
input_message = HumanMessage(content="Can you play Taylor Swift's most popular song?")
for event in app.stream({"messages": [input_message]}, config, stream_mode="values"):
event["messages"][-1].pretty_print()
================================[1m Human Message [0m=================================
Can you play Taylor Swift's most popular song?
==================================[1m Ai Message [0m==================================
Tool Calls:
play_song_on_spotify (call_2xNBN9YmS_GUhm7XFNP3dw)
Call ID: call_2xNBN9YmS_GUhm7XFNP3dw
Args:
song: Taylor Swift's most popular song
=================================[1m Tool Message [0m=================================
Name: play_song_on_spotify
Successfully played Taylor Swift's most popular song on Spotify!
==================================[1m Ai Message [0m==================================
I have successfully played Taylor Swift's most popular song on Spotify!
查看和更新状态
我们可以使用get_state
方法来查看应用的当前状态,并使用get_state_history
方法来查看状态历史。
app.get_state(config).values["messages"]
[HumanMessage(content="Can you play Taylor Swift's most popular song?", additional_kwargs={}, response_metadata={}, id='eecdf1a1-e6b4-4a13-b4e9-9c478ca96c55'),
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'function': {'arguments': '{"song":"Taylor Swift\'s most popular song"}', 'name': 'play_song_on_spotify'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 33, 'prompt_tokens': 22, 'total_tokens': 55, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'yi-large-fc', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-d7dc8d82-dd8d-47c0-94a8-5bc7a2ca5af2-0', tool_calls=[{'name': 'play_song_on_spotify', 'args': {'song': "Taylor Swift's most popular song"}, 'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'type': 'tool_call'}], usage_metadata={'input_tokens': 22, 'output_tokens': 33, 'total_tokens': 55, 'input_token_details': {}, 'output_token_details': {}}),
ToolMessage(content="Successfully played Taylor Swift's most popular song on Spotify!", name='play_song_on_spotify', id='31c7cd35-b414-49ff-8ce8-72f4fbfd8f81', tool_call_id='call_2xNBN9YmS_GUhm7XFNP3dw'),
AIMessage(content="I have successfully played Taylor Swift's most popular song on Spotify! ", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 17, 'prompt_tokens': 68, 'total_tokens': 85, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'yi-large-fc', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-9e58f0c3-d4de-417a-bafa-7c448c5c3ede-0', usage_metadata={'input_tokens': 68, 'output_tokens': 17, 'total_tokens': 85, 'input_token_details': {}, 'output_token_details': {}})]
all_states = []
for state in app.get_state_history(config):
print(state)
all_states.append(state)
print("--")
StateSnapshot(values={'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?", additional_kwargs={}, response_metadata={}, id='eecdf1a1-e6b4-4a13-b4e9-9c478ca96c55'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'function': {'arguments': '{"song":"Taylor Swift\'s most popular song"}', 'name': 'play_song_on_spotify'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 33, 'prompt_tokens': 22, 'total_tokens': 55, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'yi-large-fc', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-d7dc8d82-dd8d-47c0-94a8-5bc7a2ca5af2-0', tool_calls=[{'name': 'play_song_on_spotify', 'args': {'song': "Taylor Swift's most popular song"}, 'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'type': 'tool_call'}], usage_metadata={'input_tokens': 22, 'output_tokens': 33, 'total_tokens': 55, 'input_token_details': {}, 'output_token_details': {}}), ToolMessage(content="Successfully played Taylor Swift's most popular song on Spotify!", name='play_song_on_spotify', id='31c7cd35-b414-49ff-8ce8-72f4fbfd8f81', tool_call_id='call_2xNBN9YmS_GUhm7XFNP3dw'), AIMessage(content="I have successfully played Taylor Swift's most popular song on Spotify! ", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 17, 'prompt_tokens': 68, 'total_tokens': 85, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'yi-large-fc', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-9e58f0c3-d4de-417a-bafa-7c448c5c3ede-0', usage_metadata={'input_tokens': 68, 'output_tokens': 17, 'total_tokens': 85, 'input_token_details': {}, 'output_token_details': {}})]}, next=(), config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1efa1985-b182-61d6-8003-07e9a72803a6'}}, metadata={'source': 'loop', 'writes': {'agent': {'messages': [AIMessage(content="I have successfully played Taylor Swift's most popular song on Spotify! ", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 17, 'prompt_tokens': 68, 'total_tokens': 85, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'yi-large-fc', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-9e58f0c3-d4de-417a-bafa-7c448c5c3ede-0', usage_metadata={'input_tokens': 68, 'output_tokens': 17, 'total_tokens': 85, 'input_token_details': {}, 'output_token_details': {}})]}}, 'step': 3, 'parents': {}}, created_at='2024-11-13T08:22:00.718383+00:00', parent_config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1efa1985-a322-6b97-8002-91857b204400'}}, tasks=())
--
StateSnapshot(values={'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?", additional_kwargs={}, response_metadata={}, id='eecdf1a1-e6b4-4a13-b4e9-9c478ca96c55'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'function': {'arguments': '{"song":"Taylor Swift\'s most popular song"}', 'name': 'play_song_on_spotify'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 33, 'prompt_tokens': 22, 'total_tokens': 55, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'yi-large-fc', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-d7dc8d82-dd8d-47c0-94a8-5bc7a2ca5af2-0', tool_calls=[{'name': 'play_song_on_spotify', 'args': {'song': "Taylor Swift's most popular song"}, 'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'type': 'tool_call'}], usage_metadata={'input_tokens': 22, 'output_tokens': 33, 'total_tokens': 55, 'input_token_details': {}, 'output_token_details': {}}), ToolMessage(content="Successfully played Taylor Swift's most popular song on Spotify!", name='play_song_on_spotify', id='31c7cd35-b414-49ff-8ce8-72f4fbfd8f81', tool_call_id='call_2xNBN9YmS_GUhm7XFNP3dw')]}, next=('agent',), config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1efa1985-a322-6b97-8002-91857b204400'}}, metadata={'source': 'loop', 'writes': {'action': {'messages': [ToolMessage(content="Successfully played Taylor Swift's most popular song on Spotify!", name='play_song_on_spotify', id='31c7cd35-b414-49ff-8ce8-72f4fbfd8f81', tool_call_id='call_2xNBN9YmS_GUhm7XFNP3dw')]}}, 'step': 2, 'parents': {}}, created_at='2024-11-13T08:21:59.211304+00:00', parent_config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1efa1985-a31b-66bf-8001-6b59c0db8cfe'}}, tasks=(PregelTask(id='f1463cbd-8f99-eea6-67cc-6c721fced5e4', name='agent', path=('__pregel_pull', 'agent'), error=None, interrupts=(), state=None, result={'messages': [AIMessage(content="I have successfully played Taylor Swift's most popular song on Spotify! ", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 17, 'prompt_tokens': 68, 'total_tokens': 85, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'yi-large-fc', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-9e58f0c3-d4de-417a-bafa-7c448c5c3ede-0', usage_metadata={'input_tokens': 68, 'output_tokens': 17, 'total_tokens': 85, 'input_token_details': {}, 'output_token_details': {}})]}),))
--
StateSnapshot(values={'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?", additional_kwargs={}, response_metadata={}, id='eecdf1a1-e6b4-4a13-b4e9-9c478ca96c55'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'function': {'arguments': '{"song":"Taylor Swift\'s most popular song"}', 'name': 'play_song_on_spotify'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 33, 'prompt_tokens': 22, 'total_tokens': 55, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'yi-large-fc', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-d7dc8d82-dd8d-47c0-94a8-5bc7a2ca5af2-0', tool_calls=[{'name': 'play_song_on_spotify', 'args': {'song': "Taylor Swift's most popular song"}, 'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'type': 'tool_call'}], usage_metadata={'input_tokens': 22, 'output_tokens': 33, 'total_tokens': 55, 'input_token_details': {}, 'output_token_details': {}})]}, next=('action',), config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1efa1985-a31b-66bf-8001-6b59c0db8cfe'}}, metadata={'source': 'loop', 'writes': {'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'function': {'arguments': '{"song":"Taylor Swift\'s most popular song"}', 'name': 'play_song_on_spotify'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 33, 'prompt_tokens': 22, 'total_tokens': 55, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'yi-large-fc', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-d7dc8d82-dd8d-47c0-94a8-5bc7a2ca5af2-0', tool_calls=[{'name': 'play_song_on_spotify', 'args': {'song': "Taylor Swift's most popular song"}, 'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'type': 'tool_call'}], usage_metadata={'input_tokens': 22, 'output_tokens': 33, 'total_tokens': 55, 'input_token_details': {}, 'output_token_details': {}})]}}, 'step': 1, 'parents': {}}, created_at='2024-11-13T08:21:59.208313+00:00', parent_config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1efa1985-8a73-6a65-8000-0b9a2c5c2c0e'}}, tasks=(PregelTask(id='bf19a6f7-20fa-d472-3b76-cfb22f386a5d', name='action', path=('__pregel_pull', 'action'), error=None, interrupts=(), state=None, result={'messages': [ToolMessage(content="Successfully played Taylor Swift's most popular song on Spotify!", name='play_song_on_spotify', id='31c7cd35-b414-49ff-8ce8-72f4fbfd8f81', tool_call_id='call_2xNBN9YmS_GUhm7XFNP3dw')]}),))
--
StateSnapshot(values={'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?", additional_kwargs={}, response_metadata={}, id='eecdf1a1-e6b4-4a13-b4e9-9c478ca96c55')]}, next=('agent',), config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1efa1985-8a73-6a65-8000-0b9a2c5c2c0e'}}, metadata={'source': 'loop', 'writes': None, 'step': 0, 'parents': {}}, created_at='2024-11-13T08:21:56.623011+00:00', parent_config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1efa1985-8a6e-6c89-bfff-69f5d699568e'}}, tasks=(PregelTask(id='a4faf1b9-d4e2-bc5a-ae11-1ff31b8a719a', name='agent', path=('__pregel_pull', 'agent'), error=None, interrupts=(), state=None, result={'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'function': {'arguments': '{"song":"Taylor Swift\'s most popular song"}', 'name': 'play_song_on_spotify'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 33, 'prompt_tokens': 22, 'total_tokens': 55, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'yi-large-fc', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-d7dc8d82-dd8d-47c0-94a8-5bc7a2ca5af2-0', tool_calls=[{'name': 'play_song_on_spotify', 'args': {'song': "Taylor Swift's most popular song"}, 'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'type': 'tool_call'}], usage_metadata={'input_tokens': 22, 'output_tokens': 33, 'total_tokens': 55, 'input_token_details': {}, 'output_token_details': {}})]}),))
--
StateSnapshot(values={'messages': []}, next=('__start__',), config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1efa1985-8a6e-6c89-bfff-69f5d699568e'}}, metadata={'source': 'input', 'writes': {'__start__': {'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?", additional_kwargs={}, response_metadata={})]}}, 'step': -1, 'parents': {}}, created_at='2024-11-13T08:21:56.621018+00:00', parent_config=None, tasks=(PregelTask(id='c154f1c6-2dbb-9cf0-197d-cdbd0f566dd7', name='__start__', path=('__pregel_pull', '__start__'), error=None, interrupts=(), state=None, result={'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?", additional_kwargs={}, response_metadata={}, id='eecdf1a1-e6b4-4a13-b4e9-9c478ca96c55')]}),))
--
我们可以选择一个状态进行重放,或者更新状态并重新运行工作流。
to_replay = all_states[2]
to_replay.values
{'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?", additional_kwargs={}, response_metadata={}, id='eecdf1a1-e6b4-4a13-b4e9-9c478ca96c55'),
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'function': {'arguments': '{"song":"Taylor Swift\'s most popular song"}', 'name': 'play_song_on_spotify'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 33, 'prompt_tokens': 22, 'total_tokens': 55, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'yi-large-fc', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-d7dc8d82-dd8d-47c0-94a8-5bc7a2ca5af2-0', tool_calls=[{'name': 'play_song_on_spotify', 'args': {'song': "Taylor Swift's most popular song"}, 'id': 'call_2xNBN9YmS_GUhm7XFNP3dw', 'type': 'tool_call'}], usage_metadata={'input_tokens': 22, 'output_tokens': 33, 'total_tokens': 55, 'input_token_details': {}, 'output_token_details': {}})]}
for event in app.stream(None, to_replay.config):
for v in event.values():
print(v)
{'messages': [ToolMessage(content="Successfully played Taylor Swift's most popular song on Spotify!", name='play_song_on_spotify', id='dbd6cda4-78f2-4874-bbca-99318fd79d46', tool_call_id='call_2xNBN9YmS_GUhm7XFNP3dw')]}
{'messages': [AIMessage(content="I have played Taylor Swift's most popular song on Spotify. Enjoy! ", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 18, 'prompt_tokens': 68, 'total_tokens': 86, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'yi-large-fc', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-5e138398-87ab-408e-a21c-d1883dcff442-0', usage_metadata={'input_tokens': 68, 'output_tokens': 18, 'total_tokens': 86, 'input_token_details': {}, 'output_token_details': {}})]}
我们可以通过更新状态中的消息来改变工作流的行为。
last_message = to_replay.values["messages"][-1]
last_message.tool_calls[0]["name"] = "play_song_on_apple"
branch_config = app.update_state(
to_replay.config,
{"messages": [last_message]},
)
for event in app.stream(None, branch_config):
for v in event.values():
print(v)
{'messages': [ToolMessage(content="Successfully played Taylor Swift's most popular song on Apple Music!", name='play_song_on_apple', id='25c9c1a7-935f-44ea-a8c5-a3dda3497578', tool_call_id='call_2xNBN9YmS_GUhm7XFNP3dw')]}
{'messages': [AIMessage(content="I have successfully played Taylor Swift's most popular song on Apple Music for you! ", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 19, 'prompt_tokens': 68, 'total_tokens': 87, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'yi-large-fc', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-7f8c8d4e-21ab-46ad-854d-53e42b47599c-0', usage_metadata={'input_tokens': 68, 'output_tokens': 19, 'total_tokens': 87, 'input_token_details': {}, 'output_token_details': {}})]}
我们也可以完全替换状态中的消息。
from langchain_core.messages import AIMessage
last_message = to_replay.values["messages"][-1]
new_message = AIMessage(
content="It's quiet hours so I can't play any music right now!", id=last_message.id
)
branch_config = app.update_state(
to_replay.config,
{"messages": [new_message]},
)
branch_state = app.get_state(branch_config)
branch_state.values
{'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?", additional_kwargs={}, response_metadata={}, id='eecdf1a1-e6b4-4a13-b4e9-9c478ca96c55'),
AIMessage(content="It's quiet hours so I can't play any music right now!", additional_kwargs={}, response_metadata={}, id='run-d7dc8d82-dd8d-47c0-94a8-5bc7a2ca5af2-0')]}
branch_state.next
()
通过这些步骤,我们可以看到如何使用LangChain和LangGraph来创建、运行和更新一个音乐播放的工作流。
参考链接:https://langchain-ai.github.io/langgraph/how-tos/human_in_the_loop/time-travel/#replay-a-state