🐦 第9章 实战案例:看图学英语智能助手
📄 一句话概括

结束节点交出去五个字段:word、phonetic、pos、meaning、example。 只声明三个,另外两个取不到——.get 给空字符串,下标直接抛异常。 纯文本五十三字、JSON 一百一十八字、卡片六十三字。只有 JSON 能被程序取字段。

📝 本章和前面几章的关系

第 8.7 节讲过「要不要声明」,这一节讲「声明哪几个、怎么交」。 这一节很短,但它是整条链唯一的出口。出口的形状错了,前面五步全白干。 和第 8 章不同的是:那次交的是文案,给人读;这次交的是字段,给智能体渲染卡片。 给人读和给程序用,要求完全不一样。

一、声明五个,和只声明三个

五个字段全声明,每个都能单独取。只声明三个(word、pos、meaning),另外两个就取不到。 取不到有两种表现:「键不存在」和「值是空」。演示里把两种都跑了一遍。 「键不存在」是结构问题,「值是空」是数据问题。 结构问题要在设计时解决, 数据问题要在运行时兜底。

很多人把两者混在一起,结果是一个空值的字段被当成「这个节点没配好」,白查半天。

二、两种取法,两种坏法

下游取值有两种写法:.get('phonetic', '') 和 g['phonetic']。

写法 字段不在时 后果
.get(k, 空串) 返回空字符串 程序接着跑,卡片上少一行
下标 g[k] 抛 KeyError 整条链停在这一步

两种都比「报错」难查。抛异常至少你知道错了;给空字符串那个,卡片看着没问题,只是缺一行。 演示里特意点了一句:空白那张图看着没错。 用户不会报「卡片少了音标」,他只会觉得这张卡有点空。 所以字段多的卡片要加一道检查:必填字段为空就不发,改发兜底文案。

三、三种交出去的形态

纯文本:一句话把词、音标、词性、释义、例句串起来,五十三字。 JSON:五个键值对,一百一十八字。最长,但只有它能让下游写代码。 卡片:一段带标题和引用的富文本,六十三字。客户端渲染成一张卡,人看着舒服,程序取不出字段。

怎么选?看谁接。 人接就发文本或卡片,程序接就发 JSON。 智能体这一层两种都行:它能把 JSON 渲染成卡片,也能直接把富文本丢出去。 推荐发 JSON——智能体要按字段拼话的时候,有结构才好拼。

四、和第 8 章那一节的区别

第 8.7 节的结束节点交的是 title、text、img,给公众号和小红书用。 这一节交的是五个语言学字段,给卡片渲染用。 内容完全不同,做法一模一样:定名字、定类型、只留下游真用的。 唯一的新东西是多了一个 meaning——它不是从图上抽的,是翻译节点算出来的。

这说明结束节点的字段可以不来自同一个上游。谁产出的都行,只要交的时候在。

五、动手 Demo:结束节点:五个字段,少一个就断

同一张卡片准备两个版本:声明五个字段、只声明三个。 下游分别用两种写法取值,看两边各坏成什么样。

FULL  = {u'word': ..., u'phonetic': ..., u'pos': ...,
         u'meaning': ..., u'example': ...}
THREE = {u'word': ..., u'pos': ..., u'meaning': ...}

THREE.get(u'phonetic', u'')     # -> 空字符串,卡片少一行
THREE[u'phonetic']              # -> KeyError,整链停住

实跑输出:

--------------------------------------------------------------------
结束节点:五个字段,少一个就断
--------------------------------------------------------------------


  ① 声明五个,和只声明三个
  --------------------------------------------------------------------

| 字段 | 声明五个 | 只声明三个 |
|---|---|---|
| word | apple | apple |
| phonetic | /ˈæpl/ | 〈键不存在〉 |
| pos | n. | n. |
| meaning | 一种红皮的圆形水果 | 一种红皮的圆形水果 |
| example | I ate an apple after lunch. | 〈键不存在〉 |

  「空」和「键不存在」是两种不同的坏法,下游处理方式也不一样。

  ② 下游取值的两种写法,坏法不同
  --------------------------------------------------------------------

| 字段 | 用 .get 取 | 用下标取 |
|---|---|---|
| word | apple | apple |
| phonetic | 〈空字符串〉 | 抛 KeyError |
| pos | n. | n. |
| meaning | 一种红皮的圆形水果 | 一种红皮的圆形水果 |
| example | 〈空字符串〉 | 抛 KeyError |

  .get 给空字符串,程序接着往下跑,卡片上出现一行空白;下标直接抛异常,整条链停在这里。
  ! 两种都比「报错」难查:空白那张图看着没错,只是缺了一行。

  ③ 三种交出去的形态
  --------------------------------------------------------------------

| 形态 | 字符数 | 程序能取字段吗 | 适合谁 |
|---|---:|---|---|
| 纯文本 | 53 | 不能 | 直接把话讲给人听 |
| JSON | 118 | 能 | 下游程序按字段取 |
| 卡片 | 63 | 不能 | 客户端渲染成一张卡 |

  JSON 那行最长,但只有它能让下游写代码。这就是「声明字段」的全部意义。

①第一张表五行:声明五个时全有值,只声明三个时两个是「键不存在」。 ②第二张表同样是五行,两种取法:.get 给「空字符串」,下标给「抛 KeyError」。 ③后面那句提醒最要紧:空白那张图看着没错,只是少一行,用户不会来报。 ④第三张表三种形态:纯文本 53 字、JSON 118 字、卡片 63 字。 ⑤只有 JSON 那行「程序能取字段吗」写的是「能」。这就是声明字段的全部意义。

30 秒实验

  1. 打开你的结束节点,数一下声明了几个字段。超过五个的,砍到下游真用的那几个。
  2. 把每个字段的类型写清楚。image 和 string 写混了,下游解析时才出错,很难查。
  3. 试一次只声明三个字段,用 .get 和下标各取一次,看两种坏法的差别。

常见误区

  1. 「字段多声明几个保险。」多一个字段就多一处要保证它有值。声明五个用三个是负担。
  2. 「取不到会报错。」用 .get 不报错,返回空字符串。卡片少一行,没人会发现。
  3. 「卡片更好看,就交卡片。」程序取不出字段。要程序接就交 JSON,要人看才交卡片。
自测三问(点开对答案) 1. 结束节点要声明哪五个字段? —— word、phonetic、pos、meaning、example。前四个来自提取和翻译,第五个也来自提取。 2. `.get` 和下标取值的区别? —— `.get` 给空字符串,链照跑;下标抛 KeyError,链停住。两种都比报错难查。 3. 三种形态怎么选? —— 看谁接。人接就发文本或卡片,程序接就发 JSON。智能体这一层推荐发 JSON。

五个模块全配好了,下一节整条链跑一遍。要跑三张图,其中一张是空图。

相关笔记