1.什么是FORM?
FORM 就像我们注册qq账号一样
(1)先我们要登陆腾讯网页点击注册 ,这是我们的意图
(2) 然后会让我们填写 用户名 ,这是填写 id 槽位
(3) 下一步填写 密码 , 这是填写 pwd槽位
(4) 下一步填写 手机号, 这是填写 msisdn槽位
当我们把所有的内容都填写完毕,点击完成。
在我们填写信息的时候也有其他的问题:
1.填写校验:例如手机号码,是不是11位。如果填写错误,会让你从新填写
2.填写到一般时候,不想注册了,直接关闭网页
3.等等情况
Form 就是设计好需要填写的信息,然后一步步填写。
Form在domain文件中定义:
forms:
restaurant_form:
使用Form则需要在config文件中引入FormPolicy。
表单的激活与停止:
处理打断
例如:在填写注册的时候,喝了一杯水继续填写
rules:
- rule: Example of an unhappy path
condition:Condition that form is active.
- active_loop: restaurant_form
steps:
This unhappy path handles the case of an intent
chitchat
.- intent: chitchat
- action: utter_chitchat
Return to form after handling the
chitchat
intent- action: restaurant_form
- active_loop: restaurant_form
- active_loop: restaurant_form
放弃填槽
1.可以这样处理,用action_deactivate_loop
例如:不想注册了,直接退出
stories:
- story: User interrupts the form and doesn’t want to continue
steps:- intent: request_restaurant
- action: restaurant_form
- active_loop: restaurant_form
- intent: stop
- action: utter_ask_continue
- intent: stop
- action: action_deactivate_loop
- active_loop: null
Slot Mappings : 槽映射
1.在默认的情况下,槽只会被用户输入里与其名称相同的实体所填充。
2. 若我们想以其他方式(如用户选择或用户直接输入)来填槽,可以借助slot_mappings方法来实现。
forms:
restaurant_form:
cuisine:
- type: from_entity
entity: cuisine
not_intent: chitchat
num_people:
- type: from_entity
entity: number
intent: [inform, request_restaurant]
outdoor_seating:
- type: from_entity
entity: seating
- type: from_intent
intent: affirm
value: true
- type: from_intent
intent: deny
value: false
preferences:
- type: from_intent
intent: deny
value: no additional preferences
- type: from_text
not_intent: affirm
使用from_entity、from_intent 、from_text 等方式填充。
自定义槽位映射:
1.方法的名称:extract_<slot_name>
2.槽位在 domain 声明
3.将槽位添加到required_slots中
from typing import Dict, Text, List, Optional, Any
from rasa_sdk import Tracker
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.forms import FormValidationAction
class ValidateRestaurantForm(FormValidationAction):
def name(self) -> Text:
return “validate_restaurant_form”
async def required_slots(
self,
slots_mapped_in_domain: List[Text],
dispatcher: "CollectingDispatcher",
tracker: "Tracker",
domain: "DomainDict",
) -> Optional[List[Text]]:
required_slots = slots_mapped_in_domain + ["outdoor_seating"]
return required_slots
async def extract_outdoor_seating(
self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
) -> Dict[Text, Any]:
text_of_last_user_message = tracker.latest_message.get("text")
sit_outside = "outdoor" in text_of_last_user_message
return {"outdoor_seating": sit_outside}
其实form 是action的其中一种,我们可以自定义一个表单
关于动作restaurant_form,需要定义三个方法:
(1)def name(…) -> Text 用于get动作名称;
(2)def required_slots(…) -> List[Text] 用于get需要被填的槽名称列表
(3)def submit(…) -> List[Dist] 用于槽填满后进行后续处理,比如调用查询天气的的API
槽值验证
正如我们上面注册的信息需要验证,槽值也是可以验证的:
添加在domain
actions:
- validate_restaurant_form
需要自定义 action ,需要验证的槽位在自定义action 的方法名 ,必须是validate_<slot_name>
例如:
class ValidateRestaurantForm(FormValidationAction):
def name(self) -> Text:
return “validate_restaurant_form”
@staticmethod
def cuisine_db() -> List[Text]:
"""Database of supported cuisines"""
return ["caribbean", "chinese", "french"]
def validate_cuisine(
self,
slot_value: Any,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict,
) -> Dict[Text, Any]:
"""Validate cuisine value."""
if slot_value.lower() in self.cuisine_db():
return {"cuisine": slot_value}
else:
return {"cuisine": None}