1750 字
约 5 分钟
8
S21-J06 · Eino 编排:Chain、Graph 与 Workflow 字段映射

适用读者:要用 Go 把"多步模型调用"写成可控流程、而不是一串 if 的人;被节点类型对齐折磨过的人。
前置:S21-B02(ReAct 与规划)、B03(工具设计)、J01(Harness 工程)。
覆盖旧文:A-3581(1. Chain 与 Graph 编排)、A-3584(2. Workflow 与字段映射)、A-3673(链 / LangChain 对照)→ 3 篇 / 6.4 万字符。
扩展点:E-S21-019(编排三步:定义→连接→编译)、E-S21-020(Graph 的类型对齐困境与三种错解)、E-S21-021(Workflow 的"控制流 / 数据流分离"判据)。
上一篇:S21-J05 · CLI 与 GUI Agent
下一篇:S21-J07 · ADK 多智能体编排与生产化特性。


1. 一句话结论

ReAct 让模型自由发挥,编排让你自己定顺序。 前者适合"下一步不确定",后者适合"流程已知但分支多"。Eino 的 compose 包把编排拆成定义 → 连接 → 编译三步;编译期做类型检查,错误不等到运行时才炸。

出处:A-3581、A-3584(秀才,Eino 教程,2026-04)。

Chain  ⊂  Graph  ⊂  Workflow(表达力)
Chain 简单  →  Graph 任意 DAG  →  Workflow 字段级映射

2. 三步模型(E-S21-019)

步 做什么 产物
① 定义节点 每个节点是一个组件:ChatModel / Prompt 模板 / 工具集 / 自定义函数(Lambda) *compose.Node
② 连接节点 AddEdge(顺序)、AddBranch(条件)、并行扇出 DAG
③ 编译 Compile 做类型检查与连接校验 Runnable
// 形状示意(API 以 Eino 当前版本为准)
chain := compose.NewChain[Input, Output]()
chain.AppendChatTemplate(tpl).AppendChatModel(model)
runnable, err := chain.Compile(ctx)   // ← 类型/连接在这里报错
out, err := runnable.Invoke(ctx, in)

判据:"定义与执行分离"是它的核心收益——启动时编译一次,运行时零额外开销;相对的,很多动态解释型框架把错误留到运行时。


3. Chain:线性流水线

chain := compose.NewChain[map[string]any, *schema.Message]()
chain.
    AppendChatTemplate(prompt.FromMessages(schema.FString, sysTpl, userTpl)).
    AppendLambda(compose.InvokableLambda(func(ctx context.Context, in map[string]any) (map[string]any, error) {
        // 自定义逻辑:清洗、拼装、取上下文
        return in, nil
    })).
    AppendChatModel(model)
方法 追加什么
AppendChatModel 模型节点
AppendChatTemplate Prompt 模板节点
AppendLambda 任意函数(最常用)
AppendBranch 条件分支

要点:AppendLambda 是"逃生口"。任何框架没覆盖的逻辑,都包成 Lambda 塞进去,不必改框架。


4. Graph:任意 DAG

g := compose.NewGraph[In, Out]()
g.AddChatModelNode("model", model)
g.AddLambdaNode("score", compose.InvokableLambda(scoreFn))
g.AddEdge(compose.START, "model")
g.AddEdge("model", "score")
g.AddEdge("score", compose.END)
r, err := g.Compile(ctx)
能力 API 说明
顺序 AddEdge(a, b) 数据从 a 流到 b
条件路由 AddBranch(node, branch, map[string]bool{...}) 按条件选边
并行 从同一节点扇出多条边 下游并行执行,再汇合
Invoke  → 一次性拿完整结果
Stream  → 边算边吐(首 token 更快,见 J05)

判据:要"流式输出"就用 Stream;要"拿完整对象再处理"就用 Invoke。 混用会让下游拿到半截数据。


5. Graph 的类型对齐困境(E-S21-020)

问题:AddEdge 同时决定"执行顺序"和"数据传递"——A 的输出必须能赋值给 B 的输入。

A 输出 []*schema.Message
B 输入 ScoreInput{Text string, Dimension string}
→ 类型对不上

三种常见错解:

错解 后果
万能结构体 每个节点背一堆无关字段,业务语义糊掉
全用 map[string]any 丢掉编译期类型检查,运行时断言炸
到处插转换 Lambda 几十个节点时,胶水比业务还多

判据:类型不匹配的根因是"控制流与数据流被绑在一起"。 解法不是加胶水,是把两者拆开。


6. Workflow:字段级映射(E-S21-021)

wf := compose.NewWorkflow[In, Out]()
wf.AddLambdaNode("count", ...)     // 只要 text
wf.AddLambdaNode("keyword", ...)   // 只要 text + keyword
wf.AddLambdaNode("merge", ...)     // 要两个结果

// 关键:用 AddInput 声明"这个节点的每个字段来自哪里"
wf.AddInput("count", compose.MapFields("text", "Text"))
wf.AddInput("merge", compose.MapFields("countResult", "Count", "keywordResult", "Hits"))
wf.AddInput("merge", compose.SetStaticValue("Unit", "char"))
机制 作用
MapFields 把上游输出字段映射到本节点字段
MapFieldPaths 深层路径映射(嵌套结构)
SetStaticValue 注入常量(单位、阈值)
AddDependency 只控顺序、不传数据

判据:控制依赖与数据依赖分开声明。 需要"先跑完 A 再跑 B,但 B 不用 A 的数据"时,用 AddDependency,别硬塞一个没用的字段。

6.1 三者怎么选

场景 选
线性 2–5 步 Chain
有分支/并行、节点类型天然一致 Graph
节点各自有业务结构、字段来源多样 Workflow
需要动态调整拓扑(运行时改图) 以上都不合适 → 自己写调度

7. 反例与排障

现象 原因 处理
Compile 报类型不匹配 边两端类型不一致 改 Workflow + MapFields
运行时 nil 字段 映射的字段名拼错 用小图先跑通映射
并行节点结果顺序乱 汇合处没定顺序 用 map 收集后按 key 取
Stream 下游拿不到完整值 用了只支持 Invoke 的 Lambda 换 StreamableLambda 或改 Invoke
分支永远走一条 AddBranch 的条件函数恒真/恒假 打日志确认分支函数的输入

8. 常见误区

误区 纠正
"Chain 就是简化版 Graph,功能一样" Chain 无分支/并行表达力
"类型对不上就加 Lambda" 胶水会淹没业务,应换 Workflow
"编译过了就一定跑得对" 编译只管类型与连接,不管语义
"并行一定更快" 受下游汇合与限流约束
"Workflow 比 Graph 高级" 同一层,差别只在数据映射方式

9. 自测

  1. Eino 编排的三步是什么?哪一步做类型检查?
  2. Graph 里 AddEdge 同时决定了哪两件事?这带来什么问题?
  3. 节点 B 只要 A 输出的 Score 字段,Graph 与 Workflow 各怎么写?
  4. 只想控制顺序、不传数据,用哪个 API?
答案
  1. 定义节点 → 连接节点 → Compile(编译期类型检查)。
  2. 执行顺序 + 数据传递;导致相邻节点类型必须完全匹配。
  3. Graph:插转换 Lambda 或改类型;Workflow:AddInput("B", MapFields("A", "Score", ...))。
  4. AddDependency。

10. 下一篇

S21-J07 · ADK 多智能体编排与生产化特性 —— 四种 Agent 类型(ChatModel / Sequential / Parallel / Loop)如何嵌套,以及回调、中断恢复、Session Values 与中间件怎么把 Demo 推成生产。


本篇属于系列《S21 · Agent 工程与 MCP》。旧文来源:A-3581/3584;扩展点 E-S21-019/020/021。Eino API 名称以官方文档当前版本为准。

S21-J06 · Eino 编排:Chain、Graph 与 Workflow 字段映射
https://www.clxhxhhr.top/posts/5490/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。