Python 聊天机器人构建指南(二)

原文:Building Chatbots with Python

协议:CC BY-NC-SA 4.0

四、使用困难方式构建聊天机器人

“艰难地构建聊天机器人”并不难学。完全控制你自己的聊天机器人是构建聊天机器人的艰难方式。如果你想自己做所有的事情,那么你会选择困难的路线。更难的路,当你走过的时候是艰难的,但当你回头看的时候却是美丽而清晰的。

这是一条通向伟大顶峰的崎岖之路。

——卢修斯·安纳乌斯·塞内卡

如果你很了解 Python,并且对如何设置包有一点了解,等等。,学习这一章不会有任何问题。如果你是开发者,对你来说应该很容易。如果你是一个管理人员或者非技术人员,你仍然可以像每个部分提到的那样一个一个地做步骤,把事情做好。我强烈建议每个人都完成这一章,这样你就能学到关于构建聊天机器人的核心知识。

本章不仅教你从零开始构建聊天机器人,还向你展示了核心机器学习(ML)如何在拉莎·NLU 的帮助下与 NLP 一起工作。正如本书第一章提到的,当你在构建聊天机器人时,有决策树总是好的。在这一章中,我们几乎不用任何规则,但是 ML 还没有达到 100%可靠的程度。因此,这个决定完全基于您的用例,以及您是否想在 ML 模型中应用一些业务逻辑。有时候,你的 ML 模型可能工作得很好,以至于你根本不需要任何启发。但是根据我的经验,当你继续销售你的聊天机器人或者将它们商业化的时候,你必须小心一点。没有功能总比有一个没有意义的功能好。

我们将使用一个名为 Rasa NLU 的开源库来学习如何从头开始构建聊天机器人,而不使用任何云服务,如 Dialogflow,Watson,wit.ai 等。记住,拉莎·NLU 是一个非常复杂的图书馆,里面有很多功能。我们将只涉及对我们构建聊天机器人很重要的概念和特性。

什么是拉莎·NLU?

Rasa NLU 是一个开源的自然语言处理库,用于聊天机器人的意图分类和实体提取。它帮助你为你的聊天机器人构建和编写定制的 NLP。

我们将在本章中讨论 Rasa 的两个部分。

  • 拉莎·NLU:在拉莎·NLU 的帮助下,我们将学习为聊天机器人准备训练数据,编写配置文件,选择管道和训练模型。最后,我们将使用我们的模型预测文本的意图。我们还将学习如何使用 Rasa NLU 解析实体。

  • Rasa Core: 在第二部分中,我们将学习训练 Rasa Core 对话管理模型来准备对用户的响应。当你的聊天机器人有各种各样的意图以及他们的后续问题或回答时,这一部分就变得非常重要。与其在我们的决策树中编写大量条件,并在大型企业级应用程序的情况下花费数小时进行调试,不如教会模型创建响应。看看我们训练有素的模型在这方面表现如何会很有趣。我们不能只是把什么都以文字的形式吐槽给用户;应该说得通。

我为什么要用拉莎·NLU?

拉莎·NLU 不仅仅是一个有很多方法来做一些事情的图书馆。它有能力构建你能想象到的几乎任何类型的聊天机器人。Rasa 为您带来了训练机器理解文本含义的神奇能力,而不是您编写规则来理解它。

让我们从以下几点来看为什么我们应该使用 Rasa NLU:

  • Rasa NLU 是一个积极维护的项目,有一个很好的社区来支持它。

  • 如果我们不想与第三方分享我们用户的敏感数据,我们必须使用像拉莎·NLU 这样的开源工具从头开始构建聊天机器人。这样,所有数据都保留在我们自己的服务器上进行处理。

  • 依靠第三方服务来训练您的数据并发现用户话语的意图将需要您调用可能并不总是可靠的 API。如果他们的服务器关闭了,你的 chatbot 应用程序会怎么样?

  • 使用拉沙·NLU 建造聊天机器人将会让你完全控制你的聊天机器人。您可以使用您想要的数据,按照您想要的方式对其进行训练、调整和优化。使用 Rasa NLU,我们可以试验哪种最大似然算法最适合我们的数据集,而不是依赖于固定的算法。

直接潜入拉萨 Into

在本节中,我们将直接进入动手部分,尝试安装 Rasa 堆栈,并通过训练数据开始构建我们的 ML 模型。我们将使用一些更酷的开源库来让我们的生活更轻松。

安装 Rasa

要安装 Rasa,运行下面的 pip 命令,我们在前面的章节中尝试安装 spaCy。请注意,我们将使用 Rasa 版本 0.13.2。

pip install rasa-nlu==0.13.2

Rasa NLU 有多个用于分类意图和识别实体的组件。Rasa 的不同组件有自己的依赖集。

当我们训练模型时,拉莎·NLU 会检查是否安装了所有必需的依赖项。如果您想要安装完全使用 Rasa 库所需的全部要求,可以执行以下步骤:

git clone https://github.com/RasaHQ/rasa_nlu.git #Clone the repo
cd rasa_nlu #Get into the rasa directory
pip install -r alt_requirements/requirements_full.txt #Install full requirements

第一步可能需要一些时间。像地球一样耐心,直到它完成。

决定 Rasa 的管道

Pipeline 不过是一套用来训练你的模型的算法。Rasa NLU 有两条被广泛使用的管道,分别叫做spacy_sklearntensorflow_embedding。让我们了解一下这两者。

  • spacy_sklearn pipeline 利用来自 GloVe 算法或脸书人工智能团队开发的 fastText 算法的预训练单词向量。

  • spacy_sklearn 在这样的情况下非常有效,假设你有这样一句话,“波士顿的天气如何?”当我们在同一个话语示例上训练我们的模型,然后要求它预测“伦敦的天气如何?”我们的模型现在足够智能,可以知道单词“Boston”和“London”是相似的,它们属于相同的意图。

  • 这种管道对于小数据集非常有用。

spacy_sklearn

  • tensor flow _ embeddingpipeline 不使用任何像 spacy_sklearn 这样预先训练好的词向量,而是根据我们自己提供的数据集进行自我调整。

  • 关于 tensorflow_embedding 管道的好处是,我们的词向量将与我们的域一致。

  • 为了用一个例子来解释 tensorflow_embedding 是如何工作的,在英语中,单词“play”可能与“一项运动”或“一项享受或娱乐的活动”密切相关,它可能看起来与单词“一个行为”非常不同。在一个戏剧领域中,“戏剧”和“一个行为”是密切相关的,其中“戏剧”意味着“剧作家写的一种文学形式”,非常有必要告诉我们的模型学习特定于我们的领域,而不是由于一些预先训练的模型而混淆。

tensorflow_embedding

从头开始训练和构建聊天机器人

如果你读过这本书的第三章,你一定很熟悉我们用 Dialogflow 搭建的“点餐聊天机器人”。你必须意识到聊天机器人的意图、实体和对最终用户的回应。

同样,在本章中,我们将采用聊天机器人的一个用例,并从头开始构建它。你不一定要用同样的例子。请随意查找您自己的用例,遵循本章中的步骤,并在本章结束时构建您自己的聊天机器人。

我们将建立一个星座机器人,它可以理解用户的查询,并告诉他们当天的星座。那么,我们开始吧。

建造一个占星机器人

在这个使用开源库 Rasa NLU 完全自主构建聊天机器人的例子中,我们将构建一个占星机器人。让我们决定这个聊天机器人的范围,看看它做什么和能做什么。

  • 星座机器人应该能够理解问候,并回复问候。

  • 机器人应该能够理解用户是否在询问星座。

  • 如果用户不提供,机器人应该可以询问用户的星座。

  • 如果用户不知道他/她的星座,机器人应该询问用户的出生日期(DOB)并为他们找到它。

  • 机器人应该订阅/取消订阅用户获得每日星座。

  • 机器人应该从现有的响应中学习,以制定新的响应。

  • 机器人应该能够处理用户的拼写错误。

我们的机器人应该做的事情非常简单。

可能的意图

  • 问候意图:用户以问候开始

  • 获取星座意向:用户询问星座

  • 用户的星座意图:用户说出星座

  • 用户的 DOB 意图:用户告知他/她的 DOB

  • 订阅意图:用户请求订阅

根据你设计你的机器人和编写代码的方式,你可能需要也可能不需要以上所有的意图,或者你可能需要定义一些额外的意图来涵盖我们希望我们的机器人做的所有用例。随着本章的深入,我们将尝试构建一个机器人来完成给出星座的基本任务;作为练习的一部分,我们可以添加更多的用例。

这就是我们到目前为止所做的,根据机器人和用户之间的简单对话来识别可能的意图。

占星机器人和用户之间的对话脚本

让我们在聊天机器人和用户之间创建一个可能的对话脚本。正如第一章中提到的,编写对话脚本就像在构建软件之前准备软件需求文档一样。它以后可能会改变,但会让您对最终的 chatbot 应用程序有一个总体的了解。

下面是我们在用户和机器人之间的对话:

  • **用户:**你好

  • **星座机器人:**你好!希望你一切都好。

  • **用户:**我想知道我的星座。

  • 当然,我可以知道你的星座吗?

  • **使用者:**反复无常

  • 星座机器人:对不起,你是说摩羯座吗?

  • **用户:**是。

  • 星座机器人:好了,这是你今天的星座。今天你可能会感到乐观和积极。与那些感到不满足的人分享这种能量。你的态度会对你的朋友、伴侣、配偶和孩子产生深远的影响。邻居和大家庭可以在你没有意识到的情况下吸取你的精神。如果有人受伤或生气,要鼓励他。一切最终都会解决的。

  • 星座机器人 : 你想订阅每日更新吗?如果是,就说订阅。

  • **用户:**是的,请订阅。

  • **星座机器人:**太好了,你现在订阅了。祝你愉快。

这个对话只是为了对我们的聊天机器人对话有一个公平的想法。我们可能想也可能不想根据自己的需求改变谈话的流程。

我们可以训练我们的聊天机器人模型本身来准备一个有效的响应,而不是写一堆 if…else 语句。

为聊天机器人准备数据

Rasa NLU 有多种方法来定义我们的自定义数据的意图及其实体。它支持 markdown 中的数据、JSON 中的单个文件或包含多个文件的目录。

我们将首先讨论最困难但高度可扩展的方法。手动创建 JSON 文件很困难,但是通过编程非常容易且可伸缩。

以 JSON 格式为模型创建数据

Rasa NLU 期望的数据的 JSON 格式有一个名为 rasa_nlu_data 的顶层对象,键为 common_examplesentity _ synonymsregex _ features

我们将要使用的最重要的工具是**。下面是我们的 JSON 数据的大致形式:**

{
    "rasa_nlu_data": {
        "common_examples": [],
        "regex_features" : [],
        "entity_synonyms": []
    }
}

JSON 数据中的 common_examples 键是用于训练我们的模型的中心位置。我们将在 common_examples 数组中添加我们所有的训练示例。

regex_features 是帮助意图分类器识别实体或意图,提高意图分类准确率的工具。

让我们开始编写 JSON 文件。姑且称之为 data.json.

  1. 创建一个名为占星 _ 机器人的文件夹。

  2. 将当前工作目录更改为占星 _bot。

  3. 开始 Jupyter 笔记型电脑#jupyter 笔记型电脑。

  4. 创建一个名为 data 的新文件夹。

  5. 点击数据文件夹,进入 Jupyter 笔记本新菜单下的“文本文件”。

  6. 点击创建的文件名,将名称改为 data.json ,并为聊天机器人编写您的意图。

对于第 5 步和第 6 步,请随意使用您喜欢的编辑器,如 Sublime、Notepad++和 PyCharm 等。,来处理 JSON 文件。

下面是我在数据文件夹下的 data.json 的样子:

{
  "rasa_nlu_data": {
    "common_examples": [
      {
        "text": "Hello",
        "intent": "greeting",
        "entities": []
      },
      {
        "text": "I want to know my Horoscope",
        "intent": "get_horoscope",
        "entities": []
      },
      {
        "text": "Can you please tell me my horoscope?",
        "intent": "get_horoscope",
        "entities": []
      },
      {
        "text": "Please subscribe me",
        "intent": "subscription"
      }
    ],
    "regex_features": [],
    "entity_synonyms": []
  }
}

正如你所看到的,用手准备这个看起来很笨拙。你一定还记得我们在 Dialogflow 中使用的简单易用的方法。因此,让我们来看看一个很酷很有趣的工具,它可以以 Rasa 期望的格式创建训练数据。它是由 Polgár András 创建的,对于检查和修改我们之前准备的现有数据也非常有用。如果您正在处理一个必须手动创建数据的小项目,此工具可以节省大量时间。在您构建的任何完全由数据驱动的应用程序中可视化数据总是一个好主意。

因此,只需保存我们之前创建的 data.json 文件,直到我们使用更好的方法扩展数据收集。

可视化和修改 Rasa 的 JSON 数据格式

在本节中,我们将利用一个名为 Rasa NLU 训练器的工具来可视化我们的数据。(即,我们到目前为止已经创建的数据)。这个工具也帮助我们注释数据。如果你还记得 Dialogflow 接口是在第三章中解释的,那么定义实体、它们的名字和类型是非常容易的。我们将使用开源工具做同样的事情。

Rasa NLU 教练是一个非常好和方便的工具,编辑我们的训练数据的权利,从我们的浏览器本身。处理 JSON 数据很棘手,也可能导致错误。有了这个方便的工具,我们可以很容易地添加更多的例子到我们的训练数据或编辑现有的。它节省了手动注释数据的大量时间。rasa-nlu-trainer 是一个基于 javascript 的工具,所以我们需要安装 node.js 来在我们的系统上运行这个工具。做那件事不需要超过 5 分钟。让我们按照以下步骤进行设置:

  1. 前往 https://www.npmjs.com/get-npm 下载 node.js

  2. 按照网站上的指导在您的系统上安装软件包。安装完成后,进入系统上一个新的终端/命令行界面,键入“npm ”,看看它是否能工作。

我已经安装了 LTS 版本 8.11.4。安装后,运行以下命令来安装 rasa-nlu-trainer:

sudo npm i -g rasa-nlu-trainer

成功安装该命令后,您将看到类似于以下内容的日志:

[fsevents] Success: "/usr/local/lib/node_modules/rasa-nlu-trainer/node_modules/fsevents/lib/binding/Release/node-v57-darwin-x64/fse.node" already installed
Pass --update-binary to reinstall or --build-from-source to recompile
npm WARN slick-carousel@1.8.1 requires a peer of jquery@>=1.8.0 but none is installed. You must install peer dependencies yourself.

+ rasa-nlu-trainer@0.2.7
added 492 packages in 10.14s

即使您的消息看起来不像这样,只要它没有抛出任何错误,也不用担心。我们很快就会知道我们的 rasa-nlu-trainer 是否安装成功并且运行良好。

让我们转到之前在终端中创建的数据文件夹,并运行以下命令:

rasa-nlu-trainer

键入此命令将启动端口 55703 上的本地服务器,并在默认浏览器中打开它。它看起来有点像图 4-1 。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-1

本地主机中的 rasa-nlu-trainer

如您所见,data.json 中的所有现有数据都是由这个神奇的工具挑选出来供我们删除或编辑的,我们还可以从这里添加新的示例,它将继续扩展 data.json 文件。

我建议你在你的意图中增加更多的数据,以便更好地训练这个模型。你可以在发行商提供的源代码 zip 或 repo 中获得这个 data.json,如果你正在尝试构建本章解释的相同的聊天机器人。

正如我们在第三章中使用 Dialogflow 选择话语中的实体来定义它们一样,我们可以使用这个工具做同样的事情,并为我们的实体命名,以便稍后进行解析。因此,单击示例中的切换按钮,选择文本,并通过给实体命名来添加实体。

在我定义的每个意图中,我都添加了五到六个话语示例。我们添加的示例越多,就越有利于模型的训练并提供更好的准确性。

如果您现在查看 data.json 文件,它会自动添加更多的示例。因此,继续验证您的 data.json 文件,看看您是否有从 rasa-nlu-trainer UI 添加的所有示例。

您还会注意到,在 data.json 文件中,您可能已经使用 rasa-nlu-trainer UI 定义的实体在 common_examples 列表中被捕获为具有 startend 键,这告诉模型特定实体值在示例中的开始点和结束点。

同一个 dictionary 对象还描述了实体的值和我们定义的实体的名称。对于我们的示例,它看起来如下:

{
        "text": "19-01",
        "intent": "dob_intent",
        "entities": [
          {
            "start": 0,
            "end": 2,
            "value": "19",
            "entity": "DD"
          },
          {
            "start": 3,
            "end": 5,
            "value": "01",
            "entity": "MM"
          }
        ]
      }

训练聊天机器人模型

在本节中,我们将根据准备好的数据训练一个模型。由于我们使用 Jupyter Notebook 创建和管理文件,我们将创建一个新的。ipynb 并开始编写我们的 Python 代码,通过选择我们在本章前面讨论的管道之一来训练我们的模型。

创建配置文件

让我们使用之前使用 Jupyter 创建 json 文件的相同方法再次创建一个 JSON 文件,并将其命名为 config.json 。让我们把它放在我们的数据文件夹之外(例如,在我们的项目目录——占星 _bot 中)。

向其中添加以下配置:

{
  "pipeline":"tensorflow_embedding",
  "path":"./models/nlu",
  "data":"./data/data.json"
}

如您所见,在我们的 config.json 文件中有一些重要的配置参数。让我们试着去理解它们。

  • 管道:管道将指定使用什么样的特征化器或特征提取器来处理文本消息并提取必要的信息。在我们的例子中,我们使用了 tensorflow_embedding

  • path : path 本质上是我们在训练后保存模型的目录。我们将把我们的模型保存在/models/nlu 文件夹中。

  • 数据:数据是我们需要指定的路径;它基本上是我们的训练数据所在的地方。

当我们完成了 config.json 文件之后,让我们转到一些 Python 代码来训练我们的 ML 模型。

YAML 构型

也可以用。yml 文件作为配置文件,如下所示。您可以在 github repo 中获得示例 config.yml 文件。

  • 例 1:

  • 例 2:

language: "en"
pipeline: "tensorflow_embedding"

language: "en"
    pipeline:
    - name: "nlp_spacy"
    - name: "tokenizer_spacy"
    - name: "intent_entity_featurizer_regex"
    - name: "intent_featurizer_spacy"
    - name: "ner_crf"
    - name: "ner_synonyms"
    - name: "intent_classifier_sklearn"

所有传入的消息都按照定义的组件顺序进行处理。已定义的组件按顺序一个接一个地运行,因此被称为处理管道。不同的组件用于不同的目的,例如实体提取、意图分类、预处理等。

这种格式的好处是,我们可以通过 Rasa 以一种清晰的方式指定预定义的管道。

编写 Python 代码来训练模型和预测

让我们打开一个新的。ipynb 文件并开始编写我们的代码。让我们将 ipynb 命名为 rasa-nlu.ipynb。确保您已经成功安装了您正在使用的 Python 版本的rasa-nlu==0.13.2

下面是我们的代码在 Python 中使用我们的 data.json 和 config.json,并使用 tensorflow_embedding 管道训练一个模型的样子。

from rasa_nlu.training_data import load_data
from rasa_nlu.model import Trainer
from rasa_nlu import config
from rasa_nlu.model import Interpreter

def train_horoscopebot(data_json, config_file, model_dir):
    training_data = load_data(data_json)
    trainer = Trainer(config.load(config_file))
    trainer.train(training_data)
    model_directory = trainer.persist(model_dir, fixed_model_name = 'horoscopebot')

def predict_intent(text):
    interpreter = Interpreter.load('./models/nlu/default/horoscopebot')
    print(interpreter.parse(text))

在代码的第一部分,我们从 rasa_nlu 包中导入所有必需的库。然后,我们定义了两个方法,称为train _ 占星机器人predict_intent ,其中第一个方法在给定数据、配置文件和模型目录(存储模型的位置)的情况下训练模型,predict_intent 方法使用 rasa_nlu 的解释器模型来加载预训练的模型文件,并让用户能够预测任何新的文本示例。

训练模型

我们运行下面的代码片段,用各自的参数调用我们的 train _ astrong bot 方法

train_horoscopebot('./data/data.json', 'config.json', './models/nlu')

在我们的 rasa-nlu.ipynb 中运行这段代码后,我们将得到如下输出:

Epochs: 100%|██████████| 300/300 [00:01<00:00, 175.69it/s, loss=0.075, acc=1.000]

用于训练聊天机器人模型的代码将创建模型文件夹,您可以使用 Jupyter 或您的文件资源管理器或 finder 应用程序看到该文件夹。它将在我们提供的模型目录目的地创建一组索引、元和 pickle 文件。

从模型中预测

让我们通过传递文本来调用 predict_intent 方法,以查看我们的训练模型的执行情况。

predict_intent("I am looking for my horoscope for today. I am wondering if you can tell me that.")

该方法本身打印输出。对于上面的文本,我的输出如下所示:

INFO:tensorflow:Restoring parameters from ./models/nlu/default/horoscopebot/intent_classifier_tensorflow_embedding.ckpt

{
  "intent": {
    "name": "get_horoscope",
    "confidence": 0.9636583924293518
  },
  "entities": [],
  "intent_ranking": [
    {
      "name": "get_horoscope",
      "confidence": 0.9636583924293518
    },
    {
      "name": "dob_intent",
      "confidence": 0.03462183475494385
    },
    {
      "name": "greeting",
      "confidence": 0
    },
    {
      "name": "subscription",
      "confidence": 0
    }
  ],
  "text": "I am looking for my horoscope for today. I am wondering if you can tell me that."
}

哇!是不是很神奇?我们的模型以 96%的置信度预测了这段文字。您可以在提供的 ipynb 文件中看到,我们的模型在预测其他意图方面也做得很好。这就是 tensorflow 和 ML 整体的力量。rasa_nlu 库就不用说了,让它这么容易相信。所以,现在是你回顾过去的时候了,如果你还记得本书的第三章,那么你一定还记得每当我们添加一个新的例子时,用于重新训练模型的对话流。在幕后,它实际上和我们刚才做的一样。我们不能改变模型或调整任何参数,但我们现在可以完全控制这些。

既然我们已经使用 tensorflow 成功地构建和训练了一个模型,并对其进行了测试,我们将继续讨论对话管理的下一个主题。我会要求您测试您的机器人可能面临的所有场景,以便您知道您的模型在哪些方面表现不佳,因此,如果需要,您可以添加更多数据或调整参数。

此外,请记住,只要训练数据发生变化,您就只需要重新训练模型。如果训练数据没有变化,我们可以加载现有的训练模型来继续预测新的示例。

使用 Rasa 核心的对话管理

在这一节中,我们将通过培训另一个 Rasa 核心对话管理模型来动手实践。请记住,此时我们已经有了一个模型来预测文本的意图,我们可以编写一些 Python 代码来制定响应,并且我们可以回复客户。但是如果我们想给我们的机器人添加更多的意图呢?在具有大量特性的大型应用程序中,这种方法是否具有可伸缩性?答案是否定的。Rasa Core 的对话管理解决了这个问题。

如果你曾经尝试在任何平台上使用任何机器人,你一定会看到它在某些条件下失败。是的,我们都经历过这种情况,它仍然存在,因为今天的机器人无法悲惨地管理对话的上下文或遵循对话的规则。借助 Rasa Core 基于 ML 的对话框架,我们可以轻松解决这个问题。Rasa Core 已经为企业级应用程序提供了很好的证明,并被成千上万的开发人员使用,因为它是生产就绪的,易于使用和扩展,最重要的是,它是开源的。

更多了解 Rasa 核心和对话系统

在我们真正进入我们的对话管理模型的 Rasa 核心的编码部分之前,理解为什么和从哪里来是非常重要的。

我们将努力理解我们迄今为止是如何构建聊天机器人的,以及这将如何被永远改变。

让我们举个例子:

如果我们要构建一个简单的聊天机器人,帮助用户预订航班/公共汽车/电影/火车票,最简单的方法是创建一个状态机或决策树,写一堆 if…else,就可以完成了。这可以工作,但无法扩展。如果顾客最初对某样东西有很好的体验,他们会想更多地使用它。通过一些试探法,我们可以证明聊天机器人是聪明的,但不会持续很长时间。当代码的控制流从 try 块到 except 块,我们就开始挠头了。

图 4-2 是构建这个聊天机器人的状态机的简单表示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-2

订票聊天机器人的状态图表示

如果我们看一下我们的状态图,它可能适用于一个普通的对话,在这个对话中,用户正在寻找电影票、公共汽车票或火车票,或者在索要电影票之后想要预订一张公共汽车票。如果用户同时要公交票和电影票怎么办?你可能会说,我们可以在已经嵌套的代码中再添加几个 if…else 语句来处理这个问题。如果你是一个优秀的开发人员,从状态机写一个 in-out 或者扩展你的决策树不会花你太多时间。但是想象一下,当这些情况开始呈指数级增长时,你必须不断增加病例来处理,它们也开始相互干扰。

我们的大脑以一种学习和再学习的方式工作。如果一个孩子不知道火会对他们做什么,他们会去碰它,但是当它伤害了他们,他们不会再去做了。他们强调了一个事实,那就是它是有害的。奖励也是如此——当你做了某件事并得到某样东西时,你会联想到这样一个事实:做某件事会带来奖励或更好的奖励,然后你打算再做一次。这在 ML 中被称为强化学习,机器通过执行动作和理解结果来学习如何在特定情况下表现。强化学习有时不是最好的方法,例如在数据不足以学习的情况下,数据质量不好以学习奖励场景等。

图 4-3 是帮助您理解 Rasa 核心如何很好地适应 Rasa 堆栈及其与 Rasa NLU 的作用的图表,这是我们到目前为止一直在学习的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-3

图中显示了 Rasa NLU 和 Rasa 核心的工作情况

使用 Rasa Core,我们可以指定我们的机器人应该说或做的所有事情。这些被称为动作。一个动作可能是向用户打招呼或查询数据库,也可能是使用某种 web 服务或 API 检索某些信息。

Rasa Core 提供了训练我们的概率模型的工具,以根据用户的历史对话来预测必须采取什么行动。想象一下,在没有 ML 模型的情况下,编写数百个用例来计算应该发送或执行什么响应或动作。简单来说,Rasa Core 为你解决了这个问题。

让我们看看我们在第三章构建在线机器人时构建的用户与机器人的并行对话。

|

用户

|

网上吃饭

|
| — | — |
| 你好 OnlineEats | 你好!我能帮你什么吗? |
| 我想点菜 | 当然,你今天想要订购什么? |
| 一个鸡肉汉堡 | 完成了。你的最终金额是 3.99 美元 |
| 谢谢你 | 非常感谢 |

这种对话非常简单,即使我们确实使用了一个训练有素的模型来识别其中的意图和实体,也可以在没有任何 ML 模型的情况下完成。

现在,你会想到一个有趣的问题,“如果我想让我的机器人能够改变顺序,该怎么办?如果我希望我的机器人能够移除或添加更多数量的食物,该怎么办?”因此,正如所讨论的,在代码中添加更多的用例、更多的复杂性、更多的意图及其表达方式、更多的 if…else 来处理角落情况,但是当你为一个企业构建聊天机器人时,你必须扩展它以通过它产生更多的收入。所有的软件系统都是这样做的,那些没有失败的都活了下来。底线是,我们不能一直改变和部署代码。

因此,我们可以在 Rasa Stack 的帮助下,采取 ML 路线来解决这个问题,而不是在所有情况发生时处理它们并重复这样做,Rasa Stack 会根据用户的上下文和对话状态告诉我们机器人下一步应该做什么。由于模型根据之前对话数据的上下文进行自我学习,因此机器人更容易保持对话更加自然和用户友好,而不是随机选择四到五个固定的句子。

Rasa 建议数据很少或没有数据的用户使用交互式学习。在本章的后面,我们将了解更多关于互动学习的内容。

在我们真正开始使用 Rasa Stack 编写我们的 bot 的核心部分之前,首先我们需要理解几个概念。

理解 Rasa 概念

在真正尝试在代码中完全使用 Rasa 之前,理解一些与 Rasa 相关的特定概念非常重要。在这一部分,我们将学习一些重要且非常有用的拉莎·NLU 概念。请确保您完全理解这些概念,因为我们将使用 Rasa 的域文件格式来构建我们的第一个内部聊天机器人。如果我们不理解这些概念的含义,那么就很难迈出下一步。

行动

顾名思义,这是一个可以采取的具体行动。根据 Rasa 文档,它说,“Next action to be taken in response to a dialog state

例如,如果用户询问今天的星座运势,我们的机器人可以执行“GetTodaysHoroscope”动作。让我们看看一个“GetTodaysHoroscope”动作在代码中是什么样子的。

from rasa_core.actions import Action
from rasa_core.events import SlotSet

class GetTodaysHoroscope(Action):
   def name(self):
      return "get_todays_horoscope"

   def run(self, dispatcher, tracker, domain):
      # type: (Dispatcher, DialogueStateTracker, Domain) -> List[Event]

      user_horoscope_sign = tracker.get_slot('horoscope_sign')
      """Write your logic to get today’s horoscope details
         for the given Horoscope sign based on some API calls
         or retrieval from the database"""

return [SlotSet("horoscope_sign", user_horoscope_sign)]

name 方法返回动作的名称,我们将在域文件中将其称为自定义方法名称。

run 方法完成完成动作的主要工作——也就是说,核心业务逻辑驻留在这里。如你所见,它需要三个参数:分派追踪器域。

让我们逐一了解这些参数:

  • **dispatcher:**dispatcher 用于向我们的用户发回消息。我们可以使用dipatcher.utter_message()来达到同样的目的。

  • **跟踪器:**当前用户的状态跟踪器。我们可以使用tracker.get_slot(slot_name),来访问槽值,并且可以使用tracker.latest_message.text来获取最新的用户消息。

  • **域:**bot 的域。我们将在本章后面更详细地讨论这个领域。

注意

run 方法返回事件实例列表。

时间

插槽是那些让机器人负责像人类一样工作的东西。插槽就像一个存储空间,可以存储用户给出的信息,也可以使用从数据库或 API 预取的信息。

不同的使用情形有不同的插槽类型:

例如,在我们想要构建星座机器人的用例中,我们可能想要使用插槽类型作为用户提供的星座符号text

根据您想要保留的插槽类型,Rasa 提供了一些预定义的插槽类型。

除文本外,Rasa 还有以下插槽类型:

  • 布尔型用于真/假

  • 分类用于您必须选择某个值的情况

  • Float 用于连续值

  • 列表用于值列表

  • 特色化用于不影响通话的内部值存储

模板

当你在寻找发送电子邮件、准备文档、建立作品集网站或遵循流程的模板时,模板是一个你在生活中至少听过一次的词。

Rasa 中的模板用于话语。话语模板包含一组预设文本,当某个动作被触发时,这些文本将被发送给用户。通过使用与话语相同的动作名称或者使用自定义代码的动作,我们可以将格式化的消息以模板的形式发送给用户。

域文件中模板的简单表示可能如下所示:

templates:
  utter_greet:
    - "hello {name}!"   # name can be filled by a slot of same name or by custom code
  utter_goodbye:
    - "goodbye"
    - "take care bye"   # multiple templates allow the bot to randomly pick from them
  utter_default:
    - "Sorry, I didn’t get that."

现在,我们已经学习了动作、插槽和模板这三个概念,并且我们已经知道了意图和实体是什么,作为我们从第三章学习的一部分,我们现在准备深入 Rasa 并开始为我们的第一个聊天机器人编写代码。

正在为聊天机器人创建域文件

使用 Rasa stack 构建聊天机器人的首要任务是创建一个域文件。

根据 Rasa 的文档,“域定义了你的机器人运行的宇宙。它指定了你的机器人应该知道的意图、实体、插槽和动作。可选地,它还可以包括你的机器人可以说的东西的模板。”

现在,通过了解 Rasa 的核心概念,你知道为什么我们必须事先为这种情况做好准备。

让我们用 YAML 定义创建一个 DefaultDomain 文件。拉莎使用。yml 文件来定义域格式。

最初 YAML 的意思应该是Yet Another Markup Language,描述它作为一种标记语言的使用,但后来它被理解为 YAML 不是标记语言,一种递归的缩写,以区分它作为面向数据而不是文档标记语言的目的。

现在,让我们回到 rasa-nlu Jupyter 笔记本目录,开始创建文件。请注意,我们可以使用命令行在单独的文件中编写所有代码,并使用编辑器对其进行编辑。我发现 Jupyter 笔记本更具互动性,浏览文件也更容易。无论你觉得哪种都可以,但是了解 Jupyter Notebook 提供的大部分功能还是有好处的。

转到主占星 _bot 目录下,创建一个文件,姑且称之为horoscope_domain.yml

以下是我们 bot 的horoscope_domain.yml内容:

slots:
    horoscope_sign:
        type: text
    DD:
        type: text
    MM:
        type: text

    subscribe:
        type: bool

intents:
    - greeting
    - get_horoscope

    - subscription
    - dob_intent

entities:
     - horoscope_sign
     - DD
     - MM
     - subscribe
     - dob_intent

templates:
    utter_greet:
        - 'Hello! How are you doing today?'
    utter_ask_horoscope_sign:
        - 'What is your horoscope sign?'
    utter_ask_dob:
        - 'What is your DOB in DD-MM format?'
    utter_subscribe:
        - 'Do you want to subscribe for daily updates?'

actions:
  - utter_greet
  - utter_ask_horoscope_sign
  - utter_ask_dob
  - utter_subscribe
  - get_todays_horoscope
  - subscribe_user

正如您所看到的,域文件由五个重要部分组成:intents, entities, slots, templatesactions,我们在前面已经讨论过了。

注意,对于每个模板,都定义了一个 utterAction,比如utter_greet, utter_ask_horoscope_signutter_ask_dob,我们必须在模板部分定义一个同名的模板。

正如您在我们的示例中看到的,主要定义了五个动作,其中前三个动作只是为了向用户说出模板文本,但最后两个动作要求我们要么从数据库中检索数据,要么调用 API 来获取当天的星座并将其返回给用户。

对于subscribe_user动作,我们需要做一个操作,将当前用户添加到数据库的订阅列表中。这些用户定义的操作称为自定义操作。为了拥有这样的自定义动作,我们需要编写当这些动作被触发时,机器人应该做什么。

在下一节中,我们将学习如何编写自定义操作。

编写聊天机器人的自定义动作

正如我们所知,每当一个UtterAction被触发,我们的机器人会用模板中为该动作定义的完整文本进行响应。但是当一些自定义动作被触发时会发生什么呢?在这一节中,我们将编写 Python 代码来创建自定义操作,我们可以用它来进行 API 调用或几乎任何你可以用 Python 做的事情。

让我们在我们的项目目录中创建一个名为actions.py的新文件(即,在我们的例子中,在horoscope_bot文件夹中)。

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import requests
from rasa_core_sdk import Action
from rasa_core_sdk.events import SlotSet

class GetTodaysHoroscope(Action):

    def name(self):
        return "get_todays_horoscope"

    def run(self, dispatcher, tracker, domain):
        # type: (Dispatcher, DialogueStateTracker, Domain) -> List[Event]

        user_horoscope_sign = tracker.get_slot('horoscope_sign')
        base_url = http://horoscope-api.herokuapp.com/horoscope/{day}/{sign}
        url = base_url.format(**{'day': "today", 'sign': user_horoscope_sign})
        #http://horoscope-api.herokuapp.com/horoscope/today/capricorn
        res = requests.get(url)
        todays_horoscope = res.json()['horoscope']
        response = "Your today's horoscope:\n{}".format(todays_horoscope)

        dispatcher.utter_message(response)
        return [SlotSet("horoscope_sign", user_horoscope_sign)]

正如我们所看到的,在我们的操作中有两个方法叫做 GetTodaysHoroscope。第一个方法 name 只是返回动作的名称。另一个方法是运行,正如前面讨论的,这个方法通过执行我们编写的业务逻辑来实际完成任务。

在我们的方法中,我们使用了一个开源 API,代码托管在 github [ https://github.com/tapasweni-pathak/Horoscope-API ]上

API url 如下所示:

http://horoscope-api.herokuapp.com/horoscope/today/capricorn

它以 JSON 格式返回数据:

{
  "date": "2018-08-29",
  "horoscope": "You will be overpowered with nostalgia and may long to get in touch with old pals. And as Ganesha says, chances are that you may take a liking to your ex-lover, while simultaneously strengthening your social standing. All in all, the day will be a productive one.",
  "sunsign": "capricorn"
}

正如你在 run 方法中看到的,我们将来自 API 的响应转换为 Python JSON 对象,然后从 JSON 中访问“星座”键以获得实际的星座。在从 JSON 中获得实际的星座之后,我们使用dispatcher对象及其方法 utter_message 制定一个响应并将其发送回用户。

最后,我们使用SlotSet方法设置插槽。SlotSet 就像保存您从用户的响应中发现的变量,这样您就可以在对话过程中的任何时候在代码中使用它们。

注意

使用上面的 API,我们可以通过提供星座来获得今天的星座。你可以自由使用你自己的 API 或者数据库。您只需要将 API 调用替换为您想要使用的其他资源。

就像我们在actions.py文件中添加了GetTodaysHoroscope动作一样,我们也将添加SubscribeUser动作。我们不打算使用任何数据库来存储用户的订阅偏好,但是当您为真实用户构建聊天机器人时,您可能必须拥有可以在数据库中与他们的订阅相关联的 user _ ids。

以下是 SubscribeUser 操作的外观:

class SubscribeUser(Action):
    def name(self):
        return "subscribe_user"

    def run(self, dispatcher, tracker, domain):
        # type: (Dispatcher, DialogueStateTracker, Domain) -> List[Event]

        subscribe = tracker.get_slot('subscribe')

        if subscribe ==True:
            response = "You're successfully subscribed"
        if subscribe ==False:
            response = "You're successfully unsubscribed"

        dispatcher.utter_message(response)
        return [SlotSet("subscribe", subscribe)]

像这样,我们可以根据需要编写任意多的自定义操作。

接下来就是数据了。Rasa 的对话管理模型是在用户和聊天机器人的实际对话中训练出来的。这里重要的一点是,这些对话必须转换成故事的形式。

故事只不过是用户和聊天机器人之间的实际对话,其中用户的输入被转换为意图和实体,而聊天机器人返回的响应被视为聊天机器人在需要时应该触发的动作。

下表给出了用户和聊天机器人之间的真实对话看起来像故事的一个例子。

情景一

|

用户

|

星座运势

|
| — | — |
| 你好。 | 发出问候 |
| 我想知道我今天的星座运势 | 说出星座 |
| 我的星座是摩羯 | 动作(s)。gettodayhorocscope-格达多约罗斯-格达多约罗斯-格达多约罗斯-格达多约罗斯-格达多约罗斯-格达多约罗斯-格达多约罗斯 |
| 你能帮我订阅更新吗? | 行动。订户用户 |

情景二

|

用户

|

星座运势

|
| — | — |
| 你好。 | 发出问候 |
| 我想知道我今天的星座运势 | 说出星座 |
| 我不知道我的星座 | 直言不讳 |
| 12-12 | 动作(s)。gettodayhorocscope-格达多约罗斯-格达多约罗斯-格达多约罗斯-格达多约罗斯-格达多约罗斯-格达多约罗斯-格达多约罗斯 |

我们还没有涵盖代码中用户不知道他的星座,但知道他的出生日期的场景。这里,我们的代码需要做一些修改,以便在找不到星座值时获得日期和月份实体。

我们可以使用 DD-MM 值来检查星座,然后显式地调用 GetTodaysHoroscope 方法,或者以这种方式训练模型。

训练机器人的数据准备

在进行任何类型的 ML 之前,拥有高质量的数据总是很重要的。为了训练我们的聊天机器人,我们也需要数据;用户和聊天机器人之间的对话是我们需要用来训练模型的数据。有时很难在网上找到一个符合我们需要的数据集。

我们应该花我们需要的时间来收集数据。我们可以要求我们的朋友和家人向我们提供示例对话文本,说明他们将如何与您正在构建的一种机器人进行交互。有些人为此创建了示例应用程序,并对数据进行了众包。所以,数据越好,模型越好,聊天机器人的反应越好。

当谈到准备数据时,Rasa 想尽一切办法,并提供了一个很酷的功能,称为互动学习。它帮助您轻松地生成故事数据,并在我们不断添加故事数据时训练对话管理模型。你可以称之为实时 ML 训练。因此,随着我们不断添加我们的故事数据,我们开始知道我们的模型是否产生正确的输出。最重要的是,当我们添加新的故事时,我们可以看到模型是在改进还是在退化。在大多数情况下,它会变得更好,因为我们会做一些强化学习,我们告诉 ML 模型去遗忘和重新学习——就像人类做的那样。

创建故事数据

正如我们所知,故事数据只是用户和聊天机器人之间的一种对话方式,讨论它将如何导致逻辑上的结束。一般来说,所有聊天机器人都是为了帮助用户完成一组预定义的事情;故事只是代表了他们是怎么做的。

我们将尝试按照 Rasa 期望的格式准备一些简单的对话。这些对话将是无状态的,也就是说,它们不依赖于以前的对话。我们将使用我们手工制作的无状态故事进行互动学习。

我们将花几分钟时间来手工整理几个我们知道的故事,以便我们适应故事数据是如何创建的。

让我们首先在我们的数据文件夹中创建一个名为stories.md的文件。

## story_001
* greeting
  - utter_greet
* get_horoscope
  - utter_ask_horoscope_sign
* get_horoscope{"horoscope_sign": "Capricorn"}
  - slot{"horoscope_sign": "Aries"}
  - get_todays_horoscope
  - utter_subscribe

## story_002
* greeting
  - utter_greet
* get_horoscope{"horoscope_sign": "Capricorn"}
  - slot{"horoscope_sign": "Cancer"}
  - get_todays_horoscope
  - utter_subscribe
* subscription
  - slot{"subscribe": "True"}
  - subscribe_user

## Horoscope query with horoscope_sign

* greeting
    - utter_greet
* get_horoscope
    - utter_ask_horoscope_sign
* get_horoscope{"horoscope_sign": "capricorn"}
    - slot{"horoscope_sign": "capricorn"}
    - get_todays_horoscope
    - slot{"horoscope_sign": "capricorn"}
    - utter_subscribe
* subscription{"subscribe": "True"}
    - slot{"subscribe": "True"}
    - subscribe_user
    - slot{"subscribe": true}

## Horoscope with sign provided
* greeting
    - utter_greet
* get_horoscope{"horoscope_sign": "leo"}
    - slot{"horoscope_sign": "leo"}
    - get_todays_horoscope
    - slot{"horoscope_sign": "leo"}
    - utter_subscribe
* subscription{"subscribe": "True"}
    - slot{"subscribe": "True"}
    - subscribe_user
    - slot{"subscribe": true}

## When user directly asks for subscription
* greeting
    - utter_greet
* subscription{"subscribe": "True"}
    - slot{"subscribe": "True"}
    - subscribe_user
    - slot{"subscribe": true}

如果你盯着这些故事看几分钟,它们会向你坦白它们的意思;弄清楚正在发生的事情应该不难。前两个故事之间的主要区别是,在第一个故事中,用户没有提到他的星座,机器人应该问星座,然后继续这个故事。

在第二个故事中,用户自己说出星座,然后用订阅对话框结束故事。我们增加了几个故事,涵盖了更多的用例。请随意在同一个文件中添加您自己的故事。

所以,基本上故事是降价文件,我们可以按照前面显示的降价格式写尽可能多的故事。手工完成这项任务似乎有点困难。因此,我们将尝试学习如何使用 Rasa 自己的互动学习工具来生成更多这样的故事。

让我们开始吧。

互动学习

到目前为止,我们一直在零零碎碎地谈论交互式学习,但现在是时候实际编写一些代码并付诸实践了。交互式学习是 Rasa 最酷的功能之一,它使 ML 部分变得有趣和简单。有两个部分:在第一部分中,我们通过使用各种策略给出我们的初始数据集来训练模型,在第二部分中,我们测试模型,修正它,并以交互的方式重新训练它。

训练聊天机器人代理模型

让我们在主项目目录中创建一个名为train_initialize.py的新文件。train_initialize.py的内容是这样的:

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from rasa_core import utils
from rasa_core.agent import Agent
from rasa_core.policies.keras_policy import KerasPolicy
from rasa_core.policies.memoization import MemoizationPolicy
from rasa_core.policies.sklearn_policy import SklearnPolicy

if __name__ == '__main__':
    utils.configure_colored_logging(loglevel="DEBUG")

    training_data_file = './data/stories.md'
    model_path = './models/dialogue'

    agent = Agent("horoscope_domain.yml",
                  policies=[MemoizationPolicy(), KerasPolicy()])

    training_data = agent.load_data(training_data_file)

    agent.train(
            training_data,
            augmentation_factor=50,
            epochs=500,
            batch_size=10,

            validation_split=0.2
    )

    agent.persist(model_path)

这是我们写在train_initialize.py文件中的代码。现在,在我们进入下一个代码文件之前,让我们先试着理解其中的要点。

  1. 首先,我们从 future 模块中导入一些方法。Python 中的未来语句有特殊的用法,它们改变了 Python 模块的解析方式,也改变了现有方法的行为方式。

    Curious personality ? Try the below code in your python interpreter
         from __future__ import braces
    
    
  2. 从 rasa_core 模块导入utils方法来配置日志记录。

  3. 从代理模块导入代理类以创建代理对象。

  4. KerasPolicy,KerasPolicy 将作为策略参数传递给代理类。

  5. **configure _ colored _ logging:**utils . py 中定义的使用 Python 的 coloredlogs 包进行彩色日志记录的实用方法。

  6. **Agent:**Rasa 定义的一个类,提供一个接口来利用最重要的 Rasa 核心功能,比如训练、处理消息、加载对话模型、获取下一个动作、处理通道。

  7. load_data: 从给定路径加载训练数据。

  8. train: 使用提供的文件中的数据训练给定的策略/策略集合。

  9. 训练 _ 数据:加载 _ 数据方法返回的对象。DialogueStateTracker列表。这只是我们的训练数据文件。

  10. **augment _ factor:**告诉 Rasa 在给定初始故事集的情况下应该创建多少个虚拟故事。10x 因子是用于训练数据生成器的扩充回合的启发。

  11. 历元: 1 个历元是整个训练数据集上的完整训练周期。训练数据向前和向后传递的总数。

  12. batch_size: 告诉您每次使用的训练样本的数量。batch_size 为 10 的 100 个示例将需要 10 个历元来遍历整个数据集。

  13. validation_split: 验证模型无偏准确性的数据百分比。

  14. persist: 该方法用于将代理对象持久保存在给定的目录中,以便重用。

此时,您应该非常清楚每个方法的作用以及代码内部发生了什么。

在我们继续运行这个脚本之前,确保在执行这个脚本之前已经安装了 rasa_core 库。

您可以使用以下命令安装 rasa_core:

pip install rasa_core==0.11.1

如果你遵循本书中的聊天机器人示例,那么确保你只安装了上述版本,因为 Rasa 可能不是向后兼容的。他们正迅速提出更新更优化的方法。

最新的 rasa_core

您也可以从 github repo 安装 rasa_core 的最新版本。你只需要执行下面这组命令,这些命令会在安装之前直接从 github 获取最新的代码。

git clone https://github.com/RasaHQ/rasa_core.git
cd rasa_core
pip install -r requirements.txt
pip install -e .

让我们试着运行这个代码文件,按照给定的参数训练我们的模型。

$python train_initialize.py

您也可以使用 Jupyter 的 magic 命令从 Jupyter 笔记本本身运行该脚本,如下所示:

如果您已经为 python3 安装了 rasa,请使用 python3

在我们这样的小数据集上训练模型应该需要大约 25 到 30 秒。我在策略列表中添加了SklearnPolicy以及 MemorizationPolicy 和 KerasPolicy 来训练我的模型。不同的政策有各自的好处。阅读更多关于它们的内容,以了解哪一种可能更适合您的用例;对于我的数据集,SklearnPolicy 有时似乎比 KerasPolicy 表现得更好。

脚本执行完毕后,您应该会看到一些成功的消息,如下所示:

2018-08-30 04:24:31 INFO    rasa_core.policies.keras_policy  - Done fitting keras policy model
2018-08-30 04:24:31 INFO    rasa_core.featurizers  - Creating states and action examples from collected trackers (by MaxHistoryTrackerFeaturizer)...
Processed trackers: 100%|████████| 96/96 [00:00<00:00, 898.31it/s, # actions=75]
2018-08-30 04:24:31 INFO    rasa_core.featurizers  - Created 75 action examples.
2018-08-30 04:24:31 INFO    rasa_core.policies.sklearn_policy  - Done fitting sklearn policy model
2018-08-30 04:24:31 INFO    rasa_core.agent  - Model directory models/nlu exists and contains old model files. All files will be overwritten.
2018-08-30 04:24:31 INFO    rasa_core.agent  - Persisted model to '/Users/sumit/apress_all/Chapter IV/horoscope_bot/models/nlu'

您还会发现几个根据型号名称创建的文件夹。确保您在脚本中给出的 model_path 中有它们。以下是我在 model_path 文件夹中看到的文件夹/文件。

policy_0_MemoizationPolicy
policy_1_KerasPolicy
policy_2_SklearnPolicy
domain.json
domain.yml
Policy_metadata.json

如果您已经验证了您的模型已经成功地完成了执行,并且在您的本地系统中持久化了模型,那么我们就可以进入下一步的交互式培训了。

通过强化进行实时训练

在这一节中,我们将编写更多的代码来训练我们的对话模型,并在它给出不正确的输出时进行重新训练。

因此,当我们的机器人做错了什么,我们会立即跳出来,通过告诉它什么是正确的,让模型知道它的预测是错误的。无需停止,模型会重新训练自己,一旦我们完成,用户和机器人之间的交互就会被捕获到一个文件中,并添加到我们现有的训练数据中。它在每一步都更像一个反馈系统,而不是在最后等待一个单一的奖励。

下一步是用下面的内容创建一个名为endpoints.yml的新文件。我们将在 Python 代码文件train_online.py.中使用这个文件。通过这个配置,我们可以将 Rasa 方法公开为 HTTP APIs。

action_endpoint:
  url: http://localhost:5055/webhook

#nlg:
#  url: http://localhost:5056/nlg

core_endpoint:
  url: http://localhost:5005

现在,让我们为我们的在线/交互式培训创建train_online.py

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import logging

from rasa_core import utils, train
from rasa_core.training import online
from rasa_core.interpreter import NaturalLanguageInterpreter

logger = logging.getLogger(__name__)

def train_agent(interpreter):
    return train.train_dialog_model(domain_file="horoscope_domain.yml",
                                      stories_file="data/stories.md",
                                      output_path="models/dialog",
                                      nlu_model_path=interpreter,
                                      endpoints="endpoints.yml",
                                      max_history=2,
                                      kwargs={"batch_size": 50,
                                              "epochs": 200,
                                              "max_training_samples": 300
                                              })

if __name__ == '__main__':
    utils.configure_colored_logging(loglevel="DEBUG")
    nlu_model_path = "./models/nlu/default/horoscopebot"
    interpreter = NaturalLanguageInterpreter.create(nlu_model_path)
    agent = train_agent(interpreter)
    online.serve_agent(agent)

max_history是模型要跟踪的状态数。

在我们继续运行我们的最终脚本train_online.py之前,我们应该了解并为 rasa-nlu-sdk 做好准备。

rasa-nlu SDK

Rasa NLU 堆栈提出了 rasa-nlu-sdk,这是一个 Python SDK,用于为 Rasa 核心开发自定义操作。至于我们的聊天机器人示例,我们需要定义一些自定义操作,比如点击 API 来获取今天的星座,或者可能是数据库写操作来将用户添加到订阅列表。

好消息是他们有一个单独的库,我们可以使用 pip 来安装它。

让我们使用以下命令来安装它:

pip install rasa-core-sdk==0.11.0

现在,我们需要转到终端的另一个选项卡或一个新的命令行,并在我们的项目目录(我们的actions.py文件所在的位置)中执行以下命令:

python -m rasa_core_sdk.endpoint --actions actions

INFO:__main__:Starting action endpoint server...
INFO:rasa_core_sdk.executor:Registered function for 'get_todays_horoscope'.
INFO:rasa_core_sdk.executor:Registered function for 'subscribe_user'.
INFO:__main__:Action endpoint is up and running. on ('0.0.0.0', 5055)

该命令将启动一个动作服务器,该服务器将监听模型预测的任何自定义动作。一旦任何动作被触发,它将执行它并根据方法给出响应。

在本地主机上,操作服务器端点的默认端口是 5055。如果你想改变它,你可以在命令行中添加 pass --port参数。

一个快速的问题浮现在脑海:为什么?为什么我需要一个单独的服务器?为什么不能用普通 Python?是的,我们可以使用普通的 Python,但是假设您要用任何其他语言来开发所需的操作,或者您已经将一些操作公开为 API。现在,您只需要转到我们已经创建的endpoints.yml,,并使用它来说明应该在哪里使用您的操作服务器以及应该在哪里使用您的 core_endpoint 服务器。在生产系统中,两者可以是具有完全不同的 URL 的不同服务器。

现在,当我们运行下一个脚本时,其中提到了我们的 endpoints.yml 文件,Rasa 将读取该文件并获取我们的 action_server 的配置,它已经按照我们之前所做的配置启动并运行。

action_endpoint:
       url: http://localhost:5055/webhook

让我们在新的命令行终端中运行train_online.py

$python3 train_online.py

在对话模型的成功训练之后,我们将得到这样的消息:

2018-08-30 07:09:37 INFO     rasa_core.policies.keras_policy  - Done fitting keras policy model
2018-08-30 07:09:37 INFO     rasa_core.agent  - Model directory models/nlu exists and contains old model files. All files will be overwritten.
2018-08-30 07:09:37 INFO     rasa_core.agent  - Persisted model to '/Users/sumit/apress_all/Chapter IV/horoscope_bot/models/nlu'
2018-08-30 07:09:37 INFO     rasa_core.training.online  - Rasa Core server is up and running on http://localhost:5005
Bot loaded. Type a message and press enter (use '/stop' to exit).
127.0.0.1 - - [2018-08-30 07:09:37] "GET /domain HTTP/1.1" 200 996 0.001847

现在,你可以开始和你刚出生的机器人说话了。从现在开始,你如何训练它完全掌握在你手中。每当它对不好的或意想不到的事情做出反应时,你都可以纠正它。

让我们这样做,看看它是否有所改善。

我输入“Hi”作为第一条消息,机器人返回以下内容:

---------------------------------------------------------------------------

Chat history:

      bot did: action_listen

      user said: hi

      whose intent is: {'confidence': 0.8472929307505297, 'name': 'greeting'}

we currently have slots: DD: None, MM: None, horoscope_sign: None, subscribe: None

------

The bot wants to [utter_greet] due to the intent. Is this correct?

      1\.      Yes
      2\.      No, intent is right but the action is wrong
      3\.      The intent is wrong
      0\.      Export current conversations as stories and quit

---------------------------------------------------------------------------

现在,机器人正在根据用户所说的话和他对它的理解告诉我它做了什么。现在,它也给了我们四个选择。我们一会儿会谈到这一点。

这里的 bot_did 是 action_listen 的意思;它只是在等待用户输入一些东西,这很好。

Bot 说出了意图*{ ’ confidence ‘:0.8472929307505297,’ name’: ‘greeting’}* ,这是正确的,所以我们会按 1,意思是 bot 正在理解并试图正确地做的事情。

1
---------------------------------------------------------------------------
Chat history:

      bot did: action_listen

      user said: hi

      whose intent is: {'confidence': 0.8472929307505297, 'name': 'greeting'}

      bot did: utter_greet

we currently have slots: DD: None, MM: None, horoscope_sign: None, subscribe: None

------
The bot wants to [action_listen]. Is this correct?

      1\.      Yes.
      2\.      No, the action is wrong.
      0\.      Export current conversations as stories and quit
---------------------------------------------------------------------------

你看,我们的机器人至少正确地问候了用户。如果你看到前面提到的回应,你实际上可以检查我们的机器人做了什么;在我们训练它的时候,它会记录所有这些。

bot did: utter_greet

现在,机器人说接下来的事情是等待并听用户将要说什么(即,等待用户输入)。这是正确的吗?是的,这是正确的,所以我们再次按 1,机器人给用户一个提示。

我输入,“我今天的星座是什么?”

---------------------------------------------------------------------------
Chat history:

      bot did: action_listen

      user said: hi

             whose intent is: {'confidence': 0.8472929307505297, 'name': 'greeting'}

      bot did: utter_greet

      bot did: action_listen

      user said: what's my horoscope for today?

      whose intent is: {'confidence': 0.8902154738608781, 'name': 'get_horoscope'}

we currently have slots: DD: None, MM: None, horoscope_sign: None, subscribe: None

------
The bot wants to [utter_ask_horoscope_sign] due to the intent. Is this correct?

      1\.      Yes
      2\.      No, intent is right but the action is wrong
      3\.      The intent is wrong
      0\.      Export current conversations as stories and quit

---------------------------------------------------------------------------

现在,机器人非常正确地识别出“获取星座”的意图,准确率达到 89%,这是非常好的。机器人还说它想**说出 _ ask _ 占星 _sign,**这又是正确的,因为用户还没有提到任何占星符号,槽仍然是无,如图所示。

我们再次按 1。

---------------------------------------------------------------------------

Chat history:

      bot did: action_listen

      user said: hi

      whose intent is: {'confidence': 0.8472929307505297, 'name': 'greeting'}

      bot did: utter_greet

      bot did: action_listen

      user said: what's my horoscope for today?

      whose intent is: {'confidence': 0.8902154738608781, 'name': 'get_horoscope'}

      bot did: utter_ask_horoscope_sign

we currently have slots: DD: None, MM: None, horoscope_sign: None, subscribe: None

------
The bot wants to [action_listen]. Is this correct?

      1\.      Yes.
      2\.      No, the action is wrong.
      0\.      Export current conversations as stories and quit

---------------------------------------------------------------------------

现在,机器人会询问是否到了等待用户输入的时间。是的,用户需要提供星座。

我们再次按 1,出现提示时,我们输入“摩羯”作为输入。

---------------------------------------------------------------------------

Chat history:

      bot did: action_listen

      user said: hi

      whose intent is: {'confidence': 0.8472929307505297, 'name': 'greeting'}

      bot did: utter_greet

      bot did: action_listen

      user said: what's my horoscope for today?

      whose intent is: {'confidence': 0.8902154738608781, 'name': 'get_horoscope'}

      bot did: utter_ask_horoscope_sign

      bot did: action_listen

      user said: Capricorn

      whose intent is: {'confidence': 0.8456705103362621, 'name': 'get_horoscope'}

      with horoscope_sign: capricorn

we currently have slots: DD: None, MM: None, horoscope_sign: capricorn, subscribe: None

The bot wants to [get_todays_horoscope] due to the intent. Is this correct?

      1\.      Yes
      2\.      No, intent is right but the action is wrong
      3\.      The intent is wrong
      0\.      Export current conversations as stories and quit

---------------------------------------------------------------------------

现在,正如我们所看到的,星座槽被自动设置为“摩羯座

下一步是教机器人调用get _ today _ 占星和调用get _ today _ 占星动作。到目前为止,我们的槽已经为我们在占星 _ 域. yml 中定义的占星 _ 符号变量设置好了,所以如果再次调用这个动作,聊天机器人应该会返回当天的实际占星。让我们试试。

我输入了“摩羯座”

bot 点击动作服务器的端点,并将结果返回给用户,正如我们在自定义动作中定义的那样。

Your today's horoscope:

乐观是从失败走向成功的动力。甘尼萨说,你今天会非常乐观——对你的工作、未来和一切能让你成功的东西。在处理日常工作时,你也会非常小心,会利用每一个能让你离目标更近一步的机会。决心和好运是你实现梦想所需要的一切;今天你将两者兼得。

这似乎是公平的,因为我错过了完成这一章的最后期限,现在是早上 6 点,我还没有睡觉。尽一切努力让你的钱值得花在这本书上。

好吧,让我们回去看看我们的机器人下一步要做什么。

------
The bot wants to [action_listen]. Is this correct?

      1\.      Yes.
      2\.      No, the action is wrong.
      0\.      Export current conversations as stories and quit

也许我们不想让我们的机器人在说出今天的星座之后还在听。我们希望我们的机器人要求用户根据我们的对话脚本以及我们创建的故事订阅更新。

所以,我会按 2,它会说

------
what is the next action for the bot?

         0                           action_listen    1.00
         1                          action_restart    0.00
         2                 action_default_fallback    0.00
         3                             utter_greet    0.00
         4                utter_ask_horoscope_sign    0.00
         5                           utter_ask_dob    0.00
         6                         utter_subscribe    0.00
         7                    get_todays_horoscope    0.00
         8                          subscribe_user    0.00

因为我们希望用户订阅,所以我们应该按 6,这样机器人会询问用户是否希望订阅每日更新。

机器人回答,“你想订阅每日更新吗?”

现在机器人说:

---------------------------------------------------------------------------
The bot wants to [get_todays_horoscope]. Is this correct?

      1\.      Yes.
      2\.      No, the action is wrong.
      0\.      Export current conversations as stories and quit

这里的动作不正确,所以我们按 2,训练机器人听用户这里的动作。

---------------------------------------------------------------------------
what is the next action for the bot?

         0                           action_listen    0.21
         1                          action_restart    0.01
         2                 action_default_fallback    0.01
         3                             utter_greet    0.21
         4                utter_ask_horoscope_sign    0.51
         5                           utter_ask_dob    0.01
         6                         utter_subscribe    0.02
         7                    get_todays_horoscope    0.78
         8                          subscribe_user    0.22
---------------------------------------------------------------------------

当机器人等待知道正确的下一步时,我们按 0。机器人现在将在我们的交互式学习过程中等待用户输入。

用户在这里说,“请订阅我,”我们的机器人以 80%的信心成功地识别出这是一个订阅意图,并且根据我们在 data.json 中的训练数据,很容易理解用户是在请求订阅而不是取消订阅。换句话说,它将 subscribe 的槽设置为 True,如下所示:

---------------------------------------------------------------------------

      user said: Please subscribe me

      whose intent is: {'confidence': 0.795172441763619, 'name': 'subscription'}

      with subscribe: True

we currently have slots: DD: None, MM: None, horoscope_sign: capricorn, subscribe: True
---------------------------------------------------------------------------

现在,我们的机器人已经理解了它的意图,并解析了其中的实体,是时候回复用户说“他已经成功订阅了”,然后我们从机器人那里得到一条消息:

You're successfully subscribed

这就对了。你完全可以自己成功构建自己的室内聊天机器人。作为练习的一部分,我建议你添加我们讨论过的星座机器人的所有用例,看看它是否有效。当我们到目前为止所做的一切都运行良好时,尝试添加更多的用例和更多的功能。

您可以在这里添加更多的话语信息,以便机器人在对话完成后说,“再见,祝您愉快”。我坚信你应该有能力做到这一点。一定要这样做,并让我们知道你的进展如何。

现在,最后一部分是将所有这些学习反馈给用户,这样我们就不必再次教授相同的故事,机器人会尝试从现有的故事和未来的故事中学习。

将对话导出为故事

现在,互动学习部分的下一步是按 0,将我们当前的对话导出为故事,然后退出。

为此,我们按 0,机器人会提示如下内容:

File to export to (if file exists, this will append the stories) [stories.md]:

只需输入我们的 stories.md 文件名,如果您保留了任何其他名称,请确保您给出了正确的文件名。

Rasa 为我们完成了这项艰巨的工作,并自动生成了一个 stories.md 文件,如下所示:

## Generated Story 3797421409943253925
* greeting
    - utter_greet
* I want to know my horoscope
    - utter_ask_horoscope_sign
* get_horoscope

## Generated Story 7304374603374920907
* greeting
    - utter_greet
* what is my todays horoscope?
    - utter_ask_horoscope_sign
* Cancer

## Generated Story -6877464862083507836
* greeting
    - utter_greet
* get_horoscope
    - utter_ask_horoscope_sign
* get_horoscope{"horoscope_sign": "capricorn"}
    - slot{"horoscope_sign": "capricorn"}
    - get_todays_horoscope
    - slot{"horoscope_sign": "capricorn"}
    - utter_subscribe
* subscription{"subscribe": "True"}
    - slot{"subscribe": "True"}
    - subscribe_user
    - slot{"subscribe": true}

您可以在使用上述文件训练模型时更改 stories 文件的源,也可以将新生成的故事复制并粘贴到我们的原始 stories.md 文件中。现在,我将把这些故事复制并粘贴到我们原来的 stories.md 文件中。在再次测试或进行交互式学习之前,请确保再次运行您的模型。

测试机器人

测试机器人是我们互动学习过程的一部分。我们不断检查最初为机器人想到的所有可能的场景,并相应地训练它。我测试了一些其他场景的星座机器人,并对其进行了相应的训练。下面是其中一个与我们在本章前面所做的有点不同的例子。

测试案例 1

让我们运行第一个测试:

  • 用户:你好!

  • **星座机器人:**你好!能为你做什么?

  • **用户:**摩羯座今天的星座是什么?

  • **星座机器人:**你今天的星座:

乐观是从失败走向成功的动力。甘尼萨说,你今天会非常乐观——对你的工作、未来和一切能让你成功的东西。在处理日常工作时,你也会非常小心,会利用每一个能让你离目标更近一步的机会。决心和好运是你实现梦想所需要的一切;今天你将两者兼得。

  • **星座机器人:**要订阅每日更新吗?

  • **用户:**请订阅我。

  • **星座机器人:**您已成功订阅。

正如你在用户和聊天机器人之间的对话中看到的,我们测试了机器人是否处理用户自己提供星座运势同时询问当天星座运势的场景。在这种情况下,机器人做得很好,并最终要求订阅,并根据用户的响应,采取适当的行动。

您应该对机器人的对话进行健全性测试,以确定正常流是否正常工作。

我还测试了我们在 stories.md 文件中提到的故事,当用户直接要求订阅时,它也工作正常。

测试案例 2

现在是第二个测试:

  • **用户:**嗨

  • **星座机器人:**你好!能为你做什么?

  • **用户:**请为我订阅每日更新。

  • **星座机器人:**您已成功订阅。

我还会添加一些新的故事,这样机器人就可以完美地工作了。但是现在我们有了一个完全正常工作的机器人。在 github 的第二个版本中,你还会发现这个机器人正在纠正星座的拼写错误,根据用户的出生日期检索星座,说再见信息,等等。我强烈建议您检查代码,看看它是如何完成的,并提供您的反馈。但在此之前,考虑一下将如何完成以及变化将会发生在哪里。我们故意没有在本章中提到其他用例的代码,这样当你集中精力学习交易技巧时,它不会变得繁琐。

您可以从我们的 github repo 下载最新的 Python 代码和 Jupyter 笔记本,并尝试安装正确的包来运行它。你会发现在本章讨论的代码中处理了更多的用例。

摘要

在这一章中,我们了解了 Rasa-NLU,以及为什么 Rasa-NLU 比市场上任何其他开源工具都好。我们学习了如何在管道配置中使用 tensorflow、sklearn 和 keras 来配置管道。

我们学会了在本地系统上从头开始创建一切,而不依赖于任何需要您使用其 API 的服务,如 Dialogflow、wit.ai 等。

我们还学习了如何创建故事,以及如何训练 NLU 模型和对话模型,并使用 Rasa Core 通过使用最酷的功能交互式学习进行训练来构建机器人。在开源工具如 rasa-nlu-trainer 的帮助下,我们也对如何轻松地创建训练数据并轻松地进行注释有了一个相当好的想法。我希望这一章对你来说比其他任何一章都更具互动性。如果你没有成就感,那就为下一章做好准备,在那里我们将把它真实地呈现给我们的观众,并向世界展示机器人的能力。我们将学习使用我们自己的网络服务器把本章的聊天机器人集成到各种平台上,比如脸书和 Slack。

继续训练你的机器人,直到下一章我们把它投入使用。

下一章见。**

五、部署您的聊天机器人

在这一章中,我们将学习如何在网络上部署聊天机器人。人们可以通过各种方式和渠道向外界部署或公开他们的 chatbot web 应用程序。举个例子,我们可以在脸书和 Slack 上用 NLU 和对话模型来展示我们的星座机器人,因为他们已经为你提供了一个用户界面。您可能还想拥有自己的 web 应用程序,它完全运行在您自己的服务器上。在本章末尾,我们还将探索如何使用我们自己的用户界面在我们自己的服务器上部署聊天机器人。

第一步

第一步是创建一个你在第四章中创建的现有聊天机器人的副本,并制作一个新的副本,以便你有一个备份。因为,我们将通过添加一些新代码来做一些更改,所以让我们将两个项目分开。

于是,我创建了一个名为“第五章的新文件夹,并将我的horoscope_bot文件夹粘贴在那里。所以,现在我所有的模型文件、数据集和代码文件都被复制了,我可以直接使用它们进行部署。

Rasa 的凭证管理

Rasa 提供了一种在一个地方管理您所有凭据的方法。你可能有一个单一的模型,但你可能希望它被部署在各种其他平台上,如脸书,Slack,Telegram 等。所有这些第三方平台都需要一些凭据才能在连接时使用。这些凭证存储在名为credentials.yml的 YAML 文件中。

让我们在我们的项目目录horoscope_bot文件夹中创建一个名为credentials.yml file 的文件,并在那里添加我们的脸书凭证。如果你不知道如何得到它,那么现在就创建这个文件,在本章的下一节你可以找到得到脸书证书的步骤。

credentials.yml的内容将如下所示:

facebook:
  verify: "horoscope-bot"
  secret: "bfe5a34a8903e745e32asd18"
  page-access-token: "HPaCAbJJ1JmQ7qDedQKdjEAAbO4iJKr7H9nx4rEBAAuFk4Q3gPQcNT0wtD"

这些凭据是假凭据;令牌或密码的长度以及字符类型可能因您的脸书应用而异。

如果你正在做一个大项目,在这个项目中,你要在各种平台上集成你的聊天机器人,并且你想让这个项目更容易维护,那么最好使用credentials.yml。如果你是一家企业,并试图建立一个可以在各种平台上工作的机器人,如脸书、Slack、Twitter、Telegram 或你自己的网站,我强烈建议你维护一个credentials.yml。在这种情况下,管理密钥和秘密变得更加容易。

管理应用程序级密钥的一个好方法是将密钥存储为环境变量,并编写代码从操作系统环境本身读取密钥值或任何其他敏感信息。记住,在代码中保存任何类型的键都不是一个好主意。

您也可以创建一个点(。)env 文件,并从该文件中读取密钥,在您的代码存储库中没有对该文件进行跟踪。

为了简单起见,我们将在部署的独立脚本中使用访问密钥和秘密密钥。我们将使它变得简单易懂,这样你首先能够构建机器人,然后你可以尝试扩展它,最重要的是你可以考虑安全级别的问题。

如果您需要在多个平台上部署您的 bot,并希望使用 credentials.yml 来维护不同的凭证,那么您可以通过传递一个额外的参数来使用它。例如,在运行 rasa core 时使用上面名为credentials.yml的凭证文件,可以使用下面的命令。

python -m rasa_core.run -d models/dialogue -u models/nlu/current   --port 5002 --credentials credentials.yml

对于更大的企业级聊天机器人开发来说,知道这一点很好,但是正如所讨论的,我们将在即将到来的示例中直接在我们的脚本中使用凭证。

在脸书部署聊天机器人

在本节中,我们首先将使用 Heroku 在云中部署我们的聊天机器人。Heroku 是一个平台即服务(PaaS ),使开发人员能够完全在云中构建、运行和操作应用程序。Heroku 的好处是,我们可以轻松地让我们的应用程序在 https 上运行,没有太多痛苦。在我们学习和测试聊天机器人的时候,我们不需要去购买 SSL 证书。之所以需要 https,是因为脸书等一些平台不允许开发者使用非 https 的 URL 作为回调 URL。

我们将按照一系列步骤一步一步地成功地将我们的聊天机器人部署为云中的 web 服务。一旦我们成功地做到了这一点,将它与不同的平台如 Slack、Telegram 等整合起来就容易多了。那么,我们开始吧。

在 Heroku 上创建应用程序

让我们开始吧:

在 Heroku 上注册,创建一个应用程序,并将其命名为 actions,因为这将是我们的 actions 服务器应用程序。看看图 5-1 中的截图,你可以给你的动作服务器一个唯一的名字,这个名字应该在 Heroku 上可以找到。一旦该名称可用,您就可以单击 Create app 按钮来创建 actions 服务器应用程序。

如果你的名字不可用,你可以随意给它取任何你想要的名字,但是要尽量取一些有意义的名字。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-1

在 Heroku 上创建名为星座机器人 1212-动作的动作服务器应用程序

在本地系统上设置 Heroku

在本地操作系统上安装 Heroku CLI。参考此链接: https://devcenter.heroku.com/articles/heroku-cli

如果您在 macOS 上,请使用以下命令:

brew install heroku/brew/heroku

在脸书创建和设置应用程序

为了能够在脸书上部署我们的聊天机器人,首先我们需要有脸书应用程序的凭证。为了获得脸书证书,我们需要设置一个脸书应用程序和一个页面,就像我们在第三章中所做的那样。

  1. Go to https://developers.facebook.com/ and create an app if you don’t have one already. We created one for our OnlineEatsBot; now we’ll create one for HoroscopeBot. Enter the details and click on Create App ID. Check Figure 5-2 to see how to enter the display name of your bot and your contact email.

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    图 5-2

    为开发者在脸书上创建应用

  2. Once your app is created, go to Basic under Settings, and click on the Show button under App Secret. This is your fb_secret. Refer Figure 5-3 to see where exactly you will get your fb_secret key.

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    图 5-3

    从脸书的应用程序中获取应用程序秘密

  3. Go to the dashboard for the app and scroll down to “Add a Product.” Click Add Product and then add Messenger (click on SetUp). Check Figure 5-4.

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    图 5-4

    将 Messenger 作为产品添加到脸书应用程序

  4. Under settings for Messenger, when you scroll down to the Token Generation section you will get a link to create a new page for your app. If you don’t have a page already, then create it or choose a page from the “Select a page” dropdown. The “Page Access Token” is your fb_access_token here. Refer Figure 5-5.

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    图 5-5

    为 Facebook Messenger 应用程序生成令牌

    您可以访问以下链接,为您的 bot 项目创建一个全新的页面:

    https://www.facebook.com/pages/creation/

  5. Right after the Token Generation section, under Webhooks, click on “Setup Webhooks.” Refer Figure 5-6.

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    图 5-6

    设置脸书 Webhooks

  6. Next, choose a verify token, which we’ll need to use later. The verify token can be any random string. This will be your fb_verify. Check Figure 5-7 to understand where to add the verification token in facebook app. Now, leave the callback URL section blank as it is. Don’t close the browser; just leave it—we’ll come back here again.

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    图 5-7

    将验证令牌添加到脸书 webhook 设置中

  7. 随身携带fb_verify, fb_secretfb_access_token将你的机器人连接到脸书。

在 Heroku 上创建和部署 Rasa Actions 服务器应用程序

在这一步中,我们将使用我们的 actions Heroku 应用程序作为 Rasa action 的服务器。我们需要两个不同的应用程序,因为我们不能在一个 Heroku 应用程序中运行两个 web 应用程序。转到命令行,按照指示从项目目录中执行以下命令。

  1. 创建一个名为 actions_app and的新文件夹,进入目录:

    mkdir actions_app

    光盘操作 _ 应用程序

  2. 将您的 actions.py 从主项目目录复制到 actions_app 目录。

  3. 用以下内容创建一个 requirements.txt 文件。会告诉 Heroku 应用程序安装软件包及其版本。

    rasa-core-sdk==0.11.0

    请求数==2.18.4

  4. 用以下内容创建一个名为 Procfile 的文件。Procfile 是 Heroku 了解如何启动应用程序的文件。

    web: python -m rasa_core_sdk.endpoint --actions actions --port $PORT
    
    
  5. 运行下面的命令集:

    $ heroku 登录

    去吧,init

    $ heroku git:remote -a

    $ heroku buildpacks:设定 heroku/python

    $ heroku config:设置端口=5055

    去给我。

    $ git commit -am “部署我的机器人”

    $ git 推出 heroku master

在最后一个命令之后,Heroku 将按照 requirements.txt 文件安装我们需要的所有包。如果您的应用程序成功部署,您应该会收到类似以下内容的日志:

remote:
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote:
remote: -----> Compressing...
remote:        Done: 48.3M
remote: -----> Launching...
remote:        Released v4
remote:        https://horoscopebot1212-actions.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/horoscopebot1212-actions.git
 * [new branch]      master -> master

此时,我们将验证我们的应用程序是否正在响应公共请求。为了做到这一点,让我们点击附加了“webhook”的应用程序 url

在我的例子中,应用程序 url 是 https://horoscopebot1212-actions.herokuapp.com/ ,因此我将检查我的操作的服务器是否有响应。

我访问这个网址 https://horoscopebot1212-actions.herokuapp.com/webhook ,不出所料,它返回说方法不允许,如图 5-8 所示,这完全没问题,意味着应用程序按照用户请求正确响应。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-8

正在验证操作服务器端点

创建 Rasa 聊天机器人 API 应用程序

在这一步中,我们将遵循一些类似于我们刚才所做的步骤和命令,但这是一个我们将创建的新应用程序,它将成为我们用于对话管理的主要应用程序。所以,我们开始吧。首先回到主项目目录(即,在占星 _bot 中)并创建一个文件名( Procfile) 并向其中添加以下内容:

web: python -m spacy download en && python facebook.py

为 Facebook Messenger 聊天机器人创建独立脚本

在同一个项目目录下创建一个文件名facebook.py。Python 文件的内容应该如下所示:

from rasa_core.channels.facebook import FacebookInput
from rasa_core.agent import Agent
from rasa_core.interpreter import RasaNLUInterpreter
import os
from rasa_core.utils import EndpointConfig

# load your trained agent
interpreter = RasaNLUInterpreter("models/nlu/default/horoscopebot/")
MODEL_PATH = "models/dialog"
action_endpoint = EndpointConfig(url="https://horoscopebot1212-actions.herokuapp.com/webhook")

agent = Agent.load(MODEL_PATH, interpreter=interpreter)

input_channel = FacebookInput(
        fb_verify="YOUR_FB_VERIFY_TOKEN",
        # you need tell facebook this token, to confirm your URL
        fb_secret="YOUR_FB_SECRET",  # your app secret
        fb_access_token="YOUR_FB_ACCESS_TOKEN"
        # token for the page you subscribed to
)
# set serve_forever=False if you want to keep the server running
s = agent.handle_channels([input_channel], int(os.environ.get('PORT', 5004)), serve_forever=True)

确保用我们在步骤 3 中保留的值替换代码中的fb_verifyfb_secret,fb_access_token变量值。

创建一个新的 requirements.txt 文件,并添加这个项目所需的所有包及其版本。我的 requirements.txt 看起来是这样的;对于您的项目,需求可能会有所不同,但是如果您遵循本章中的同一个 bot 示例,这些需求应该没问题。

rasa-core==0.11.1
rasa-core-sdk==0.11.0
rasa-nlu==0.13.2
gunicorn==19.9.0
requests==2.18.4
spacy==2.0.11
sklearn-crfsuite==0.3.6

在服务器上安装我们的软件包。

现在,让我们像之前一样在 Heroku 中再次创建一个新的应用程序。转到 Heroku 仪表盘,创建一个新的应用程序,如图 5-9 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-9

在 Heroku 中创建对话管理应用程序

创建应用程序后,现在可以转到项目根目录,从项目文件夹中的命令行运行以下命令集:

$ git init
$ heroku git:remote -a <your-heroku-app-name>
$ heroku buildpacks:set heroku/python
$ heroku config:set PORT=5004
$ git add .
$ git commit -am "deploy my bot"
$ git push heroku master

如果您在部署后得到一个运行时错误,它可能如下所示

ValueError:您可能试图用 Python 3 读取用 Python 2 生成的 joblib pickle。joblib 不支持此功能。

如果您使用的是 Python 2.x 版本,这种情况就会发生。Heroku 默认使用 Python 3.x 版本。因此,如果您想使用 Python 2.x,您需要执行以下步骤来解决上述错误。把 Python 3.6 改成 Python-2.7.15。来做这个。

在项目的根应用程序目录下创建一个文件 runtime.txt。打开 runtime.txt,添加下面一行 python-2.7.15,然后保存。Heroku 将只使用前面提到的 Python 版本来构建您的项目。

一旦成功完成部署,您将看到 Heroku 给出的一个 url,上面写着应用程序已部署到。

remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Python app detected
remote: -----> Installing requirements with pip
remote:
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote:
remote: -----> Compressing...
remote:        Done: 254M
remote: -----> Launching...
remote:        Released v17
remote:        https://horoscopebot1212.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/horoscopebot1212.git
   cd3eb1b..c0e081d  master -> master

这个部署需要一点时间,所以尽可能耐心一点——您将会看到奇迹。如果您没有收到任何错误消息,那么您已经成功地将您的聊天机器人部署到 Heroku on cloud,使其能够与 Facebook Messenger 一起工作。我们来验证一下是否有效。

在 Heroku 上验证我们的对话管理应用程序的部署

为了验证我们的对话管理应用是否成功部署在 Heroku 上,我们将执行以下步骤。

  1. 获取 Heroku 给出的 url,并将这个端点附加到它后面:/webhooks/facebook/webhook?hub.verify_token=YOUR_FB_VERIFY_TOKEN&hub.challenge=successfully_verified。确保使用您在脸书用于 webhooks 设置的正确验证令牌。对我来说,完整的网址如下: https://horoscopebot1212.herokuapp.com/webhooks/facebook/webhook?hub.verify_token=my-secret-verify-token&hub.challenge=success

  2. 转到浏览器并粘贴整个 url,如果您的 hub.verify_token 正确,它应该会返回您的 hub.challenge 值。您的完整 url 将如下所示: https://horoscopebot1212.herokuapp.com/webhooks/facebook/webhook?hub.verify_token=YOUR_FB_VERIFY_TOKEN&hub.challenge=successsfully_verified 。如果您收到消息successsfully_verif ied in the browser,那么您的应用程序已成功部署并运行。

将 Webhook 与脸书集成

现在让我们回到我们的脸书应用程序配置。我们将回到我们在步骤 3 中停止的地方,添加我们的回调 URL。确保检查订阅字段中的消息。查看图 5-10 以供参考。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-10

Facebook Messenger webhooks 配置

点击“验证并保存”脸书将使用上述 url 匹配验证令牌,即服务器,或者说我们的应用程序将只响应具有正确验证令牌的请求。一旦验证令牌匹配,我们的应用程序的 webhook 订阅将被激活。

接下来,在页面的 Webhooks 部分下,选择一个页面,您可以将 webhook 订阅到该页面事件。点击订阅(见图 5-11 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-11

为 webhook 订阅脸书页面事件

全部完成!是时候在脸书测试我们的星座机器人了。

部署后验证:脸书聊天机器人

在正常的软件开发场景中,人们构建软件,测试软件,然后部署并进行 PDV(部署后验证)。我们也将做一些类似的事情,在 Facebook Messenger 上成功部署后,我们将为我们的聊天机器人做一个 PDV。这很重要,因为正如您所了解的,聊天机器人有一部分需要连接到动作服务器,以响应用户的一些意图请求。PDV 就像是一个健全性测试,以查看应用程序的健康状况总体良好。如果您正在构建一个使用 10 到 15 个不同供应商的 API 的 bot,那么必须检查您的 bot 访问动作服务器并使用 API 将数据返回给用户的所有场景。

所以,打开你的 messenger 应用程序或电脑浏览器中的脸书,搜索你的机器人开始说话。

数字 5-12.1 到 5-12.3 显示了我的星座机器人做了什么并告诉我。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-12.3

horoscope _ bot facebook

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-12.2

horoscope _ bot facebook

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-12.1

horoscope _ bot facebook

瞧啊。我们的第一个内置聊天机器人应用程序部署在网络上,可以通过 Facebook Messenger 平台访问。所以,请与你的家人、朋友、同事和全世界分享吧。

在 Slack 上部署聊天机器人

在本节中,我们将把我们的聊天机器人部署到 Slack。Slack 是一个团队协作工具,在开发人员和企业中广受欢迎。如果你不是一个社交媒体人,那么你可能需要 Slack 的帮助来使用界面与你的聊天机器人交谈。因此,让我们开始构建我们的第一个内部 Slack 聊天机器人。

为了将我们的星座聊天机器人部署到 slack,我们将编写一个独立的脚本,就像我们在脸书的例子中所做的那样。

为 Slack 聊天机器人创建独立脚本

在项目目录中创建一个名为slack.py的新文件。文件slack.py的内容如下所示:

from rasa_core.channels.slack import SlackInput
from rasa_core.agent import Agent
from rasa_core.interpreter import RasaNLUInterpreter
import os
from rasa_core.utils import EndpointConfig

# load your trained agent
interpreter = RasaNLUInterpreter("models/nlu/default/horoscopebot/")
MODEL_PATH = "models/dialogue"
action_endpoint = EndpointConfig(url="https://horoscopebot1212-actions.herokuapp.com/webhook")

agent = Agent.load(MODEL_PATH, interpreter=interpreter, action_endpoint=action_endpoint)

input_channel = SlackInput(
            slack_token="YOUR_SLACK_TOKEN",
            # this is the `bot_user_o_auth_access_token`
            slack_channel="YOUR_SLACK_CHANNEL"
            # the name of your channel to which the bot posts (optional)
    )
# set serve_forever=False if you want to keep the server running
s = agent.handle_channels([input_channel],  int(os.environ.get('PORT', 5004)), serve_forever=True)

facebook.pyslack.py的主要区别在于我们创建的input_channel对象。Rasa 提供了各种内置通道,如脸书、Slack、Mattermost、Telegram、Twilio、RocketChat 和 Microsoft Bot Framework,我们可以直接使用这些通道轻松地在各种通道上部署同一个 Bot。

如你所见,我们需要添加一个slack_tokenslack_channel到我们的脚本中。由于我们必须在脸书的开发者平台上创建一个脸书应用程序,同样我们也必须在 Slack 上创建一个应用程序。

让我们一步一步来:

  1. Got to this url https://api.slack.com/slack-apps and click on the button “Create App.” Refer Figure 5-13.

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    图 5-13

    在 Slack 中创建应用程序

  2. The next step is to create a Bot User. To create a bot user, click on Bots under “Add features and functionality.” In the new page you will get an option to “Add a Bot User.”. Check Figure 5-14 to see how to add details and add a bot user.

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    图 5-14

    在 Slack 上给你的机器人命名

  3. 根据您正在构建的聊天机器人填写详细信息。显示名称可以是您喜欢的任何名称;默认用户名必须是唯一的;你可以顺其自然。切换最后一个选项“总是将我的机器人显示为在线”就是总是将机器人显示为用户可用。这就是聊天机器人的意义所在——人类不可能全天候可用,但聊天机器人可以,所以我们打开了这个功能。确保您点击保存更改。

  4. Go back to the “Basic Information” tab. Click “Install your app to your workspace.” The app will ask to confirm the identity. Please authorize it like you do for any other app. Check Figure 5-15 which shows how the authorization would look like.

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    图 5-15

    授权您的 Slack 应用程序

你会在“添加特性和功能”下找到带有绿色勾号的“机器人和权限”选项卡,这意味着我们的机器人和应用程序集成良好。这是一个迹象,表明我们目前做得很好。

  1. 转到 OAuth & Permissions 部分,复制 Bot 用户 OAuth 访问令牌。

  2. 将复制的令牌粘贴到我们的 Python 脚本slack.py中。给一个你喜欢的频道名。如果你想让你的机器人发布到一个频道,那么你可以给一个频道名称。我已经给了@slackbot。如果不设置slack_channel关键字参数,消息将被传递回发送它们的用户。

编辑您的个人资料

在这一步中,我们不会创建任何新的 Procfile,因为我们使用的是相同的代码库。我们将对现有的 Procfile 进行如下修改,使其适用于我们的 slack bot。因此,我们只需将脚本文件的名称从facebook.py更改为slack.py,这样 Heroku 就可以使用给定的文件来启动应用程序。

web: python -m spacy download en && python slack.py

Slack Bot 在 Heroku 的最终部署

为了最终将我们的新 Slack bot 部署到 Heroku,我们将从命令行运行一组类似的 Heroku 命令来部署我们的应用程序。

$ git init
$ heroku git:remote -a <your-heroku-app-name>
$ git add .
$ git commit -am "deploy my bot"
$ git push heroku master

订阅时差事件

现在,点击“事件订阅选项卡,通过切换屏幕上的按钮激活事件订阅功能。为 Slack 输入 Heroku 应用程序的 webhook url。

如果您的应用程序使用修改后的 Procfile 正确地部署在 Heroku 上,那么您的 Slack 的 webhook url 将是app_url + /webhooks/slack/webhook,如下所示:

https://horoscopebot1212.herokuapp.com/webhooks/slack/webhook

在 Slack 向上述 URL 发送一个带有挑战参数的 HTTP POST 请求后,您将看到一个经过验证的勾号,我们的端点必须用挑战值进行响应。这类似于我们在构建脸书聊天机器人的秘密令牌时讨论的内容。查看图 5-16 了解更多信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-16

为您的机器人激活事件订阅

订阅机器人事件

在这一步中,我们只需向下滚动事件订阅页面,转到“订阅 Bot 事件”部分,然后单击“添加 Bot 用户事件”参考图 5-17 了解导航位置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-17

订阅机器人事件

订阅机器人事件只不过是声明机器人必须回复的事件。这里我们只演示两种情况:第一,当有人提到机器人的名字时(即app _ reference),第二,当有人直接向机器人发送消息时(即 message.im )。

现在,单击保存更改,您就完成了。是时候测试我们的 Slack 聊天机器人了,就像我们在上一节为脸书做的那样。

部署后验证:Slack Bot

让我们转到我们用来创建应用程序的工作区,在左侧的应用程序下,您会找到您的机器人。试着和它说话,看看它做得好不好。我的机器人做得很好,给了我今天的星座运势,读起来很不错。如果你到现在还不能来,那么检查图 5-18 看看我的 Slack 机器人如何响应。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-18

测试 Slack 聊天机器人

所以,伙计们,我们完成了我们的松弛机器人。在下一节中,我们将把我们的机器人部署到我们自己的 UI 中。构建你自己的 UI 可能需要一些前端技能,但是不要担心——我们对此有计划。

自己部署聊天机器人

这个标题听起来很酷,不是吗?到目前为止,我们一直使用脸书或 Slack 在网上部署聊天机器人,或者我们可以使用 Telegram 等。,但现在是我们自己部署一切的时候了—我们自己的服务器、我们自己的数据,以及使用我们自己的用户界面的我们自己的配置模型。如果你是一个组织或一个崭露头角的企业家,你可能会在脸书、推特或 Slack 上有你的机器人创意,但你总是希望它也能在你自己的网站上工作,这样你的品牌价值就会随着用户群的增加而越来越大。

在这一节中,我们将使用我们迄今为止的所有辛勤工作,最终构建一个聊天机器人,它具有完整的功能,并且独立于任何第三方 API 调用或工具,如 Dialogflow、wit.ai、Watson 等。你将拥有世界上所有的控制权,以你想要的方式调整你的聊天机器人,最重要的是,以你想要的方式轻松地扩展到数百万人。

那么,我们开始吧。

第一步是确保我们在前面章节中部署的两个应用程序已经启动并运行。您已经知道如何进行基本的健全性检查。要在任何平台上使用 chatbot 模型,您始终需要运行您的对话管理器应用程序和操作应用程序。

现在,在我们创建 facebook.py 和 slack.py 的同一个项目目录中,我们将创建一个名为myown_chatbot.py的新文件。之前创建的脚本,如facebook.pyslack.py,是我们创建的独立脚本,这样我们就可以在命令中告诉 Heroku 运行哪个脚本来启动应用程序。现在,我们正在创建自己的脚本,它将通过 REST APIs 公开用户和聊天机器人之间的请求/响应。

部署你自己的聊天机器人有两个部分。在第一部分中,我们将编写一个脚本来创建一个定制通道,并将其作为 REST APIs 进行部署。在第二部分,我们需要自己的用户界面,因为到目前为止,我们一直在使用脸书和 Slack 的聊天屏幕进行对话。

为您自己的聊天机器人频道编写脚本

这个脚本类似于我们到目前为止所学习和编写的内容,但是它需要我们覆盖 rasa_core 的一些现有方法,以便我们可以为 API 身份验证定义自己的规则。我在下面的代码中完成了令牌验证的基本字符串检查。对于生产级系统,这是不建议的,所以如果您正在为更大的系统构建聊天机器人,请确保小心编写该部分。

创建一个名为 myown_chatbot.py 的新文件,并向其中添加以下内容:

import os

from rasa_core.channels.rasa_chat import RasaChatInput
from rasa_core.agent import Agent
from rasa_core.interpreter import RasaNLUInterpreter
from rasa_core.utils import EndpointConfig

# load your trained agent
interpreter = RasaNLUInterpreter("models/nlu/default/horoscopebot/")
MODEL_PATH = "models/dialogue"
action_endpoint = EndpointConfig(url="https://horoscopebot1212-actions.herokuapp.com/webhook")

agent = Agent.load(MODEL_PATH, interpreter=interpreter, action_endpoint=action_endpoint)

class MyNewInput(RasaChatInput):
    def _check_token(self, token):
        if token == 'mysecret':
            return {'username': 1234}
        else:
            print("Failed to check token: {}.".format(token))
            return None

input_channel = MyNewInput(url='https://horoscopebot1212.herokuapp.com')
# set serve_forever=False if you want to keep the server running
s = agent.handle_channels([input_channel],  int(os.environ.get('PORT', 5004)), serve_forever=True)

这里需要注意几点:

  • rasa_core中的_check_token方法基本看起来如下,它进行 API 调用来获取用户对象。这主要完成用户级认证/验证的工作。在前面被覆盖的方法中,我们保持了它的简单性,以使它能够工作并理解它的用法。

    def _check_token(self, token):
            url = "{}/users/me".format(self.base_url)
            headers = {"Authorization": token}
            logger.debug("Requesting user information from auth server {}."
                         "".format(url))
            result = requests.get(url,
                                  headers=headers,
                                  timeout=DEFAULT_REQUEST_TIMEOUT)
    
            if result.status_code == 200:
                return result.json()
            else:
                logger.info("Failed to check token: {}. "
                            "Content: {}".format(token, request.data))
                return None
    
    
  • 使用 Rasa 自己的_check_token方法可能需要您编写一个 API 或 web 服务来接受请求并以指定的方式返回响应。

  • 请确保将操作的服务器端点更改为您自己的 url。

  • 请记住,代码中的mysecret字符串将在以后用于进行 API 调用。

编写概要文件并部署到

到目前为止,您一定非常熟悉为 Heroku 部署创建 Procfiles。我们将再次使用现有的 Procfile,并在那里进行修改,以将基于 API 的 chatbot 部署到 web 上。在创建现有 Procfile 的备份后,可以随意创建新的 proc file。

以下是我的 Procfile 内容的样子:

web: python -m spacy download en && python myown_chatbot.py

完成后,只需执行我们在部署 Facebook Messenger 和 Slack Bot 时已经学习过的下一组命令。

$ git init
$ heroku git:remote -a <your-heroku-app-name>
$ git add .
$ git commit -am "deploy my bot"
$ git push heroku master

在最后一个命令之后,你将从 Heroku 获得一些日志,这些日志与部署版本、对应用程序所做的更改等相关。

验证您的聊天机器人 API

在获得成功部署的消息后,让我们测试一下我们的 chatbot APIs 是否工作正常。为了快速进行健全性测试,请点击以下 url:

<your-basic-app-url>+/webhooks/rasa/

举例:

https://horoscopebot1212.herokuapp.com/webhooks/rasa/

在浏览器中打开这个 url 应该会得到如下的响应。如果它给你一个“ok”的状态,那么你就可以开始了——放松,坐下来,调试。

{"status":"ok"}

有时,仅仅是这种验证可能还不够,所以让我们通过尝试检查聊天机器人是否正在识别意图并基于此给出响应来测试它。

我将使用 POSTMAN 工具(POSTMAN 是一个非常好的基于 GUI 的工具来进行 API 测试)。你可以使用任何你觉得舒服的工具。我们只是要测试我们的聊天机器人应该理解和响应的意图之一。我测试了问候的意图,它工作得非常好。机器人返回了预期的响应,如图 5-19 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-19

在 POSTMAN 中测试聊天机器人 API

创建聊天机器人用户界面

正如我们之前讨论的,作为第二步的一部分,我们需要有自己的 UI,为聊天机器人和用户之间的对话提供一个用户友好的场所。如果你是一个前端开发人员,或者你的团队中有一个前端开发人员,你可以很容易地给出我们构建到这一点的 chatbot APIs,前端团队应该可以很容易地将这与他们的 chatbot UI 集成。他们可以利用常规的 HTTP 调用来使用这些 API。Websockets 是一种更好的聊天机器人方式,但这不在本书的解释范围之内。

如果你不熟悉 HTML/CSS/Javascript 之类的前端技术,那么我确实推荐 Pro HTML5 搭配 CSS、Javascript、多媒体 (Apress,2017)。

为了我们的读者——或者我应该说是学习者——的方便,我们创建了一个聊天机器人和用户对话所需的基本 UI。你可以在 github 或 Apress 的网站上找到完整的工作代码。我将告诉你使它为你的机器人工作所需要的配置。

一旦你下载了本章的代码,你会在主文件夹中找到一个名为my_own_chatbot的文件夹。进入这个文件夹,进入 assets - > js - > script.js 文件。

将下面一行 javascript 代码更改为您自己的端点 url。如果你的应用程序名称不同,那么下面的网址将是不同的。使用您自己的 url 和 javascript 代码中的标记,如下所示。

var baseUrl = "https://horoscopebot1212.herokuapp.com/webhooks/rasa/webhook?token=YOUR-SECRET";

保存文件并在浏览器中打开index.html文件,你可以很容易地看到一个聊天机器人 UI 已经准备好了。但是从本地提供的简单 HTML 进行 API 调用会引发一个 CORS 问题。因此,为了避免这种情况,我们将对现有的myown_chatbot.py稍作修改,以服务于 Heroku 应用本身的 HTML。

将您的myown_chatbot.py更改为下面的,然后我们将讨论所做的更改。

import os

from rasa_core.channels.rasa_chat import RasaChatInput
from rasa_core.channels.channel import CollectingOutputChannel, UserMessage
from rasa_core.agent import Agent
from rasa_core.interpreter import RasaNLUInterpreter
from rasa_core.utils import EndpointConfig
from rasa_core import utils

from flask import render_template, Blueprint, jsonify, request

# load your trained agent
interpreter = RasaNLUInterpreter("models/nlu/default/horoscopebot/")
MODEL_PATH = "models/dialogue"
action_endpoint = EndpointConfig(url="https://horoscopebot1212-actions.herokuapp.com/webhook")

agent = Agent.load(MODEL_PATH, interpreter=interpreter, action_endpoint=action_endpoint)

class MyNewInput(RasaChatInput):
    @classmethod
    def name(cls):
        return "rasa"

    def _check_token(self, token):
        if token == 'secret':
            return {'username': 1234}
        else:
            print("Failed to check token: {}.".format(token))
            return None

    def blueprint(self, on_new_message):
        templates_folder = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'myown_chatbot')

        custom_webhook = Blueprint('custom_webhook', __name__, template_folder = templates_folder)

        @custom_webhook.route("/", methods=['GET'])
        def health():
            return jsonify({"status": "ok"})
        @custom_webhook.route("/chat", methods=['GET'])
        def chat():
            return render_template('index.html')

        @custom_webhook.route("/webhook", methods=['POST'])
        def receive():
            sender_id = self._extract_sender(request)
            text = self._extract_message(request)
            should_use_stream = utils.bool_arg("stream", default=False)

            if should_use_stream:
                return Response(
                        self.stream_response(on_new_message, text, sender_id),
                        content_type='text/event-stream')
            else:
                collector = CollectingOutputChannel()
                on_new_message(UserMessage(text, collector, sender_id))
                return jsonify(collector.messages)

        return custom_webhook

input_channel = MyNewInput(url='https://horoscopebot1212.herokuapp.com')
# set serve_forever=False if you want to keep the server running
s = agent.handle_channels([input_channel],  int(os.environ.get('PORT', 5004)), serve_forever=True)

以下是我们所做的更改:

  • 在我们的类中覆盖现有的nameblueprint方法,这允许我们创建自己的端点,也给了我们定义它应该如何行为的自由。

  • 我们创建了一个新的端点/聊天,并提供了 index.html 文件,这只是聊天机器人的用户界面。这将是我们聊天机器人的主页链接。

  • 我们必须根据需要导入一些必要的类和方法,比如utils, CollectingOutputChannelUserMessage来使事情正常运行。

保存文件,并使用以下命令将更改再次部署到我们的 Heroku 应用程序:

$ git add .
$ git commit -am "deploy my bot"
$ git push heroku master

一旦部署成功,瞧!我们已经准备好与全世界分享我们的机器人,它使用两个 Heroku 应用程序工作:一个用于对话管理,一个用于动作。

在浏览器中打开以下 url,我们将在其中看到我们的自定义聊天机器人 UI:

https://horoscopebot1212.herokuapp.com/webhooks/rasa/chat

图 5-20.1 和 5-20.2 显示了我自己的聊天机器人在对话过程中的样子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-20.2

在你自己的网站上定制聊天机器人

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-20.1

在你自己的网站上定制聊天机器人

使用 Heroku 的自定义域名功能,人们可以轻松地将同一个应用程序指向自己网站的名称,如www.example.com。当你觉得你的聊天机器人足够好,可以向全世界公开,无论是盈利还是非盈利,就这么做吧。

所以,这就是所有的乡亲!这就是使用自然语言处理和机器学习用 Python 构建聊天机器人的方式。我希望这一章和前几章对你有所帮助,你可以学习学习和构建聊天机器人的实用方法。

摘要

在本章中,我们学习了如何使用 Heroku 将我们自己的应用程序部署到我们自己的服务器上。我们学会了如何使用脸书的开发平台将我们的聊天机器人与脸书集成。我们还学习了为 Slack 应用程序创建自定义聊天机器人,并对其进行了测试。最后,正如在第三章末尾所承诺的,去除所有对任何社交媒体平台的依赖,我们创建了自己的 UI,并在 Heroku 上部署和测试了它。我们看到它非常有效——在训练它的时候它就起作用了。因为我们有了一个基本的模型,现在你可以处理 chatbot 不能很好工作的情况。确定是否是与数据或培训、操作服务器或自定义代码处理相关的问题。一旦您找到了根本原因,修复它,再次部署,并检查 chatbot 是否有所改进。我们从小做起,打造大软件。

我期待着收到你的来信,并且很想知道在看完这本书之后你制作了什么样的聊天机器人。如果您在任何概念、代码执行或部署方面遇到困难,我很乐意随时为您提供帮助。

谢谢,干杯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值