Graph 包使用指南
Graph 包是 trpc-agent-go 中用于构建和执行工作流的核心组件。它提供了一个类型安全、可扩展的图执行引擎,支持复杂的 AI 工作流编排。
概述
Graph 包允许您将复杂的 AI 工作流建模为有向图,其中节点代表处理步骤,边代表数据流和控制流。它特别适合构建需要条件路由、状态管理和多步骤处理的 AI 应用。
使用模式
Graph 包的使用遵循以下模式:
- 创建 Graph:使用
StateGraph
构建器定义工作流结构 - 创建 GraphAgent:将编译后的 Graph 包装为 Agent
- 创建 Runner:使用 Runner 管理会话和执行环境
- 执行工作流:通过 Runner 执行工作流并处理结果
这种模式提供了:
- 类型安全:通过状态模式确保数据一致性
- 会话管理:支持多用户、多会话的并发执行
- 事件流:实时监控工作流执行进度
- 错误处理:统一的错误处理和恢复机制
Agent 集成
GraphAgent 实现了 agent.Agent
接口,可以:
- 作为独立 Agent:通过 Runner 直接执行
- 作为 SubAgent:被其他 Agent(如 LLMAgent)作为子 Agent 使用
- 不支持 SubAgent:GraphAgent 本身不支持子 Agent,专注于工作流执行
这种设计使得 GraphAgent 可以灵活地集成到复杂的多 Agent 系统中。
主要特性
- 类型安全的状态管理:使用 Schema 定义状态结构,支持自定义 Reducer
- 条件路由:基于状态动态选择执行路径
- LLM 节点集成:内置对大型语言模型的支持
- 工具节点:支持函数调用和外部工具集成
- 流式执行:支持实时事件流和进度跟踪
- 并发安全:线程安全的图执行
核心概念
1. 图 (Graph)
图是工作流的核心结构,由节点和边组成:
虚拟节点:
Start
:虚拟起始节点,通过SetEntryPoint()
自动连接End
:虚拟结束节点,通过SetFinishPoint()
自动连接- 这些节点不需要显式创建,系统会自动处理连接
2. 节点 (Node)
节点代表工作流中的一个处理步骤:
3. 状态 (State)
状态是在节点间传递的数据容器:
内置状态键:
Graph 包提供了一些内置状态键,主要用于系统内部通信:
用户可访问的内置键:
StateKeyUserInput
:用户输入(一次性,消费后清空,由 LLM 节点自动持久化)StateKeyOneShotMessages
:一次性消息(完整覆盖本轮输入,消费后清空)StateKeyLastResponse
:最后响应(用于设置最终输出,Executor 会读取此值作为结果)StateKeyMessages
:消息历史(持久化,支持 append + MessageOp 补丁操作)StateKeyNodeResponses
:按节点存储的响应映射。键为节点 ID,值为该 节点的最终文本响应。StateKeyLastResponse
用于串行路径上的最终输 出;当多个并行节点在某处汇合时,应从StateKeyNodeResponses
中按节 点读取各自的输出。StateKeyMetadata
:元数据(用户可用的通用元数据存储)
系统内部键(用户不应直接使用):
StateKeySession
:会话信息(由 GraphAgent 自动设置)StateKeyExecContext
:执行上下文(由 Executor 自动设置)StateKeyToolCallbacks
:工具回调(由 Executor 自动设置)StateKeyModelCallbacks
:模型回调(由 Executor 自动设置)
用户应该使用自定义状态键来存储业务数据,只在必要时使用用户可访问的内置状态键。
4. 状态模式 (StateSchema)
状态模式定义状态的结构和行为:
使用指南
1. 创建 GraphAgent 和 Runner
用户主要通过创建 GraphAgent 然后通过 Runner 来使用 Graph 包。这是推荐的使用模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
|
2. 使用 LLM 节点
LLM 节点实现了固定的三段式输入规则,无需配置:
- OneShot 优先:若存在
one_shot_messages
,以它为本轮输入。 - UserInput 其次:否则若存在
user_input
,自动持久化一次。 - 历史默认:否则以持久化历史作为输入。
重要说明:
- SystemPrompt 仅用于本次输入,不落持久化状态。
- 一次性键(
user_input
/one_shot_messages
)在成功执行后自动清空。 - 所有状态更新都是原子性的,确保一致性。
- GraphAgent/Runner 仅设置
user_input
,不再预先把用户消息写入messages
。这样可以允许在 LLM 节点之前的任意节点对user_input
进行修改,并能在同一轮生效。
三种输入范式
-
OneShot(
StateKeyOneShotMessages
): -
当该键存在时,本轮仅使用这里提供的
[]model.Message
调用模型, 通常包含完整的 system prompt 与 user prompt。调用后自动清空。 -
适用场景:前置节点专门构造 prompt 的工作流,需完全覆盖本轮输入。
-
UserInput(
StateKeyUserInput
): -
当
user_input
非空时,LLM 节点会取持久化历史messages
,并将 本轮的用户输入合并后发起调用。结束后会把用户输入与助手回复通过MessageOp
(例如AppendMessages
、ReplaceLastUser
)原子性写入 到messages
,并自动清空user_input
以避免重复追加。 -
适用场景:普通对话式工作流,允许在前置节点动态调整用户输入。
-
Messages only(仅
StateKeyMessages
): - 多用于工具调用回路。当第一轮经由
user_input
发起后,路由到工具 节点执行,再回到 LLM 节点时,因为user_input
已被清空,LLM 将走 “Messages only” 分支,以历史中的 tool 响应继续推理。
通过 Reducer 与 MessageOp 实现的原子更新
Graph 包的消息状态支持 MessageOp
补丁操作(如 ReplaceLastUser
、
AppendMessages
等),由 MessageReducer
实现原子合并。这带来两个
直接收益:
- 允许在 LLM 节点之前修改
user_input
,LLM 节点会据此在一次返回中将 需要的操作(例如替换最后一条用户消息、追加助手消息)以补丁形式返回, 执行器一次性落库,避免竞态与重复。` - 兼容传统的直接
[]Message
追加用法,同时为复杂更新提供更高的表达力。
示例:在前置节点修改 user_input
,随后进入 LLM 节点。
3. GraphAgent 配置选项
GraphAgent 支持多种配置选项:
4. 条件路由
5. 工具节点集成
工具调用配对机制与二次进入 LLM:
- 从
messages
尾部向前扫描最近的assistant(tool_calls)
;遇到user
则停止,确保配对正确。 - 当工具节点完成后返回到 LLM 节点时,
user_input
已被清空,LLM 将走 “Messages only” 分支,以历史中的 tool 响应继续推理。
6. Runner 配置
Runner 提供了会话管理和执行环境:
7. 消息状态模式
对于对话式应用,可以使用预定义的消息状态模式:
8. 状态键使用场景
用户自定义状态键:用于存储业务逻辑数据
内置状态键:用于系统集成
高级功能
1. 自定义 Reducer
Reducer 定义如何合并状态更新:
2. 命令模式
节点可以返回命令来同时更新状态和指定路由:
Fan-out 与动态路由:
- 节点返回
[]*graph.Command
即可在下一步并行创建多个分支。 - 使用
Command{ GoTo: "target" }
时,路由在运行时动态触发,无需静态可达性边。需确保目标节点存在;若为终点,请保留SetFinishPoint(target)
。
示例(并行 fan-out + 动态路由):
3. 执行器配置
4. 虚拟节点和路由
Graph 包使用虚拟节点来简化工作流的入口和出口:
这种设计使得工作流定义更加简洁,开发者只需要关注实际的业务节点和它们之间的连接。
最佳实践
1. 状态管理
- 使用常量定义状态键,避免硬编码字符串
- 为复杂状态创建 Helper 函数
- 使用 Schema 验证状态结构
- 区分内置状态键和用户自定义状态键
2. 错误处理
- 在节点函数中返回有意义的错误
- 使用错误类型常量进行分类
- 在条件函数中处理异常情况
3. 性能优化
- 合理设置执行器缓冲区大小
- 使用最大步数限制防止无限循环
- 考虑并行执行路径(如果支持)
4. 测试
常见用例
1. 文档处理工作流
这是一个完整的文档处理工作流示例,展示了如何使用 GraphAgent 和 Runner:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
|
2. 对话机器人
3. 数据处理管道
4. GraphAgent 作为 SubAgent
GraphAgent 可以作为其他 Agent 的子 Agent,实现复杂的多 Agent 协作:
关键特点:
- GraphAgent 实现了
agent.Agent
接口,可以被其他 Agent 作为子 Agent 使用 - 协调器 Agent 可以通过
transfer_to_agent
工具委托任务给 GraphAgent - GraphAgent 专注于工作流执行,不支持自己的子 Agent
- 这种设计实现了复杂工作流与多 Agent 系统的无缝集成
故障排除
常见错误
- "node not found":检查节点 ID 是否正确
- "invalid graph":确保图有入口点和所有节点可达
- "maximum execution steps exceeded":检查是否有循环或增加最大步数
- "state validation failed":检查状态模式定义
调试技巧
- 使用事件流监控执行过程
- 在节点函数中添加日志
- 验证状态模式定义
- 检查条件函数逻辑
总结
Graph 包提供了一个强大而灵活的工作流编排系统,特别适合构建复杂的 AI 应用。通过 GraphAgent 和 Runner 的组合使用,您可以创建高效、可维护的工作流应用。
关键要点
工作流创建:
- 使用
StateGraph
构建器创建图结构 - 定义清晰的状态模式和数据流
- 合理使用条件路由和工具节点
应用集成:
- 通过
GraphAgent
包装工作流图 - 使用
Runner
管理会话和执行环境 - 处理流式事件和错误响应
Agent 集成:
- GraphAgent 实现了
agent.Agent
接口 - 可以作为其他 Agent 的子 Agent 使用
- 支持复杂的多 Agent 协作场景
- 专注于工作流执行,不支持自己的子 Agent
最佳实践:
- 使用类型安全的状态键常量
- 实现适当的错误处理和恢复机制
- 测试和监控工作流执行过程
- 合理配置执行器参数和缓冲区大小
- 考虑将复杂工作流封装为 GraphAgent 子 Agent
典型使用流程
这种模式使得 Graph 包特别适合构建企业级的 AI 工作流应用,提供了良好的可扩展性、可维护性和用户体验。