🐦 第4章 扣子工作流详解
📄 一句话概括

工作流是一张图纸:谁先谁后、什么条件走哪条路,都画在图上,不由模型临场决定。 骨架只有三种——顺序、分支、循环。再复杂的图也是这三种套起来。 本节的第一个坎是循环:平台的循环在节点内部转,图上不能有环。

📝 本章和前面几章的关系

前三章讲的是「单个能力」:平台有什么、插件能办什么、卡片怎么摆。 这一章讲怎么把它们串成一条流水线,是全书的骨头。 第 1 章说智能体有四件要素,其中「循环」是让模型自己决定下一步。 工作流相当于把这一件拿回来,改由图纸决定。 读完这五篇,第 5 章的知识库、第 8 到 16 章的九个案例,都是在这张图上加节点。

一、工作流是一张图纸

一个智能体接了五个插件,用户说一句话,模型决定先调哪个、再调哪个。 它多数时候对,但每十次会错一两次,而且错法不固定——今天漏了一步,明天顺序反了。 工作流把这件事挪到图上:顺序由你连的线决定,条件由你写的判断决定。模型只在被点名的那些节点里干活。 所以准确的说法是:工作流不是更聪明的智能体,是把聪明换成确定。它牺牲「看情况」的灵活, 换来「每次都一样」。

这句话反过来也成立:需要看情况的地方,别硬画图。硬画出来的分支会越来越多,最后图比代码还难读。

二、三种骨架

顺序:一步接一步,没有分岔。演示里四个节点,走四步,每步都走。 分支:中间放一个选择器,条件成立走一边,不成立走另一边。 演示里五个节点,实际只走了四步,另一个被跳过。 循环:同一段处理做若干次。演示里循环体只进了一次,原因在下一段。

骨架 图上长什么样 什么时候用
顺序 一条直线 步骤固定、每步都要走
分支 一个岔口两条路 有「看情况」的地方
循环 一个节点,里面转 同一件事对一批数据做

三种骨架的图长什么样,下面的 Demo 打了三张执行轨迹表。 轨迹表比图直观:它告诉你这一次到底走了哪几步、哪一步被跳过了。

三、循环为什么不是图上的环

这是全书最容易搞混的一处。你在纸上画一个圈,A 做完回到 A,图上就出现环了——听着很自然。 但平台的校验不让存。这类引擎的硬约束是 DAG,有向无环图:箭头只能往前走,不能指回来。 那重复怎么办?用「循环节点」:一个节点里面转,图上仍然是一条直线。

为什么要这么设计?因为图上一旦有环,就没法算「这一步之前该做什么」。 调度器排不出顺序,不知道从哪一步开始跑。 演示里第三张表只有三步,循环体那一行是「代码」,输出端口写着 acc 和 done。 那一个节点内部转了几圈,轨迹上看不出来。 记住这一条,后面第 9 章(批量处理)、第 13 章(多轮对话)都用得上:要重复,找循环节点, 别在图上画圈。

四、平台上分两类

平台里「工作流」这个词有两层意思,得分开看。 工作流:输入一段话或者一组变量,跑完给一个结果。一问一答,不记上下文。 对话流:带多轮记忆,能追问、能停下来等用户补一句。第 13 章那些智能体用的就是它。

两者的画法几乎一样,差别在「有没有记忆」和「能不能中途停」。 判断很简单:一次问清一件事用工作流,要来回几次用对话流。

五、什么时候画图,什么时候不画

该画:步骤固定、每次都要走全、出错要能定位、要接好几个能力。 不该画:只有一步、判断依据说不清、需求还在变。 还有一条:用户只要其中一步的时候别画图。 硬走完反而烦人,这一条第 3.2 节算过账。

最后一条经验:先用一句话把流程说给同事听。他说「懂了」,再动手画; 他说「等等,这里为什么」,说明你自己还没想清。

六、动手 Demo:三种骨架:顺序、分支、循环

用同一个最小执行器跑三张图,看轨迹表的差别。三张表都只有一项关键信息:走了几步、哪一步被跳过。

class Node:
    def __init__(self, nid, kind, title, fn, ins=(), outs=()):
        self.nid, self.kind, self.title = nid, kind, title
        self.fn, self.ins, self.outs = fn, ins, outs

class Flow:
    def topo(self):        # 拓扑排序:算「这一步之前该做什么」
        ...
    def check(self):       # 查环、查孤儿、查悬空出口、查结束节点个数
        ...
    def run(self, inputs): # 按拓扑序跑,按边判「这一支该不该跳」
        ...

实跑输出:

--------------------------------------------------------------------
三种骨架:顺序、分支、循环
--------------------------------------------------------------------


  ① 顺序:一步接一步
  --------------------------------------------------------------------

| 步 | 节点 | 类型 | 输出端口 | 毫秒 |
|---:|---|---|---|---:|
|  1 | 开始 | 开始 | text | 0.0 |
|  2 | 知识库检索 | 知识库检索 | hit | 0.0 |
|  3 | 大模型 | 大模型 | a | 0.0 |
|  4 | 结束 | 结束 | out | 0.0 |

  节点 4 个,走了 4 步。没有分岔,每一步都走。

  ② 分支:看情况拐弯
  --------------------------------------------------------------------

| 步 | 节点 | 类型 | 输出端口 | 毫秒 |
|---:|---|---|---|---:|
|  1 | 开始 | 开始 | q | 0.0 |
|  2 | 选择器 | 选择器 | (无输出) | 0.0 |
|  3 | 代码节点 | 代码 | r | 0.0 |
|  4 | 知识库检索 | 知识库检索 | 跳过 | — |
|  5 | 结束 | 结束 | out | 0.0 |

  节点 5 个,走了 5 步,其中跳了 1 个。

  ③ 循环:同一段做几次
  --------------------------------------------------------------------

| 步 | 节点 | 类型 | 输出端口 | 毫秒 |
|---:|---|---|---|---:|
|  1 | 开始 | 开始 | n | 0.0 |
|  2 | 循环体 | 代码 | acc、done | 0.0 |
|  3 | 结束 | 结束 | out | 0.0 |

  演示里循环体只进了一次——因为工作流的「循环」是一个节点内部的重复,不是图上的环。
  ! 这一点最容易搞混:图必须无环,循环靠节点内部转。 图上真有环,平台不让存。

①第一张表是顺序:四个节点走四步,每步都走。看「输出端口」那一列,它告诉你这一步交出去的是什么。 ②第二张是分支:五个节点,知识库检索那一行标着「跳过」。 跳过的节点在轨迹里还占一行——真机上它是变灰。 ③第三张只有三步。循环体那一行是「代码」,输出端口写着 acc、done。 一个节点内部转了几圈,轨迹上看不出来。 ④这就是「图必须无环」的代价:循环的信息藏在节点内部,调试时要看节点自己的日志,不能只看图。 ⑤最后那句提醒看一遍就够:要重复找循环节点,别在图上画圈。 图上真画了圈,平台保存时就报「存在循环」。

30 秒实验

  1. 把你手上一个流程画成三行:第一步做什么、第二步做什么、最后给什么。画不出来说明还没想清。
  2. 找你流程里唯一一个「看情况」的地方,问它能不能用一条阈值代替。能就省掉一个分支。
  3. 打开平台随便一个模板工作流,数它有几个循环节点、几个选择器。

常见误区

  1. 「工作流是更聪明的智能体。」反过来,它是把聪明换成确定。 模型只在被点名的节点里干活,其余都是死规则。
  2. 「循环就是在图上画个圈。」平台不让存。要重复用循环节点,图必须无环。
  3. 「步骤越多越专业。」步骤多意味着出错点多。能三步做完的别画五步。
自测三问(点开对答案) 1. 工作流和智能体最本质的差别是什么? —— 谁决定下一步。工作流由图纸决定,智能体由模型临场决定。前者确定,后者灵活。 2. 平台的循环怎么实现? —— 循环节点内部转,图上是一条直线。图上不允许有环——有环就排不出拓扑序,调度器不知道从哪开始。 3. 工作流和对话流怎么分? —— 一次问清一件事用工作流,不记上下文;要来回几次、要记上下文用对话流。

三种骨架会画了,下一个问题是它到底解决了什么。 下一节把同一件事用两种做法跑二十遍,让「稳」和「准」这两件事分开站。

相关笔记