聊天机器人的应用非常广泛,无人驾驶、智能音箱、问答系统、客服机器人、对话机器人、个性化推荐、搜索引擎等等产品都有所应用。
说起聊天机器人想必大家都已经很熟悉了,比如亚马逊的Alex,谷歌的谷歌助手,苹果的Siri,百度的度秘以及众多大厂小厂都投身于聊天机器人相关技术的研发。
聊天机器人的火热程度勿用多说,从各大厂商对聊天机器人的投入也可以看出聊天机器人在商业上的价值巨大。作为机器人行业的从业者,从0开始打造一款自己的聊天机器人显得犹为重要。自己开发一款聊天机器人的好处在于可以对相关的技术都有所进行涉猎,明白聊天机器人相关技术的优劣才能在之后的研究工作中扬长避短发挥最大价值。
下面就请跟着笔者的脚步一步一步的打造自己的聊天机器人吧。
上图是一个简单的聊天机器人系统框图,包括语音识别(ASR)、语音合成(TTS)、自然语言理解(NLU)、对话管理(DM)、自然语言生成(NLG)几个模块组成。其中:
理解了聊天机器人的基本模块以及对应模块的功能之后下一步就可以开发自己的聊天机器人了。
想象一下,假设我们要开发一个打招呼的聊天机器人,应该怎么做呢?
首先分析一下如果是人类如何做的,朋友或者同事见面的时候都会有如下类似的对话:
A:B,早上好,吃早饭没!
B:早!刚吃!
A:周末过得如何?
B:还不错,去了深圳湾骑单车。你呢?
A:我比较宅,就在家里宅着。
B:哈哈,宅着也挺好,出门都是看人的。
A:哈哈,我上班去了。
B:恩,好的,再见。
A:再见
上述模拟了一个简单的会话场景,当然我们需要实现的打招呼机器人并没有那么复杂,如果真要实现上述对话,那么涉及的技术将远远不是本文就能介绍完的。
我们可以抽象一下上述对话,上述对话其实就只有3个动作:打招呼、闲聊和再见。
这3个动作在自然语言处理中成为‘意图(intent)’。意图往往表示着将要实行某一系列的行为。在这里我们定义3个意图:greet,chat,goodbye。
虽然有了意图,那我们又该如何判断是那个意图呢?这里我们直接通过关键字是判别,比如当提到‘早’的时候往往就意味着是在打招呼(greet),而提到‘再见’就显然表示是再见(goodbye)了,而除此之外的,我们都归结为闲聊(chat)。
意图识别的代码如下:
if '早' in message:
intent='greet'
elif '再见' in message:
intent='goodbye'
else:
intent='chat'
有了意图,就可以对意图作出相应的反馈策略了。
greet:
'早上好'
goodbye:
'再见'
chat:
‘听起来很有趣的样子’
好了,到这里我们想要打造的聊天机器人的雏形就出来了。首先接收用户的输入,然后根据用户的输入判定意图,之后根据相应的意图生成对应的回答。这样就完成了一次会话过程。伪代码可以表示如下:
input_string=""#输入
intent_object=intent(input_string)#意图识别
response=policy(intent_object)#回复生成
print(response)#返回用户
理清楚了具体的对话流程,下面就可以开始着手对我们的聊天机器人进行开发了。这里我们用到的rasa框架,rasa中用领域(domain)对会话进行区分,每一个领域下面有不同的意图,意图是由实体进行区分的,每一个意图对应着一个会话动作。
pip install rasa_core
git clone https://github.com/RasaHQ/rasa_core.git
cd rasa_core
pip install -r requirements.txt
python setup.py install
在完成安装之后可以运行helloworld示例来检验是否正常安装成功:
python examples/hello_world/run.py
Bot loaded. Type hello and press enter :
hello
hey there!
当‘hey there!’的回复之后就是安装成功了。安装成功之后就利用hello_world示例项目实现上文提到的打招呼机器人。
#创建文件common_domain.yml,复制如下代码
intents:#定义意图
- greet
- goodbye
- chat
entities:
- action
templates:#表示对于相应的意图采取什么样的回复
utter_greet:
- "hello!"
utter_goodbye:
- "byebye :("
utter_chat:
- "It seems like funny!"
actions:
- utter_greet
- utter_goodbye
- utter_chat
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import logging
import numpy as np
from rasa_core import utils
from rasa_core.actions.action import ACTION_LISTEN_NAME
from rasa_core.agent import Agent
from rasa_core.channels.console import ConsoleInputChannel
from rasa_core.domain import TemplateDomain
from rasa_core.interpreter import NaturalLanguageInterpreter
from rasa_core.policies import Policy
from rasa_core.tracker_store import InMemoryTrackerStore
logger = logging.getLogger(__name__)
class CommonPolicy(Policy):
def predict_action_probabilities(self, tracker, domain):
# type: (DialogueStateTracker, Domain) -> List[float]
#将对应的意图与动作绑定
responses = {
"greet": 2,
"goodbye": 3,
"chat": 4,
}
if tracker.latest_action_name == ACTION_LISTEN_NAME:
key = tracker.latest_message.intent["name"]
action = responses[key] if key in responses else 4
return utils.one_hot(action, domain.num_actions)
else:
return np.zeros(domain.num_actions)
class HelloInterpreter(NaturalLanguageInterpreter):
def parse(self, message):
# intent = "greet" if 'hello' in message else "default"
global intent
#进行意图识别
if 'hello' in message:
intent='greet'
elif 'goodbye' in message:
intent='goodbye'
else:
intent='chat'
return {
"text": message,
"intent": {"name": intent, "confidence": 1.0},
"entities": []
}
def run_hello_world(serve_forever=True):
default_domain = TemplateDomain.load("./common_domain.yml")#加载多个domain怎么办
agent = Agent(default_domain,
policies=[CommonPolicy()],
interpreter=HelloInterpreter(),
tracker_store=InMemoryTrackerStore(default_domain))
if serve_forever:
# Attach the commandline input to the controller to handle all
# incoming messages from that channel
agent.handle_channel(ConsoleInputChannel())
return agent
if __name__ == '__main__':
run_hello_world()
本文分析了聊天机器人会话的主要流程,并介绍了基本的会话实现过程,最后基于rasa实现了一个初步机器人。