In [1]
已复制!
%%capture --no-stderr
%pip install -U langgraph
%%capture --no-stderr %pip install -U langgraph
定义孙子图¶
In [1]
已复制!
from typing_extensions import TypedDict
from langgraph.graph.state import StateGraph, START, END
class GrandChildState(TypedDict):
my_grandchild_key: str
def grandchild_1(state: GrandChildState) -> GrandChildState:
# NOTE: child or parent keys will not be accessible here
return {"my_grandchild_key": state["my_grandchild_key"] + ", how are you"}
grandchild = StateGraph(GrandChildState)
grandchild.add_node("grandchild_1", grandchild_1)
grandchild.add_edge(START, "grandchild_1")
grandchild.add_edge("grandchild_1", END)
grandchild_graph = grandchild.compile()
from typing_extensions import TypedDict from langgraph.graph.state import StateGraph, START, END class GrandChildState(TypedDict): my_grandchild_key: str def grandchild_1(state: GrandChildState) -> GrandChildState: # NOTE: 子图或父图的键将在此处不可访问 return {"my_grandchild_key": state["my_grandchild_key"] + ", how are you"} grandchild = StateGraph(GrandChildState) grandchild.add_node("grandchild_1", grandchild_1) grandchild.add_edge(START, "grandchild_1") grandchild.add_edge("grandchild_1", END) grandchild_graph = grandchild.compile()
In [2]
已复制!
grandchild_graph.invoke({"my_grandchild_key": "hi Bob"})
grandchild_graph.invoke({"my_grandchild_key": "hi Bob"})
Out[2]
{'my_grandchild_key': 'hi Bob, how are you'}
定义子图¶
In [3]
已复制!
class ChildState(TypedDict):
my_child_key: str
def call_grandchild_graph(state: ChildState) -> ChildState:
# NOTE: parent or grandchild keys won't be accessible here
# we're transforming the state from the child state channels (`my_child_key`)
# to the child state channels (`my_grandchild_key`)
grandchild_graph_input = {"my_grandchild_key": state["my_child_key"]}
# we're transforming the state from the grandchild state channels (`my_grandchild_key`)
# back to the child state channels (`my_child_key`)
grandchild_graph_output = grandchild_graph.invoke(grandchild_graph_input)
return {"my_child_key": grandchild_graph_output["my_grandchild_key"] + " today?"}
child = StateGraph(ChildState)
# NOTE: we're passing a function here instead of just compiled graph (`child_graph`)
child.add_node("child_1", call_grandchild_graph)
child.add_edge(START, "child_1")
child.add_edge("child_1", END)
child_graph = child.compile()
class ChildState(TypedDict): my_child_key: str def call_grandchild_graph(state: ChildState) -> ChildState: # NOTE: 父图或孙子图的键将在此处不可访问 # 我们正在将状态从子图状态通道(`my_child_key`) # 转换到孙子图状态通道(`my_grandchild_key`) grandchild_graph_input = {"my_grandchild_key": state["my_child_key"]} # 我们正在将状态从孙子图状态通道(`my_grandchild_key`) # 转换回子图状态通道(`my_child_key`) grandchild_graph_output = grandchild_graph.invoke(grandchild_graph_input) return {"my_child_key": grandchild_graph_output["my_grandchild_key"] + " today?"} child = StateGraph(ChildState) # NOTE: 我们在这里传递一个函数,而不是一个已编译的图(`child_graph`) child.add_node("child_1", call_grandchild_graph) child.add_edge(START, "child_1") child.add_edge("child_1", END) child_graph = child.compile()
In [4]
已复制!
child_graph.invoke({"my_child_key": "hi Bob"})
child_graph.invoke({"my_child_key": "hi Bob"})
Out[4]
{'my_child_key': 'hi Bob, how are you today?'}
注意
我们将 `grandchild_graph` 调用封装在一个单独的函数(`call_grandchild_graph`)中,该函数在调用孙子图之前转换输入状态,然后将孙子图的输出转换回子图状态。如果您只是将 `grandchild_graph` 直接传递给 `.add_node` 而不进行转换,LangGraph 将会抛出错误,因为子图和孙子图状态之间没有共享状态通道(键)。
请注意,子图和孙子图具有自己的 **独立** 状态,该状态与父图不共享。
定义父图¶
In [5]
已复制!
class ParentState(TypedDict):
my_key: str
def parent_1(state: ParentState) -> ParentState:
# NOTE: child or grandchild keys won't be accessible here
return {"my_key": "hi " + state["my_key"]}
def parent_2(state: ParentState) -> ParentState:
return {"my_key": state["my_key"] + " bye!"}
def call_child_graph(state: ParentState) -> ParentState:
# we're transforming the state from the parent state channels (`my_key`)
# to the child state channels (`my_child_key`)
child_graph_input = {"my_child_key": state["my_key"]}
# we're transforming the state from the child state channels (`my_child_key`)
# back to the parent state channels (`my_key`)
child_graph_output = child_graph.invoke(child_graph_input)
return {"my_key": child_graph_output["my_child_key"]}
parent = StateGraph(ParentState)
parent.add_node("parent_1", parent_1)
# NOTE: we're passing a function here instead of just a compiled graph (`<code>child_graph</code>`)
parent.add_node("child", call_child_graph)
parent.add_node("parent_2", parent_2)
parent.add_edge(START, "parent_1")
parent.add_edge("parent_1", "child")
parent.add_edge("child", "parent_2")
parent.add_edge("parent_2", END)
parent_graph = parent.compile()
class ParentState(TypedDict): my_key: str def parent_1(state: ParentState) -> ParentState: # NOTE: 子图或孙子图的键将在此处不可访问 return {"my_key": "hi " + state["my_key"]} def parent_2(state: ParentState) -> ParentState: return {"my_key": state["my_key"] + " bye!"} def call_child_graph(state: ParentState) -> ParentState: # 我们正在将状态从父图状态通道(`my_key`) # 转换到子图状态通道(`my_child_key`) child_graph_input = {"my_child_key": state["my_key"]} # 我们正在将状态从子图状态通道(`my_child_key`) # 转换回父图状态通道(`my_key`) child_graph_output = child_graph.invoke(child_graph_input) return {"my_key": child_graph_output["my_child_key"]} parent = StateGraph(ParentState) parent.add_node("parent_1", parent_1) # NOTE: 我们在这里传递一个函数,而不是一个已编译的图(`
child_graph
`) parent.add_node("child", call_child_graph) parent.add_node("parent_2", parent_2) parent.add_edge(START, "parent_1") parent.add_edge("parent_1", "child") parent.add_edge("child", "parent_2") parent.add_edge("parent_2", END) parent_graph = parent.compile()注意
我们将 `child_graph` 调用封装在一个单独的函数(`call_child_graph`)中,该函数在调用子图之前转换输入状态,然后将子图的输出转换回父图状态。如果您只是将 `child_graph` 直接传递给 `.add_node` 而不进行转换,LangGraph 将会抛出错误,因为父图和子图状态之间没有共享状态通道(键)。
让我们运行父图,并确保它正确调用了子图和孙子图
In [6]
已复制!
parent_graph.invoke({"my_key": "Bob"})
parent_graph.invoke({"my_key": "Bob"})
Out[6]
{'my_key': 'hi Bob, how are you today? bye!'}
完美!父图正确调用了子图和孙子图(我们知道这一点,因为 ", how are you" 和 "today?" 被添加到我们原始的 "my_key" 状态值中)。