08|Workflow 实战:用字段映射表达业务流程 - eino框架
08Workflow 实战用字段映射表达业务流程《Eino 实战用 Go 构建 AI 应用与智能体》· 第 08 篇关键词compose.Workflow、DAG、MapFields、字段级依赖、并行前置条件已完成 07Graph 实战。Graph 用“节点 边”描述流程直观且灵活。但它有个副作用当节点变多、数据来源变复杂时整块传递会变得含糊——下游到底需要上游的哪部分数据只能翻代码才知道。Workflow 换了个角度不描述“谁连谁”而描述数据依赖。它面向有向无环图DAG并支持在结构体字段级别做映射。一、核心差异声明依赖而不是连线对比两种写法// Graph显式连线_g.AddEdge(classify,merge)_g.AddEdge(keywords,merge)// Workflow声明依赖关系并指定字段映射node.AddInput(classify,compose.MapFields(Category,Category)).AddInput(keywords,compose.MapFields(Keywords,Keywords))AddInput同时表达了两件事执行依赖——merge必须等classify和keywords都完成后再执行。数据映射——把上游输出的某个字段映射到本节点输入的某个字段。因此Workflow 里的并行是自动的只要两个节点之间没有依赖声明它们就可以同时执行一旦都被某个下游AddInput它们会在那里汇聚。二、MapFields字段级映射compose.MapFields(from,to)from是上游输出结构体中的字段名。to是本节点输入结构体中的字段名。例如AddInput(classify,compose.MapFields(Category,Category))含义是“把 classify 节点输出的Category字段填入本节点的Category字段”。这个设计的好处是依赖关系写在字段上代码读起来就是数据流。想知道某个字段从哪来搜索MapFields的目标字段即可。需要注意一条约束同一个输入字段不能被多个上游同时映射。如果两个MapFields的第二个参数都写成Line编译会直接报错two terminal field paths conflict for node merge: [Line], [Line]这是实际踩到的错误见下方示例。含义很明确一个字段只能有一个来源需要合并多个上游的数据时应分别映射到不同字段再在节点内部组合。三、完整示例下面这段程序不访问网络可直接运行。它把“分类”和“提取关键词”两个互不依赖的节点并行执行再汇聚到一个节点packagemainimport(contextfmtlogstringsgithub.com/cloudwego/eino/compose)// TicketInput 是工作流的整体输入。typeTicketInputstruct{Rawstring}// ClassifyOutput 只提供分类字段。typeClassifyOutputstruct{Categorystring}// ExtractOutput 只提供关键词字段。typeExtractOutputstruct{Keywordsstring}// SummaryOutput 是最终汇总结果。typeSummaryOutputstruct{CategorystringKeywordsstringLinestring}funcmain(){iferr:run();err!nil{log.Fatal(err)}}funcrun()error{ctx:context.Background()wf:compose.NewWorkflow[TicketInput,SummaryOutput]()// 分类节点读取输入的 Raw 字段。wf.AddLambdaNode(classify,compose.InvokableLambda(func(_context.Context,in TicketInput)(ClassifyOutput,error){ifstrings.Contains(in.Raw,打印)||strings.Contains(in.Raw,离线){returnClassifyOutput{Category:hardware},nil}returnClassifyOutput{Category:other},nil},)).AddInput(compose.START)// 关键词节点同样读取 Raw 字段可与分类节点并行。wf.AddLambdaNode(keywords,compose.InvokableLambda(func(_context.Context,in TicketInput)(ExtractOutput,error){returnExtractOutput{Keywords:打印机,离线},nil},)).AddInput(compose.START)// 汇总节点用字段映射分别从上游取字段组装成自己的输入。wf.AddLambdaNode(merge,compose.InvokableLambda(func(_context.Context,in SummaryOutput)(SummaryOutput,error){in.Linein.Category | in.Keywordsreturnin,nil},)).AddInput(classify,compose.MapFields(Category,Category)).AddInput(keywords,compose.MapFields(Keywords,Keywords))wf.End().AddInput(merge)runnable,err:wf.Compile(ctx)iferr!nil{returnfmt.Errorf(编译 Workflow 失败: %w,err)}out,err:runnable.Invoke(ctx,TicketInput{Raw:三楼打印机离线无法出纸})iferr!nil{returnfmt.Errorf(执行 Workflow 失败: %w,err)}fmt.Printf(Workflow 输出: %v\n,out)returnnil}实机输出Workflow 输出: {Category:hardware Keywords:打印机,离线 Line:hardware | 打印机,离线}可以看到merge节点的输入同时拿到了来自classify的Category和来自keywords的Keywords节点内部再把它们组合成Line。四、几个关键约定1. 数据依赖即执行依赖。没有AddInput声明的节点不会被执行也不会自动连到流程里。每个节点都要能找到从START出发的依赖路径。2. 输入输出必须能映射。MapFields的字段名基于结构体字段写错会在编译期报错或映射不到值。这比运行时才发现问题好得多。3. 一个字段一个来源。同一个输入字段被多次映射会直接冲突报错需重新设计结构体字段。4. Workflow 无环。它是 DAG不支持循环。需要回退重试时用 Graph第 07 篇。5. 并行是隐式的。没有互相依赖的节点会被并行调度不必显式声明。这既是优点也有代价并行度不直观需要通过依赖关系推断。五、Workflow、Graph、Chain 怎么选场景推荐理由顺序处理步骤少Chain最简洁需要循环、复杂动态分支Graph支持环控制力最强多节点、依赖关系明确、字段来源多样Workflow字段级映射让数据流可读需要向模型/工具传整块消息列表Graph 或 ChainWorkflow 偏向结构化字段还有一点要再次强调因为概念名称容易混compose.Workflow是组件编排 API而 ADK 里的SequentialAgent、ParallelAgent、LoopAgent是智能体组合方式第四、五篇展开。它们不是同一个东西也不是彼此的别名。六、常见问题编译报字段路径冲突同一个输入字段被多个上游映射。改用不同目标字段或在节点内部合并。节点没有执行缺少AddInput依赖声明节点没有被纳入执行链。字段映射后取到零值MapFields的字段名与本节点结构体字段名不匹配或上游没有填充该字段。想要执行顺序但不想传数据可以用AddDependency之类的方式只表达依赖。若确实只是“先后执行”用 Graph 的AddEdge反而更直观。上游需要整块结构而不是某几个字段AddInput不传MapFields时表达的是整块依赖。具体行为以官方文档为准涉及整块传递时建议先用小示例验证。七、小结Workflow 面向 DAG用AddInput声明执行依赖与字段映射。MapFields(from, to)描述字段级数据流让依赖关系可读。无依赖关系的节点自动并行无需显式声明。一个输入字段只能有一个来源冲突会在编译期报错。Workflow 不支持环需要重试回退时用 Graph。下一篇《流式编程从模型分片到完整业务结果》我们处理 Eino 中最现实也最容易出错的一环流。参考资料与版本说明资料核对日期为2026 年 10 月 9 日Workflow 编排框架Chain/Graph 编排介绍Eino 主仓库本文示例按Eino v0.9.21编写实机运行正文输出为真实结果。文中“字段冲突”报错的原文也来自实际运行。

相关新闻

Python+Tkinter桌面天气应用开发:API接入、线程刷新与打包实战

Python+Tkinter桌面天气应用开发:API接入、线程刷新与打包实战

最近手头有个需求:把天气数据搬到电脑桌面上,做一个能常驻、能一眼看清当天和未来几天情况的桌面版天气预报应用。说实话,一开始我是有一点轻视这个项目的——天气API一调、窗口一画,不就完事了?结果真正做起来才发现&…

2026/10/14 6:28:27 阅读更多 →
Python入门:吃透第一行print,理解函数、字符串与参数

Python入门:吃透第一行print,理解函数、字符串与参数

如果让我只给一句关于 Python 入门的建议,我会说:不要停在“把教程看完”这一步,也不要以复制代码为目标,请认认真真写下你的第一行print("Hello, World!"),然后追着去问一句“它到底做了什么”。这个从零到…

2026/10/14 6:28:27 阅读更多 →
零依赖实验:用原生HTML/CSS/JS打造个人导航页,摆脱Webpack与node_modules

零依赖实验:用原生HTML/CSS/JS打造个人导航页,摆脱Webpack与node_modules

上个月翻仓库,翻出一个五年前的旧项目。当年为了显得“正规”,我给它配齐了webpack、babel、eslint、jest、husky,一份小得可怜的业务代码,外面裹了三层构建工具。项目早就没人维护了,而那天我光是让它重新跑起来&…

2026/10/14 6:28:27 阅读更多 →

最新新闻

Redisson集成全攻略:原始依赖与Spring Boot Starter实战对比

Redisson集成全攻略:原始依赖与Spring Boot Starter实战对比

在实际项目中,用 Redis 做分布式锁、缓存预热、接口幂等性控制,几乎是 Java 后端开发绕不开的日常操作。而 Redisson 作为 Redisson 官方出品的 Java 客户端,能提供分布式锁、限流器、消息队列、本地缓存等一系列高级能力,很多团队…

2026/10/14 7:07:35 阅读更多 →
AnyPS5实战指南:从局域网到公网,让任何设备都能远程玩PS5

AnyPS5实战指南:从局域网到公网,让任何设备都能远程玩PS5

你是不是也遇到过这种场景:客厅电视被家里人占着追剧,刚入手的 PS5 只能搁那儿吃灰;出差住酒店,手痒想打两把,主机却远在几百公里外;晚上躺在床上想玩会儿游戏,又懒得把显示器和主机全搬到卧室。…

2026/10/14 7:07:34 阅读更多 →
Natron G‘MIC Wave 节点完全指南:波浪变形滤镜的参数详解与应用配置

Natron G‘MIC Wave 节点完全指南:波浪变形滤镜的参数详解与应用配置

音视频视频处理图形学桌面应用 【免费下载链接】Natron Open-source video compositing software. Node-graph based. Similar in functionalities to Adobe After Effects and Nuke by The Foundry. 项目地址: https://gitcode.com/gh_mirrors/na/Natron 点击查看 …

2026/10/14 7:07:34 阅读更多 →
基于蝴蝶优化算法的IEEE30节点无功优化Matlab实现

基于蝴蝶优化算法的IEEE30节点无功优化Matlab实现

1. 无功优化问题的工程本质与算法选型逻辑1.1 无功功率优化到底在优化什么做过电力系统仿真的朋友都知道,最优无功功率分配(ORPD)和最优潮流(OPF)之间有一条清晰的边界:OPF关心的是整个电网的经济运行点&am…

2026/10/14 7:07:34 阅读更多 →
管网三维自动化建模的关键技术:数据治理、拓扑生成与参数调优

管网三维自动化建模的关键技术:数据治理、拓扑生成与参数调优

简介:蚂蚁管网三维自动化建模软件是一款面向城市管网规划、设计与维护人员的专业工具,将二维管网数据(如CSV中的坐标与属性)自动转化为三维模型,支持OBJ与3DTiles格式输出,可无缝对接GIS、BIM等平台。压缩包…

2026/10/14 7:07:34 阅读更多 →
TypeScript只读映射类型:Readonly<Record>与直接声明对比

TypeScript只读映射类型:Readonly<Record>与直接声明对比

1. TypeScript 只读映射类型深度解析在 TypeScript 的类型系统中&#xff0c;Readonly<Record<K, V>> 和 { readonly [K in Key]: Value } 这两种看似相似的只读映射类型声明方式&#xff0c;在实际项目中有完全不同的类型行为和适用场景。作为从 TypeScript 1.5 版…

2026/10/14 7:06:34 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起&#xff1a;它到底想解决什么问题第一次看到"AnyPS5"这个标题&#xff0c;我脑子里冒出来的第一个念头是&#xff1a;这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述&#xff1a;Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师&#xff0c;我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性&#xff0c;实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景&#xff0c;也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间&#xff0c;确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中&#xff0c;这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介&#xff1a;基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码&#xff0c;面向计算机相关专业课程设计与期末大作业学生&#xff0c;以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程&#xff0c;…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程&#xff1a;键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化&#xff0c;十个新手有八个栽在"往输入框里填东西"这件事上&#xff1a;要么填不进去&#xff0c;要么填了一半&#xff0c;要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →