跳到内容

如何传递私有状态

通常,您可能希望节点之间能够相互传递状态,但这些状态不应该成为图的主模式的一部分。这通常很有用,因为有些信息可能不需要作为输入/输出(因此放在主模式中并不太合理),但作为中间工作逻辑的一部分却是必需的。

让我们来看下面的一个例子。在这个例子中,我们将创建一个 RAG(检索增强生成)管道,该管道:1. 接收用户问题 2. 使用 LLM(大型语言模型)生成搜索查询 3. 检索与该生成查询相关的文档 4. 基于这些文档生成最终答案

每个步骤都将有一个单独的节点。我们只会在整体状态中包含 questionanswer。然而,我们需要为 search_querydocuments 设置单独的状态——我们将通过在每个相关节点上定义 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 注解填充的中间步骤不会出现在最终输出中。