跳转至

时间旅行

在典型的聊天机器人工作流中,用户会与机器人进行一次或多次交互以完成任务。内存人类在环 让你能够在图状态中创建检查点并控制后续的响应。

如果你希望用户能够从之前的某个回复重新开始,探索不同的结果怎么办?或者你希望用户可以倒带你的聊天机器人的执行过程,以修复错误或尝试不同策略(这在诸如“自主软件工程师”这类应用中很常见)怎么办?

你可以使用 LangGraph 内置的时间旅行功能来创建这些体验。

Note

本教程基于自定义状态

1. 回滚你的图

通过使用图的 get_state_history 方法获取检查点来回滚你的图。然后你可以从这个过去的时间点恢复执行。

pip install -U "langchain[openai]"
import os
from langchain.chat_models import init_chat_model

os.environ["OPENAI_API_KEY"] = "sk-..."

llm = init_chat_model("openai:gpt-4.1")

👉 Read the OpenAI integration docs

pip install -U "langchain[anthropic]"
import os
from langchain.chat_models import init_chat_model

os.environ["ANTHROPIC_API_KEY"] = "sk-..."

llm = init_chat_model("anthropic:claude-3-5-sonnet-latest")

👉 Read the Anthropic integration docs

pip install -U "langchain[openai]"
import os
from langchain.chat_models import init_chat_model

os.environ["AZURE_OPENAI_API_KEY"] = "..."
os.environ["AZURE_OPENAI_ENDPOINT"] = "..."
os.environ["OPENAI_API_VERSION"] = "2025-03-01-preview"

llm = init_chat_model(
    "azure_openai:gpt-4.1",
    azure_deployment=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"],
)

👉 Read the Azure integration docs

pip install -U "langchain[google-genai]"
import os
from langchain.chat_models import init_chat_model

os.environ["GOOGLE_API_KEY"] = "..."

llm = init_chat_model("google_genai:gemini-2.0-flash")

👉 Read the Google GenAI integration docs

pip install -U "langchain[aws]"
from langchain.chat_models import init_chat_model

# Follow the steps here to configure your credentials:
# https://docs.aws.amazon.com/bedrock/latest/userguide/getting-started.html

llm = init_chat_model(
    "anthropic.claude-3-5-sonnet-20240620-v1:0",
    model_provider="bedrock_converse",
)

👉 Read the AWS Bedrock integration docs

API Reference: TavilySearch | BaseMessage | InMemorySaver | StateGraph | START | END | add_messages | ToolNode | tools_condition

from typing import Annotated

from langchain_tavily import TavilySearch
from langchain_core.messages import BaseMessage
from typing_extensions import TypedDict

from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode, tools_condition

class State(TypedDict):
    messages: Annotated[list, add_messages]

graph_builder = StateGraph(State)

tool = TavilySearch(max_results=2)
tools = [tool]
llm_with_tools = llm.bind_tools(tools)

def chatbot(state: State):
    return {"messages": [llm_with_tools.invoke(state["messages"])]}

graph_builder.add_node("chatbot", chatbot)

tool_node = ToolNode(tools=[tool])
graph_builder.add_node("tools", tool_node)

graph_builder.add_conditional_edges(
    "chatbot",
    tools_condition,
)
graph_builder.add_edge("tools", "chatbot")
graph_builder.add_edge(START, "chatbot")

memory = InMemorySaver()
graph = graph_builder.compile(checkpointer=memory)

2. 添加步骤

为你的图添加步骤。每一步都会在其状态历史中建立检查点:

config = {"configurable": {"thread_id": "1"}}
events = graph.stream(
    {
        "messages": [
            {
                "role": "user",
                "content": (
                    "I'm learning LangGraph. "
                    "Could you do some research on it for me?"
                ),
            },
        ],
    },
    config,
    stream_mode="values",
)
for event in events:
    if "messages" in event:
        event["messages"][-1].pretty_print()
================================ 人类消息 =================================

I'm learning LangGraph. Could you do some research on it for me?
================================== AI 消息 ==================================

[{'text': "当然可以!我很乐意为你研究一下 LangGraph。为了获取最新且准确的信息,我将使用 Tavily 搜索引擎来查询。现在就为你查找。", 'type': 'text'}, {'id': 'toolu_01BscbfJJB9EWJFqGrN6E54e', 'input': {'query': 'LangGraph latest information and features'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]
工具调用:
  tavily_search_results_json (toolu_01BscbfJJB9EWJFqGrN6E54e)
 调用 ID: toolu_01BscbfJJB9EWJFqGrN6E54e
  参数:
    query: LangGraph latest information and features
================================= 工具消息 =================================
名称: tavily_search_results_json

[{"url": "https://blockchain.news/news/langchain-new-features-upcoming-events-update", "content": "LangChain 作为 AI 开发领域的领先平台,发布了最新更新,展示了其生态系统中的新用例与增强功能。根据 LangChain 博客,这些更新涵盖了 LangGraph Platform 的进展、LangSmith 的自我改进评估器,以及为 LangGraph 改版的文档。"}, {"url": "https://blog.langchain.dev/langgraph-platform-announce/", "content": "基于这些经验,我们决定将最新的一些产品整合为 LangGraph Platform。LangGraph Platform 目前包括 LangGraph Server、LangGraph Studio 以及 CLI 和 SDK。……我们在 LangGraph Server 中添加了功能,以兑现若干关键价值点。下面我们将重点关注 LangGraph Platform 的这些方面。"}]
================================== AI 消息 ==================================

谢谢等待。我为你找到了关于 LangGraph 的一些最新信息。下面是要点总结:

1. LangGraph 是 LangChain 生态的一部分,它是 AI 开发领域的领先平台。

2. LangGraph 的最新更新与特性包括:

   a. LangGraph Platform:这似乎是 LangGraph 的云版本,尽管搜索结果中没有提供具体细节。
...
3. 关注 LangGraph Platform 的进展,因为基于云的解决方案通常能为初学者提供更简单的起点。
4. 考虑 LangGraph 在更广泛的 LangChain 生态中的位置,尤其是它与 LangSmith 等工具的交互。

你想更了解 LangGraph 的哪个具体方面?我可以就特定功能或用例做更聚焦的检索。
输出已截断。可作为可滚动元素查看或在文本编辑器中打开。可调整单元格输出设置...
events = graph.stream(
    {
        "messages": [
            {
                "role": "user",
                "content": (
                    "Ya that's helpful. Maybe I'll "
                    "build an autonomous agent with it!"
                ),
            },
        ],
    },
    config,
    stream_mode="values",
)
for event in events:
    if "messages" in event:
        event["messages"][-1].pretty_print()
================================ 人类消息 =================================

Ya that's helpful. Maybe I'll build an autonomous agent with it!
================================== AI 消息 ==================================

[{'text': "这个想法很棒!用 LangGraph 构建一个自主代理确实是一个很好的应用。LangGraph 特别适合创建复杂的多步 AI 工作流,这对自主代理来说再合适不过。让我为你收集一些使用 LangGraph 构建自主代理的更具体信息。", 'type': 'text'}, {'id': 'toolu_01QWNHhUaeeWcGXvA4eHT7Zo', 'input': {'query': 'Building autonomous agents with LangGraph examples and tutorials'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]
工具调用:
  tavily_search_results_json (toolu_01QWNHhUaeeWcGXvA4eHT7Zo)
 调用 ID: toolu_01QWNHhUaeeWcGXvA4eHT7Zo
  参数:
    query: Building autonomous agents with LangGraph examples and tutorials
================================= 工具消息 =================================
名称: tavily_search_results_json

[{"url": "https://towardsdatascience.com/building-autonomous-multi-tool-agents-with-gemini-2-0-and-langgraph-ad3d7bd5e79d", "content": "Building Autonomous Multi-Tool Agents with Gemini 2.0 and LangGraph | by Youness Mansar | Jan, 2025 | Towards Data Science 使用 Gemini 2.0 和 LangGraph 构建多工具自主代理 一篇包含完整代码示例的实操教程,展示如何构建与运行多工具代理。"}, {"url": "https://github.com/anmolaman20/Tools_and_Agents", "content": "GitHub - anmolaman20/Tools_and_Agents:该仓库提供使用 Langchain 和 Langgraph 构建 AI 代理的资源。包含动手示例、实用教程与资源,帮助开发者与 AI 爱好者掌握智能系统与工作流的构建。"}]
================================== AI 消息 ==================================

好主意!用 LangGraph 构建自主代理非常令人兴奋。基于我刚刚找到的最新信息,这里有一些关于用 LangGraph 构建自主代理的见解与建议:

1. 多工具代理:LangGraph 特别适合创建能够使用多种工具的自主代理。这让代理可以拥有多样化能力,并为每个任务选择合适的工具。

2. 与大语言模型(LLM)集成:你可以将 LangGraph 与强大的 LLM(如 Gemini 2.0)结合,以构建更智能、更强大的代理。LLM 可以作为代理的“大脑”,进行决策与生成响应。

3. 工作流管理:LangGraph 擅长管理复杂的多步 AI 工作流。这对需要将任务拆解为更小步骤并按正确顺序执行的自主代理非常关键。
...
6. 注意如何构建代理的决策流程与工作流。
7. 不要忘了实现适当的错误处理与安全措施,尤其是在代理需要与外部系统交互或做出重要决策时。

构建自主代理是一个迭代过程,因此请做好不断优化改进的准备。祝你项目顺利!在你推进过程中若需要更具体的信息,随时告诉我。
输出已截断。可作为可滚动元素查看或在文本编辑器中打开。可调整单元格输出设置...

3. 重放完整的状态历史

现在你已经为聊天机器人添加了步骤,你可以重放整个状态历史,查看发生的所有事情。

to_replay = None
for state in graph.get_state_history(config):
    print("Num Messages: ", len(state.values["messages"]), "Next: ", state.next)
    print("-" * 80)
    if len(state.values["messages"]) == 6:
        # We are somewhat arbitrarily selecting a specific state based on the number of chat messages in the state.
        to_replay = state
消息数量:  8 下一步:  ()
--------------------------------------------------------------------------------
消息数量:  7 下一步:  ('chatbot',)
--------------------------------------------------------------------------------
消息数量:  6 下一步:  ('tools',)
--------------------------------------------------------------------------------
消息数量:  5 下一步:  ('chatbot',)
--------------------------------------------------------------------------------
消息数量:  4 下一步:  ('__start__',)
--------------------------------------------------------------------------------
消息数量:  4 下一步:  ()
--------------------------------------------------------------------------------
消息数量:  3 下一步:  ('chatbot',)
--------------------------------------------------------------------------------
消息数量:  2 下一步:  ('tools',)
--------------------------------------------------------------------------------
消息数量:  1 下一步:  ('chatbot',)
--------------------------------------------------------------------------------
消息数量:  0 下一步:  ('__start__',)
--------------------------------------------------------------------------------

检查点会在图的每一步保存。这会跨越多次调用,因此你可以在整个线程的历史中回滚。

从检查点恢复

to_replay 状态恢复,该状态位于第二次图调用中的 chatbot 节点之后。从此处恢复将会接下来调用 action 节点。

print(to_replay.next)
print(to_replay.config)
('tools',)
{'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1efd43e3-0c1f-6c4e-8006-891877d65740'}}

4. 从某一时刻加载状态

to_replay.config 中的检查点包含一个 checkpoint_id 时间戳。提供这个 checkpoint_id 值会告诉 LangGraph 的检查点器从那个时间点加载状态。

# `to_replay.config` 中的 `checkpoint_id` 对应一个我们已持久化到检查点器的状态。
for event in graph.stream(None, to_replay.config, stream_mode="values"):
    if "messages" in event:
        event["messages"][-1].pretty_print()
================================== AI 消息 ==================================

[{'text': "这个想法很棒!用 LangGraph 构建一个自主代理确实是一个很好的应用。LangGraph 特别适合创建复杂的多步 AI 工作流,这对自主代理来说再合适不过。让我为你收集一些使用 LangGraph 构建自主代理的更具体信息。", 'type': 'text'}, {'id': 'toolu_01QWNHhUaeeWcGXvA4eHT7Zo', 'input': {'query': 'Building autonomous agents with LangGraph examples and tutorials'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]
工具调用:
  tavily_search_results_json (toolu_01QWNHhUaeeWcGXvA4eHT7Zo)
 调用 ID: toolu_01QWNHhUaeeWcGXvA4eHT7Zo
  参数:
    query: Building autonomous agents with LangGraph examples and tutorials
================================= 工具消息 =================================
名称: tavily_search_results_json

[{"url": "https://towardsdatascience.com/building-autonomous-multi-tool-agents-with-gemini-2-0-and-langgraph-ad3d7bd5e79d", "content": "使用 Gemini 2.0 和 LangGraph 构建多工具自主代理 | Youness Mansar | 2025 年 1 月 | Towards Data Science。一篇包含完整代码示例的实操教程,展示如何构建与运行多工具代理。"}, {"url": "https://github.com/anmolaman20/Tools_and_Agents", "content": "GitHub - anmolaman20/Tools_and_Agents:该仓库提供使用 Langchain 和 Langgraph 构建 AI 代理的资源。包含动手示例、实用教程与资源,帮助开发者与 AI 爱好者掌握智能系统与工作流的构建。"}]
================================== AI 消息 ==================================

好主意!用 LangGraph 构建自主代理非常令人兴奋。基于我刚刚找到的最新信息,这里有一些关于用 LangGraph 构建自主代理的见解与建议:

1. 多工具代理:LangGraph 特别适合创建能够使用多种工具的自主代理。这让代理可以拥有多样化能力,并为每个任务选择合适的工具。

2. 与大语言模型(LLM)集成:你可以将 LangGraph 与强大的 LLM(如 Gemini 2.0)结合,以构建更智能、更强大的代理。LLM 可以作为代理的“大脑”,进行决策与生成响应。

3. 工作流管理:LangGraph 擅长管理复杂的多步 AI 工作流。这对需要将任务拆解为更小步骤并按正确顺序执行的自主代理非常关键。
...

请记住,构建自主代理是一个迭代过程。从简单开始,随着你对 LangGraph 及其能力的熟悉,逐步增加复杂度。

你想更了解用 LangGraph 构建自主代理的哪些具体方面?
输出已截断。可作为可滚动元素查看或在文本编辑器中打开。可调整单元格输出设置...

图从 tools 节点恢复执行。你可以从上面首先打印出的搜索引擎工具响应看出来。

恭喜!你已经在 LangGraph 中完成了时间旅行式的检查点穿梭。能够回滚并探索备选路径,将为调试、实验和交互式应用带来无限可能。

了解更多

通过探索部署与高级功能,继续你的 LangGraph 之旅: