问题
你写道:「把明天的天气摘要发给小李」。这句话背后有三个动作:读取天气,在你的联系人里找到小李,然后撰写邮件。顺序很重要:在拿到天气和地址之前,邮件不能发出。
一个边走边即兴完成这些动作的语言模型,可能会弄错顺序,编造一个不存在的工具,或者向一个只返回五条结果的工具要十条。只要什么都还没发出,错误就没有代价。可一旦邮件发出去了,代价就来了。
我想要的
我希望一切能检查的东西都在第一次调用之前检查,也就是纠正还不花钱的时候。而计划一旦启动,LIA 要如实告诉你发生了什么,不在你背后重放任何步骤。
计划长什么样
计划是一份步骤清单。每一步写明要调用的工具、它的参数,以及它需要哪些步骤。以小李为例:(1)明天的天气,(2)联系人小李,(3)邮件草稿,它要等前两步完成,并沿用第 2 步找到的地址。
- 并行的波次。不需要等待任何东西的步骤会一起出发。在这里,天气和联系人同时查找,然后才是邮件。所以一个涉及多个领域的请求,并不一定要花更多时间。
- 「对每一个」。「把议程发给我明天会议的每一位参与者」会变成一个在列表上重复执行的步骤,并设有上限。如果其中一次发送失败,其他发送的结果照样保留。而在对整个列表动手之前,LIA 会告诉你涉及多少项,并附上预览。
- 条件。一个步骤也可以是一次判断:只有在某件事成立时才做另一件事。
第一次调用之前检查什么
- 真实的工具。编造的工具名会被发现,最常见的小拼写错误会被纠正。
- 可行的计划。要回复一封邮件,需要它的标识符,也就是需要一个读取邮件的工具。LIA 会确认每个工具要求的每一项数据,都能由另一个现有的工具获得。否则就不存在有效的计划,模型只能去编造。
- 公布的限制。每个工具都说明它接受什么,比如一次返回多少条结果,规划器能看到这些。超出的值会被拉回到边界之内,计划继续进行。
- 先搜索,再筛选。「我这个月的就医预约」:你的日历会按日期搜索,却不懂什么叫「就医」。规划器会被引导去取回这段时间,把筛选留给回答;校验器则会发现这样的词溜进了搜索条件。
- 一致性。一个计划做得比要求的少或多(「我所有的联系人」,却只处理了一个),一个步骤引用了不存在的步骤,一个有风险的操作建立在模糊的信息上:计划会退回给规划器,次数有限。如果缺少一项谁也猜不出的信息,比如邮件的内容,LIA 会问你。而如果一个会修改东西的计划在这些重试之后仍有疑问,她会停下来问你。
某一步失败时
计划一旦启动,就不会在你背后重放任何东西。临时故障已经由遇到它的那个连接重试过了。一个断开的服务或被拒绝的访问,不是换个计划就能绕过的。空结果也是一种答案。每个失败的步骤都会完整地传到回答里,回答会告诉你哪个工具失败了、为什么,以及旁边哪些成功了。
反过来,读取操作找到的东西也会传到回答里:一条路线的行程时间,或一次搜索的下一页,不会卡在工具的数据里。一个服务的拒绝也不会在半路被变成成功。
按发件人、标题或位置指定结果时,LIA 会先使用实际展示过的项目。多个项目匹配时,它会询问你指哪一个。计划中的搜索若会对多个结果中的第一项采取行动,也会等待你的选择,再对该项目继续操作。
局限
计划是在看到结果之前写好的。它不会中途改道:如果你希望 LIA 在第一个来源没有回应时去找另一个来源,那是 ReAct 模式的职责,你可以用屏幕顶部的模式按钮启用它。而且校验检查的是计划的形式;它读不了你的心思。一个格式正确的计划也可能误解你想要的东西。正因如此,发送、修改或删除仍然要经过你的确认,只有少数只涉及你自己、点一下就能撤销的操作除外。
