结束节点是整条链的输出契约:交出去几个字段、每个什么类型。 不声明就是一大串文字,下游取不出任何字段——而且它不报错。 只声明下游真要用的那几个。声明十个用两个,剩下八个是维护负担。
上一节把图生成了,这一节把东西交出去。 这一节很短,但它决定了下游能不能接。 第 7.2 节讲数据库定字段,这里是同一件事——只是一个在表里,一个在节点上。 「不声明也不报错」这一条是本节的重点。所有静默失败的坑都是同一个形状。
一、两种输出形态
声明过的:一个对象,三个字段——text、img、title。每个字段单独取。 没声明的:一整串字,二十七字。它就是一串字符,没有结构。 演示里下游要取 img,声明过的直接拿到地址;没声明的拿不到,只能拿到一整串。
这不是「取不到报错」,是「取不到返回空」。 差别很大:报错你会去修,返回空你会以为没数据。
二、没声明时会怎么坏
最轻的坏法:下游拼出一句「(是一整串,取不出 img)」这种缺角的文案。 最重的坏法:卡片节点的占位一个都填不上,渲染出一张空卡。 中间的坏法:把整串字塞进了 title 字段,卡片上显示一整段文章。
三种坏法的共同点:链是通的,日志是绿的。 所以它是最难查的一类故障——你得主动去看输出,而不是等它报错。
三、该声明什么
一、每个字段一个名字,用英文或拼音。中文在引用里能拼,在代码节点里容易出编码问题。 二、每个字段一个类型:文本、图片地址、数字、布尔。类型写错,下游解析时会出问题。 三、只声明下游真要用的那几个。 声明十个,下游只用两个,剩下八个是维护负担。
第三条容易被忽略。多声明一个字段,就多一处要保证它有值的地方。
四、不同渠道要不同字段
| 场景 | 要声明的字段 |
|---|---|
| 发到公众号 | title、text、img |
| 发到小红书 | title、text、img、tags |
| 只回一句话 | text |
同一张工作流要发三个平台,怎么办?两种做法。 做法一,声明三套,用选择器挑。 一张图搞定三个渠道,但结束节点前面多一个分支。 做法二,复制三份工作流。 简单,但改一处要改三份——这是第 6.4 节说的「复制会变的东西」的坑。
推荐做法一。能用一个分支解决的,别复制整张图。
五、输出契约和输入契约
一张工作流有两个契约:开始节点的入参、结束节点的输出。 两个都要定清楚。开始节点定不清,调用方会漏填;结束节点定不清,下游会取空。 有个对称的观察:入参错一般是「报错」,出参错一般是「静默」。
因为入参有人喂,喂错了喂的人知道;出参没人验,取空了取的也不知道。所以出参那一侧要格外小心。
六、什么时候回来定这个
第 8.2 节说过:先让链跑通,再回来定结束节点。 跑通之前,你不知道中间会产出什么字段。定早了要反复改。 但也不能一直不定。判断标准:中间节点的输出稳定了(三天没改),就回来定契约。
定完之后,改契约才算「改接口」。改之前先搜一遍哪些下游在取这些字段。
七、动手 Demo:结束节点:输出不声明,下游接不住
同一份内容准备两个版本:一个声明了三个字段,一个就是一整串字。 再让下游分别去取 text、img、title,看两边结果。
APPLE = {u'text': 文案, u'img': u'https://x/1.png', u'title': 标题}
STRING = 文案 + u' ' + u'https://x/1.png' # 没声明:一整串
def take(out, field):
if isinstance(out, dict):
return out.get(field, u'(没有这个字段)')
return u'(是一整串,取不出 %s)' % field
实跑输出:
--------------------------------------------------------------------
结束节点:输出不声明,下游接不住
--------------------------------------------------------------------
① 两种输出形态
--------------------------------------------------------------------
声明的:一个对象,三个字段——text、img、title。
text = AI 眼镜销量翻倍……
img = https://x/1.png
title = AI 眼镜卖爆了
没声明的:一整串 27 字。
② 下游取字段
--------------------------------------------------------------------
| 要的字段 | 声明了 | 没声明 |
|---|---|---|
| text | AI 眼镜销量翻倍…… | (是一整串,取不出 text) |
| img | https://x/1.png | (是一整串,取不出 img) |
| title | AI 眼镜卖爆了 | (是一整串,取不出 title) |
声明了三个字段都能取到;没声明的三个全取不出——它就是一串字,没有结构。
③ 没声明时会怎么坏
--------------------------------------------------------------------
最轻的坏法:下游拼出一句「(是一整串,取不出 img)」这种缺角的文案。
最重的坏法:卡片节点的占位一个都填不上,渲染出一张空卡。
而且它不报错。 链是通的,日志是绿的。
④ 结束节点该声明什么
--------------------------------------------------------------------
一、每个字段一个名字,名字用英文或拼音,别用中文(下游引用要拼)。
二、每个字段一个类型:文本、图片地址、数字、布尔。
三、只声明下游真要用的那几个。 声明十个字段,下游只用两个,剩下八个是维护负担。
⑤ 一条对照
--------------------------------------------------------------------
| 场景 | 要声明的字段 |
|---|---|
| 发到公众号 | title、text、img |
| 发到小红书 | title、text、img、tags |
| 只回一句话 | text |
同一张工作流要发三个平台,就在结束节点声明三套,用选择器挑。别为每个平台复制一份工作流。
! 结束节点是整条链的输出契约。契约不写清,下游全靠猜。
这一条和第 7.2 节「字段要定清楚」是同一个道理,只是一个在表里,一个在节点上。
①第一段声明过的:一个对象三个字段,每个都能单独取。 ②第二张表三行对照。声明了三个都能取到;没声明的三个全取不出——它没有结构。 ③第三段讲坏法:最轻是缺角文案,最重是空卡,中间是把整段文章塞进标题。 ④三种坏法的共同点:链是通的,日志是绿的。这是最难查的一类故障。 ⑤最后那段讲入参与出参的不对称:入参错会报错,出参错会静默。所以出参那侧要格外小心。
30 秒实验
- 打开你的结束节点,数一下声明了几个字段。超过五个的,砍到下游真用的那几个。
- 顺一遍下游:它取的那几个字段,结束节点里都有吗。
- 检查一下字段名有没有中文。有就改成英文或拼音,省得以后在代码节点里出编码问题。
常见误区
- 「输出是一段文字就够了。」下游要按字段取。不声明就是一大串,什么都取不出。
- 「字段多声明几个保险。」多一个字段就多一处要保证有值。声明十个用两个是负担。
- 「取不到会报错。」不会,返回空。链照跑、日志照绿,你得主动去看输出。
自测三问(点开对答案)
1. 结束节点的作用是什么? —— 输出契约:交出去几个字段、每个什么类型。不声明下游就取不出任何字段。 2. 为什么不声明不报错? —— 它输出的是一整串合法文字,没有「错」。只是没有结构,下游取字段时返回空。 3. 入参错和出参错有什么不对称? —— 入参错一般报错(喂的人知道),出参错一般静默(取的人也不知道)。所以出参要格外小心。五个模块都装好了,下一节整条链跑一遍。要跑三种输入,不是一种。
- ☐ (本篇完,下一篇 8.8 完整工作流测试)
相关笔记
- 配置图片生成模块:文案转画图提示词
- 创建扣子数据库:字段怎么定
- 扣子工作流的逻辑结构:四道校验
- 🐦 扣子开发 AI Agent · 索引