文章目录
注:本文写作时rasa版本比较老,新版rasa core有改动,有关rasa请参考:
RASA 开发中文指南系列博文:
- Rasa中文聊天机器人开发指南(1):入门篇
- Rasa中文聊天机器人开发指南(2):NLU篇
- Rasa中文聊天机器人开发指南(3):Core篇
- Rasa中文聊天机器人开发指南(4):RasaX与模型评估
- Rasa中文聊天机器人开发指南(5):浅析Mitie、spaCy和CRF实体识别器
- Rasa中文聊天机器人开发指南(6):浅析Mitie、Sklearn和Embedding意图分类器
注:本系列博客翻译自Rasa官方文档,并融合了自己的理解和项目实战,同时对文档中涉及到的技术点进行了一定程度的扩展,目的是为了更好的理解Rasa工作机制。与本系列博文配套的项目GitHub地址:ChitChatAssistant,欢迎star
和issues
,我们共同讨论、学习!
1. Rasa Core简介
Rasa Core是Rasa框架提供的对话管理模块,它类似于聊天机器人的大脑,主要的任务是维护更新对话状态和动作选择,然后对用户的输入作出响应。所谓对话状态是一种机器能够处理的对聊天数据的表征,对话状态中包含所有可能会影响下一步决策的信息,如自然语言理解模块的输出、用户的特征等;所谓动作选择,是指基于当前的对话状态,选择接下来合适的动作,例如向用户追问需补充的信息、执行用户要求的动作等。举一个具体的例子,用户说“帮我妈妈预定一束花”,此时对话状态包括自然语言理解模块的输出、用户的位置、历史行为等特征。在这个状态下,系统接下来的动作可能是:
- 向用户询问可接受的价格,如“请问预期价位是多少?”;
- 向用户确认可接受的价格,如“像上次一样买价值200的花可以吗?”
- 直接为用户预订
下面是Rasa Core文档中给出的一个对话场景:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3LH8Avuk-1582980505120)(http://rasa.com/docs/rasa/_images/mood_bot.png)]
1.1 Rasa Core消息处理流程
由前面描述的对话管理模块了解到,它应该是负责协调聊天机器人的各个模块,起到维护人机对话的结构和状态的作用。对话管理模块涉及到的关键技术包括对话行为识别、对话状态识别、对话策略学习以及行为预测、对话奖励等。下面是Rasa Core消息处理流程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9vb6YiSI-1582980505121)(http://rasa.com/docs/rasa/_images/rasa-message-processing.png)]
- 首先,将用户输入的Message传递到
Interpreter(NLU模块)
,该模块负责识别Message中的"意图(intent)“和提取所有"实体”(entity)数据; - 其次,Rasa Core会将Interpreter提取到的意图和识别传给
Tracker对象
,该对象的主要作用是跟踪会话状态(conversation state); - 第三,利用
policy
记录Tracker对象的当前状态,并选择执行相应的action,其中,这个action是被记录在Track对象中的; - 最后,将执行action返回的结果输出即完成一次人机交互。
注:整个执行过程由Rasa Core框架中的
rasa_core.agent.Agent
类处理。
1.2 安装Rasa Core
pip install rasa_core
2. Dialogue模型训练
2.1 Story样本数据
Story样本数据就是Rasa Core对话系统要训练的样本,它描述了人机对话交互过程成可能出现的故事情节,通过对Stories样本和domain的训练得到人机对话系统所需的对话模型。每个story的格式基本是一样的,只是组成的内容不一样,即以##
开头的行表示一个story的开始,跟随的文本只用于描述;以*
开始的行表示一个意图和填充的slot;以缩进 -
开始表示Rasa NLU识别到该意图后Rasa Core要执行的action。以下是stories.md文件的部分内容:
## story1:greet only
* greet
- utter_answer_greet
> check_greet
## story2:
* goodbye
- utter_answer_goodbye
## story3:thanks
* thanks
- utter_answer_thanks
## story4:change address or data-time withe greet
> check_greet
* weather_address_date-time{
"address": "上海", "date-time": "明天"}
- action_report_weather
## story5:change address or data-time withe greet
> check_greet
* weather_address_date-time{
"address": "上海", "date-time": "明天"}
- action_report_weather
- utter_report_weather
* weather_address{
"address": "北京"} OR weather_date-time{
"date-time": "明天"}
- action_report_weather
- utter_report_weather
...
...
其中,> check_*
用于模块化和简化训练数据,即story复用;OR Statements
用于处理同一个story中可能出现2个以上走向(意图),这有利于简化story,但是相应的训练时间相当于训练了两个以上故事,但也不建议使用的太密集。
Visualizing Stories:可视化Stories
Rasa Core中提供了rasa_core.visualize模块可视化故事,这有利于我们更容易掌握设计故事流程。
命令如下:
python -m rasa_core.visualize -d domain.yml -s data/stories.md -o graph.html -c config.yml
其中,-m
指定运行模块;-d
指定domain.yml文件路径;-s
指定story路径;-o
指定输出文件名;-c
指定Policy配置文件。最终,在项目根目录得到一个graph.html,用浏览器打开可见:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tXXmwE7w-1582980505121)(http://rasa.com/docs/rasa/_images/interactive_learning_graph.gif)]
当然,除了使用命令生成stories的可视化关系图,我们还可以创建visualize.py代码实现。
from rasa_core.agent import Agent
from rasa_core.policies.keras_policy import KerasPolicy
from rasa_core.policies.memoization import MemoizationPolicy
if __name__ == '__main__':
agent = Agent("domain.yml",
policies=[MemoizationPolicy(), KerasPolicy()])
agent.visualize("data/stories.md",
output_file="graph.html", max_history=2)
2.2 Domain
domain.yml定义了对话机器人应知道的所有信息,它相当于大脑框架,指定了意图intents
、实体entities
、插槽slots
以及动作actions
,其中,intents、entities应与NLU模型训练样本中标记的致,slots应与标记的entities一致,actions为对话机器人对应用户的请求需作出的动作。此外,domain.yml中的templates
部分针对utter_
类型action定义了模板消息,便于对话机器人对相关动作自动回复。假如我们要做一个天气资讯的人机对话系统,并且定义一个查询天气和污染程度的action,那么我们要这么做。domain.yml示例:
intents:
- greet
- goodbye
- thanks
- whoareyou
- whattodo
- whereyoufrom
- search_weather
- search_weather_quality
- search_datetime
- search_city
slots:
city:
type: text
datetime:
type: text
matches:
type: unfeaturized
entities:
- city
- datetime
actions:
- utter_answer_greet
- utter_answer_goodbye
- utter_answer_thanks
- utter_introduce_self
- utter_introduce_selfcando
- utter_introduce_selffrom
- action_search_wether
- action_search_weather_quality
templates:
utter_answer_goodbye:
- text: "再见"
- text: "拜拜"
- text: "虽然我有万般舍不得,但是天下没有不散的宴席~祝您安好!"
- text: "期待下次再见!"
- text: "嗯嗯,下次需要时随时记得我哟~"
- text: "88"
utter_answer_thanks:
- text: "嗯呢。不用客气~"
- text: "这是我应该做的,主人~"
- text: "嗯嗯,合作愉快!"
utter_introduce_self:
- text: "您好!我是您的AI机器人呀~"
utter_introduce_selfcando:
- text: "我能帮你查询天气信息"
utter_introduce_selffrom:
- text: "我来自xxx"
utter_ask_city:
- text: "请问您要查询哪里的天气?"
utter_ask_datetime:
- text: "请问您要查询哪天的天气"
utter_report_search_result:
- text: "{matches}"
utter_default:
- text: "小x还在学习中,请换种说法吧~"
- text: "小x正在学习中,等我升级了您再试试吧~"
- text: "对不起,主人,您要查询的功能小x还没学会呢~"
说明:
intents |
things you expect users to say. See Rasa NLU |
---|---|
actions |
things your bot can do and say |
templates |
template strings for the things your bot can say |
entities |
pieces of info you want to extract from messages. See Rasa NLU |
slots |
information to keep track of during a conversation (e.g. a users age) - see Using Slots |
2.2.0 intents
intents,即意图,这里枚举了在训练NLU模型样本时,样本中标出的所有intent。
intents:
- greet
- goodbye
- thanks
- search_weather
- search_weather_quality
- search_datetime
- search_city
2.2.1 actions
当Rasa NLU识别到用户输入Message的意图后,Rasa Core对话管理模块就会对其作出回应,而完成这个回应的模块就是action。Rasa Core支持三种action,即default actions、utter actions以及 custom actions,它们的作用和区别如下:
1. default actions
DefaultAction是Rasa Core默认的一组actions,我们无需定义它们,直接可以story和domain中使用。包括以下三种action:
- action_listen:监听action,Rasa Core在会话过程中通常会自动调用该action;
- action_restart:重置状态,比初始化Slots(插槽)的值等;
- action_default_fallback:当Rasa Core得到的置信度低于设置的阈值时,默认执行该action;
2. utter actions
UtterAction是以utter_
为开头,仅仅用于向用户发送一条消息作为反馈的一类actions。定义一个UtterAction很简单,只需要在domain.yml文件中的actions:
字段定义以utter_
为开头的action即可,而具体回复内容将被定义在templates:
部分,这个我们下面有专门讲解。定义utter actions示例如下:
actions:
- utter_answer_greet
- utter_answer_goodbye
- utter_answer_thanks
- utter_introduce_self
- utter_introduce_selfcando
- utter_introduce_selffrom
3. custom actions
CustomAction,即自定义action,允许开发者执行任何操作并反馈给用户,比如简单的返回一串字符串,或者控制家电、检查银行账户余额等等。它与DefaultAction不同,自定义action需要我们在domain.yml文件中的actions
部分先进行定义,然后在指定的webserver中实现它,其中,这个webserver的url地址在endpoint.yml
文件中指定,并且这个webserver可以通过任何语言实现,当然这里首先推荐python来做,毕竟Rasa Core为我们封装好了一个rasa-core-sdk
专门用来处理自定义action。关于action web的搭建和action的具体实现,我们在后面详细讲解,这里我们看下在在Rasa Core项目中需要做什么。假如我们在天气资讯的人机对话系统需提供查询天气和空气质量两个业务,那么我们就需要在domain.yml文件中定义查询天气和空气质量的action,即:
actions:
...
- action_search_weather
- action_search_weather_quality
2.2.2 templates
在前面我们说的,domain.yml的templates:
部分就是描述UtterActions具体的回复内容,并且每个UtterAction下可以定义多条信息,当用户发起一个意图,比如"你好!",就触发utter_answer_greet
操作,Rasa Core会从该action的模板中自动选择其中的一条信息作为结果反馈给用户。templates部分示例如下:
templates:
utter_answer_greet:
- text: "您好!请问我可以帮到您吗?"
- text: "您好!请说出您要查询的具体业务,比如跟我说'查询身份证号码'"
- text: "您好!
utter_answer_goodbye:
- text: "再见"
- text: "拜拜"
- text: "虽然我有万般舍不得,但是天下没有不散的宴席~祝您安好!"
- text: "期待下次再见!"
- text: "嗯嗯,下次需要时随时记得我哟~"