小到毕业设计,大到项目应用,都有可能会使用到多轮对话技术。目前最知名且功能最强大的开源框架,莫过于rasa。而网络上关于rasa的教程博客绝大多数还停留在rasa的老版本,而最新的几个rasa版本已经内嵌了bert、xlnet等语义理解的buff加持。本文将带你从rasa安装,到多轮对话demo的一步步实现。
从本文中你将学到:
•基于rasa构建的一个简单的多轮对话demo•加上bert语义理解的buff,让你的看起来demo更加智能•基于填槽的多轮对话任务•如何让你的demo展示不仅仅停留在黑乎乎的terminal界面上
开始搭建
rasa的版本更迭实在太快,笔者前段时间在使用rasa做项目的时候,rasa版本号还是1.8.x,现在rasa的最新版本已经是1.10.2了。许多关于rasa的技术博客还停留在rasa_nlu和rasa_core分开安装的阶段,但实际上rasa早就已经将两者合并。
第一步,安装rasa。
炒鸡简单加方便:pip install rasa即可。
第二步,创建一个rasa项目。
rasa init --no-prompt
这个命令将会在当前目录下新建一个rasa项目,里面包含了所有rasa项目需要的文件。这些文件中还包含了样例数据。具体包含的文件包括:
nlu.md
先看看nlu.md
长啥样。
## intent:greet
- hey
- hello
- hi
- good morning
- good evening
- hey there
## intent:goodbye
- bye
- goodbye
- see you around
- see you later
## intent:affirm
- yes
- indeed
- of course
- that sounds good
- correct
从文件名就可以理解该文件的作用,它是以markdown的形式,告诉rasa用户说的某些话是什么意图。例如,如果用户对rasa说“hello”,那么rasa就知道用户是在跟它打招呼(greet意图)。
domain.yml
再来看看domain.yml
里面都是什么。
intents:
- greet
- goodbye
- affirm
- deny
- mood_great
- mood_unhappy
- bot_challenge
responses:
utter_greet:
- text: "Hey! How are you?"
utter_did_that_help:
- text: "Did that help you?"
utter_happy:
- text: "Great, carry on!"
utter_goodbye:
- text: "Bye"
utter_iamabot:
- text: "I am a bot, powered by Rasa."
这个文件其实也好理解,就是在rasa理解了用户说话的意图之后,该如何进行回应。例如在用户讲了“hello”,rasa识别到是greet意图之后,rasa就会回复说:“Hey! How are you?”注意,在这个文件中,所有针对意图的回复,都必须以utter_
开头。
stories.md
然后是stories.md
## happy path
* greet
- utter_greet
* mood_great
- utter_happy
## sad path 1
* greet
- utter_greet
* mood_unhappy
- utter_cheer_up
- utter_did_that_help
* affirm
- utter_happy
## sad path 2
* greet
- utter_greet
* mood_unhappy
- utter_cheer_up
- utter_did_that_help
* deny
- utter_goodbye
这玩意其实就是根据之前的nlu.md
和domain.yml
文件来编故事,即你要是想让rasa实现多轮对话任务,你得先帮它设计好对话内容。看到这你是不是觉得rasa好傻,“不就是一堆规则嘛?”
对啊,就是一堆规则,人工智能本质不就是这样嘛?(手动狗头)
config.yml
接下来就是配置文件config.yml
。这玩意是用来配置内置模型和多轮对话策略的。相信读者如果想要做多轮对话的demo或项目,肯定是针对的中文,因此这里贴出来的是和中文多轮对话相关的配置信息(英文的官网教程上展示的就是)。
# Configuration for Rasa NLU.
# https://rasa.com/docs/rasa/nlu/components/
language: ch
pipeline:
- name: HFTransformersNLP
model_name: "bert"
model_weights: "bert-base-chinese"
- name: LanguageModelTokenizer
- name: LanguageModelFeaturizer
- name: DIETClassifier
epochs: 50
- name: EntitySynonymMapper
- name: ResponseSelector
epochs: 50
# Configuration for Rasa Core.
# https://rasa.com/docs/rasa/core/policies/
policies:
- name: MemoizationPolicy
- name: TEDPolicy
max_history: 5
epochs: 50
- name: MappingPolicy
- name: FormPolicy
这里面的配置详情从命名大概就知道它代表的是什么意思了。包括使用bert模型进行语义理解,使用LanguageModelTokenizer
去进行分词,使用EntitySynonymMapper
进行命名实体识别等等,其他配置请从官网查询(https://rasa.com/docs/rasa/nlu/choosing-a-pipeline/)。
配置到这里,你就可以训练模型,完成一个很简单的对话demo了,但也仅仅是实现了一问一答的简单形式。在terminal中运行rasa train
,模型就会根据你config.yml
中的模型进行训练。训练完成后,运行rasa shell
,好了,你就进入了那个黑乎乎的终端界面,可以输入自然语言,敲个回车,不出意外的话,rasa机器人就可以和你聊天了。但是很low,你说:"hello",它说:“Hey! How are you?”;你说:“goodbye”,它说"Bye"。撒不撒。这玩意逗逗自己可以,还真拿不出手给老板做展示。
rasa迁移到项目
为了让rasa能够更加强大、且能够处理日常业务需求,我们需要给rasa进行升级,其中一种有效方式就是让rasa进行主动询问,引导用户进行对话,然后rasa从对话内容中提取关键信息,进行填槽,直到所有需要的槽位都被填满,然后进行下一步的处理。具体的slot代码该如何写,小编偷懒了,这里给个博客连接(https://blog.rasa.com/building-contextual-assistants-with-rasa-formaction/?_ga=2.60731246.212028585.1569243725-1349818766.1563821081),里面已经介绍的很详细。
当你按照上面的步骤一步一步进行操作,然后run action
, run shell
之后,却依然只能在黑乎乎的界面上进行操作。若想将其迁移到项目后端,实现在花里胡哨的聊天界面上进行多轮对话,你会发现超级多的坑。这里小编就将处理这个问题的核心代码写在这里,并加上注释,告诉读者每一行代码的作用。
import asyncio #用到了异步
from rasa.utils.endpoints import EndpointConfig #从rasa调用EndpointConfig
from rasa.core.agent import Agent #从rasa调用Agent
loop = asyncio.get_event_loop()
model_path="models/2020xxxxxx.tar.gz" #经过 rasa train命令之后 训练出的模型,在models文件夹中
endpoint = EndpointConfig(url="http://localhost:5055/webhook") #这个是你的action.py运行起来之后的服务端口
agent = Agent.load( #将上面两个参数装载之后,一个后台实时待命的聊天机器人就设置好了
model_path,
action_endpoint=endpoint
)
async def chatbot(message): #因为用到了异步等骚操作,这里还使用了await。反正将rasa返回的对话取出来,挺麻烦
result = await agent.handle_text(message)
return result
@app.route('xxxx', methods=['get', 'post']) #基于flask
def return_message():
message = request.args.get('message')
result = loop.run_until_complete(chatbot(message)) #使用run_until_complete取出返回的信息
#剩下的操作就是如何对返回的信息进行再处理,以及如何返回给前端
#...
小编使用rasa之后的体会
•貌似在1.7版本之后,rasa开始支持bert、xlnet等语言模型,加载了这些东西之后,模型在识别输入的句子时,会更加精准。比如在你的nlu.md
里的greet意图中,只有“你好”,但是你说的是“早上好”,rasa也可以大概率理解出你的意图是greet。•rasa的官方博客有许多基于rasa的多轮对话教程,且代码都开源在github。但是如何将多轮对话应用到我们的项目中(从黑乎乎的terminal中解脱出来),网上相关信息要么太旧,不适应新版本,要么就是根本找不到,小编为了解决这个问题也是费力好多时间。•粗的来看,rasa的多轮对话其实就是一种高级的规则,故事线需要我们自己设计。如果我们想要设计出更加智能的聊天助手,需要复杂且系统化的设计故事线、domin、nlu等。
欢迎关注我的公众号“数据科学杂谈”,原创技术文章第一时间推送。