Skip to content

Graph API overview

这一章我们具体讨论

  1. Graph API 的核心抽象是什么
  2. State 到底是什么
  3. Node 到底是什么
  4. Edge 到底是什么
  5. 为什么一定要 compile
  6. schema / multiple schemas / reducers 在解决什么问题
  7. messageschannel 这些词在这一层怎么理解

Graph API的核心抽象是什么

官方文档中提到,主要用到了三个关键组件

  • State
    • 一个共享数据结构,表示应用程序的当前快照,它可以是任何数据类型,但是通常是使用共享状态模式定义
  • Nodes
    • 节点,编码智能体逻辑的函数,它们接受当前状态作为输入,执行一些计算,并返回更新后的状态
  • Edges
    • 边,根据当前状态决定接下来执行哪个节点的函数,它们可以是条件分支,也可以是固定转换

State 到底是什么

  • State 是应用当前快照的共享数据结构
  • State 通常由一个共享 state schema 定义。
  • Graph 里的所有 Nodes 和 Edges,都会以这个 State schema 作为输入语义基础。
  • State 不只是“字段集合”,还包括 reducer functions,用于定义节点更新如何应用到 state。
  • schema 可以用 TypedDictdataclassPydantic BaseModel 来定义;官方还特别提示 Pydantic 验证强,但性能不如 TypedDictdataclass

本质上是整张图的共享运行状态

Node 到底是什么

  • Node 是 function
  • Node 接收当前 state 作为输入,执行计算或副作用,然后返回 state 的更新。
  • 官方还特意强调:Nodes and Edges are nothing more than functions
  • Node 里面既可以放 LLM,也可以只是普通代码

Edge 到底是什么

  • Edge 也是 function。
  • Edge 的职责是:根据当前 state 决定下一个执行哪个 node
  • Edge 可以是固定跳转,也可以是条件分支。

node 负责“做事”,edge 负责“做完之后去哪”。

为什么 Graph 可以做循环、并行,而不是只是线性流程

  • 通过组合 nodes 和 edges,可以形成 complex, looping workflows
  • 底层运行机制采用 message passing
  • 执行按离散的 super-steps 推进。
  • 同一 super-step 中的 nodes 可以并行,顺序执行的 nodes 会分属不同 super-step。
  • 当所有 nodes 都 inactive 且没有消息在传输中时,图执行结束。

为什么一定要 compile

  • 构图流程是:先定义 state,再加 nodes 和 edges,最后 compile
  • compile 会做一些基本结构检查,比如 no orphaned nodes
  • compile 也是指定 runtime args 的地方,比如 checkpointersbreakpoints
  • 必须 compile 后才能使用 graph

Schema 在解决什么问题

  • graph 可以默认使用同一套 input/output schema。
  • 也可以显式定义 input schemaoutput schema
  • 还可以有 internal/private state channels,用于图内部节点通信,而不是暴露给 graph 输入输出。
  • 官方明确说了:不同 schema 的意义之一是:
    • 输入输出不一定要暴露所有内部状态
    • 内部节点之间可能需要私有通信字段。

state channels

部分原文直接用了这些说法:

  • “same state channels”
  • “private state channels”
  • “write to any state channel in the graph state”

所以这里可以明确得出:

  • 在 Graph API 这一层,官方虽然主要讲 State,但已经把 State 的 key/slot 看成 channels
  • 也就是说,state 和 channel 在这里不是完全不同的两套世界,而是同一运行模型在不同抽象层上的表述。这个判断还会在 Pregel runtime 那篇被进一步坐实。

Reducer 在解决什么问题

  • 节点返回的不是完整 state,而是 state update
  • 这些 update 如何应用到每个 key,由 reducer 决定。
  • 默认 reducer 是 override
  • 也可以通过 Annotated[..., add] 这类方式定义“累加/合并”式 reducer。

最后更新于: