如何查看和更新过去的图状态¶
一旦你开始检查点你的图,你就可以轻松地获取或更新代理在任何时间点的状态。这允许一些事情
- 你可以在中断时向用户展示状态,让他们接受操作。
- 你可以倒带图以重现或避免问题。
- 你可以修改状态,将你的代理嵌入到更大的系统中,或让用户更好地控制其操作。
用于此功能的关键方法是
- get_state: 从目标配置中获取值
- update_state: 将给定的值应用于目标状态
注意:这需要传入一个检查点器。
以下是一个快速示例。
设置¶
首先,我们需要安装所需的包
在 [1]
已复制!
%%capture --no-stderr
%pip install --quiet -U langgraph langchain_openai
%%capture --no-stderr %pip install --quiet -U langgraph langchain_openai
接下来,我们需要为 OpenAI(我们将使用的 LLM)设置 API 密钥
在 [2]
已复制!
import getpass
import os
def _set_env(var: str):
if not os.environ.get(var):
os.environ[var] = getpass.getpass(f"{var}: ")
_set_env("OPENAI_API_KEY")
import getpass import os def _set_env(var: str): if not os.environ.get(var): os.environ[var] = getpass.getpass(f"{var}: ") _set_env("OPENAI_API_KEY")
ANTHROPIC_API_KEY: ········
构建代理¶
我们现在可以构建代理。我们将构建一个相对简单的 ReAct 风格的代理,它进行工具调用。我们将使用 Anthropic 的模型和假工具(仅用于演示目的)。
在 [42]
已复制!
# Set up the tool
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
@tool
def play_song_on_spotify(song: str):
"""Play a song on Spotify"""
# Call the spotify API ...
return f"Successfully played {song} on Spotify!"
@tool
def play_song_on_apple(song: str):
"""Play a song on Apple Music"""
# Call the apple music API ...
return f"Successfully played {song} on Apple Music!"
tools = [play_song_on_apple, play_song_on_spotify]
tool_node = ToolNode(tools)
# Set up the model
model = ChatOpenAI(model="gpt-4o-mini")
model = model.bind_tools(tools, parallel_tool_calls=False)
# Define nodes and conditional edges
# Define the function that determines whether to continue or not
def should_continue(state):
messages = state["messages"]
last_message = messages[-1]
# If there is no function call, then we finish
if not last_message.tool_calls:
return "end"
# Otherwise if there is, we continue
else:
return "continue"
# Define the function that calls the model
def call_model(state):
messages = state["messages"]
response = model.invoke(messages)
# We return a list, because this will get added to the existing list
return {"messages": [response]}
# Define a new graph
workflow = StateGraph(MessagesState)
# Define the two nodes we will cycle between
workflow.add_node("agent", call_model)
workflow.add_node("action", tool_node)
# Set the entrypoint as `agent`
# This means that this node is the first one called
workflow.add_edge(START, "agent")
# We now add a conditional edge
workflow.add_conditional_edges(
# First, we define the start node. We use `agent`.
# This means these are the edges taken after the `agent` node is called.
"agent",
# Next, we pass in the function that will determine which node is called next.
should_continue,
# Finally we pass in a mapping.
# The keys are strings, and the values are other nodes.
# END is a special node marking that the graph should finish.
# What will happen is we will call `should_continue`, and then the output of that
# will be matched against the keys in this mapping.
# Based on which one it matches, that node will then be called.
{
# If `tools`, then we call the tool node.
"continue": "action",
# Otherwise we finish.
"end": END,
},
)
# We now add a normal edge from `tools` to `agent`.
# This means that after `tools` is called, `agent` node is called next.
workflow.add_edge("action", "agent")
# Set up memory
memory = MemorySaver()
# Finally, we compile it!
# This compiles it into a LangChain Runnable,
# meaning you can use it as you would any other runnable
# We add in `interrupt_before=["action"]`
# This will add a breakpoint before the `action` node is called
app = workflow.compile(checkpointer=memory)
# 设置来自 langchain_openai 的工具 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 @tool def play_song_on_spotify(song: str): """在 Spotify 上播放歌曲""" # 调用 Spotify API ... return f"已成功在 Spotify 上播放 {song}!" @tool def play_song_on_apple(song: str): """在 Apple Music 上播放歌曲""" # 调用 Apple Music API ... return f"已成功在 Apple Music 上播放 {song}!" tools = [play_song_on_apple, play_song_on_spotify] tool_node = ToolNode(tools) # 设置模型 model = ChatOpenAI(model="gpt-4o-mini") 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) # 将入口点设置为 `agent` # 这意味着此节点是第一个被调用的节点 workflow.add_edge(START, "agent") # 我们现在添加一个条件边 workflow.add_conditional_edges( # 首先,我们定义起始节点。我们使用 `agent`。 # 这意味着这些是在调用 `agent` 节点后采取的边。 "agent", # 接下来,我们传入一个函数,它将确定调用哪个节点。 should_continue, # 最后,我们传入一个映射。 # 键是字符串,值是其他节点。 # END 是一个特殊的节点,表示图应该结束。 # 将发生的事情是我们将调用 `should_continue`,然后其输出 # 将与该映射中的键进行匹配。 # 基于它匹配的内容,将调用该节点。 { # 如果是 `tools`,则我们调用工具节点。 "continue": "action", # 否则我们结束。 "end": END, }, ) # 我们现在从 `tools` 添加一个普通边到 `agent`。 # 这意味着在调用 `tools` 后,将下一个调用 `agent` 节点。 workflow.add_edge("action", "agent") # 设置内存 memory = MemorySaver() # 最后,我们编译它! # 这将其编译成一个 LangChain 可运行对象, # 意味着你可以像使用任何其他可运行对象一样使用它 # 我们添加 `interrupt_before=["action"]` # 这将在调用 `action` 节点之前添加一个断点 app = workflow.compile(checkpointer=memory)
与代理交互¶
我们现在可以与代理交互。让我们询问它播放泰勒·斯威夫特最受欢迎的歌曲
在 [43]
已复制!
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()
from langchain_core.messages import HumanMessage config = {"configurable": {"thread_id": "1"}} input_message = HumanMessage(content="你能播放泰勒·斯威夫特最受欢迎的歌曲吗?") for event in app.stream({"messages": [input_message]}, config, stream_mode="values"): event["messages"][-1].pretty_print()
================================ Human Message ================================= Can you play Taylor Swift's most popular song? ================================== Ai Message ================================== Tool Calls: play_song_on_apple (call_uhGY6Fv6Mr4ZOhSokintuoD7) Call ID: call_uhGY6Fv6Mr4ZOhSokintuoD7 Args: song: Anti-Hero by Taylor Swift ================================= Tool Message ================================= Name: play_song_on_apple Succesfully played Anti-Hero by Taylor Swift on Apple Music! ================================== Ai Message ================================== I've successfully played "Anti-Hero" by Taylor Swift on Apple Music! Enjoy the music!
检查历史记录¶
让我们浏览此线程的历史记录,从头到尾。
在 [44]
已复制!
app.get_state(config).values["messages"]
app.get_state(config).values["messages"]
Out[44]
[HumanMessage(content="Can you play Taylor Swift's most popular song?", id='7e32f0f3-75f5-48e1-a4ae-d38ccc15973b'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_uhGY6Fv6Mr4ZOhSokintuoD7', 'function': {'arguments': '{"song":"Anti-Hero by Taylor Swift"}', 'name': 'play_song_on_apple'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 22, 'prompt_tokens': 80, 'total_tokens': 102}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-af077bc4-f03c-4afe-8d92-78bdae394412-0', tool_calls=[{'name': 'play_song_on_apple', 'args': {'song': 'Anti-Hero by Taylor Swift'}, 'id': 'call_uhGY6Fv6Mr4ZOhSokintuoD7', 'type': 'tool_call'}], usage_metadata={'input_tokens': 80, 'output_tokens': 22, 'total_tokens': 102}), ToolMessage(content='Succesfully played Anti-Hero by Taylor Swift on Apple Music!', name='play_song_on_apple', id='43a39ca7-326a-4033-8607-bf061615ed6b', tool_call_id='call_uhGY6Fv6Mr4ZOhSokintuoD7'), AIMessage(content='I\'ve successfully played "Anti-Hero" by Taylor Swift on Apple Music! Enjoy the music!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 126, 'total_tokens': 146}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'stop', 'logprobs': None}, id='run-bfee6b28-9f16-49cc-8d28-bfb5a5b9aea1-0', usage_metadata={'input_tokens': 126, 'output_tokens': 20, 'total_tokens': 146})]
在 [45]
已复制!
all_states = []
for state in app.get_state_history(config):
print(state)
all_states.append(state)
print("--")
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?", id='7e32f0f3-75f5-48e1-a4ae-d38ccc15973b'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_uhGY6Fv6Mr4ZOhSokintuoD7', 'function': {'arguments': '{"song":"Anti-Hero by Taylor Swift"}', 'name': 'play_song_on_apple'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 22, 'prompt_tokens': 80, 'total_tokens': 102}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-af077bc4-f03c-4afe-8d92-78bdae394412-0', tool_calls=[{'name': 'play_song_on_apple', 'args': {'song': 'Anti-Hero by Taylor Swift'}, 'id': 'call_uhGY6Fv6Mr4ZOhSokintuoD7', 'type': 'tool_call'}], usage_metadata={'input_tokens': 80, 'output_tokens': 22, 'total_tokens': 102}), ToolMessage(content='Succesfully played Anti-Hero by Taylor Swift on Apple Music!', name='play_song_on_apple', id='43a39ca7-326a-4033-8607-bf061615ed6b', tool_call_id='call_uhGY6Fv6Mr4ZOhSokintuoD7'), AIMessage(content='I\'ve successfully played "Anti-Hero" by Taylor Swift on Apple Music! Enjoy the music!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 126, 'total_tokens': 146}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'stop', 'logprobs': None}, id='run-bfee6b28-9f16-49cc-8d28-bfb5a5b9aea1-0', usage_metadata={'input_tokens': 126, 'output_tokens': 20, 'total_tokens': 146})]}, next=(), config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1ef6bcf1-364f-6228-8003-dd67a426334e'}}, metadata={'source': 'loop', 'writes': {'agent': {'messages': [AIMessage(content='I\'ve successfully played "Anti-Hero" by Taylor Swift on Apple Music! Enjoy the music!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 126, 'total_tokens': 146}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'stop', 'logprobs': None}, id='run-bfee6b28-9f16-49cc-8d28-bfb5a5b9aea1-0', usage_metadata={'input_tokens': 126, 'output_tokens': 20, 'total_tokens': 146})]}}, 'step': 3, 'parents': {}}, created_at='2024-09-05T21:37:39.955948+00:00', parent_config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1ef6bcf1-318f-6dc8-8002-dbdf9aaeac83'}}, tasks=()) -- StateSnapshot(values={'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?", id='7e32f0f3-75f5-48e1-a4ae-d38ccc15973b'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_uhGY6Fv6Mr4ZOhSokintuoD7', 'function': {'arguments': '{"song":"Anti-Hero by Taylor Swift"}', 'name': 'play_song_on_apple'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 22, 'prompt_tokens': 80, 'total_tokens': 102}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-af077bc4-f03c-4afe-8d92-78bdae394412-0', tool_calls=[{'name': 'play_song_on_apple', 'args': {'song': 'Anti-Hero by Taylor Swift'}, 'id': 'call_uhGY6Fv6Mr4ZOhSokintuoD7', 'type': 'tool_call'}], usage_metadata={'input_tokens': 80, 'output_tokens': 22, 'total_tokens': 102}), ToolMessage(content='Succesfully played Anti-Hero by Taylor Swift on Apple Music!', name='play_song_on_apple', id='43a39ca7-326a-4033-8607-bf061615ed6b', tool_call_id='call_uhGY6Fv6Mr4ZOhSokintuoD7')]}, next=('agent',), config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1ef6bcf1-318f-6dc8-8002-dbdf9aaeac83'}}, metadata={'source': 'loop', 'writes': {'action': {'messages': [ToolMessage(content='Succesfully played Anti-Hero by Taylor Swift on Apple Music!', name='play_song_on_apple', id='43a39ca7-326a-4033-8607-bf061615ed6b', tool_call_id='call_uhGY6Fv6Mr4ZOhSokintuoD7')]}}, 'step': 2, 'parents': {}}, created_at='2024-09-05T21:37:39.458185+00:00', parent_config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1ef6bcf1-3185-663e-8001-12b1ec3114b8'}}, tasks=(PregelTask(id='3a4c5ddb-14b2-5def-a766-02ddc32948ba', name='agent', error=None, interrupts=(), state=None),)) -- StateSnapshot(values={'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?", id='7e32f0f3-75f5-48e1-a4ae-d38ccc15973b'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_uhGY6Fv6Mr4ZOhSokintuoD7', 'function': {'arguments': '{"song":"Anti-Hero by Taylor Swift"}', 'name': 'play_song_on_apple'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 22, 'prompt_tokens': 80, 'total_tokens': 102}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-af077bc4-f03c-4afe-8d92-78bdae394412-0', tool_calls=[{'name': 'play_song_on_apple', 'args': {'song': 'Anti-Hero by Taylor Swift'}, 'id': 'call_uhGY6Fv6Mr4ZOhSokintuoD7', 'type': 'tool_call'}], usage_metadata={'input_tokens': 80, 'output_tokens': 22, 'total_tokens': 102})]}, next=('action',), config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1ef6bcf1-3185-663e-8001-12b1ec3114b8'}}, metadata={'source': 'loop', 'writes': {'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_uhGY6Fv6Mr4ZOhSokintuoD7', 'function': {'arguments': '{"song":"Anti-Hero by Taylor Swift"}', 'name': 'play_song_on_apple'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 22, 'prompt_tokens': 80, 'total_tokens': 102}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-af077bc4-f03c-4afe-8d92-78bdae394412-0', tool_calls=[{'name': 'play_song_on_apple', 'args': {'song': 'Anti-Hero by Taylor Swift'}, 'id': 'call_uhGY6Fv6Mr4ZOhSokintuoD7', 'type': 'tool_call'}], usage_metadata={'input_tokens': 80, 'output_tokens': 22, 'total_tokens': 102})]}}, 'step': 1, 'parents': {}}, created_at='2024-09-05T21:37:39.453898+00:00', parent_config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1ef6bcf1-29b8-6370-8000-f9f6e7ca1b06'}}, tasks=(PregelTask(id='01f1dc72-5a39-5876-97a6-abdc12f70c2a', name='action', error=None, interrupts=(), state=None),)) -- StateSnapshot(values={'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?", id='7e32f0f3-75f5-48e1-a4ae-d38ccc15973b')]}, next=('agent',), config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1ef6bcf1-29b8-6370-8000-f9f6e7ca1b06'}}, metadata={'source': 'loop', 'writes': None, 'step': 0, 'parents': {}}, created_at='2024-09-05T21:37:38.635849+00:00', parent_config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1ef6bcf1-29b3-6514-bfff-fe07fb36f14f'}}, tasks=(PregelTask(id='348e1ba7-95c6-5b89-80c9-1fc4720e35ef', name='agent', error=None, interrupts=(), state=None),)) -- StateSnapshot(values={'messages': []}, next=('__start__',), config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1ef6bcf1-29b3-6514-bfff-fe07fb36f14f'}}, metadata={'source': 'input', 'writes': {'__start__': {'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?")]}}, 'step': -1, 'parents': {}}, created_at='2024-09-05T21:37:38.633849+00:00', parent_config=None, tasks=(PregelTask(id='f1cfbb8c-7792-5cf9-9d28-ae3ac7724cf3', name='__start__', error=None, interrupts=(), state=None),)) --
重放状态¶
我们可以回到这些状态中的任何一个,并从那里重新启动代理!让我们回到工具调用执行之前的状态。
在 [46]
已复制!
to_replay = all_states[2]
to_replay = all_states[2]
在 [47]
已复制!
to_replay.values
to_replay.values
Out[47]
{'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?", id='7e32f0f3-75f5-48e1-a4ae-d38ccc15973b'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_uhGY6Fv6Mr4ZOhSokintuoD7', 'function': {'arguments': '{"song":"Anti-Hero by Taylor Swift"}', 'name': 'play_song_on_apple'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 22, 'prompt_tokens': 80, 'total_tokens': 102}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-af077bc4-f03c-4afe-8d92-78bdae394412-0', tool_calls=[{'name': 'play_song_on_apple', 'args': {'song': 'Anti-Hero by Taylor Swift'}, 'id': 'call_uhGY6Fv6Mr4ZOhSokintuoD7', 'type': 'tool_call'}], usage_metadata={'input_tokens': 80, 'output_tokens': 22, 'total_tokens': 102})]}
在 [48]
已复制!
to_replay.next
to_replay.next
Out[48]
('action',)
要从这个地方重放,我们只需要将它的配置传回代理。请注意,它只是从它离开的地方恢复——进行工具调用。
在 [49]
已复制!
for event in app.stream(None, to_replay.config):
for v in event.values():
print(v)
for event in app.stream(None, to_replay.config): for v in event.values(): print(v)
{'messages': [ToolMessage(content='Succesfully played Anti-Hero by Taylor Swift on Apple Music!', name='play_song_on_apple', tool_call_id='call_uhGY6Fv6Mr4ZOhSokintuoD7')]} {'messages': [AIMessage(content='I\'ve started playing "Anti-Hero" by Taylor Swift on Apple Music! Enjoy the music!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 126, 'total_tokens': 146}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'stop', 'logprobs': None}, id='run-dc338bbd-d623-40bb-b824-5d2307954b57-0', usage_metadata={'input_tokens': 126, 'output_tokens': 20, 'total_tokens': 146})]}
从过去的状态分支¶
使用 LangGraph 的检查点功能,你可以做的不仅仅是重放过去的状态。你可以从以前的位置分支出来,让代理探索备用轨迹,或者让用户“版本控制”工作流程中的更改。
让我们展示如何做到这一点,以在特定时间点编辑状态。让我们更新状态,而不是在 Apple 上播放歌曲,而是在 Spotify 上播放
在 [52]
已复制!
# Let's now get the last message in the state
# This is the one with the tool calls that we want to update
last_message = to_replay.values["messages"][-1]
# Let's now update the tool we are calling
last_message.tool_calls[0]["name"] = "play_song_on_spotify"
branch_config = app.update_state(
to_replay.config,
{"messages": [last_message]},
)
# 现在让我们获取状态中的最后一条消息 # 这是我们要更新的包含工具调用的消息 last_message = to_replay.values["messages"][-1] # 现在让我们更新我们正在调用的工具 last_message.tool_calls[0]["name"] = "play_song_on_spotify" branch_config = app.update_state( to_replay.config, {"messages": [last_message]}, )
然后,我们可以使用此新的branch_config
进行调用,以从这里继续运行,状态已更改。我们可以从日志中看到,工具被调用了不同的输入。
在 [53]
已复制!
for event in app.stream(None, branch_config):
for v in event.values():
print(v)
for event in app.stream(None, branch_config): for v in event.values(): print(v)
{'messages': [ToolMessage(content='Succesfully played Anti-Hero by Taylor Swift on Spotify!', name='play_song_on_spotify', tool_call_id='call_uhGY6Fv6Mr4ZOhSokintuoD7')]} {'messages': [AIMessage(content='I\'ve started playing "Anti-Hero" by Taylor Swift on Spotify. Enjoy the music!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 19, 'prompt_tokens': 125, 'total_tokens': 144}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'stop', 'logprobs': None}, id='run-7d8d5094-7029-4da3-9e0e-ef9d18b63615-0', usage_metadata={'input_tokens': 125, 'output_tokens': 19, 'total_tokens': 144})]}
或者,我们可以更新状态,甚至不调用工具!
在 [54]
已复制!
from langchain_core.messages import AIMessage
# Let's now get the last message in the state
# This is the one with the tool calls that we want to update
last_message = to_replay.values["messages"][-1]
# Let's now get the ID for the last message, and create a new message with that ID.
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]},
)
from langchain_core.messages import AIMessage # 现在让我们获取状态中的最后一条消息 # 这是我们要更新的包含工具调用的消息 last_message = to_replay.values["messages"][-1] # 现在让我们获取最后一条消息的 ID,并使用该 ID 创建一条新消息。 new_message = AIMessage( content="现在是安静时间,我无法播放任何音乐!", id=last_message.id ) branch_config = app.update_state( to_replay.config, {"messages": [new_message]}, )
在 [55]
已复制!
branch_state = app.get_state(branch_config)
branch_state = app.get_state(branch_config)
在 [56]
已复制!
branch_state.values
branch_state.values
Out[56]
{'messages': [HumanMessage(content="Can you play Taylor Swift's most popular song?", id='7e32f0f3-75f5-48e1-a4ae-d38ccc15973b'), AIMessage(content="It's quiet hours so I can't play any music right now!", id='run-af077bc4-f03c-4afe-8d92-78bdae394412-0')]}
在 [57]
已复制!
branch_state.next
branch_state.next
Out[57]
()
你可以看到快照已更新,现在正确地反映了没有下一步。