使用Oscova在C#中构建聊天机器人-人工智能与机器学习

恬静的小魔龙 2020-12-11 16:05:44 8359

导言

接下来我们将使用Oscova和Oryzer FBP平台构建一个设备上的离线聊天机器人,以了解离线聊天机器人开发标准背后的概念。

在这篇文章中,我们将创建一个带有数据表的聊天机器人,为此,我将使用免费可用的工具,特别是一个基于流的免费编程平台Oryzer Studio,并将尝试一步一步地让大家了解这些概念。在文章的末尾,我们可以成功地创建一个带有数据表的聊天机器人,并且在Oryzer中测试它,然后将它导入到一个控制台应用程序中。

创建一个带有数据表的机器人需要一个工具,那就是基于流的免费编程平台Oryzer Studio,并将尝试一步一步地让大家了解这些概念。

背景

在深入研究之前,我强烈建议观众看一看我上一篇文章,其中我创建了一个用于与数据库交互的聊天机器人。本文重点介绍了本文中使用的许多基本概念。

本文非常全面,介绍了聊天机器人开发、WPF GUI、设置数据库实用程序类和将聊天机器人的操作绑定到数据库的基础知识。

开始之前

为了项目的开发和运行,您将必须具备以下技能。

  • 了解基于流的编程结构(组件/节点、端口和连接)
  • 具备在VisualStudio中工作的知识
  • C#/.NET编程的基本知识
  • 博特建筑基础知识

对于本文,您只需要以下内容:

术语

我可以在本文的整个过程中使用以下术语及其缩写(缩写),为了更好地理解,我建议您熟悉它。

  • 知识库(KB):机器人可以参与的对话集合。
  • 组件/节点:这些术语在整个文章中可能会互换使用。
  • 基于流的编程(FBP):一种通过连接功能组件来构建逻辑的编程结构.
  • 工作区:类似于图形画布,您的节点将被放置并与其他节点连接。

我们开始吧

首先你要从上面提到的链接下载OryzerStudio,我们首先创建一个对话框。

为了创建这个聊天机器人,我们将在会话流程中从用户那里收集以下信息:

  1. 预定的日期
  2. 时间安排(早餐、午餐或晚餐)
  3. 预订桌子的人数
  4. 用户号码以确认预订

    对话(问候对话)

对话是意图的集合,更像是对话的话题。例如,如果你说“嘿”,机器人不得不说“嗨,你好”,把它们分组到一个名为Greetings的对话框是将相似意图分组到唯一标识符下的一种很好的方法。

若要创建对话框,请执行以下操作:

  • 打开OryzerStudio。
  • 在右侧的节点资源管理器Node Explorer中,展开Oscova类别。
  • 选择Dialog节点并将其拖到工作区。
  • 如果您意外地拖动了一个错误的节点,简单地按下Delete它将被移除。

您刚刚拖动的是一个节点,并将其拖到您所拖动的位置,称为工作区(Workspace)。

Node在Oryzer Studio中,是一个执行专门任务的功能单元。节点包括:

  • 输入端口-左边的蓝色框
  • 输出端口-右边的蓝色框

输入端口通常存储某些允许节点执行其专用任务的变量值。

输出端口另一方面,是节点在完成任务时返回的值。在某些情况下,输出端口也可以是节点本身。

因此,我们现在已经创建了一个Dialog节点,它将帮助我们启动与用户的对话,并为保留表提供第一组选项。

您可以看到Dialog节点有两个输入和输出端口:

  • 输入端口-Name, Intent Alias, DomainIntents
  • 输出端口-(self)-将节点本身作为输出返回

我们称这个对话框为greet_dialog我们会把两个意图连接起来。将对话框命名为Name端口,只需键入greet_dialog.

按下此工作区Ctrl+S和命名文件Table-reservation-bot.west.

意图(问候意向)

意图是将用户查询绑定到响应,或者是在给定意图的表达式(用户查询示例)匹配时的操作。为了开始我们的谈话,我们将添加一个名为greet_intent指向我们的greet_dialog.

我们的greet_intent会问候用户,自我介绍一下,并收集我们进行预订所需的初始信息集。

要向对话框添加意图,我们将执行以下操作:

  • 拖曳Intent节点资源管理器中的节点(右侧)。
  • 单击并从输出中拖动(self)Intent节点到Intents对话框节点的输入端口。

我们现在已经创建了一个对话框,并将其连接到其中。

表达式

在机器人发展领域,表达式是一组用户查询示例。\这可以帮助机器人引擎训练自己找到相似性检测的模式。您提供的表达式示例越多,机器人在检测类似的用户查询方面就越好。

表达式将用户查询映射到意图,然后将其映射到响应或操作。为了简洁起见,我们不会在这里添加太多的表达式,而只是其中的几个来澄清这个概念。

我们将继续添加4个表达式示例(记住,这些是用户查询的示例)。

  • Hi there
  • Hello there
  • Hey can I book a table?
  • I would Iike to book a table please.

现在,让我们将表达式节点添加到工作区,并将它们连接到上述意图节点:

  • 拖曳Expression节点资源管理器中的节点。
  • Value端口的文本框,为每个新表达式节点输入上述表达式示例。
  • 的输出端口连接。Expression节点到greet_intent如下图所示:

既然我们已经向聊天机器人系统提供了一些用户查询的示例,那么当匹配一个示例查询(表达式)时,我们必须指定聊天机器人的响应是什么。

响应

响应是当用户查询匹配与意图关联的表达式时调用的动作的一部分。我们已经添加了4个表达式,如果用户查询与我们添加的表达式匹配,那么现在让我们添加一个响应。

我们的反应如下:

  • 发送一条文本信息,要求用户提供一些信息。
  • 向用户提供选项,以便迅速为聊天机器人的消息选择后续响应。
  • 设置上下文来创建一个流(我们将在下一节中了解它)

所以现在,让我们拖动一个Response节点并将其连接到greet_intent如下所示:

由于我们的第一个任务是添加文本消息,所以我们将拖动另一个名为Input Text节点并将其连接到Text端口的Response节点。

文本节点的内容将是:

正文部分

Hi there! I am here to help you book a table.
So let's begin by letting me know for when would you like to book a table?

我们还将添加两个要显示给用户的输入选项,方法是在Response节点

Today|Tomorrow

除了询问用户何时需要预订之外,我们还需要准备另一个意图,以准备接受用户对我们的开场白所提供的答案。

我们会继续下去Context Add节点,并将其连接到响应节点。因此,当调用响应时,将添加相关上下文。

Context上下文环境(表-日期-CON)

聊天机器人开发中的上下文通常是添加到称为聊天会话若要创建分层会话流,请执行以下操作。这些上下文字符串的存在或不存在控制着意图的激活。

如下图所示,我拖掉了一个Context Add节点的输出端口,并将其连接到Response节点。每当意图生成响应时,该节点将被执行,并得到一个上下文项。table-date-con将被添加到会话中,并将存在于接下来的2个用户查询中。因为我们已经选择了LifespanValue2.

意图(表日期意向)

如果你还记得我们greet_intent的响应,我们已经询问了用户何时想要保留表。好吧,如果用户指定了一个日期,比如今天明天,我们需要有一个捕捉的意图。

这个意图有几个任务要完成:

  • 捕获用户指定的日期。
  • 将用户指定的日期值存储在名为用户变量.
  • 提示用户指定用餐类型/时间(早餐、午餐或晚餐)
  • 创建另一个名为table-time-con帮助实现跟踪意图。

既然您已经知道了如何拖动、删除和连接节点,我就不需要冗余地重新解释这样做的步骤了。

语境与表达

让我们继续,并指定此意图要求上下文术语table-date-con存在于用户聊天会话中,然后我们将继续指定一个表达式,以确保它只从用户输入中捕获日期值。

在上面的截图中,您可以看到我已经指定了一个具有名称的上下文table-date-con,如果您还记得这个上下文是由greet_intent.

现在,通过在这个意图中指定上下文名称,我们告诉聊天机器人系统匹配该意图的表达式当且仅当上下文table-date-con存在于用户聊天会话中。

表达@sys.date是与日期匹配的预置系统实体。

反应

这一意图的反应有三部分:

  1. 将日期值存储到某个用户变量(我们将在响应中使用该值)。
  2. 创建新的后续上下文table-time-con这样下一个意图就能捕捉到食物类型。
  3. 提示用户指定用餐类型。

为此:

  • 拖曳Response节点并将其连接到意图。

首先,我们将继续存储用户指定的日期部分。注意,只有当用户指定日期值时,才会调用此意图。greet_intent

为此:

  • 拖曳Entity Get节点并将实体类型指定为sys.date
  • 然后拖动Variable Set节点并连接ValueEntity Get节点到Variable Value的输入端口Variable Set节点。
  • 将变量名指定为table-date

确保在Entity Get节点的Get属性,您已经设置了Value作为get类型,并在Variable Set节点选择User作为目标。

瞧!我们现在准备好了。每当调用此响应节点时,一个名为table-date将保存在用户变量.

语境和语境反应

我们将不得不为下一个意图添加一个新的上下文,以捕获餐的类型或时间。所以让我们继续拖动并连接一个Context Add节点到call输出端口Response node.

我们的上下文是table-time-con如下图所示:

除了为下一个后续意图添加上下文之外,我们还将提供一个文本响应,它将显示如下消息:

Alright so the table's set for Lunch and for which meal would you like to come?(如果用户指定午饭作为用餐类型/时间)

注意我们用了$sys.user.table-date在我们的答复中。这是一个特殊的参数,它告诉聊天机器人系统用存储的用户变量替换该值。table-date.

如果由于某种原因,在聊天机器人的变量集合中存储了一个变量,那么参数将是$sys.聊天机器人.table-date.

实体创造

在上面的意图中,我们给出了选择Breakfast|Lunch|Dinner给用户吃饭的时间。当用户输入上述任何一个值时,我们将需要捕获它。

这里的一个简单的解决方法就是简单地将它们转换为已知的实体类型。为了创建一个类型的实体,例如@meal-type,我们将遵循以下步骤:

  • 拖放Entity Recognizer节点。
  • 连接(self)此节点的输出端口到输入端。RecognizerOscova 聊天机器人节点。
  • 将实体类型指定为meal-typeEntity Type端口编辑器。

接下来,让我们通过以下方式为这个实体Recognizer节点指定3个条目值:

  • 拖动3个入口节点。
  • 指定Breakfast, LunchDinner作为它们的入口值。
  • 连接他们(self)输出端口到输入端EntriesEntry Recognizer节点。

让我们来测试一下机器人

到目前一切尚好。现在我们的两个意图已经准备好了,我们可以继续尝试与机器人交互。为了测试聊天机器人,我们首先必须连接Dialog节点到Oscova Bot节点,然后将其连接到Oscova Bot 节点到Oscova Test Panel测试面板节点。

连接您的greet_dialog节点到Oscova 聊天机器人节点:

  • 只需拖动Oscova Bot 节点旁边的对话节点。
  • 连接(self)对话框节点的输出端口到Dialogs输入端口Oscova Bot节点。

这个Oscova Bot节点是表示整个聊天机器人的实际节点。此节点有两个输入端口,可以将其他几个节点类型连接到该端口。

现在,让我们把这个节点连接到Oscova Test Panel节点来测试我们的机器人的响应。

在你连接好之后Oscova Bot`和**Oscova Test Panel** `节点:

  • 点击Train Bot开始测试。
  • hi there应该是我们收到的第一条消息。
  • 键入Today,那么第二个意图的反应应该显示出来。

    继续前进

现在您已经(很可能)看到并测试了您的机器人的响应,在下一阶段,我们将迁移到其他重要的意图,这将捕获用户的一些附加信息。

所以我们采取了日期现在已经要求用户向我们提供饭食时间安排。我们接下来的两个意图将很简单。他们手头的任务是:

  • 捕捉我们之前的意图所要求的用餐时间。
  • 请求用户提供表应保留的人数。

在这两个意图之后,将有我们的最终确认意图,将显示我们的关闭消息给用户。

为了保持事物的可理解性,我们将限制在变量中存储任何进一步的信息,因为您已经知道如何这样做了。因此,增加这样一个额外的层将无助于我们的学习过程。

对话框(TABLE_Config_DIALOG)

从这里开始就更简单了。再次,让我们添加一个Dialog节点到工作区,连接其(self)输出端口到Oscova Bot节点的Dialogs输入端口。

Name端口编辑器,指定table_config_dialog作为名字。

意图(表时间意图)

添加一个新的Intent节点,指定意图table_time_intent。这个意图将捕获我们之前的意图所要求的膳食类型(早餐、午餐或晚餐),并将提示用户指定预定餐桌的人数。

  • 丢下Intent节点
  • Name节点的端口编辑器,指定table_time_intent作为名字
  • 将其连接到table_config_dialog对话框节点。

因为之前的意图添加了一个table-time-con上下文项目。我们将指定此意图要求该上下文存在,同时,我们还将添加一个Expression节点,该节点将捕获类型的实体。@meal-type.

所以,继续:

  • 拖放aContext节点并连接其(self)输出端口到意图节点。
  • 将上下文名称指定为table-time-con.
  • 拖放表达式节点并指定@meal-typeValue端口编辑器。这是因为我们希望在用户指定早餐、午餐或晚餐作为响应时调用此意图。

接下来,让我们简单地为我们的下一个后续意图添加一个响应和一个上下文项,它将捕获要保留表的人数。

  • 添加一个新的Response节点,将其连接到意图。
  • 添加一个新的Context Add节点,指定table-num-con作为上下文名称
  • 添加一个Input Text节点,指定Perfect! How many people shall I book the table for?作为文本值。
  • 连接Input Text节点到Response节点。

意图

现在,为了这个目的,让我们捕获用户对我们的问题的响应,这个问题要求用户提供表必须保留的人数。

  • 添加一个Intent节点,指定意图table_num_intent.
  • 加一个Context节点和Expression节点并将其连接到意图节点的输入端口。
  • table-num-con作为上下文名称。
  • @sys.number作为表达式节点的值。

我想,到现在为止,我们一直在干预的所有连接和节点背后都有要点。

让我们添加一个响应节点,存储人数的值,并为我们的最终确认意图设置上下文。

  • 添加一个新的Response节点并将其连接到意图节点。
  • 放下一个新的Context Add节点,指定table-phone-con作为上下文名称,并将其连接到响应节点。
  • 放下一个新的Entity GetVariable Set节点。将它们配置为存储@sys.number实体。
  • 添加一个Input Text节点的响应文本。太棒了!我会把桌子设为$sys.number People。我们已准备好了。请您告诉我您的电话号码好吗?这样我就可以确认您的预订了。

响应包含$sys.number参数,该参数将替换为用户为表保留的人数指定的值。

对话框(确认_对话框)-最后!

我们与用户的最后对话是显示有关预订的确认消息。以下是我们的confirm_dialog设置。

  • 添加一个新的Intent节点并命名它。confirm_intent.
  • 我们添加一个Context若要指定应该存在的上下文术语,请执行以下操作。
  • 我们使用@sys.number预置实体类型。
  • 最后给出一个文本回应,上面写着非常感谢!您对$sys.user.table-日期$sys.user.table-num的预订现在已经确认。您很快就会在您的手机号码$sys.number上收到通知。我们使用两个参数,$sys.user.table-date$sys.user.table-num它将被用户指定的日期和表计数替换。

让我们来测试一下

继续Train 聊天机器人Oscova Test Panel`节点并跟踪会话流。如果一切顺利,那么您与机器人的对话最终应该看起来如下所示:

导入控制台应用程序

既然我们的聊天机器人知识库(KB)已经准备好了,为什么不检查一下如何将这样的知识库导入应用程序呢?如果我们只是在Oryzer中创建KB并将它留在那里,显然是没有任何意义的。

创建C#控制台项目

在您的计算机中启动VisualStudio 2019或更高版本。

  • 启动VisualStudio 2019。
  • 选择控制台应用程序(.NET Core)作为你的项目类型。

  • 你可以给这个项目起任何名字。我选择了TableReservationBot作为项目名称。

导入NuGet包

到目前为止,我们开发的知识库是为一个名为聊天机器人的开发平台而开发的。Oscova它是Syn.聊天机器人可在NuGet上找到的框架。

要导入NuGet包:

  • 打开项目
  • 点击Tools,选择NuGet Package Manager 选择Package Manager Console
  • 类型Install-Package Syn.聊天机器人若要安装所需的包及其引用,请执行以下操作。

替换Program.cs类文件具有以下内容:

using System;
using Syn.Bot.Oscova;

namespace TableReservationBot
{
    class Program
    {
        static void Main(string[] args)
        {
            var bot = new OscovaBot();
            bot.ImportWorkspace(@"C:\Users\Workstation\Documents\table-reservation-bot.west");
            bot.Trainer.StartTraining();

            bot.MainUser.ResponseReceived += (sender, eventArgs) =>
            {
                Console.WriteLine($"Bot: {eventArgs.Response.Text}");
            };

            while (true)
            {
                var request = Console.ReadLine();
                var evaluationResult = bot.Evaluate(request);
                evaluationResult.Invoke();
            }
        }
    }
}

在上面的代码中,我们创建了一个Oscova聊天机器人类,称为ImportWorskspace方法,并在我们基于工作区的知识库文件的位置传递。

在接下来的行中,我们只是简单地接收用户输入,处理它并显示机器人的输出消息。

构建并运行项目,并在第一个输入中键入Hi让谈话顺其自然。

你就在这里!我们已经成功地创建了一个表预订机器人,并在Oryzer中进行了测试,甚至将其导入到一个控制台应用程序中。啊,这是多么漫长的旅程啊!)

总结

好的!所以我个人认为我在这里几乎没有触及到深层次的代码。与我以前的以代码为中心的文章相比,这篇文章采取了不同的做法。我没有使用任何后端C#代码,因为我想完全停留在基于流的编程结构上,这与我上一篇文章不同。

在现实世界的逻辑中,确实会有后端代码对机器人收集的信息进行处理。我使用节点创建的任何逻辑也可以使用纯C#后端代码创建。

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 95 7 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
恬静的小魔龙
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区