草庐IT

基于状态机的聊天机器人设计经验总结

MicroStone 2023-03-28 原文
为了更好地了解智能机器人项目的需求和改进方向,我们常常需要研发一些工具。在我参与的多个机器人项目中,大多数都能够成功地满足产品需求。通过这些实践,我们深刻认识到,如果要不断进步和提高,就必须对现有的机器人定义语言进行重大的改进。

  • 简化需要复杂对话流程的机器人的创建过程。
  • 最大限度地提高可重用性,通过重用过去已经定义过的模块和对话路径来创建机器人
在传统的做法中,完成这些并不容易,因为意图定义与部分排序约束混合在一起,限制了对话路径的自由度。这对于处理“开放式”机器人(常见于FAQ样式的机器人),其中大多数问题是独立的且始终可用的,这已经足够了。但对于更“封闭”的机器人来说,潜在的对话限制要多得多(比如用于从在线订票机器人)。

为了将聊天机器人定义语言的功能提升到一个新的水平,在一些项目中我们引进了更接近状态机语义的DSL,并完全将意图定义与控制机器人执行定点可用意图的转换规则分离,这么做有以下优势:

  1. 新机器人中可以复用以前的意图,即使设置的对话路径不同。
  2. 可以使用状态机定义复杂的对话流,让机器人保持清晰和精确的语义。
  3. 可以创建复杂的状态守护来控制转换。根据用户输入、即将发生的事件以及之前的数据、对话参数等,将机器人移动到新状态。
  4. 可以使用状态主体来存储复杂的对话逻辑,以响应用户请求。
  5. 可以将机器人模块化,以便在其他机器人中重用部分状态机。
  6. 可以将本地回退定义为状态行为的一部分。除了默认的全局回退,还可以将本地回退与状态相关联,以便在状态上下文中处理错误,比如显示一条消息,帮助用户回答机器人在对话中的特定状态下提出的问题。

意图定义语言

意图定义现在与执行部分解耦,但仍然是一个单独的子语言。对于每个意图,我们只需提供一些训练句子,让机器人能够识别出用户话语的意图,并从中提取所需的参数。

举个例子,我们有一个简单的机器人,它只能理解两种类型的用户话语:问候和陈述姓名。我们可以为每种话语类型提供几个示例句子,让机器人学会如何识别它们。当用户输入一个话语时,机器人会根据它的意图执行相应的操作,并从中提取所需的参数。

intent Hello {
inputs {
"你好"
"早上好"
}
}

intent MyNameIs {
inputs {
"我的名字叫小明"
"我是小明"
"你可以叫我小明"
}
creates context Greetings {
set parameter name from fragment "小明" (entity any)
}
}
我们为每种意图提供一些样本句子,来训练机器人如何识别它们。此外,在某些情况下,我们还会在上下文中收集一些参数(例如,用户的姓名),以便以后能够更个性化地回答用户。

我们还没有具体说明机器人应该先尝试匹配哪种意图,这是执行部分语言的内容。这种方法使我们能够重复利用这些意图(例如,在另一个机器人中,我们可能需要询问用户的姓名,而不仅仅是在问候意图之后)。

执行定义语言

使用执行文件来定义一个状态机,描述机器人如何响应意图/事件,并且可以进行转换。这使得机器人的设计者可以查看执行文件,了解整个对话流程。

执行语言中的每个状态包含 3 个部分

  • Body (可选):机器人在进入状态时执行的反应。
  • Next (必选):定义了出站转换,表示为 condition –> State。 当接收到事件/意图时,会评估条件,如果满足转换,则执行引擎会移动到指定的状态并执行其相应的反应。需要注意的是,转换条件可以非常复杂。 它们是真正的守卫,这意味着如果整个条件不为真,则转换不可导航,引擎将保持当前状态。
  • Fallback (可选):此部分可以包含任意代码(就像 Body 部分一样),如果引擎无法找到可导航的转换,则会执行这些代码。
执行模型还包含 2 个特殊状态:

  • Init:是创建用户会话时进入的常规状态。它可以包含 Body、_Next_和 Fallback 部分。
  • Default_Fallback:它只能包含 Body 部分,并且不能作为转换的目标状态。该状态表示在当前状态中未定义本地回退时执行的默认回退代码。该状态可用于打印通用错误消息(例如,“抱歉,我没明白您的意思”),而本地回退则可以打印针对当前状态的定制消息(例如,“请回答是或否”)。
最后,一个状态可以定义一个单一的通配符转换(使用保留字符___作为转换条件),当计算状态主体时将自动导航。这使我们能够在多个地方重用相同的代码并模块化执行逻辑。下面是一个简单的机器人示例,它只回复问候意图,询问用户名并向用户问好。这个机器人的回复可以通过我们基于 React 的聊天小部件显示。

//We can always have an init state in case we need to initialize some bot parameters (e.g. welcoming message)
Init {
Next {
//Here we state that the bot will first listen for an utterance matching the Hello intent, it will ignore anything else
intent == Hello --> HandleHello
}
}
HandleHello {
Body {
ReactPlatform.Reply("你好, 你叫什么名字?")
}
Next {
//We wait for the user to input the name, no other transition is possible at this point
//Obviously, in more complex bots we may have several possible outgoing transitions in a given state
intent == MyNameIs --> HandleMyNameIs
}
}
HandleMyNameIs {
Body {
ReactPlatform.Reply("你好 " + context.get("Greetings").get("name"))
}
Next {
// An automatic transition to the Init state since at this point the conversation is finished and we can start again
_ --> Init
}
}
// Default Fallback state could go here

有关基于状态机的聊天机器人设计经验总结的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  3. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  4. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

  5. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  6. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  7. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  8. SPI接收数据异常问题总结 - 2

    SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手

  9. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  10. ruby-on-rails - 为模型创建状态属性 - 2

    我想为我的Task模型创建一个status属性,该属性将按以下顺序指示它在三部分进度中的位置:打开=>进行中=>完成。它的工作方式类似于亚马逊包裹的交付方式:已订购=>已发货=>已交付。我想知道设置此属性的最佳方法是什么。我可能是错的,但创建三个独立的bool属性似乎有点多余。实现此目标的最佳方法是什么? 最佳答案 Rails4有一个内置的enummacro.它使用单个整数列并映射到键列表。classOrderenumstatus:[:ordered,:shipped,:delivered]end状态映射如下:{ordered:0,

随机推荐