背景
上一篇文章提到了百度UNIT智能客服教学机器人,下面用Rasa实现同样的效果。环境如下
Rasa Version : 3.1.0
Minimum Compatible Version: 3.0.0
Rasa SDK Version : 3.1.1
Rasa X Version : 1.1.0
Python Version : 3.8.10
Operating System : Linux-5.15.0-69-generic-x86_64-with-glibc2.29
效果
UNIT
首先通过百度UNIT智能客服教学机器人熟悉一下基本概念:
- 首先确认需要解决的问题,如上图所示:1. 实现业务办理中推荐手机 2. 实现售后咨询 3. 无法处理给出兜底回复
- 梳理对话流程
- UNIT中将对话分为FAQ问答技能即单轮对话,对话技能即多轮对话
- 确定需要的技能和对话模板,也就是对话模板
Rasa 和 UNIT 概念对比
Rasa Intent VS UNIT技能
UNIT技能配置
Rasa Intent(意图)
- Rasa工程目录如上图
- 在nlu.yml中定义意图,训练数据相关文档在这里
- 通过将意图相同的训练数据罗列在一起,使得Rasa具备’推断’意图的能力
nlu:
- intent: period
examples: |
- 保修期有多久?
- 多长时间啊,保修期?
- 多久会过保呢?
- 保修期多长时间啊?
- intent: return
examples: |
- 支持七天无理由退换货吗
- 有七天无理由退换货服务吗?
- 可以退换货吗?七天无理由的
- 七天无理由退换货支持吗
- 支持无理由退换货吗
- intent: recommend
examples: |
- 我的手机坏了,推荐一款新的吧
- 推荐一个合适的手机
- 根据我的情况给我推荐一款手机
- 推荐一个性价比高的手机
- 给我推荐一款手机吧
- 推荐一款手机给我
- [华为](user_phone_brand)有不错的吗
- 有没有性价比高的荣耀(user_phone_brand)手机
- 我想买[荣耀](user_phone_brand)的手机,有什么推荐吗?
- 给我推荐一款[华为](user_phone_brand)的手机
- intent: SELECT_PRICE
examples: |
- 2000元以下
- 2000元~5000元
- 5000元以上
FAQ问答技能
period
和return
是所谓的UNIT中FAQ问答技能,一般都是一问一答- intent: period
后边的名称可以自定义examples: |
需要把类似的话术列到这里,Rasa是要求至少两条
对话技能
recommend
是所谓的对话技能,一般指多轮对话,既然是多轮对话,有一些信息需要记录下来,例如手机的品牌,下一轮的对话是要用到的。这个就是所谓UNIT中词槽的概念,在Rasa中名称为Slot[华为](user_phone_brand)有不错的吗
涉及到了标注概念,将实体’华为’标注出来之后,将词槽填充
UNIT配置对话流程 Vs Rasa rule.yml/stories.yml
UNIT可视化配置对话流程
UNIT对流流程支持编程模式和可视化配置,这里以可视化为例
Rasa配置对话
- Rasa的官方可视化界面是Rasa X,目前Rasa3.0以上是不支持的
- 非官方的可视化界面有botfront,kairon等
- 所以这里只演示编程模式。
FAQ问答
- 也称知识库问答,一般为单轮对话,用户问,Bot回复
- 将上一节定义的意图和定义好的答复列到这里,构成一轮对话
- 定义在rule.yml文件中,Rule相关文档在这里
- rule: faq for period
steps:
- intent: period #意图
- action: utter_period #答案
- rule: faq for return
steps:
- intent: return #意图
- action: utter_return #答案
rule: faq for period
rule的名称,可自定义intent
是上一节定义的意图action
是bot的回应,utter_
开头的是文字回复,action_
开头的是执行一段函数
回复定义
- 回复定义在domain.yml文件中
utter_
开头是固定文本action_
开头是python函数名,在python函数中可以执行业务代码,最终生成回复文本
responses:
utter_period:
- text: 本产品免费保修期是自手机激活日起,12个月。同时过保后,也提供收费维修服务呢~
utter_return:
- text: 您好,商品没有人为损坏的情况下,均支持七天无理由退换货服务哦~
对话技能
- 即多轮对话
- 这里使用了
Rasa Form
,下一节有介绍 - 定义在stories.yml文件中,Story相关文档在这里
- story: recommend story
steps:
- intent: recommend
- action: recommend_phone_form
- active_loop: recommend_phone_form
- slot_was_set:
- requested_slot: user_phone_brand
- requested_slot: search_type
- active_loop: null
- slot_was_set:
- requested_slot: null
- action: action_recommend_phone
story: recommend story
对话流程名称,可自定义intent: recommend
是上一节定义的意图action: recommend_phone_form
是Rasa action中专门用于收集用户信息的action,进入form后,需要将所有slot填充才能结束active_loop
是指激活recommend_phone_form
slot_was_set
以及以下几行是描述用户的输入需要填充user_phone_brand
search_type
这两个词槽才能继续,否则会一直要求用户输入对应信息active_loop: null
词槽被填充后,可以继续下面的流程即调用action_recommend_phone
函数action_recommend_phone
调用函数,执行业务逻辑,输出结果
form定义
- Rasa中专门用于收集用户信息的模块,类似于html中的form表单
- 这里我们定义了一个form用于收集用户对手机的信息包括:品牌、价格
recommend_phone_form
定义在domain.yml中,form相关文档在这里
forms:
recommend_phone_form:
required_slots:
- user_phone_brand
- search_type
form需要的slot的回复定义遵循utter_ask_(form name)_(slot name),如下
utter_ask_recommend_phone_form_user_phone_brand:
- text: 请问您想买哪个品牌的手机呢
utter_ask_recommend_phone_form_search_type:
- buttons:
- title: 2000元以下
payload: /SELECT_PRICE{{"search_type":"low"}}
- title: 2000元~5000元
payload: /SELECT_PRICE{{"search_type":"medium"}}
- title: 5000元以上
payload: /SELECT_PRICE{{"search_type":"high"}}
text: 您希望购买什么价位的手机?
slot定义
slot定义在domain.yml中,Domain相关文档在这里
entities:
- user_phone_brand
- search_type
slots:
user_phone_brand:
type: text
influence_conversation: false
mappings:
- type: from_entity
entity: user_phone_brand
search_type:
type: text
influence_conversation: true
mappings:
- type: from_entity
entity: search_type
conditions:
- active_loop: recommend_phone_form
action_recommend_phone函数
action_recommend_phone
在action.py中,Action相关文档在这里
class ActionRecommendPhone(Action):
def name(self) -> Text:
return "action_recommend_phone"
def run(self, dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
slots = {
"user_phone_brand":None,
"search_type":None
}
price_range = tracker.get_slot('search_type')
if price_range == 'low':
dispatcher.utter_message(response="utter_recommend_result",formatted_price='1999')
elif price_range == 'medium':
dispatcher.utter_message(response="utter_recommend_result",formatted_price='3999')
else:
dispatcher.utter_message(response="utter_recommend_result",formatted_price='5999')
return [SlotSet(slot,value) for slot,value in slots.items()]
兜底回复
在Config.yml中配置,Config相关文档在这里
pipeline:
- name: "MitieNLP"
model: "dict/total_word_feature_extractor_zh.dat"
- name: "JiebaTokenizer"
dictionary_path: "dict/jieba"
- name: "MitieFeaturizer"
- name: "RegexFeaturizer"
- name: "DIETClassifier"
epochs: 300
constrain_similarities: True
- name: "EntitySynonymMapper"
- name: "FallbackClassifier"
threshold: 0.95
其中Component FallbackClassifier组件用户兜底回复,如果用户输入后,Rasa判断没有意图的置信度超过上图定义的0.95,则认为失败,回复定义好的内容
在rule.yml中
- rule: Ask the user to rephrase whenever they send a message with low NLU confidence
steps:
- intent: nlu_fallback
- action: utter_fallback
其中 nlu_fallback为Rasa预定义
回复定义在Domain.yml中
utter_fallback:
- text: 对不起,没有明白您的意图!
训练
在项目目录中输入rasa train
即可,生成的模型位于model文件中
对话
模型训练完成之后,可以通过各种Channel进行对话,Channel的定义在credentials.yml文件,相关文档在这里
rest:
# # you don't need to provide anything here - this channel doesn't
# # require any credentials
#facebook:
# verify: "<verify>"
# secret: "<your secret>"
# page-access-token: "<your page access token>"
#slack:
# slack_token: "<your slack token>"
# slack_channel: "<the slack channel>"
# slack_signing_secret: "<your slack signing secret>"
#socketio:
# user_message_evt: <event name for user message>
# bot_message_evt: <event name for bot messages>
# session_persistence: <true/false>
#mattermost:
# url: "https://<mattermost instance>/api/v4"
# token: "<bot token>"
# webhook_url: "<callback URL>"
# This entry is needed if you are using Rasa X. The entry represents credentials
# for the Rasa X "channel", i.e. Talk to your bot and Share with guest testers.
rasa:
url: "http://localhost:5002/api"
shell
linux shell是对话通道之一,如下如使用shell进行测试,首先启动rasa shell和 rasa run actions(用于执行函数)
rest
通过http rest进行对话,首先启动rasa run 和 rasa run actions (用于执行函数)
chat-room
可以使用chatroom进行对话,首先启动rasa run --cors "*"
和rasa run actions
注意参数 --cors需要传递,否则会报跨域问题
演示视频
Rasa实现百度UNIT智能客服教学机器人