跳到主要内容

写誓言、演角色、排行程

这一章讲三件事: 面向个人的三类用法各自怎么做; 数字人那一类为什么最值得拆;以及「能说话」这件事真正难在哪。

它在全书链条里的位置: 第 13、14 章讲的是干活, 这一章讲的是陪伴和玩——它是全书离普通人最近的一章, 也是第 19、20 章那两个消费级产品案例的技术底子。

1. 三类,各解决一种没辙

这一节先把三类分开,因为它们的做法完全不同。

类别你什么时候需要它它靠什么解决
创作助手要写情书、道歉信、起名字、对联,卡在没灵感、没知识、没那门语言1给它一个范本 + 你的具体细节
数字人角色扮演想跟一个虚拟人物聊天人设 + 一批这个角色说过的原话
旅行计划助手不了解当地交通和景点、估不准花销、排行程太费时间2让它排,插件替你订

这三类里,第二类的做法最值得拆,因为它把第 13 章那套骨架用在了一个意想不到的地方。

2. 创作助手:它需要你给一个范本和两件具体的事

这一节讲第一类,它的关键在「你给了什么」。

书里的场景是:一位新郎要写婚礼誓言,抓耳挠腮了一周, 除了找到一份觉得还不错的现代诗,没有丝毫灵感3

第一轮:他把那首诗整个贴进去,让它照着写一篇 300 字左右的结婚誓言4。 它交回来的东西把诗里的意象换了个说法:凌霄花、鸟儿、木棉、根、叶—— 结构和比喻全部来自那首诗。

问题也在这里:誓言里没有他和新娘的任何细节。

第二轮:他补了两件具体的事—— 「誓言当中还需要增加我们两人在新疆通过旅游结识, 并有外出游玩的共同爱好的内容,要使用更多的排比句」5

这一次它交回来的东西换了一整套意象:丝绸之路的风、草原的花海、天山山脉、 柯坪大佛、群山长存的石林6

对比两轮,这一节的结论就出来了:

第一轮第二轮
你给了什么一首诗一首诗 + 两件具体的事
它还你什么那首诗的改写一篇只属于这两个人的稿子

这和第 14 章第 2 节是同一条规律:参数越具体,产出越不可替代。

3. 数字人:人设只占一格

这一节拆第二类,它的做法是第 13 章那套骨架的一个变体。

书里先说清楚这一类难在哪:角色需要故事背景、情节、独特个性等内核予以支持, 并且在扮演过程中始终如一地呈现其特定的形象和风格; 另外两个痛点是缺乏多样性(台词少、背景交代不够,玩家容易预测它的反应) 和互动角色不足7

书里给的做法是四步8:

① 数据准备 ── 写人设 + 收集这个角色说过的话


② 把那批对话变成一串串数,存进本地库


③ 用户问一句 ── 这句话也变成一串数,去库里捞最像的几段


④ 把「人设 + 捞回来的原话 + 用户的问题」拼成一段,交给它答

看第 ① 步的人设长什么样。 书里给的例子是一位江湖人物:

内容
基本情况秦川,男,33 岁9
身形身高 1.9 米,体型健壮,锐利的眼睛,短发,手腕上镶嵌着精致的刻字刀,脸上有一道明显的刀疤
出身曾是大名鼎鼎的侠客家的四公子,因不满父母的束缚而离家出走
性格正直豪爽、讲义气、绝不服输、因为过去的故事而显得分外孤独
武艺擅长使用刀,江湖上有「刀客秦川」之称10

这一整段人设,在请求里只占一格。 书里说得很清楚:请求消息是一个对象数组,每个对象都有一个角色,一共三种—— 系统(用来指导它在整个对话中的行为,角色扮演里就用它来放人设)、 用户(存用户说的话)、助手(存先前的对话内容,为了能持续接上话)11

换句话说:人设是一句话级别的东西,而「像不像那个人」靠的是第 ③ 步捞回来的原话。

4. 主走查:「如果我忽然想去淄博吃烧烤,怎么办?」

这是本章的主走查,四步全部来自书里。

第几步发生了什么手里拿到什么
1用户问如果我忽然想去淄博吃烧烤,怎么办?12
2这句话被变成一串数,去本地库里捞捞到两段相似度超过 0.9 的原话:「那你肯定是疯了!」和「这于我毫无价值可言」12
3拼成一段提问系统那一格放人设(「你是中年侠客秦川,侠骨柔肠,刀法精湛,正义无私,行侠仗义,孤独而坚韧」);用户那一格放**「请用下面这几段来回答这个问题」+ 那两段原话 + 用户的问题**13
4它作答照着人设和那两段原话的口吻答;返回之前还要做一次无害化处理14

第 2 步那个「0.9」是这条走查的关键,请看清它的含义: 它不是「答案的正确率是 0.9」,是「这两段原话跟你这句话的意思有多接近」。 书里用的说法是用一个叫余弦距离的量来表示两个句子间的相似度,分数越高说明匹配度越高15

余弦——这个词你不必记,它量的是那两串数之间的夹角有多小; 记住那个 0.9 说的是「像不像」就够了。

再看第 3 步:那两段原话跟淄博烧烤没有任何关系。 它们被捞回来,不是因为内容对得上,是因为「口吻对得上」。 这就是这一整套做法的性格:它不保证答得对,它保证答得像那个人。

对照第 13 章第 4 节那位提公积金的老人:

政务那一段数字人这一段
捞回来的东西政策条文这个角色说过的话
追求什么
捞错了会怎样给错政策串味,但不致命

同一套骨架,两个完全不同的目标——这一点书里没有点破,是我们指出来的。

5. 那批原话是怎么变成可以捞的东西的

这一节把第 3 节的第 ② 步拆开,因为它是这一整套做法里唯一有工程量的一步。

书里给的步骤是这样的16:

第几步干什么关键细节
1把角色跟他人对话的大量内容清洗成表格或结构化文件格式并且分成小块
2用嵌入把这些问和答变成一串串数结果要保存到本地
3把原始文本和那串数一起存,这样可以按数反查回原文书里的说法是「参考全文索引中给数据建索引」
4把这些问答的编号和对应的答案存进一个普通的数据库里

第 3 步那句「原始文本和那串数一起存」是最实用的一条: 你捞回来的是一串数,可你要拼进提问的是那段人话—— 中间必须有一张能反查的表。

这一节和第 13 章第 2 节是同一套骨架的两个实例,请对照着记:

第 13 章(政务/法律/人力)本章(数字人)
切的是什么政策文件、案卷、简历这个角色说过的话
存在哪本地(法律那一段特意强调)本地
捞回来干什么当依据当口吻

书里还交代了这套做法出现之前的样子,对照很鲜明: 在过去,虚拟角色必须在确认基本特点、个性特质、故事背景和命运之后, 由编剧或策划完成与角色相关的文案创作;这一构建过程几乎完全依赖「人工」来转换场景, 难以支持角色独立向个人输出17

一句话:以前是人把每一句台词都写出来,现在是人写一段人设,剩下的靠捞。

6. 旅行助手:它能排九天,但会把地名编错

这一节讲第三类,而且要说一件书里没说的事。

书里的场景是:一位用户想做一个九天的新西兰自驾游行程, 从奥克兰开始,途经皇后镇、基督城,最后回到奥克兰18

它交回来的是一份逐日的行程:第 1 天奥克兰(天空塔、海港大桥)、 第 2 天飞皇后镇、第 3 天冰川一日游、第 4 天步行上山跳伞、第 5 天到基督城…… 一直到第 9 天返回19用户还可以接着追问租车、住宿和预算, 并利用插件在对话中直接预订酒店和租车20

这一段必须泼一盆冷水,而书里没有泼:那份行程里有编造的地名。 「卡波迪斯特里亚」「富士湾」「托皮罗」这些地方并不是新西兰的地名, 「学习马达卡语」这一条也不成立。 判断(我们的,不是书里的):这一段恰恰是第 05 章那个毛病的活标本, 而书里把它当成一个成功案例展示了出来。 如果错,会错在: 如果这些名字只是中文译名不通行(而非编造), 那么这一条批评就过重了;但至少「行程里的地名需要逐个核对」这个结论仍然成立。

这一段的正确读法是:让它排骨架(几天、怎么串、每天干什么), 地名、价格、营业时间一律自己核。

7. 这一块书架上有:让它能说话

这一节是书外补充,标明来源。书里的数字人只到文字为止, 而「能说话」这件事的难点在别处。

书里那位角色扮演的例子全程是文字对话。可你真要做一个能陪你聊天的角色, 第一件事就是让它开口——而难的不是发声。

补充(不在书里,依据我们的 agent 书架):真正难的是两件事—— 判断「你说完没有」,以及「你插嘴时它怎么立刻闭嘴」。 一套广泛使用的语音对话框架把这两件事做成了可替换的部件: 「说话开始」的判定是一条独立策略(最简单的一种是: 只要检测到有人声,就认为这一轮开始了); 判定之后要做三件事,其中一件是广播一个「打断」信号。 依据: shelf=ai-agent-reference/pipecat#index.md §3.2 语音打断与轮次 @acead0507d7de44e216d24533964106ca1d1d044 事实=最薄的一种开始判定策略就是收到「有人声」这个信号就触发「用户回合开始」; 判定后在同一个处理器里做三件事,第三件是调 broadcast_interruption()。

打断为什么难? 因为机器人正在滔滔不绝的时候, 下游排着一大堆还没播出去的音频,「打断」这个信号必须能越过那一堆被立刻处理。 那套框架的做法是把消息分成三个梯队,打断走高优先级通道, 命中之后直接把正在排队的那一堆待播内容整个丢掉—— 这就是「打断即闭嘴」的实现。 依据: shelf=ai-agent-reference/pipecat#index.md §3.1 帧流水线引擎 @acead0507d7de44e216d24533964106ca1d1d044 事实=系统帧走优先队列插队;打断到来时直接取消并重建处理任务, 排队中的旧数据帧因此被瞬间丢弃;但「结束」这类不可打断的帧会被保留。

还有一件事值得记:「你说完没有」这个判定,那套框架刻意不替你决定。 「停顿了半秒到底算不算说完」是个产品问题,不是技术问题—— 所以它把这一步做成可替换件,除了「听没听到人声」, 还可以按转写出来的文字判、按最少词数判、按唤醒词判。 依据: shelf=ai-agent-reference/pipecat#index.md §3.2 语音打断与轮次 @acead0507d7de44e216d24533964106ca1d1d044 事实=「判定说完」是一组独立策略,目录里并排放着好几种实现; 文档明说这是个很难的产品问题,框架把它做成可替换件而不是替你决定。

这一节和书里那一章的关系:书里的人设和捞原话解决的是「说什么」, 这一节解决的是「什么时候说、什么时候闭嘴」。两件事缺一不可。

8. 边界与局限

  • 书里没有讲长期记忆。 数字人聊到第五十轮时,它还记得你第一轮说过什么吗? 书里在这一章一句没提——而这正是第 01 章那个缺口。 (今天外面是怎么做的,第 13 章第 8 节讲。)
  • 书里没有讲角色会不会串味。 捞回来的原话如果和当前话题差得远, 第 4 节那个例子就是活生生的证据(两段原话和淄博烧烤毫无关系)。
  • 书里没有讲角色扮演的合规风险。 扮演真实人物、已故者、未成年人角色, 这些问题在 2023 年之后成了这一类产品最大的麻烦,书里完全没有涉及。
  • 旅行那一段的编造地名书里没有核。 见第 6 节。

9. 作者的判断与证据

说法性质
婚礼誓言两轮实录,书里给了完整前后文
人设的那五项示例,作者编的角色
三种角色格(系统/用户/助手)可核的事实,书里给了可运行的代码片段
淄博烧烤那两段原话与 0.9实录
新西兰九天行程实录,但书里没有核对其中的地名
「可能创造出集游戏、社交、UGC 于一体的全新娱乐体验」作者的展望,没有证据21

10. 可带走的

  1. 创作类:给一个范本 + 两件只属于你的具体事。 参数越具体,产出越不可替代。
  2. 数字人:人设只占一格,像不像靠的是捞回来的原话。
  3. 它捞原话看的是「口吻像不像」,不是「内容对不对」——所以它保证像,不保证对。
  4. 同一套骨架在政务里追求「准」,在数字人里追求「像」。
  5. 行程类:让它排骨架,地名、价格、时间一律自己核。
  6. 「能说话」真正难的是两件事:判断你说完没有,以及被打断时立刻闭嘴。
  7. 「停顿多久算说完」是个产品问题,不是技术问题。

11. 原文地图

主题原书章原文位置
创作的三个痛点12 创意娱乐型应用text/14-ch12.txt:8(搜「创意瓶颈」)
婚礼誓言第一轮12 创意娱乐型应用text/14-ch12.txt:44(搜「请参考以下内容,帮我写一篇300字左右的结婚誓言」)
第二轮补细节12 创意娱乐型应用text/14-ch12.txt:82(搜「誓言当中还需要增加我们两人在新疆通过旅游结识」) · text/14-ch12.txt:89(搜「我会像丝绸之路的」)
角色扮演的三个痛点12 创意娱乐型应用text/14-ch12.txt:121(搜「角色塑造困难」)
秦川的人设12 创意娱乐型应用text/14-ch12.txt:172(搜「秦川,男,33岁」) · text/14-ch12.txt:185(搜「客秦川」)
四步做法12 创意娱乐型应用text/14-ch12.txt:163(搜「生成特征向量」) · text/14-ch12.txt:192(搜「请求问题Embedding」)
三种角色格12 创意娱乐型应用text/14-ch12.txt:208(搜「用来指导模型在整个对话过程中的行为」)
淄博烧烤12 创意娱乐型应用text/14-ch12.txt:273(搜「如果我忽然想去淄博吃烧烤」) · text/14-ch12.txt:275(搜「那你肯定是疯了」)
余弦距离12 创意娱乐型应用text/14-ch12.txt:266(搜「可以使用余弦距离来表示两个句子间的相似度」)
新西兰九天12 创意娱乐型应用text/14-ch12.txt:345(搜「芝芝最近想要去新西兰玩耍」) · text/14-ch12.txt:393(搜「第9天:从富士湾到奥克兰」)

Footnotes

  1. 出处:「12 创意娱乐型应用」第 8 段(text/14-ch12.txt:8,搜「创意瓶颈」)。三个痛点是创意瓶颈、知识匮乏、语言障碍。

  2. 出处:「12 创意娱乐型应用」第 312 段(text/14-ch12.txt:312,搜「不了解当地公共交通的情况」)。四个痛点在第 312–319 段。

  3. 出处:「12 创意娱乐型应用」第 40 段(text/14-ch12.txt:40,搜「抓耳挠腮了一周」)。

  4. 出处:「12 创意娱乐型应用」第 44 段(text/14-ch12.txt:44,搜「请参考以下内容,帮我写一篇300字左右的结婚誓言」)。那首诗在第 46–56 段,它的回稿在第 60–77 段。

  5. 出处:「12 创意娱乐型应用」第 82 段(text/14-ch12.txt:82,搜「誓言当中还需要增加我们两人在新疆通过旅游结识」)。

  6. 出处:「12 创意娱乐型应用」第 89 段(text/14-ch12.txt:89,搜「我会像丝绸之路的」)。第二稿在第 87–106 段。

  7. 出处:「12 创意娱乐型应用」第 121 段(text/14-ch12.txt:121,搜「角色塑造困难」)。三个痛点在第 121–131 段。

  8. 出处:「12 创意娱乐型应用」第 163 段(text/14-ch12.txt:163,搜「生成特征向量」)。四步分别在第 166、188、192、196 段。

  9. 出处:「12 创意娱乐型应用」第 172 段(text/14-ch12.txt:172,搜「秦川,男,33岁」)。

  10. 出处:「12 创意娱乐型应用」第 185 段(text/14-ch12.txt:185,搜「客秦川」)。

  11. 出处:「12 创意娱乐型应用」第 208 段(text/14-ch12.txt:208,搜「用来指导模型在整个对话过程中的行为」)。三种角色格在第 208–214 段,可运行的示例在第 218–239 段。

  12. 出处:「12 创意娱乐型应用」第 273 段(text/14-ch12.txt:273,搜「如果我忽然想去淄博吃烧烤」)与第 275 段(text/14-ch12.txt:275,搜「那你肯定是疯了」)。 2

  13. 出处:「12 创意娱乐型应用」第 286 段(text/14-ch12.txt:286,搜「Use the following passages」)。

  14. 出处:「12 创意娱乐型应用」第 300 段(text/14-ch12.txt:300,搜「无害化处理」)。

  15. 出处:「12 创意娱乐型应用」第 266 段(text/14-ch12.txt:266,搜「可以使用余弦距离来表示两个句子间的相似度」)。

  16. 出处:「12 创意娱乐型应用」第 246 段(text/14-ch12.txt:246,搜「清洗成CSV」)、第 252 段(text/14-ch12.txt:252,搜「把原始的文本和请求到的数字向量一起存储」)与第 254 段(text/14-ch12.txt:254,搜「关系数据库」)。

  17. 出处:「12 创意娱乐型应用」第 151 段(text/14-ch12.txt:151,搜「在过去,虚拟角色必须在确认角色的基本特点」)。

  18. 出处:「12 创意娱乐型应用」第 349 段(text/14-ch12.txt:349,搜「帮我做一个新西兰9天的行程」)。

  19. 出处:「12 创意娱乐型应用」第 354 段(text/14-ch12.txt:354,搜「第1天:奥克兰」)到第 395 段。

  20. 出处:「12 创意娱乐型应用」第 405 段(text/14-ch12.txt:405,搜「利用ChatGPT插件库」)。

  21. 出处:「12 创意娱乐型应用」第 417 段(text/14-ch12.txt:417,搜「可能在创意娱乐领域」)。