如何为子图添加线程级持久性¶
设置¶
首先,让我们安装所需的包
为 LangGraph 开发设置 LangSmith
注册 LangSmith 可快速发现问题并提升您的 LangGraph 项目性能。LangSmith 允许您使用跟踪数据调试、测试和监控您使用 LangGraph 构建的 LLM 应用程序 — 点击此处了解更多入门信息。
定义具有持久性的图¶
要为包含子图的图添加持久性,您只需在编译父图时传递一个检查点保存器。LangGraph 会自动将检查点保存器传播到子图。
注意
您不应在编译子图时提供检查点保存器。相反,您必须定义一个**单一的**检查点保存器,并将其传递给 parentGraph.compile()
,LangGraph 会自动将该检查点保存器传播到子图。如果您将检查点保存器传递给 subgraph.compile()
,它将被忽略。当您添加一个显式调用子图的节点函数时,这也适用。
让我们定义一个包含单个子图节点的简单图,以展示如何实现。
import { StateGraph, Annotation } from "@langchain/langgraph";
// subgraph
const SubgraphStateAnnotation = Annotation.Root({
foo: Annotation<string>,
bar: Annotation<string>,
});
const subgraphNode1 = async (state: typeof SubgraphStateAnnotation.State) => {
return { bar: "bar" };
};
const subgraphNode2 = async (state: typeof SubgraphStateAnnotation.State) => {
// note that this node is using a state key ('bar') that is only available in the subgraph
// and is sending update on the shared state key ('foo')
return { foo: state.foo + state.bar };
};
const subgraph = new StateGraph(SubgraphStateAnnotation)
.addNode("subgraphNode1", subgraphNode1)
.addNode("subgraphNode2", subgraphNode2)
.addEdge("__start__", "subgraphNode1")
.addEdge("subgraphNode1", "subgraphNode2")
.compile();
// parent graph
const StateAnnotation = Annotation.Root({
foo: Annotation<string>,
});
const node1 = async (state: typeof StateAnnotation.State) => {
return {
foo: "hi! " + state.foo,
};
};
const builder = new StateGraph(StateAnnotation)
.addNode("node1", node1)
// note that we're adding the compiled subgraph as a node to the parent graph
.addNode("node2", subgraph)
.addEdge("__start__", "node1")
.addEdge("node1", "node2");
我们现在可以使用内存中的检查点保存器(MemorySaver
)来编译图。
import { MemorySaver } from "@langchain/langgraph-checkpoint";
const checkpointer = new MemorySaver();
// You must only pass checkpointer when compiling the parent graph.
// LangGraph will automatically propagate the checkpointer to the child subgraphs.
const graph = builder.compile({
checkpointer: checkpointer
});
验证持久性是否有效¶
现在,让我们运行该图并检查父图和子图的持久化状态,以验证持久性是否有效。我们应该会在 state.values
中看到父图和子图的最终执行结果。
const stream = await graph.stream({
foo: "foo"
}, {
...config,
subgraphs: true,
});
for await (const [_source, chunk] of stream) {
console.log(chunk);
}
{ node1: { foo: 'hi! foo' } }
{ subgraphNode1: { bar: 'bar' } }
{ subgraphNode2: { foo: 'hi! foobar' } }
{ node2: { foo: 'hi! foobar' } }
graph.get_state()
来查看父图状态。
要查看子图状态,我们需要做两件事
- 查找子图最新的配置值
- 使用
graph.getState()
检索最新子图配置的值。
为了找到正确的配置,我们可以检查父图的状态历史,并找到从 node2
(包含子图的节点)返回结果之前的状态快照。
let stateWithSubgraph;
const graphHistories = await graph.getStateHistory(config);
for await (const state of graphHistories) {
if (state.next[0] === "node2") {
stateWithSubgraph = state;
break;
}
}
状态快照将包含接下来要执行的 tasks
列表。在使用子图时,tasks
将包含我们可以用来检索子图状态的配置。