[控场AI]
· 9 分钟阅读· 4,521 字

九个AI语音代理都是单一提示词,直到我踩到这五个坑

九个AI语音代理都是单一提示词,直到我踩到这五个坑

九个语音代理用单一提示词却暗藏状态机,五个信号决定何时该拆分。

作者管理着九个客户语音代理,全部采用单一巨型提示词架构,却在并排阅读配置时发现大多数提示词内部已经用散文写成了状态机——例如一位律师代理的提示词里明确列了七个编号阶段。文章通过一个暖通代理的真实 bug 说明单一提示词的核心风险:同一行为在阶段描述、工具规则和示例对话三处被重复指定且互相矛盾,模型每次随机选一个版本执行。作者据此提出拆分的五个信号(脚本不可协商、通话按顺序做多件事、工具列表增长、频繁写「关键」、阶段带编号),并给出留在单一提示词时的四条纪律:每条规则只说一次、通用规则按名称限定作用域、示例即测试、发布前 diff。最终把问题还原为作用域、单一事实来源等经典软件工程问题。

九个AI语音代理都是单一提示词,直到我踩到这五个坑

一位开发者管理着九个客户语音代理——暖通、屋顶、牙科、水处理、两家律所、信用修复、债务和解和预约专员。它们全部采用同一种架构:一个巨大的提示词,没有状态机,没有流程图。提示词长度从2400词到4400词不等,每个代理挂载三到四个工具。

这听起来像是反模式,但作者坚持认为这「大体上是对的」。他最近把九个配置文件并排阅读,发现了一个此前不愿承认的事实:大多数提示词其实已经是状态机了——只是把状态写成了散文。

这篇文章要讨论的是:单一提示词与显式状态之间的分界线在哪里,以及站错边时失败长什么样。

rss source: All Nine of My Voice Agents Are One Giant Prompt. Here Is Where That Stops Working.

三种代理结构,用开发者语言解释

作者构建语音代理的平台 Retell 提供了三种结构方式。

单一提示词:一大块指令包含身份、范围、通话步骤、知识、升级规则和工具用法。模型每一轮都读取全部内容并决定下一步。作者把它比作「一个没有显式控制流的大函数,模型就是解释器」。

多提示词:代理被拆分为多个状态,每个状态有独立的短提示词和工具列表,以及状态之间的转移规则。这是一个状态机,每个状态的主体仍是自然语言,但边由你定义。

对话流:可视化图。每个节点是一个步骤——说一句话、问一个问题、调用函数、按条件分支、转接。通话沿着你画的路径走。这是平台上最接近确定性代码的东西,代价是僵化。

据文章数据,九个代理中提示词最短约2400词,最长的是人身伤害律师接案线,约4400词。

状态机(State Machine) 是软件工程中的一种计算模型,它由有限个「状态」以及状态之间的「转移规则」组成。系统在任意时刻只处于一个确定状态,只有满足特定条件(事件或输入)时才会转移到另一个状态。在语音代理的语境下,多提示词和对话流本质上都是状态机的不同表现形式:多提示词把每个状态写成一个独立的短提示词,状态之间的转移由开发者显式定义;对话流则把状态和转移画成可视化的图。与之相对,单一提示词没有显式的状态变量和转移表,模型只能靠自然语言描述来「推断」自己当前应该处于哪一步——这也正是后文所述各类不一致问题的根源。理解状态机的关键在于:状态的强制性与转移的确定性,即「系统真的知道自己现在处于哪个状态」以及「什么条件下可以离开这个状态」。

我的「单一」提示词里,其实藏着七个状态

作者展示了那位4400词律师代理的标题结构:角色与目标、个性、上下文、指令、身份规则(关键)、沟通规则、排程规则、紧急升级规则、阶段、异议处理、工具、示例对话。

其中「阶段」下面列了七个编号阶段:问候、案件类型确认、时间资格、伤害与紧急度评估、资格判定、预约、预约后。

「七个编号阶段。这是一个穿着风衣的多提示词代理。」作者写道。区别在于,模型每一轮都看到全部七个阶段、全部工具和全部规则,而且没有任何机制强制它「认为自己在第三阶段时,就真的处于第三阶段」。

只要规则之间从不互相矛盾,这种做法出奇地有效。但这正是问题所在。

提示词作用域(Prompt Scoping) 借用编程语言中变量的作用域概念,指的是某条规则或指令在多大范围内生效。在传统代码里,一个函数内声明的局部变量不会泄漏到其他函数;但在单一提示词中,所有文字都在同一个扁平上下文中,模型每一轮都会读到全部内容。因此,一条写着「在任何工具调用之前」的规则,实际上作用于提示词内列出的所有工具,包括作者后来才新增、但当初写规则时并不存在的工具。这种缺乏作用域的现象导致两个后果:一是旧规则会意外污染新工具的行为;二是当同一行为在多处被描述时,模型无法判断哪一处具有更高优先级。多提示词结构通过把规则拆分到各个状态来天然实现作用域隔离,而单一提示词只能靠「按名称限定」这类约定来模拟。

一条规则写在三个地方,然后三个版本打架了

作者分享了一个暖通代理的 bug,这是他学得最多的一次。

该代理有一个 getWeekAvailability 工具,加载未来两周的空位。计划很简单:在排程阶段开始时静默调用,然后询问来电者哪天方便。原始提示词在阶段描述里写的是「在阶段开始时、问任何问题之前,静默调用一次,不要宣布」。

但工具章节有一条通用规则:「在任何工具调用之前,使用简短的口头过渡语:『让我查一下』『稍等』」。

而示例对话里,代理先问「哪天方便?」,工具调用发生在这个问题之后。

同一种行为在三个章节被指定了三次,三次互相矛盾。模型无法知道哪一个是规范、哪一个是过时的。就像任何人拿到互相冲突的文档一样,它每次调用挑一个版本,而且不一定每次都挑同一个。

修复需要同时改动三处:阶段描述改为立即调用且不宣布;过渡语规则收窄为「在调用 checkCalendar 或 bookCalendar 之前」,并明确写出「不要对 getWeekAvailability 使用口头过渡」;每个示例重写为工具调用在前、提问在后。

作者从这个 bug 提炼出的教训是代码层面的,而非提示词层面的:「在单一提示词里没有作用域。一条为『任何工具』写的规则会永远适用于所有地方,包括你后来才添加的工具。每条通用规则都是一个全局变量,每段示例对话都是逻辑的第二份拷贝,会和第一份漂移。」

为什么九个代理仍然是单一提示词?

因为拆分的成本是真实的,对大多数这类通话来说还不值得付。

单一提示词是三种结构里听起来最自然的。来电者不会遵循你的阶段。他们会在你问问题时给出地址,在预约环节问价格,或者一次回答两个问题。单一提示词能处理这些,因为没有什么阻止模型跳来跳去。在多提示词代理里,每一次跳跃都是你必须设计的转移;一个在预约状态问价格的来电者可能得到一脸茫然。在对话流里,一条没有预设边的回答就是死胡同。

单一提示词也最容易修改。作者每周根据真实通话编辑代理好几次,一个从头读到尾的扁平提示词,胜过一张改动一个节点却悄悄破坏三个节点之后路径的图。

对话流(Conversational Flow) 在语音代理平台中通常指基于有向图的可视化编排方式:每个节点代表一个步骤(说一句话、问一个问题、调用函数、按条件分支、转接人工),边代表允许的路径。它的优势是确定性强——来电者只能沿着开发者画出的边前进,因此合规脚本、精确措辞和固定顺序都能被严格保证。代价则是僵化:任何没有预设边的输入(例如来电者在预约环节突然问价格)都会成为死胡同,需要开发者提前穷举所有分支。这与单一提示词形成鲜明对比:后者因为模型可以自由跳转,反而能容忍来电者的非线性行为。对话流最适合「脚本不可协商」且「通话步骤高度可预测」的场景,例如法律披露、身份验证和资格判定。

作者现在从哪里划线?

并排阅读之后,作者列出了他实际使用的拆分信号:

脚本不可协商时。如果客户要求每个来电者在任何提问之前听到一段披露声明,或者销售负责人签字确认了精确的资格判定措辞,那就是对话流。单一提示词大多数时候会遵循脚本,但合规需要的是「所有时候」。

通话按顺序做多件事时。验证身份、查询记录、预约或改期、收集后续短信所需信息——每一项都是一个有自己工具和失败模式的任务。这时多提示词开始划算,因为每个状态得到一个可以独立测试的短提示词。

工具列表增长时。作者的代理目前挂三到四个工具,日历相关的工具已经是他唯一一个真实排序 bug 的所在地。超过这个数量,模型开始在错误的时机伸手去够错误的函数。把工具限定到状态能解决大部分问题。

你不断写「关键」时。那位律师的提示词里有一个章节标题就叫「身份规则 - 关键」。在提示词里大喊大叫,说明一条规则正在和其他规则争夺注意力。一两条没问题,需要很多条时,提示词在请求被拆开。

你的阶段带编号时。如果你已经写了第一阶段到第七阶段,你就已经设计了状态机。剩下的唯一问题是,你要不要让平台来强制执行它。

留在单一提示词里的四条习惯

既然大多数代理还会在单一提示词里待一段时间,作者总结了暖通 bug 之后形成的习惯:

  1. 每条规则只说一次。如果一个行为在阶段、工具描述和示例里都被描述,要么三处都改,要么删掉两处。
  2. 通用规则按名称限定作用域。写「在 checkCalendar 或 bookCalendar 之前」,而不是「在任何工具之前」。新工具不应意外继承旧规则。
  3. 把示例当作可能出错的测试。根据作者经验,模型对示例的依赖至少不亚于对指令的依赖,所以一个过时的示例是 bug,不是文档。
  4. 发布前先 diff。作者把上一版本和新版本放在一起,正是为了这个。测试一条真实电话线路是另一个问题——电话通话没有 repro。

单一事实来源(Single Source of Truth,SSOT) 是软件工程和文档管理中的原则:任何一项数据或逻辑只应在一个地方定义,其他位置通过引用而非复制来使用它。作者在暖通 bug 中遭遇的正是 SSOT 被违反的典型场景——同一个「何时调用工具」的行为在阶段描述、工具章节和示例对话中被写了三遍,三份拷贝逐渐漂移并互相矛盾。在代码中,编译器或测试可以捕获这种不一致;但在自然语言提示词里,没有任何机制会报错,模型只会随机挑选一个版本来执行。遵循 SSOT 意味着:每条规则只保留一处权威定义,示例对话要么直接引用该规则,要么在规则变更时同步更新,否则示例就会变成「逻辑的第二份拷贝」,成为隐蔽的 bug 来源。

客户从来看不到架构

作者指出,他的客户没有一个知道或关心他们的接待员是一个提示词还是一张二十个节点的图。他们关心的是电话有没有被接起、预约有没有被订上。这也是他们构建 VoiceDash 的原因之一——一个白标门户,每个客户能看到自己的通话、转写和分析。当一个代理从一种结构迁移到另一种,客户的视图不变。

转写记录也是作者发现代理是否已经超出其结构的方式:同一步骤被跳过,或者话题转换后同样的卡顿,在多次通话中反复出现。那才是拆分的信号,而不是字数。

可复用的判断框架

这篇文章的价值不在于「单一提示词好还是状态机好」的二元结论,而在于它把提示词工程还原成了软件工程的老问题:作用域、单一事实来源、示例即测试、diff 即代码审查。如果你正在构建长提示词的 LLM 代理——不管是不是语音——作者的问题值得回答:你在一条提示词和显式状态之间的线画在哪里,又是什么最终把你推过了那条线?

本文基于开发者公开的九个语音代理配置分析整理,其中平台能力描述和代理配置数据来自原文。

#语音代理#单一提示词#多提示词架构#对话流#Retell#提示词工程#LLM代理#状态机
分享:

相关推荐