ADK 框架结构
Eino ADK 的整体模块构成,如下图所示:
Agent Interface
Eino ADK 的核心成员是 Agent 抽象(Agent Interface),ADK 的所有功能设计均围绕 Agent 抽象展开。
Agent 核心行为抽象大致可描述为:
从入参中 AgentInput、AgentRunOption 和 可选的 Context Session,获取任务详情及相关数据
执行任务,并将执行过程、执行结果输出到 AgenEvent Iterator
执行任务时,可通过 Context 中的 Session 暂存数据
1 | type Agent interface { |
在 Agent Run 的实现中,一般是 Future 模式的异步执行,大体分成三步,具体可参考 adk.ChatModelAgent 中 Run 方法的实现:
- 创建一对 Iterator、Generator
- 启动 Agent 的异步任务,并传入 Generator,处理 AgentInput。在这个异步任务中,产生新的事件时,写入到 Generator 中,供 Agent 调用方在 Iterator 中消费
- 启动任务后,返回 Iterator
Agent 扩展行为抽象大致可描述为:
Agent 既可添加子 Agent,也可添加父 Agent,即作为 父 Agent 的 子 Agent
Agent 在执行任务时,可根据需要将任务转让(Transfer)给其 父 Agent 或 子 Agent
1 | type OnSubAgents interface { |
中心化的运行状态管理:
在 ADK 组合产物的运行中,每个 Agent 均可通过 context 中的 Session map[string]any
存取一些数据,Session 对所有 Agent 可见。Session 的生命周期对应着 ADK 组合产物的一次运行的生命周期(Interrupt&Resume 视为同一个生命周期)。
1 | func SetSessionValue(ctx context.Context, key string, value any) { |
Agent Compose
围绕 Agent 抽象,提供多种简单易用、场景丰富的组合原语,可支撑开发丰富多样的 Multi-Agent 协同策略,比如 Supervisor、Plan-Execute、Group-Chat 等 Multi-Agent 场景。从而实现不同的 Agent 分工合作模式,处理更复杂的任务。
Agent 协作过程中,可能存在的协作原语:
- Agent 间协作方式
协助方式 | 描述 |
---|---|
Transfer | 直接将任务转让给另外一个 Agent,本 Agent 则执行结束后退出,不关心转让 Agent 的任务执行状态 |
ToolCall(AgentAsTool) | 将 Agent 当成 ToolCall 调用,等待 Agent 的响应,并可获取被调用Agent 的输出结果,进行下一轮处理 |
- AgentInput 的上下文策略
上下文策略 | 描述 |
---|---|
上游 Agent 全对话 | 获取本 Agent 的上游 Agent 的完整对话记录 |
全新任务描述 | 忽略掉上游 Agent 的完整对话记录,给出一个全新的任务总结,作为子 Agent 的 AgentInput 输入 |
- 决策自主性
决策自主性 | 描述 |
---|---|
自主决策 | 在 Agent 内部,基于其可选的下游 Agent, 如需协助时,自主选择下游 Agent 进行协助。 一般来说,Agent 内部是基于 LLM 进行决策,不过即使是基于预设逻辑进行选择,从 Agent 外部看依然视为自主决策 |
预设决策 | 事先预设好一个Agent 执行任务后的下一个 Agent。 Agent 的执行顺序是事先确定、可预测的 |
接下来简要说明下,Agent Compose 下的不同的组合原语。
决策自主性 | 描述 |
---|---|
自主决策 | 在 Agent 内部,基于其可选的下游 Agent, 如需协助时,自主选择下游 Agent 进行协助。 一般来说,Agent 内部是基于 LLM 进行决策,不过即使是基于预设逻辑进行选择,从 Agent 外部看依然视为自主决策 |
预设决策 | 事先预设好一个Agent 执行任务后的下一个 Agent。 Agent 的执行顺序是事先确定、可预测的 |
接下来简要说明下,Agent Compose 下的不同的组合原语。
SubAgents
- Agent 间协作方式:Transfer
- AgentInput 的上下文策略:上游 Agent 全对话
- 决策自主性:自主决策
将用户提供的 agent 作为 父 Agent,用户提供的 subAgents 列表作为 子 Agents,组合而成可自主决策的 Agent,其中的 Name 和 Description 作为该 Agent 的名称标识和描述。
- 当前限定一个 Agent 只能有一个 父 Agent
- 可采用 SetSubAgents 函数,构建 「多叉树」 形式的 Multi-Agent
- 在这个「多叉树」中,AgentName 需要保持唯一
1 | func SetSubAgents(ctx context.Context, agent Agent, subAgents []Agent) (Agent, error) { |
Workflow
提供了 顺序、并行和循环三种工作流模式,供用户灵活组合出不同的工作流图
在 Workflow Agent 中,每个 Agent 拿到相同的 AgentInput 输入,按照预先设定好的拓扑结构所表达的顺序依次运行
Sequential
- Agent 间协作方式:Transfer
- AgentInput 的上下文策略:上游 Agent 全对话
- 决策自主性:预设决策
将用户提供的 SubAgents 列表,组合成按照顺序依次执行的 Sequential Agent,其中的 Name 和 Description 作为 Sequential Agent 的名称标识和描述。
Sequential Agent 执行时,将 SubAgents 列表,按照顺序依次执行,直至将所有 Agent 执行一遍后结束。
注: 由于 Agent 只能获取到上游 Agent 的全对话,后执行的 Agent 看不到先执行的 Agent 的 AgentEvent 输出。
1 | type SequentialAgentConfig struct { |
Parallel
- Agent 间协作方式:Transfer
- AgentInput 的上下文策略:上游 Agent 全对话
- 决策自主性:预设决策
将用户提供的 SubAgents 列表,组合成基于相同上下文,并发执行的 Parallel Agent,其中的 Name 和 Description 作为 Parallel Agent 的名称标识和描述。
Parallel Agent 执行时,将 SubAgents 列表,并发执行,待所有 Agent 执行完成后结束。
1 | type ParallelAgentConfig struct { |
Loop
- Agent 间协作方式:Transfer
- AgentInput 的上下文策略:上游 Agent 全对话
- 决策自主性:预设决策
将用户提供的 SubAgents 列表,按照数组顺序依次执行,循环往复,组合成 Loop Agent,其中的 Name 和 Description 作为 Loop Agent 的名称标识和描述。
Loop Agent 执行时,将 SubAgents 列表,按照顺序依次执行,并循环往复,直至配置的最大迭代次数为止。
1 | type LoopAgentConfig struct { |
AgentAsTool
- Agent 间协作方式:ToolCall
- AgentInput 的上下文策略:全新任务描述
- 决策自主性:自主决策
将一个 Agent 转换成 Tool,被其他的 Agent 当成普通的 Tool 使用。
注:一个 Agent 能否将其他 Agent 当成 Tool 进行调用,取决于自身的实现。adk 中提供的 ChatModelAgent 支持 AgentAsTool 的功能
1 | func NewAgentTool(_ context.Context, agent Agent, options ...AgentToolOption) tool.BaseTool { |
下图展示了 Agent1 把 Agent2、Agent3 当成 Tool 进行调用的过程,类似 Function Stack Call,即在 Agent1 运行过程中,将 Agent2、Agent3 当成工具函数来进行调用。
- AgentAsTool 可作为 Supervisor Multi-Agent 的一种实现方式
Single Agent
Built-In Single Agent
ChatModelAgent
ChatModelAgent 实现了 ReAct 范式的 Agent,基于 Eino 中的 Graph 编排出 ReAct Agent 控制流,通过 callbacks.Handler 导出 ReAct Agent 运行过程中产生的事件,转换成 AgentEvent 返回。
想要进一步了解 ChatModelAgent,请看:Eino ADK: ChatModelAgent
1 | type ChatModelAgentConfig struct { |
Agent 运行
AgentRunner 是 Agent 的执行器。
通过 ADK 框架,编排组合出的 Multi-Agent,推荐采用 adk.NewRunner 包装执行。 只有通过 Runner 执行 agent 时,才可以使用 ADK 的如下功能:
- Interrupt & Resume
- 切面机制
- Context 环境的预处理
1 | type RunnerConfig struct { |
Agent 运行示例
Agent 执行时,通过 adk.NewRunner 包装执行,方便使用 adk 提供的各种扩展能力
1 | func runWithRunner() { |
参考
https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/outline/