如何定义图状态¶
本操作指南将涵盖定义图状态的不同方法。
先决条件¶
设置¶
本指南需要安装 @langchain/langgraph
和 @langchain/core
包
入门¶
Annotation
函数是为新的 StateGraph
图定义图状态的推荐方式。Annotation.Root
函数用于创建顶层状态对象,其中每个字段表示图中的一个通道。
以下是如何定义一个简单图状态的示例,其中包含一个名为 messages
的通道
import { BaseMessage } from "@langchain/core/messages";
import { Annotation } from "@langchain/langgraph";
const GraphAnnotation = Annotation.Root({
// Define a 'messages' channel to store an array of BaseMessage objects
messages: Annotation<BaseMessage[]>({
// Reducer function: Combines the current state with new messages
reducer: (currentState, updateValue) => currentState.concat(updateValue),
// Default function: Initialize the channel with an empty array
default: () => [],
})
});
每个通道都可以选择具有 reducer
和 default
函数: - reducer
函数定义了新值如何与现有状态合并。 - default
函数为通道提供初始值。
有关 reducer 的更多信息,请参阅reducer 概念指南
const QuestionAnswerAnnotation = Annotation.Root({
question: Annotation<string>,
answer: Annotation<string>,
});
如上所述,我们所做的只是定义通道,然后将未实例化的 Annotation
函数作为值传递。重要的是要注意,我们总是将每个通道的 TypeScript 类型作为第一个泛型参数传递给 Annotation
。这样做可以确保我们的图状态是类型安全的,并且我们可以在定义节点时获得正确的类型。下面展示了如何从 Annotation
函数中提取类型定义
这等同于以下类型
合并状态¶
如果您有两个图状态注解,可以通过使用 spec
值将两者合并为单个注解
const MergedAnnotation = Annotation.Root({
...QuestionAnswerAnnotation.spec,
...GraphAnnotation.spec,
})
合并注解的类型是两个注解的交集
最后,使用注解实例化图就像将注解传递给 StateGraph
构造函数一样简单
import { StateGraph } from "@langchain/langgraph";
const workflow = new StateGraph(MergedAnnotation);
状态通道¶
Annotation
函数是 LangGraph 中状态定义底层实现的便捷包装器。仍然可以使用 channels
对象(即 Annotation
的包装器)定义状态,尽管在大多数情况下不推荐。以下示例展示了如何使用此模式实现图
import { StateGraph } from "@langchain/langgraph";
interface WorkflowChannelsState {
messages: BaseMessage[];
question: string;
answer: string;
}
const workflowWithChannels = new StateGraph<WorkflowChannelsState>({
channels: {
messages: {
reducer: (currentState, updateValue) => currentState.concat(updateValue),
default: () => [],
},
question: null,
answer: null,
}
});
如上所述,我们将 question
和 answer
的值设置为 null
,因为它不包含默认值。要设置默认值,通道的实现方式应与 messages
键的实现方式相同,其中 default
工厂返回默认值。reducer
函数是可选的,如果需要可以添加到通道对象中。
使用 Zod¶
如果您想为状态添加运行时验证,可以使用 Zod 而不是 Annotation
函数来定义状态。您还可以通过导入 @langchain/langgraph/zod
来传递自定义的 reducer
和 default
工厂,这将使用 LangGraph 特定的方法扩展 Zod。
import "@langchain/langgraph/zod";
import { z } from "zod";
const AgentState = z.object({
messages: z
.array(z.string())
.default(() => [])
.langgraph.reducer(
(a, b) => a.concat(Array.isArray(b) ? b : [b]),
z.union([z.string(), z.array(z.string())])
),
question: z.string(),
answer: z.string().min(1),
});
const graph = new StateGraph(AgentState);