添加自定义动作¶
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
来测试看看对话机器人是否正常返回。
::: tip 注意!这里我们在意图前面加了个 '/',因为还没有针对这个意图的训练数据,所以我们还无法使用 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
::: warning 添加更多的意图 创建 NLU 模型最少需要两个不同的意图,可以从 Chit Chat tab 里面导入更多的意图。 :::
3. 添加一个机器人回复¶
然后我们为 utter_ok
创建一个简单的回复(找到已经存在的 utter_ok, 然后编辑即可):
::: tip
像上面这样,你刚刚创建了一个消息序列,只要用户会话中触发了 * 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"
::: tip NOTE
rasa_addons.nlu.components.duckling_http_extractor.DucklingHTTPExtractor
提供了跟 ner_http_duckling
类似的功能,同时这个 component 还提供了抽取 timezone
和 reftime
的能力,有了这些我们可以为用户创造更好的体验。详情请查看 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 的时候可以方便的重新获取。
下一步¶
在这里介绍了如何添加你的自定义动作到对话中去。