如何传递私有状态¶
通常,您可能希望节点之间能够传递不应作为图主 schema 的一部分的状态。这通常很有用,因为有些信息不需要作为输入/输出(因此将其包含在主 schema 中没有太大意义),但作为中间工作逻辑的一部分是必需的。
让我们看下面的一个例子。在这个例子中,我们将创建一个 RAG 管道,它将:1. 接收用户问题 2. 使用 LLM 生成搜索查询 3. 为生成的查询检索文档 4. 基于这些文档生成最终答案。
我们将为每个步骤设置一个单独的节点。我们只在整体状态中包含question
和answer
。但是,我们需要为search_query
和documents
设置单独的状态——我们将通过在每个相关节点上定义input
注解来将它们作为私有状态键传递。
我们来看一个例子!
import { Annotation, StateGraph } from "@langchain/langgraph";
// The overall state of the graph
const OverallStateAnnotation = Annotation.Root({
question: Annotation<string>,
answer: Annotation<string>,
});
// This is what the node that generates the query will return
const QueryOutputAnnotation = Annotation.Root({
query: Annotation<string>,
});
// This is what the node that retrieves the documents will return
const DocumentOutputAnnotation = Annotation.Root({
docs: Annotation<string[]>,
});
// This is what the node that retrieves the documents will return
const GenerateOutputAnnotation = Annotation.Root({
...OverallStateAnnotation.spec,
...DocumentOutputAnnotation.spec
});
// Node to generate query
const generateQuery = async (state: typeof OverallStateAnnotation.State) => {
// Replace this with real logic
return {
query: state.question + " rephrased as a query!",
};
};
// Node to retrieve documents
const retrieveDocuments = async (state: typeof QueryOutputAnnotation.State) => {
// Replace this with real logic
return {
docs: [state.query, "some random document"],
};
};
// Node to generate answer
const generate = async (state: typeof GenerateOutputAnnotation.State) => {
return {
answer: state.docs.concat([state.question]).join("\n\n"),
};
};
const graph = new StateGraph(OverallStateAnnotation)
.addNode("generate_query", generateQuery)
.addNode("retrieve_documents", retrieveDocuments, { input: QueryOutputAnnotation })
.addNode("generate", generate, { input: GenerateOutputAnnotation })
.addEdge("__start__", "generate_query")
.addEdge("generate_query", "retrieve_documents")
.addEdge("retrieve_documents", "generate")
.compile();
await graph.invoke({
question: "How are you?",
});
{
question: 'How are you?',
answer: 'How are you? rephrased as a query!\n\nsome random document\n\nHow are you?'
}
question
值被保留了,但generate_query
节点对其进行了改写,retrieve_documents
节点添加了"some random document"
,最后generate
节点将状态中的docs
与原始问题结合起来创建了一个answer
。传递给各个节点的input
注解所填充的中间步骤不会出现在最终输出中。