🐦 第12章 实战案例:企业营销宣传海报自动生成器
📄 一句话概括

八个节点、四条出边:开始 → 意图识别 →(产品 / 活动 / 招聘 / 追问)→ 变量聚合 → 结束。 意图识别只干一件事:吐一个类名。类名错了后面全错,而且它不报错。 没有第四条兜底支路,认不出类名的那句话会让整条链空转,用户拿到一片空白。

📝 本章和前面几章的关系

书上这一节拆成七个小节:添加配置工作流、开始节点、意图识别、图像生成、变量聚合、结束、 完整结构。这里按这个顺序讲。 这是全书第一张带分支的图。前四章都是一条直线,这一章要开始管「哪条路过、哪条路不过」。 本沙箱没有出图模型,三个图像生成节点只吐占位地址。分支怎么选、聚合怎么取值,这些是真跑的。

一、先添加,再配置

和 11.3 节一样:先在智能体的资源里「添加工作流」,再进去配置。 这一步两个字段要填准:名字「海报生成工作流」,说明「按类型生成产品、活动、招聘三类营销海报」。 说明里那三个类型名很关键——智能体判断该不该调这条工作流,看的就是这句。

二、开始节点五个参数

参数 类型 必填 填什么
brief string 是 用户原话,整段传进来
brand_color string 否 主色号,缺省用品牌色
size string 否 16:9 / 1:1 / 9:16
logo_pos string 否 logo 位置,缺省右下
extra string 否 特别要求

第一个参数收的是整句原话,不是拆好的字段。这是故意的:类型判断要看全句。 拆字段的事交给意图识别节点。开始节点只负责收,不负责懂。 其余四个是可选。可选参数越少越好,只留真正影响出图的。

三、意图识别节点:一句话一个类名

这个节点只有一件活:读 brief,吐一个类名。后面四条边靠这个类名选。 三条关键词表,各四到八个词。演示里五句话,三句判对,两句落在「未识别」:

输入 判成
新品上市,主推不锈钢保温杯,卖点是… 产品
周六店庆,全场五折,要喜庆一点 活动
招个美工,月薪八千,急 招聘
急招设计,会 PS 就行 未识别
帮我把这张图 P 一下 未识别

第四句其实是招聘的意思,可它用的是「急招」,不在表里。 第五句压根不是做海报。这两句都该落到「未识别」,但原因不一样。 真机上用大模型判,第四句能判对,第五句还是判不出——它本来就不属于这三类。 所以兜底支路不管用什么判法都得有。

四、三条分支,三套提示词

类型 提示词要点
产品 产品图居中,突出卖点,浅灰背景,电商主图风格
活动 大字号标题压上方,优惠力度高亮,红金配色,喜庆构图
招聘 上半留白放岗位信息,下半城市剪影,蓝灰配色,简洁

三段模板结构一样,要突出的东西不一样。 一个节点写三种,不如三个节点各写一种。 后者改一种不影响另外两种。 代价是节点数翻三倍。 所以只有当三种都常用的时候才值得这么画——一月来一次的类型,走兜底支路让人工做更划算。

五、变量聚合节点:四条入边取活的

三条分支加一条兜底,四条边汇到一个节点。真跑的时候只有一条是活的。 活的在全局变量里有值(p1.img 或 ask.img),聚合函数遍历四个键,取第一个有值的。 聚合节点不判断哪条对,它只找哪个有值。 判断是意图识别的事,两个节点各管一段。

这里有个容易写错的地方:按「所有入边都断才跳过」的判法,聚合节点有四条入边,三条断一条活, 它不该被跳过。反过来,如果按「有一条入边断就跳过」判,它就永远跑不起来了。 所以跳过要按边判,不按节点判。两条支路汇到一个节点时,一条断了一条还活着,那个节点就该跑。

六、结束节点交什么

image_url(图片地址)、kind(判成了哪类)、brief_used(实际用的需求)。 第二个字段是给自己看的:用户觉得不像活动海报,你一看就知道是判错了类,还是这一类没画好。 多一个字段,排错少绕一圈。 这和 11.3 节那个 prompt_used 是一个道理。

七、完整结构回头看

八个节点:开始、意图识别、三条分支、追问、聚合、结束。七条边。 跑一遍:每句话都跑五个节点,跳过三个。跳过的那三个是另外两条分支加一条兜底。 整张图最脆弱的两处:意图识别的关键词表、三个分支的提示词模板。两个都是人工维护的。

维护的办法是都放表里,别写死在节点里。加一个类型只改表加一个节点。

八、动手 Demo:三条分支,最后合成一条

五句话判类,三条分支各走一遍,再看聚合节点怎么从四条入边里取到活的那条。 两句「未识别」走兜底支路,验证「判错不会崩,只是多问一句」。

f.link(u'it', u'p1', when=u'产品')      # 意图识别 -> 三条分支
f.link(u'it', u'ask', when=u'未识别')   # 兜底支路,不能省

def agg(g):        # 四条入边只有一条活,取第一个有值的
    for k in (u'p1.img', u'p2.img', u'p3.img', u'ask.img'):
        if g.get(k):
            return {u'url': g[k]}

实跑输出:

--------------------------------------------------------------------
三条分支,最后合成一条
--------------------------------------------------------------------


| 用户说的 | 判成哪类 |
|---|---|
| 新品上市,主推不锈钢保温杯,卖点是一体成型内胆 | 产品 |
| 周六店庆,全场五折,要喜庆一点 | 活动 |
| 招个美工,月薪八千,急 | 招聘 |
| 急招设计,会 PS 就行 | 未识别 |
| 帮我把这张图P一下 | 未识别 |

  前三句都对,后两句落在「未识别」。
  第四句是「招聘」的意思,可它用的是「急招」,不在关键词表里——关键词表永远比真实说法少一条。
  第五句压根不是做海报,是改图。这句该追问,不该硬套一个类型。

  ① 意图识别节点:三条关键词表
  --------------------------------------------------------------------
  这个节点只有一件活:读一句话,吐一个类名。后面的三条分支靠这个类名选边。
  真机上可以用大模型判,也可以用关键词表。演示用关键词表——它可解释,判错了你知道为什么。

  ② 三条分支各用一套提示词
  --------------------------------------------------------------------
  产品:{title},产品图居中,突出{point},干净的浅灰背景,电商主图风格
  活动:{title},大字号标题压在画面上方,{point}高亮,红金配色,喜庆构图
  招聘:{title},上半部分留白放岗位信息,下半部分城市剪影,蓝灰配色,简洁
  三段模板结构一样,要突出的东西不一样:产品突出卖点,活动突出优惠,招聘突出岗位。
  一个节点写三种,不如三个节点各写一种。 后者改一种不影响另外两种。

  ③ 六节点真跑:三条路各走一遍
  --------------------------------------------------------------------

| 输入 | 判成 | 跑几步 | 跳过几个 | 交回 |
|---|---|---:|---:|---|
| 新品上市,主推不锈钢保温杯,卖点是一体… | 产品 | 5 | 3 | poster_product.png |
| 周六店庆,全场五折,要喜庆一点 | 活动 | 5 | 3 | poster_event.png |
| 招个美工,月薪八千,急 | 招聘 | 5 | 3 | poster_job.png |
| 急招设计,会 PS 就行 | 未识别 | 5 | 3 | (先问清楚要做哪种) |
| 帮我把这张图P一下 | 未识别 | 5 | 3 | (先问清楚要做哪种) |

  前三句各跑五个节点:开始、意图识别、一条分支、聚合、结束。另外三条分支整枝跳过。
  后两句走第四条兜底支路,跑到「追问用户」,聚合节点收到「先问清楚要做哪种」。
  没有这条兜底支路,后两句会整条链空转。
  意图识别吐出一个谁都不认的类名,四条边全断,连结束都跳过,用户拿到一片空白。

  ④ 变量聚合节点在干什么
  --------------------------------------------------------------------
  它有四条入边,只有一条是活的。按「所有入边都断才跳过」的判法,它不该被跳过——有一条活着就得跑。
  活的那条在全局变量里有值(p1.img 或 ask.img),聚合函数遍历四个键,取到第一个有值的。
  聚合节点不判断哪条对,它只找哪个有值。 判断是意图识别节点的事,两个节点各管一段。
  ! 三条分支的好处是「改一种不影响另外两种」。
  坏处是节点数翻三倍——所以只有三种类型都常用的时候才值得这么画。

①第一张表五句话判类:三句对,两句「未识别」,原因不一样。 ②第二段三条分支各一套提示词:产品突卖点、活动突优惠、招聘突岗位。 ③第三张表五行:前三句走对应分支,后两句走兜底,每行都是跑 5 步跳 3 个。 ④没有兜底支路,后两句会让整条链空转——四条边全断,连结束都跳过。 ⑤最后一节讲聚合节点:它不判断哪条对,只找哪个有值。判断是前一个节点的事。

30 秒实验

  1. 给你的三类海报各写一条提示词,只写要点,不写完整句子。写完看三条像不像。
  2. 故意造一句话,让它落在「未识别」,看你的链是空转还是走兜底。
  3. 把意图识别的关键词表单独放一张表。下次加词只改表,别去动节点。

常见误区

  1. 「三条分支不加兜底。」认不出的类名会让四条边全断,用户拿到一片空白。
  2. 「一个节点写三种提示词。」形态差太多,硬塞会互相打架。该分就分。
  3. 「聚合节点自己判断哪条对。」它只找哪个有值。判断是意图识别的事。
自测三问(点开对答案) 1. 为什么要有兜底支路? —— 认不出类名时四条边全断,整条链空转。兜底支路让「判不出」也有一个去处。 2. 变量聚合节点怎么取值? —— 遍历四条入边对应的变量,取第一个有值的。它不判断对错。 3. 跳过为什么按边判不按节点判? —— 两条支路汇到一个节点时,一条断了一条还活着,那个节点就该跑。按节点判会误跳。

链建好了,下一节测。先单独测意图识别的准确率,再整链测三条路。

相关笔记