Forms

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

policies:
- name: RulePolicy

定义表单

通过将表单forms添加到域(domain)中的部分来定义表单。 表单的名称也是可在故事stories或规则rules中用于处理表单执行action的操作的名称。
您需要强制指定插槽名称列表required_slots

  • 填充插槽和插槽
entities:
- cuisine
- number
slots:
  cuisine:
    type: text
    mappings:
    - type: from_entity
      entity: cuisine
  num_people:
    type: any
    mappings:
    - type: from_entity
      entity: number
forms:
  restaurant_form:
    required_slots:
        - cuisine
        - num_people
  • 定义要忽略整个表单的意向列表 ignored_intentsignored_intentsnot_intent

    如果您不希望在以下情况下填写表单的任何必需插槽 目的是 ,那么您需要定义以下内容(在表单之后:chitchat ignored_intents)

entities:
- cuisine
- number
slots:
  cuisine:
    type: text
    mappings:
    - type: from_entity
      entity: cuisine
  num_people:
    type: any
    mappings:
    - type: from_entity
      entity: number
forms:
  restaurant_form:
    ignored_intents: 
    - chitchat
    required_slots:
        - cuisine
        - num_people

激活表单

rules:
- rule: Activate form
  steps:
  - intent: request_restaurant
  - action: restaurant_form
  - active_loop: restaurant_form

停用表单(Deactivating a Form)

rules:
- rule: Submit form
  condition:
  # 表单处于活动状态的条件.
  - active_loop: restaurant_form
  steps:
  # 表单停用
  - action: restaurant_form
  - active_loop: null
  - slot_was_set:
    - requested_slot: null
  # 提交表单时要运行的操作
  - action: utter_submit
  - action: utter_slots_values

插槽映射 (Slot Mappings)



动态表单行为(Dynamic Form Behavior)

默认情况下,Rasa 会从插槽中请求下一个空插槽 在域文件中列出您的表单。
如果使用自定义插槽映射 , 它将请求该方法返回的第一个空插槽。如果插槽全部填充的插槽将停用表单。FormValidationActionrequired_slotsrequired_slots

您可以动态更新表单的所需槽位。
例如: 当您需要根据如何填充其他插槽时,这很有用 上一个插槽已填满,或者当您想要更改请求插槽的顺序时。

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

from typing import Text, List, Optional

from rasa_sdk.forms import FormValidationAction

class ValidateRestaurantForm(FormValidationAction):
    def name(self) -> Text:
        return "validate_restaurant_form"

    async def required_slots(
        self,
        domain_slots: List[Text],
        dispatcher: "CollectingDispatcher",
        tracker: "Tracker",
        domain: "DomainDict",
    ) -> List[Text]:
        additional_slots = ["outdoor_seating"]
        if tracker.slots.get("outdoor_seating") is True:
            # 如果用户想坐在外面,请询问
            # 如果他们想坐在阴凉处或阳光下。
            additional_slots.append("shade_or_sun")
        return additional_slots + domain_slots
  • 相反,如果要在某些条件下从域文件中定义的表单中删除槽, 您应该将 over 复制到新变量并将更改应用于该新变量,而不是直接修改 。直接修改可能会导致意外行为。例如:required_slotsdomain_slotsdomain_slotsdomain_slots
from typing import Text, List, Optional

from rasa_sdk.forms import FormValidationAction

class ValidateBookingForm(FormValidationAction):
    def name(self) -> Text:
        return "validate_booking_form"

    async def required_slots(
        self,
        domain_slots: List[Text],
        dispatcher: "CollectingDispatcher",
        tracker: "Tracker",
        domain: "DomainDict",
    ) -> List[Text]:
        updated_slots = domain_slots.copy()
        if tracker.slots.get("existing_customer") is True:
            updated_slots.remove("email_address")

        return updated_slots

使用自定义操作请求下一个插槽(Using a Custom Action to Ask For the Next Slot)

一旦表单确定用户接下来必须填写哪个插槽,它就会 执行操作或要求用户提供必要的信息。
如果常规话语不是 足够了,您还可以使用自定义操作或请求下一个插槽

from typing import Dict, Text, List

from rasa_sdk import Tracker
from rasa_sdk.events import EventType
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk import Action


class AskForSlotAction(Action):
    def name(self) -> Text:
        return "action_ask_cuisine"

    def run(
        self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> List[EventType]:
        dispatcher.utter_message(text="What cuisine?")
        return []

如果插槽有多个请求选项,Rasa 将按以下顺序确定优先级:
1.actionask<form_name><slot_name>
2.utter_ask
<form_name><slot_name>
3.action_ask
<slot_name>
4.utterask<slot_name>