# 添加自定义动作

Botfront 支持 Rasa 的自定义动作,创建和应用自定义动作非常简单。

项目的默认结构应该如下:

文件夹 描述
.botfront 包含项目配置文件, docker-compose 文件
actions 包含自定义动作文件
botfront-db MongoDB 数据库
models 训练好的模型
rasa Rasa 相关的文件

如你所见, 关于自定义动作的逻辑都放在 actions 文件夹下。

# 启动 watcher 程序

首先要做的是启动 watcher 程序,在项目根目录下执行 botfront watch,接下来所有actions 文件夹下的改动都将触发 rebuild 和 restart 动作,你就可以随时在 Botfront 里面看到结果了。

# 创建一个自定义动作

所有 actions 目录下的文件都会被 watcher 程序监控,你可以在这个目录下创建自己的自定义动作文件,或者直接在 my_actions.py 文件上修改也可以。

# 确认你的自定义动作正常导入、注册

在项目根目录下执行 botfront logs 以确认你的自定义动作被正确的导入了,正常的话你会在输出中找到诸如一下的信息: INFO:rasa_sdk.executor:Registered function for 'action_guests'.

# 把自定义动作添加到用户回应中去

然后在故事编辑器里面找到并把自定义动作添加到对用户的回应中去。

# 正式部署

正式部署的时候可以通过项目下 actions 目录中默认生成的 Dockerfile.production 文件来生成 docker 镜像并部署即可。


# 入门教程

假设我们想创建这样一个对话:

- User: We want to book a room for 2 adults and 2 kids
- Bot: You are 4 in total and that is an even number

首先我们先做一个简版的:

- User: We want to book a room for 2 adults and 2 kids
- Bot: Ok

然后一步步改进...

# 1. 新建一个故事

像这样创建一个新的故事脚本组,添加故事脚本,然后点 Train everything




* inform_guests
  - utter_ok

训练完了可以在输入框里面输入 /inform_guests 来测试看看对话机器人是否正常返回。

提示

注意!这里我们在意图前面加了个 '/',因为还没有针对这个意图的训练数据,所以我们还无法使用 nlp 处理,加个 '/' 可以让我们直接调用对应的意图处理逻辑。

对话机器人应该简单的返回 utter_ok.

# 2. 添加训练数据到 inform_guests

把下面这些语料添加到 inform_guests 意图里面,然后 重新训练 你的 NLU 模型:

We need a room for 2 adults and 2 children
A room tonight for 2 adults and 3 kids
A room for 2 adults

添加更多的意图

创建 NLU 模型最少需要两个不同的意图,可以从 Chit Chat tab 里面导入更多的意图。

# 3. 添加一个机器人回复

然后我们为 utter_ok 创建一个简单的回复(找到已经存在的 utter_ok, 然后编辑即可):

提示

像上面这样,你刚刚创建了一个消息序列,只要用户会话中触发了 * inform_guests 意图,对话机器人就会你刚刚填写的 2 条回复。

回顾一下我们的最终目标:

- User: We want to book a room for 2 adults and 2 kids
- Bot: You are 4 in total and that is an even number

为达成目标我们还需要做如下两步处理:

  1. 添加 Duckling 到我们的 NLU 管道,来抽取数字实体。
  2. 写一个自定义动作逻辑,来把用户会话中提到的数字加和处理。

# 4. 添加 Duckling 管道

Duckling 是 Facebook 开源的一个用来抽取结构化实体数据的包(比如数字、日期、金额、重量、体积等等)

事实上, Duckling 已经以 docker image 的方式被下载到本地了(详情参见项目根目录下的 docker-compose.yml 文件)

把 Duckling 添加到 NLU 管道中 意味着我们将用 Duckling 包来从用户会话中抽取数字 ("2 adults and 2 kids").

- name: "rasa_addons.nlu.components.duckling_http_extractor.DucklingHTTPExtractor"
  url: "http://duckling:8000"
  dimensions:
  - "number"

NOTE

rasa_addons.nlu.components.duckling_http_extractor.DucklingHTTPExtractor 提供了跟 ner_http_duckling 类似的功能,同时这个 component 还提供了抽取 timezonereftime 的能力,有了这些我们可以为用户创造更好的体验。详情请查看 Training Data > API tab.

# 5. 启动 watcher

在项目根目录下运行 botfront watch 可以实时监测你的自定义动作文件,当有改动时及时 rebuild

# 6. 创建一个自定义动作

打开 actions 文件夹,添加一个叫 my_actions.py 的文件(如果已经存在的话直接打开就好),把下面这些内容复制到文件中去:

import logging
from functools import reduce
from rasa_core_sdk import Action
from rasa_core_sdk.events import SlotSet, ReminderScheduled

logging.basicConfig(level="DEBUG")
logger = logging.getLogger()

class GuestsAction(Action):

    def name(self):
        return 'action_guests'

    def run(self, dispatcher, tracker, domain):
        entities = tracker.latest_message.get('entities', [])

        # Only keep 'number' entities
        numbers = list(filter(lambda e: e.get('entity') == 'number', entities))

        # Stop here if no numbers found
        if not len(numbers):
            dispatcher.utter_message("How many are you?")
            return []

        # Compute the sum of all 'number' entity values
        number_of_guests = reduce(lambda x, y: x + y, map(lambda e:e.get('value'), numbers))

        is_even = number_of_guests % 2 == 0

        message = 'You are {number_of_guests} in total and that is an {is_even} number'.format(
            number_of_guests=number_of_guests,
            is_even='even' if is_even else 'odd')

        dispatcher.utter_message(message)
        return []

点保存之后 actions 服务会 rebuild ,完成后你新开一个终端,到项目根目录下输入 botfront logs,然后你会在终端界面看到如下的 log 信息:

INFO:rasa_sdk.executor:Registered function for 'action_guests'.

# 7. 更新故事

接下来让我们用新创建的 action_guests 来取代之前我们故事中的 utter_ok 回复:


 


* inform_guests
  - action_guests

提示

自定义动作的名字 action_guests 是来自 GuestsAction 类的 name() 方法。

# 8. 重新训练和测试

重新训练后就能看到新的结果如下:

# 9. 关闭 Botfront

运行 botfront down 可以安全的关掉运行的 Botfront 项目,释放所占用的 docker 资源,你的数据存放在 botfront-db 目录,当你下次运行 Botfront 的时候可以方便的重新获取。

# 下一步

这里介绍了如何添加你的自定义动作到对话中去。