@@ -87,6 +87,7 @@ from langgraph.graph.message import add_messages
8787
8888Intent = Literal[" refund" , " replacement" , " escalate" ]
8989
90+
9091class SupportState (TypedDict ):
9192 messages: Annotated[list[BaseMessage], add_messages]
9293 item: str | None
@@ -115,6 +116,7 @@ _CATALOG = {
115116 " monitor" : (" AeroPro 4K Monitor" , " ORD-33170" ),
116117}
117118
119+
118120def _lookup_order (text : str ) -> tuple[str | None , str | None ]:
119121 lowered = text.lower()
120122 for keyword, (item, order_id) in _CATALOG .items():
@@ -162,6 +164,7 @@ def _classify_intent(text: str) -> Intent:
162164 return " refund"
163165 return " escalate"
164166
167+
165168def classify (state : SupportState) -> SupportState:
166169 intent = _classify_intent(_latest_user_text(state[" messages" ]))
167170 return {" intent" : intent}
@@ -186,6 +189,7 @@ def refund(state: SupportState) -> SupportState:
186189 " messages" : [AIMessage(content = f " I can handle that as a refund for order { order_id} . " )],
187190 }
188191
192+
189193def replacement (state : SupportState) -> SupportState:
190194 order_id = state[" order_id" ]
191195 return {
@@ -195,6 +199,7 @@ def replacement(state: SupportState) -> SupportState:
195199 ],
196200 }
197201
202+
198203def escalate (state : SupportState) -> SupportState:
199204 order_id = state[" order_id" ]
200205 return {
@@ -218,6 +223,7 @@ rewind to: order id known, decision not yet made.
218223def route (state : SupportState) -> Intent:
219224 return state[" intent" ] or " escalate"
220225
226+
221227builder = StateGraph(SupportState)
222228builder.add_node(" identify_order" , identify_order)
223229builder.add_node(" classify" , classify)
@@ -228,7 +234,8 @@ builder.add_node("escalate", escalate)
228234builder.add_edge(START , " identify_order" )
229235builder.add_edge(" identify_order" , " classify" )
230236builder.add_conditional_edges(
231- " classify" , route,
237+ " classify" ,
238+ route,
232239 {" refund" : " refund" , " replacement" : " replacement" , " escalate" : " escalate" },
233240)
234241builder.add_edge(" refund" , END )
@@ -322,8 +329,14 @@ until `identify_order` runs, then carried by every later checkpoint.
322329history = list (saver.list(prod_config))
323330for i, tpl in enumerate (reversed (history), start = 1 ):
324331 values = tpl.checkpoint.get(" channel_values" , {})
325- print (i, tpl.config[" configurable" ][" checkpoint_id" ], _stage(tpl.metadata.get(" step" )),
326- values.get(" order_id" ), values.get(" intent" ), values.get(" resolution" ))
332+ print (
333+ i,
334+ tpl.config[" configurable" ][" checkpoint_id" ],
335+ _stage(tpl.metadata.get(" step" )),
336+ values.get(" order_id" ),
337+ values.get(" intent" ),
338+ values.get(" resolution" ),
339+ )
327340```
328341
329342** In the code:** ` demo.py ` , ` # === Step 9 === ` (Phase 3, after the customer's
@@ -350,11 +363,14 @@ rehydrates it.
350363
351364``` python
352365fork_point = next (
353- (tpl for tpl in reversed (history)
354- if _values(tpl).get(" order_id" ) and not _values(tpl).get(" resolution" )),
366+ (
367+ tpl
368+ for tpl in reversed (history)
369+ if _values(tpl).get(" order_id" ) and not _values(tpl).get(" resolution" )
370+ ),
355371 history[- 1 ],
356372)
357- rehydrated = saver.get_tuple(fork_point.config) # one checkpoint read from Aerospike
373+ rehydrated = saver.get_tuple(fork_point.config) # one checkpoint read from Aerospike
358374# rehydrated state: order_id == "ORD-10482", intent == None, resolution == None
359375```
360376
@@ -376,8 +392,8 @@ same `ORD-10482`. LangGraph writes new checkpoints from here; the refund run fro
376392Phase 1 stays in Aerospike under its own checkpoint ids.
377393
378394``` python
379- fork_config = fork_point.config # thread_id + checkpoint_ns + checkpoint_id
380- forked = _resolve(graph, fork_config, CORRECTED_REQUEST ) # "...send a replacement instead."
395+ fork_config = fork_point.config # thread_id + checkpoint_ns + checkpoint_id
396+ forked = _resolve(graph, fork_config, CORRECTED_REQUEST ) # "...send a replacement instead."
381397# forked.order_id == "ORD-10482" (reused from the checkpoint)
382398# forked.resolution == "Replacement selected for order ORD-10482"
383399```
0 commit comments