Forms形式

最常见的对话模式之一是从用户那里收集一些信息以便做某事(预订餐厅、调用 API、搜索数据库等)。这也称为**槽填充**。

用法#

要在 Rasa Open Source 中使用表单,您需要确保将 规则策略添加到您的策略配置中。例如:

policies:
- name: RulePolicy

  

定义表单#

通过将表单添加到域中forms部分来定义表单。表单的名称也是您可以在 故事规则中用于处理表单执行的操作的名称。您还需要为表单应填写的每个插槽定义插槽映射。您可以为要填充的每个插槽指定一个或多个插槽映射。

下面的示例形式restaurant_form将填充槽 cuisine从所提取的实体cuisine和槽num_people从实体number

1 forms:
2 restaurant_form:
3 required_slots:
4 cuisine:
5 - type: from_entity
6 entity: cuisine
7 num_people:
8 - type: from_entity
9 entity: number

一旦第一次调用表单操作,表单就会被激活并提示用户输入下一个所需的槽值。它通过查找调用 的响应utter_ask_<form_name>_<slot_name>或未utter_ask_<slot_name>找到前者来实现此目的。确保在您的域文件中为每个必需的槽定义这些响应。

激活表格#

要激活表单,您需要添加故事规则,其中描述了助手应何时运行该表单。在特定意图触发表单的情况下,您可以例如使用以下规则:

1 rules:
2 - rule: Activate form
3 steps:
4 - intent: request_restaurant
5 - action: restaurant_form
6 - active_loop: restaurant_form

active_loop: restaurant_form步骤表示应在restaurant_form运行后激活该表单 。

停用表格#

填满所有必需的空位后,表单将自动停用。您可以使用规则或故事来描述助手在表单结尾处的行为。如果您不添加适用的故事或规则,则助手将在表单完成后自动收听下一条用户消息。以下示例utter_all_slots_filled在表单your_form填满所有必需的插槽后立即 运行话语。

 1 rules:
2 - rule: Submit form
3 condition:
4 # Condition that form is active.
5 - active_loop: restaurant_form
6 steps:
7 # Form is deactivated
8 - action: restaurant_form
9 - active_loop: null
10 - slot_was_set:
11 - requested_slot: null
12 # The actions we want to run when the form is submitted.
13 - action: utter_submit
14 - action: utter_slots_values

用户可能希望尽早退出表单。有关如何为这种情况编写故事或规则的信息,请参阅 编写不愉快形式路径的故事/规则

插槽映射#

Rasa 开源带有四个预定义的映射,用于根据最新的用户消息填充表单的插槽。如果您需要自定义函数来提取所需信息,请参阅 自定义插槽映射

来自_实体#

from_entity映射填充基于提取的实体槽。它将寻找一个被称为entity_name填充 slot的实体slot_name。如果intent_nameNone,则无论意图名称如何,都将填充插槽。否则,仅当用户的意图为 时才会填充该插槽intent_name

如果role_name和/或group_name提供,实体的角色/组标签也需要匹配给定的值。如果消息的意图是 ,则槽映射将不适用excluded_intent。请注意,您还可以为参数intent和定义意图列表not_intent

 1 forms:
2 your_form:
3 required_slots:
4 slot_name:
5 - type: from_entity
6 entity: entity_name
7 role: role_name
8 group: group name
9 intent: intent_name
10 not_intent: excluded_intent

from_entity映射中,当提取的实体唯一地映射到插槽时,即使表单没有请求该插槽,该插槽也会被填充。如果映射不是唯一的,则提取的实体将被忽略。

forms:
your_form:
required_slots:
departure_city:
- type: from_entity
entity: city
role: from
- type: from_entity
entity: city
arrival_city:
- type: from_entity
entity: city
role: to
- type: from_entity
entity: city
arrival_date:
- type: from_entity
entity: date

在上面的例子中,实体date唯一地设置槽arrival_date,一个实体city与角色from唯一地设置狭槽departure_city和一个实体city与角色to唯一地设置狭槽arrival_city,因此它们可被用于拟合即使未要求这些时隙对应的狭槽。但是,city没有角色的实体可以同时填充departure_cityarrival_city 插槽,具体取决于请求的是哪个,因此如果cityarrival_date请求插槽时提取了实体,则表单将忽略它。

from_text #

from_text映射将使用下一个使用者说话的文本,以填补插槽 slot_name。如果intent_nameNone,则无论意图名称如何,都将填充插槽。否则,仅当用户的意图为 时才会填充该插槽intent_name

如果消息的意图是 ,则槽映射将不适用excluded_intent。请注意,您可以为参数intent和定义意图列表not_intent

1 forms:
2 your_form:
3 required_slots:
4 slot_name:
5 - type: from_text
6 intent: intent_name
7 not_intent: excluded_intent

from_intent #

from_intent映射将填充槽slot_name用值my_value如果用户意图是intent_nameNone。如果消息的意图是 ,则槽映射将不适用excluded_intent。请注意,您还可以为参数intent和定义意图列表not_intent

from_intent形式的初始激活期间插槽映射将不适用。要根据激活表单的意图填充插槽,请使用from_trigger_intent 映射。

1 forms:
2 your_form:
3 required_slots:
4 slot_name:
5 - type: from_intent
6 value: my_value
7 intent: intent_name
8 not_intent: excluded_intent

from_trigger_intent #

from_trigger_intent映射将填充槽slot_name用值my_value 如果窗体通过用意图用户消息激活intent_name。如果消息的意图是 ,则槽映射将不适用 excluded_intent。请注意,您还可以为参数intent和定义意图列表not_intent

1 forms:
2 your_form:
3 required_slots:
4 slot_name:
5 - type: from_trigger_intent
6 value: my_value
7 intent: intent_name
8 not_intent: excluded_intent

为不愉快的表单路径写故事/规则#

您的用户不会总是回复您询问他们的信息。通常,用户会提出问题、闲聊、改变主意或以其他方式偏离快乐的道路。

当表单处于活动状态时,如果用户的输入未填充请求的插槽,则表单操作的执行将被拒绝,即表单将自动引发ActionExecutionRejection. 这些是表单将引发的特定场景ActionExecutionRejection

  • 请求了一个插槽,但用户没有用他们的最后一条消息填充该插槽,并且您没有定义用于验证插槽或 提取插槽的自定义操作 。
  • 请求了一个插槽,但您用于验证插槽或 提取插槽的自定义操作 未返回任何SlotSet事件。

要故意拒绝表单执行,您还可以返回一个ActionExecutionRejected事件作为自定义验证或槽映射的一部分。

要处理可能导致表单执行被拒绝的情况,您可以编写包含预期中断的规则或故事。例如,如果您希望您的用户与您的机器人聊天,您可以添加一个规则来处理这个问题:

 1 rules:
2 - rule: Example of an unhappy path
3 condition:
4 # Condition that form is active.
5 - active_loop: restaurant_form
6 steps:
7 # This unhappy path handles the case of an intent `chitchat`.
8 - intent: chitchat
9 - action: utter_chitchat
10 # Return to form after handling the `chitchat` intent
11 - action: restaurant_form
12 - active_loop: restaurant_form

在某些情况下,用户可能会在表单操作的中间改变主意,并决定不继续他们的初始请求。在这种情况下,助手应该停止请求请求的插槽。

您可以使用默认操作优雅地处理此类情况,该操作action_deactivate_loop将停用表单并重置请求的插槽。此类对话的示例故事如下所示:

 1 stories:
2 - story: User interrupts the form and doesn't want to continue
3 steps:
4 - intent: request_restaurant
5 - action: restaurant_form
6 - active_loop: restaurant_form
7 - intent: stop
8 - action: utter_ask_continue
9 - intent: stop
10 - action: action_deactivate_loop
11 - active_loop: null

这是强烈建议你建立一个使用这些规则或故事, 互动学习。如果您手写这些规则/故事,您可能会错过重要的事情。

高级用法#

使用自定义操作可以完全自定义表单。

验证表单输入#

从用户输入中提取槽值后,您可以验证提取的槽。默认情况下,Rasa Open Source 仅验证在请求插槽后是否填充了任何插槽。

您可以实施自定义操作 validate_<form_name> 来验证任何提取的插槽。确保将此操作添加到actions 域的部分:

actions:
- validate_restaurant_form

执行表单时,它将运行您的自定义操作。

此自定义操作可以扩展FormValidationAction类以简化验证提取槽的过程。在这种情况下,您需要编写validate_<slot_name>为每个提取的插槽命名的函数。

以下示例显示了自定义操作的实现,该操作验证指定的插槽cuisine是否有效。

 1 from typing import Text, List, Any, Dict
2
3 from rasa_sdk import Tracker, FormValidationAction
4 from rasa_sdk.executor import CollectingDispatcher
5 from rasa_sdk.types import DomainDict
6
7
8 class ValidateRestaurantForm(FormValidationAction):
9 def name(self) -> Text:
10 return "validate_restaurant_form"
11
12 @staticmethod
13 def cuisine_db() -> List[Text]:
14 """Database of supported cuisines"""
15
16 return ["caribbean", "chinese", "french"]
17
18 def validate_cuisine(
19 self,
20 slot_value: Any,
21 dispatcher: CollectingDispatcher,
22 tracker: Tracker,
23 domain: DomainDict,
24 ) -> Dict[Text, Any]:
25 """Validate cuisine value."""
26
27 if slot_value.lower() in self.cuisine_db():
28 # validation succeeded, set the value of the "cuisine" slot to value
29 return {"cuisine": slot_value}
30 else:
31 # validation failed, set this slot to None so that the
32 # user will be asked for the slot again
33 return {"cuisine": None}

您还可以扩展Action类并检索提取的插槽tracker.slots_to_validate 以完全自定义验证过程。

自定义插槽映射#

如果没有预定义的插槽映射适合您的用例,您可以使用 自定义操作 validate_<form_name>来编写您自己的提取代码。Rasa Open Source 会在表单运行时触发这个动作。

如果您使用的是 Rasa SDK,我们建议您扩展提供的 FormValidationAction. 使用FormValidationAction时,提取海关槽位需要三个步骤:

  1. extract_<slot_name>为每个应该以自定义方式映射的插槽定义一个方法。
  2. 确保在域文件中为表单只列出那些使用预定义映射的插槽 。
  3. 覆盖required_slots以将具有自定义映射的所有插槽添加到表单应请求的插槽列表中。

下面的示例展示了一个表单的实现outdoor_seating,除了使用预定义映射的插槽之外,它还以自定义方式 提取插槽 。该方法根据关键字是否出现在最后一条用户消息中来extract_outdoor_seating设置槽。outdoor_seatingoutdoor

 1 from typing import Dict, Text, List, Optional, Any
2
3 from rasa_sdk import Tracker
4 from rasa_sdk.executor import CollectingDispatcher
5 from rasa_sdk.forms import FormValidationAction
6
7
8 class ValidateRestaurantForm(FormValidationAction):
9 def name(self) -> Text:
10 return "validate_restaurant_form"
11
12 async def required_slots(
13 self,
14 slots_mapped_in_domain: List[Text],
15 dispatcher: "CollectingDispatcher",
16 tracker: "Tracker",
17 domain: "DomainDict",
18 ) -> Optional[List[Text]]:
19 required_slots = slots_mapped_in_domain + ["outdoor_seating"]
20 return required_slots
21
22 async def extract_outdoor_seating(
23 self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
24 ) -> Dict[Text, Any]:
25 text_of_last_user_message = tracker.latest_message.get("text")
26 sit_outside = "outdoor" in text_of_last_user_message
27
28 return {"outdoor_seating": sit_outside}

默认情况下,FormValidationAction 将自动将 设置为未填充requested_slot的第一个插槽required_slots

动态表单行为#

默认情况下,Rasa Open Source 会从域文件中为您的表单列出的插槽中请求下一个空插槽。如果您使用 自定义插槽映射FormValidationAction,它将要求该required_slots方法返回的第一个空插槽。如果required_slots填写了所有插槽,则该表格将被停用。

如果需要,您可以动态更新表单所需的插槽。例如,当您需要基于前一个槽的填充方式的更多详细信息时,或者您想更改请求槽的顺序时,这很有用。

如果您使用的是 Rasa SDK,我们建议您使用FormValidationAction和 覆盖required_slots来适应您的动态行为。您应该extract_<slot name>为每个不使用预定义映射的插槽实现一个方法,如自定义插槽映射 中所述。下面的示例将询问用户是否想坐在阴凉处或阳光下,以防他们说他们想坐在外面。

 1 from typing import Text, List, Optional
2
3 from rasa_sdk.forms import FormValidationAction
4
5 class ValidateRestaurantForm(FormValidationAction):
6 def name(self) -> Text:
7 return "validate_restaurant_form"
8
9 async def required_slots(
10 self,
11 slots_mapped_in_domain: List[Text],
12 dispatcher: "CollectingDispatcher",
13 tracker: "Tracker",
14 domain: "DomainDict",
15 ) -> Optional[List[Text]]:
16 additional_slots = ["outdoor_seating"]
17 if tracker.slots.get("outdoor_seating") is True:
18 # If the user wants to sit outside, ask
19 # if they want to sit in the shade or in the sun.
20 additional_slots.append("shade_or_sun")
21
22 return additional_slots + slots_mapped_in_domain

request_slot 插槽#

该插槽requested_slot将作为类型为 的插槽自动添加到域中text。的值requested_slot将在对话期间被忽略。如果你想改变这个行为,你需要将 加入requested_slot 到你的域文件中作为一个分类槽, influence_conversation设置为true。如果您想以不同的方式处理不愉快的路径,您可能想要这样做,具体取决于用户当前询问的插槽。例如,如果您的用户用另一个问题来回答机器人的一个问题,比如您为什么需要知道这一点? 对此explain意图的反应取决于我们在故事中的位置。在餐厅案例中,您的故事将如下所示:

 1 stories:
2 - story: explain cuisine slot
3 steps:
4 - intent: request_restaurant
5 - action: restaurant_form
6 - active_loop: restaurant
7 - slot_was_set:
8 - requested_slot: cuisine
9 - intent: explain
10 - action: utter_explain_cuisine
11 - action: restaurant_form
12 - active_loop: null
13
14 - story: explain num_people slot
15 steps:
16 - intent: request_restaurant
17 - action: restaurant_form
18 - active_loop: restaurant
19 - slot_was_set:
20 - requested_slot: cuisine
21 - slot_was_set:
22 - requested_slot: num_people
23 - intent: explain
24 - action: utter_explain_num_people
25 - action: restaurant_form
26 - active_loop: null

同样,强烈建议您使用 交互式学习来构建这些故事。

使用自定义操作请求下一个插槽#

一旦表单确定用户接下来必须填充哪个位置,它就会执行操作utter_ask_<form_name>_<slot_name>utter_ask_<slot_name> 要求用户提供必要的信息。如果常规话语还不够,您还可以使用自定义操作action_ask_<form_name>_<slot_name>或 action_ask_<slot_name>要求下一个槽。

 1 from typing import Dict, Text, List
2
3 from rasa_sdk import Tracker
4 from rasa_sdk.events import EventType
5 from rasa_sdk.executor import CollectingDispatcher
6 from rasa_sdk import Action
7
8
9 class AskForSlotAction(Action):
10 def name(self) -> Text:
11 return "action_ask_cuisine"
12
13 def run(
14 self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
15 ) -> List[EventType]:
16 dispatcher.utter_message(text="What cuisine?")
17 return []

rasa form的中断形式 自然机器语言学习 人工智能的更多相关文章

  1. java中的http请求的封装(GET、POST、form表单形式)

    目前JAVA实现HTTP请求的方法用的最多的有两种:一种是通过HTTPClient这种第三方的开源框架去实现.HTTPClient对HTTP的封装性比较不错,通过它基本上能够满足我们大部分的需求,Ht ...

  2. C#开发学习人工智能的第一步

    前言 作为一个软件开发者,我们除了要学会复制,黏贴,还要学会调用API和优秀的开源类库. 也许,有人说C#做不了人工智能,如果你相信了,那只能说明你的思想还是狭隘的. 做不了人工智能的不是C#这种语言 ...

  3. 吴裕雄--天生自然HADOOP学习笔记:hadoop集群实现PageRank算法实验报告

    实验课程名称:大数据处理技术 实验项目名称:hadoop集群实现PageRank算法 实验类型:综合性 实验日期:2018年 6 月4日-6月14日 学生姓名 吴裕雄 学号 15210120331 班 ...

  4. 吴裕雄--天生自然 oracle学习笔记:oracle理论学习详解及各种简单操作例子

    1. 数据库的发展过程 层次模型 -->网状模型 -->关系模型 -->对象关系模型 2. 关于数据库的概念 DB:数据库(存储信息的仓库) DBMS:数据库管理系统(用于管理数据库 ...

  5. 吴裕雄--天生自然HADOOP学习笔记:基本环境配置

    实验目的 学习安装Java 学习配置环境变量 学习设置免密码登陆的方法 掌握Linux环境下时间同步的配置 实验原理 1.Java的安装 java是大数据的黄金语言,这和java跨平台的特性是密不可分 ...

  6. 吴裕雄--天生自然HADOOP学习笔记:使用yum安装更新软件

    实验目的 了解yum的原理及配置 学习软件的更新与安装 学习源代码编译安装 实验原理 1.编译安装 前面我们讲到了安装软件的方式,因为linux是开放源码的,我们可以直接获得源码,自己编译安装.例如: ...

  7. 吴裕雄--天生自然HADOOP学习笔记:Shell工具使用

    实验目的 学习使用xshell工具连接Linux服务器 在连上的服务器中进入用户目录 熟悉简单的文件操作命令 实验原理 熟悉shell命令是熟悉使用linux环境进行开发的第一步,我们在linux的交 ...

  8. 吴裕雄--天生自然Hadoop学习笔记:Hadoop简介

    Hadoop是一个由Apache基金会所开发的分布式系统基础架构.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力进行高速运算和存储.Hadoop实现了一个分布式文件系统(H ...

  9. 吴裕雄--天生自然MySQL学习笔记:MySQL 导出数据

    MySQL中可以使用SELECT...INTO OUTFILE语句来简单的导出数据到文本文件上. 使用 SELECT ... INTO OUTFILE 语句导出数据 以下实例中将数据表 runoob_ ...

随机推荐

  1. CAS 原理 应用

    原子CAS操作 原子操作指令里,有原子加,原子减,cas到底是什么呢? 首先看一段代码, bool compare_and_swap(int *accum, int *dest, int newval ...

  2. ASP.NET MVC部署网站到IIS,只列出网站目录

    解决办法: 1.重启IIS 打开CMD运行以下代码: ps:根据发布网站的的.NET Framework版本进入对应的目录 4.0版本  C:\Windows\Microsoft.NET\Framew ...

  3. linux笔记全(无图版)

    1.ls 查看当前目录下的所有内容 黑色的是文件,蓝色的是文件夹,也就是目录 2.rm -f anaconda-ks. cfg 彻底删除文件(如不确定,则需要先保存备份,也就是快照) 3.ifconf ...

  4. 我一个五年Android开发,居然被一个技术不如我的面试官嫌弃了......

    背景 首先介绍一下自己的情况.目前所在的是一家小的创业公司,待了5年多,薪资一般吧.由于这几年公司也在转型.工作经历大概可以分为 3 个阶段. 第一阶段是从进公司开始做 android app 开发, ...

  5. 如何让win10开机默认开启小键盘?

    如何让win10开机默认开启小键盘? windows10默认是关闭小键盘的.每次输入开机密码的时候都需要按一下小键盘开启键(numlock),才能按数字键 一.运行注册表编辑器,修改InitialKe ...

  6. Python包安装过程

    以下是paramiko-1.7.7.1的安装过程,可以看到整个过程分为步,第一步是build,就是拷贝源文件到build文件夹里, F:\VMFiles\tmpFiles\paramiko-1.7.7 ...

  7. JavaScript学习05(操作DOM)

    操作DOM DOM(文档对象模型) 当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model). HTML DOM 模型被结构化为对象树: 通过这个对象模型,Java ...

  8. 关于解决numpy使用sklearn时的警告问题

    关于解决numpy使用sklearn时的警告问题 在使用的时候,出现提示 :219: RuntimeWarning: numpy.ufunc size changed, may indicate bi ...

  9. 面向对象第一单元总结:Java实现表达式求导

    面向对象第一单元总结:Java实现表达式求导 题目要求 输入一个表达式:包含x,x**2,sin(),cos(),等形式,对x求导并输出结果 例:\(x+x**2+-2*x**2*(sin(x**2+ ...

  10. 一款优秀的国产性能测试工具kylinPET在麒麟操作系统上的能力表现

    一直以来人们从事性能测试,使用最多的是Jmeter和LoadRuner .笔者在网上找了一下国产性能测试工具,从中筛选出一款优秀的国产的性能测试工具kylinPET.查找该款工具的历史,好像有十年历史 ...