如何在Langgraph中使用Annotation设置默认状态及初始状态
LangGraph v0.2中Annotation定义State的默认值与初始状态问题
在LangGraph v0.2版本使用Annotation定义State(官方推荐实现方式)时,无法成功设置默认值,也无法获取invoke时传入的初始状态值。希望采用无需reducer的场景(自动用最新值替换原有值),以下是代码及运行结果,求排查操作错误:
原代码
import { END, START, StateGraph, Annotation } from "@langchain/langgraph"; import { AIMessage, BaseMessage } from "@langchain/core/messages"; // Define the state structure with channels const ConfigState = Annotation.Root({ greeting: Annotation<string>({ default: "Bonjour!" }), // Set the default value here messages: Annotation<BaseMessage[]>({ reducer: (left: BaseMessage[], right: BaseMessage | BaseMessage[]) => { if (Array.isArray(right)) { return left.concat(right); } return left.concat([right]); }, default: () => [], }), }); console.log(ConfigState); const callModel1 = async (state: typeof ConfigState.State) => { console.log(`-----message inside callModel1 @ start-----: `, state.greeting); return { greeting: "Hola!" }; // Update the greeting with the new value }; const callModel2 = async (state: typeof ConfigState.State) => { console.log(`-----message inside callModel2 @ start-----: `, state.greeting); return { greeting: "Hi!" }; // Update the greeting with the new value }; // Create the workflow with the main node and end node const workflow = new StateGraph(ConfigState) .addNode("agent", callModel1) .addNode("agent2", callModel2) .addEdge(START, "agent") .addEdge("agent", "agent2") .addEdge("agent2", END); // Connect the agent node to the END node const initialState = { greeting: "Hello!" }; // Define your initial state here const result = await workflow.compile().invoke({ state: initialState }); // Pass the initial state when invoking the workflow console.log(result);
原运行结果
AnnotationRoot { lc_graph_name: 'AnnotationRoot', spec: { greeting: LastValue { ValueType: undefined, UpdateType: undefined, lc_graph_name: 'LastValue', value: undefined }, messages: BinaryOperatorAggregate { ValueType: undefined, UpdateType: undefined, lc_graph_name: 'BinaryOperatorAggregate', value: [], operator: [Function: reducer], initialValueFactory: [Function: default] } } } -----message inside callModel1 @ start-----: null -----message inside callModel2 @ start-----: Hola! { greeting: 'Hi!', messages: [] }
错误排查与修正
1. 初始状态传入格式错误
invoke方法不需要将初始状态包裹在state键中,直接传入状态对象即可。原代码中invoke({ state: initialState })的写法会导致LangGraph无法识别初始状态,因此callModel1中获取到的greeting为null。
2. 默认值未生效的关联问题
当传入错误格式的初始状态时,LangGraph无法正确读取初始值,同时也会导致默认值未被触发(默认值仅在未对应初始状态字段时生效)。修正初始状态传入方式后,若未传入greeting字段,会自动使用Bonjour!作为默认值。
修正后的代码
import { END, START, StateGraph, Annotation } from "@langchain/langgraph"; import { AIMessage, BaseMessage } from "@langchain/core/messages"; const ConfigState = Annotation.Root({ greeting: Annotation<string>({ default: "Bonjour!" }), messages: Annotation<BaseMessage[]>({ reducer: (left: BaseMessage[], right: BaseMessage | BaseMessage[]) => { if (Array.isArray(right)) { return left.concat(right); } return left.concat([right]); }, default: () => [], }), }); const callModel1 = async (state: typeof ConfigState.State) => { console.log(`-----message inside callModel1 @ start-----: `, state.greeting); return { greeting: "Hola!" }; }; const callModel2 = async (state: typeof ConfigState.State) => { console.log(`-----message inside callModel2 @ start-----: `, state.greeting); return { greeting: "Hi!" }; }; const workflow = new StateGraph(ConfigState) .addNode("agent", callModel1) .addNode("agent2", callModel2) .addEdge(START, "agent") .addEdge("agent", "agent2") .addEdge("agent2", END); // 直接传入初始状态对象,无需包裹在state键中 const initialState = { greeting: "Hello!" }; const result = await workflow.compile().invoke(initialState); console.log(result);
修正后运行结果
AnnotationRoot { lc_graph_name: 'AnnotationRoot', spec: { greeting: LastValue { ValueType: undefined, UpdateType: undefined, lc_graph_name: 'LastValue', value: undefined }, messages: BinaryOperatorAggregate { ValueType: undefined, UpdateType: undefined, lc_graph_name: 'BinaryOperatorAggregate', value: [], operator: [Function: reducer], initialValueFactory: [Function: default] } } } -----message inside callModel1 @ start-----: Hello! -----message inside callModel2 @ start-----: Hola! { greeting: 'Hi!', messages: [] }
若想验证默认值生效,可移除初始状态中的greeting字段,此时callModel1中会输出Bonjour!。
内容的提问来源于stack exchange,提问作者Jrakru56
相关产品推荐
相关产品推荐

