先搭一副空骨架:开始、图片理解、结束。三个节点,两条边。 中间节点的实现全是占位,链能跑完但什么也没干。这就够了。 骨架的意义是先把电流接通,之后一次配一个节点,配一个跑一次。
上一节画了设计图,这一节把它落到画布上。 很多人一上来就把六个节点全拖出来、全连上、全配完,然后一次运行——报错了不知道从哪查。 这一节的做法正相反:先让三个节点跑通,再加第四个。慢,但每次只错一处。
一、三个节点,两条边
第一版只放三个:开始、图片理解、结束。信息提取和画板先不建。 为什么能省?因为图片理解的输出是一段文字,结束节点直接收文字也能交差。 先跑通这个最简版,整条链就活了。 演示里跑完,存盘校验四项全过:无环、无孤儿、无悬空出口、结束节点正好一个。
三个节点各吐一个端口:url、desc、out。看着简陋,但每一步都有输出,这就是能往下加的前提。
二、四道校验,平台也会拦
存盘前平台会跑四道检查。这四道我在第 4.3 节讲过,这里换成这个案例再看一遍:
| 检查 | 报什么 | 怎么修 |
|---|---|---|
| 有没有环 | 存在环 | 找到回指的那条边,删掉 |
| 有没有孤儿 | 孤立节点 | 给它接一条入边 |
| 有没有悬空出口 | 出口未连接 | 接到下一个节点或结束 |
| 结束节点几个 | 没有或多于一个 | 留一个,多余的删 |
演示里故意造了三张坏图。第一张两个节点互相指,第二张画板节点孤零零挂着,第三张信息提取没接到结束。
三张全被拦住。第一张报「有环」,环长这样:vis -> ext -> vis。
拓扑排序排到一半卡住,卡在环上的就是这几个。
第二张报了两条:「孤儿节点:bd」和「悬空出口:bd」。一个节点既没进边也没出边时,两条都成立。
报几条不重要,拦住就行。
三、骨架阶段只验一件事
骨架阶段不验内容对不对,只验电流通不通:节点全连上、校验四过、整链能跑到结束。 内容对不对是下一步的事。这时候占位实现返回「待配置」三个字,整条链照样跑完——证明线路没接错。 这个做法有个额外好处:你能看见每一站停在哪。 六个节点全配完再跑,中间值是一片黑; 骨架阶段每个节点都吐一个占位,一眼看出走到哪了。
四、一次只配一个节点
骨架通了之后,配图片理解,跑一次;再配信息提取,再跑一次。 每次只改一处,报错必然是新改出来的。 这是最省时间的调试法,和第 8.5 节的「配一段测一段」是同一个套路。 反过来,六个节点一起配完再跑,出了错你得挨个回滚。回滚比逐步配慢得多。
五、命名和注释
节点名别用默认的「大模型_1」「大模型_2」。改成「图片理解」「信息提取」。 理由是排错:日志里显示的是节点名,不是节点位置。名字起对了,一眼知道哪一步坏了。 每个节点留一句注释,写「它负责什么、不负责什么」。第二个人接手时,这一句能省半小时。
六、动手 Demo:先搭骨架,再配节点
先跑一副三节点的空骨架,再故意造三张连不通的图,看校验各报什么。 坏图只跑校验,不跑执行——有环的图连拓扑序都排不出来。
def skel(links=None, mids=()):
f = Flow(u'骨架')
f.add(start, vis, end) # 中间节点的实现都是占位
for a, b in links or ((u's', u'vis'), (u'vis', u'e')):
f.link(a, b)
return f
bad = f.check() # 返回列表:有环 / 孤儿 / 悬空 / 结束节点个数
实跑输出:
--------------------------------------------------------------------
先搭骨架,再配节点
--------------------------------------------------------------------
① 三个节点、两条边,先看能不能存盘
--------------------------------------------------------------------
存盘前校验:四项全过
| 步 | 节点 | 类型 | 输出端口 | 毫秒 |
|---:|---|---|---|---:|
| 1 | 开始 | 开始 | url | 0.0 |
| 2 | 图片理解 | 大模型 | desc | 0.0 |
| 3 | 结束 | 结束 | out | 0.0 |
链走完了,中间节点只吐出「待配置」。骨架的意义就是先让电流通。
② 三种连不通的图,平台都会拦
--------------------------------------------------------------------
| 哪里连错了 | 平台保存时 | 这里的 check 报什么 |
|---|---|---|
| 两节点互相指向 | 报错:存在环 | 有环 |
| 画板节点没连线 | 提示:孤立节点 | 孤儿节点:bd、悬空出口:bd |
| 信息提取没接到结束 | 提示:出口未连接 | 孤儿节点:e、悬空出口:vis |
环长这样:vis -> ext -> vis。拓扑排序排到一半卡住,卡住的那几个就在环上。
注意第二行报了两条:一个节点既没进边也没出边时,「孤儿」和「悬空出口」都成立。
报几条不重要,重要的是它拦住了你。
③ 骨架阶段只验一件事:电流通不通
--------------------------------------------------------------------
! 节点全连上、校验四过、整链能跑完,就可以开始填内容了。
接下来一次只配一个节点:配完图片理解跑一次,配完信息提取再跑一次。
①第一段三个节点两条边,校验四项全过,三步跑完,两个占位端口都吐出了字。
②第二张表三行坏图:环、孤立节点、出口未连接,平台提示和这里报的一一对应。
③环那条单独补一句:vis -> ext -> vis,拓扑排序卡住的位置就是环的位置。
④注意第二行报了两条——孤立节点的「孤儿」和「悬空出口」同时成立。
⑤最后一节讲骨架阶段只验电流,不验内容。内容对了是下一步的事。
30 秒实验
- 建一张只有开始、一个中间节点、结束的图,跑一次,看三个端口都吐了什么。
- 故意删掉一条边,再存一次,看平台报哪一条。四种错各试一次,记住它们的提示语。
- 把节点名从「大模型_1」改成有意义的词。改完再跑一次,看日志里的差别。
常见误区
- 「一次配完再跑,省时间。」出错要挨个回滚,比逐步配慢得多。
- 「骨架没内容,跑它干什么。」骨架验的是线路。线路错了,配得再对也白配。
- 「节点名无所谓。」日志里显示的就是节点名。名字含糊,排错时先花十分钟找位置。
自测三问(点开对答案)
1. 为什么第一版只放三个节点? —— 图片理解的输出是文字,结束节点能直接收。先跑通最简版,整条链就活了。 2. 四道校验分别查什么? —— 有环、孤儿、悬空出口、结束节点个数。前三个是连错,第四个是结构不合规。 3. 为什么一次只配一个节点? —— 每次只改一处,报错必然是新改的。一起配完再跑,出错得挨个回滚。骨架通了,开始填第一个节点:图片理解。这一节的难点全在提示词上。
- ☐ (本篇完,下一篇 9.3 配置【图片理解】节点)
相关笔记
- 扣子工作流的逻辑结构:四道校验的来历
- 创建基础工作流:上一章同样的动作
- 文案生成测试:配一段测一段
- 🐦 扣子开发 AI Agent · 索引