三张图跑同一条链:两张出卡,一张退回原描述。 空图那一支跳过的只有画板,不是整条链——信息提取返回「没抽到」本身就是结果。 单节点测定位一步,整链测要往回追三步,线上报错往往三五步。
五个节点各自测通了,这一节连起来测。 和第 8.8 节一样,只跑一条正常路径等于只测了三分之一。 这一章的分支只有一条:抽到字段走画板,抽不到直接到结束。 但这一条分支必须测——它平时不触发,一旦触发就是用户拍了一张没字的图。
一、三张图一起跑
第一张标准卡、第二张词性是中文的、第三张白墙。三张走同一条链。
| 图 | 画板 | 交回什么 |
|---|---|---|
| card_01 | 跑了 | 5/5 字段 + 卡片 |
| card_02 | 跑了 | 5/5 字段 + 卡片 |
| card_03 | 跳过 | 退回原描述 |
三张都是五步,区别只在第四步跑没跑。 第二张虽然少一个词性字段,但五个键都在(缺的那个是空值),所以照样出卡。 「字段在但值为空」和「字段不在」是两件事——第 9.7 节讲过,这里正好看到它在链上的表现。
二、空图那一支跳过了谁
第三张的轨迹是这样的:开始、图片理解、信息提取(输出「0 个」)、画板(跳过)、结束。 跳过的只有画板。信息提取照跑,它返回「没抽到」这个信号,下游据此改道。 这里最容易写错的地方:把分支写成「整条链结束」。 跳过和结束不一样。跳过是这一支不走,结束是整张图停。
演示里靠一条边的判定做的:信息提取选 empty,那么 ext -> bd 这条边断,ext -> e 这条边活,
画板的所有入边都断了才跳过。
按节点判会出错:两条支路汇到一个节点时,一条断了一条还活着,那个节点就该跑。
所以判的是边,不是节点。
三、单节点测和整链测
单节点测:给一组输入,看输出对不对。定位一步——就是这个节点。 整链测:给一张图,看最后交回什么。坏了要往回追:是没抽到、抽错了、还是画板没画出来。 线上报错更远:日志里只有一句「某节点执行失败」,给位置不给原因。要往回追三到五步。
所以整链测不能省。 单节点测便宜,但它验不了「上游有没有把下游要的字段吐出来」这件事。
四、上线前还得测三样
一、超时:一张特别大的图,图片理解那一步会不会超时。 超时要设一个上限,超了就降级——先返回文字,图后面补。 二、连拍:用户连着发五张图,五次调用会不会互相踩。这一条要靠并发测试,不是单条链能测出来的。 三、脏图:截图、竖图、糊图、没有文字的图。四种各跑一次,看兜底触发得对不对。
第四种(没有文字)演示里测了。前三种只能拿真图去试,造不出来。
五、动手 Demo:整链测试:三张图跑一遍
同一条五节点的链,三张图各跑一次。第三张是空图,会走兜底支路。 跑完再把第三张的轨迹单独打出来,看它到底跳过了谁。
f.link(u'ext', u'bd', when=u'ok') # 抽到字段走画板
f.link(u'ext', u'e', when=u'empty') # 抽不到直接到结束
f.link(u'bd', u'e') # 画板跑完也到结束
def ext_out(pic):
d = dict(pic[1])
d[u'__pick__'] = u'ok' if d else u'empty' # 选哪条边
实跑输出:
--------------------------------------------------------------------
整链测试:三张图跑一遍
--------------------------------------------------------------------
① 三张图走同一条链
--------------------------------------------------------------------
| 图 | 节点数 | 画板 | 交回什么 | 毫秒 |
|---|---|---:|---:|---:|
| card_01.jpg | 5 | 跑了 | 5/5 字段 + 卡片 | 0.2 |
| card_02.jpg | 5 | 跑了 | 5/5 字段 + 卡片 | 0.1 |
| card_03.jpg | 5 | 跳过 | 退回原描述 | 0.1 |
第三张图没抽到字段,画板整枝跳过,结束节点退回原描述。这就是兜底支路存在的意义。
② 空图那一支到底跳过了谁
--------------------------------------------------------------------
| 步 | 节点 | 类型 | 输出端口 | 毫秒 |
|---:|---|---|---|---:|
| 1 | 开始 | 开始 | url | 0.0 |
| 2 | 图片理解 | 大模型 | desc | 0.0 |
| 3 | 信息提取 | 大模型 | hit | 0.0 |
| 4 | 画板 | 画板 | 跳过 | — |
| 5 | 结束 | 结束 | out | 0.0 |
跳过的是画板,不是整条链。信息提取返回「没抽到」这件事本身就是结果,下游据此改道。
③ 单节点测和整链测,差在哪
--------------------------------------------------------------------
| 怎么测 | 定位要几步 | 各测出什么 |
|---:|---|---|
| 单节点测 | 1 | 只验一个节点收什么、吐什么 |
| 整链测 | 3 | 要按图往上追:谁没吐出下游要的字段 |
| 线上报错 | 3 ~ 5 | 只有一句「某节点执行失败」,连追几层 |
! 单节点测便宜,整链测才敢上线。两个都跑,别只跑一个。
①第一张表三行:两张出卡、一张退回原描述。三张都是五个节点。 ②毫秒那列是 0.1,说明这条链本身几乎不耗时——时间全花在模型调用上。 ③第二段把空图那一支的轨迹单独打出来:第四步画板写的是「跳过」。 ④跳过的是画板,不是整条链。信息提取返回「0 个」这件事本身就是结果。 ⑤最后一张表:单节点测 1 步,整链测 3 步,线上报错 3~5 步。
30 秒实验
- 把你的链跑三种输入:正常的、字段缺一半的、完全抽不到的。三种的兜底各是什么。
- 故意把一条边连错,跑一次,看报错指向哪一步。记住这个位置,下次排错能省一半时间。
- 拿一张竖图、一张截图各跑一次,看版式那一段描述会不会乱。
常见误区
- 「跑通一次就算过。」跑通只证明这一条路径通。分支的另一条可能一直是坏的。
- 「空图会让整条链停下。」不会,只跳过画板。跳过和结束是两回事。
- 「单节点都测过了,整链不用测。」单节点验不了上游有没有吐出下游要的字段。
自测三问(点开对答案)
1. 空图那一支跳过了谁? —— 只跳过画板。信息提取照跑,返回「没抽到」这个信号,结束节点改交原描述。 2. 为什么按边判而不按节点判? —— 两条支路汇到一个节点时,一条断了一条还活着,那个节点就该跑。按节点判会误跳。 3. 上线前还要测什么? —— 超时、连拍并发、脏图(截图、竖图、糊图、没字的图)。这四样单条链测不出来。链测通了,最后一步把它挂到智能体上。这一节讲先判该不该调。
- ☐ (本篇完,下一篇 9.9 创建智能体调用工作流)
相关笔记
- 完整工作流测试:上一章同样的动作
- 扣子工作流的逻辑结构:分支怎么连
- 配置【结束】节点:字段在但值为空
- 🐦 扣子开发 AI Agent · 索引