使用Oscova的数据库的聊天机器人

导言

使用Oscova(一个bot开发框架)创建一个SQL数据库的自然语言界面。

Oscova和Siml的区别在于,与Siml不同的是,Oscova不依赖于严格的模式。相反,它依赖于用户输入和保存的表达式之间的语义和语法。Oscova使开发人员能够创建利用对话、指令、文本和名词识别等概念和功能的机器人,以及不需要连接到任何在线API的额外优势。

话虽如此,如果您仍然倾向于编写严格的用户输入模式,那么Siml可能是你更好的选择

在本文中,我们将利用Oscova创建一个我们与机器人对话的employees数据库。

前提条件

C#编程知识 使用SQL进行数据库管理。 WPF应用程序和XAML的基本思想。

架构

Oscova的核心部分主要包括以下几个方面:

对话框:用以发送指令、对话、文本的输入框 意图:机器人在以下情况下执行/调用的操作:发送指令。 表达式:类似于用户输入的模板模式或示例。

实现步骤

首先,我们将使用所有必需的GUI元素创建一个WPF应用程序项目。 将基本库导入到我们的项目中。 创建一个用于与数据库交互的数据库实用类。 将GUI与机器人事件连接。 为几个数据库列创建实体识别器。 创建对话框和意图 测试我们的机器人。

如果发现任何概念难以掌握,只需打开项目,并参考代码。一旦浏览了项目的代码库,事情就会变得容易得多。

搭建WPF界面

让我们首先创建一个WPF项目,它将拥有我们与聊天机器人交互所需的所有GUI内容。

在整篇文章中,我将假设您正在使用VisualStudio。如果您是在Linux环境中,那么使用GTK的Mono应该就足够了,但我将在本文中继续使用VS。

启动VisualStudio 点击File,选择New然后选择Project.. 在下面Templates,选择Windows然后选择WPF应用 命名项目NLI-Database-Oscova(如果您计划复制下面的代码,则非常重要)。NLI是缩写词自然语言接口.

WPF应用程序需要几个组件。

文本框:用于用户输入。 按钮:发送用户输入。 选项卡控件:第一个选项卡用于查看DataGrid(用于数据库),第二个选项卡用于查看JSON结果。

在解决方案资源管理器中双击MainWindow.xaml并将XAML替换为下面的代码。

<c1></c1><Window x:Class=”NLI_Database_Oscova.MainWindow” xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation” xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml” Title=”Natural Language Interface using Oscova” Height=”450″ Width=”560″ WindowStartupLocation=”CenterScreen”> <Grid> <TabControl> <TabItem Header=”Interaction”> <Grid> <Grid.RowDefinitions> <RowDefinition Height=”35″/> <RowDefinition Height=”50*”/> <RowDefinition Height=”232*”/> </Grid.RowDefinitions> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width=”414*”/> <ColumnDefinition Width=”100″/> </Grid.ColumnDefinitions> <TextBox Name=”InputBox” TextAlignment=”Center” CharacterCasing=”Upper” KeyDown=”InputBox_OnKeyDown”/> <Button Name=”ExecuteButton” Content=”Evaluate” Grid.Column=”1″ Click=”EvaluateButton_OnClick”/> </Grid> <Label Grid.Row=”1″ Name=”ResponseLabel” Content=”No Response Yet” VerticalContentAlignment=”Top” /> <TabControl Grid.Row=”2″> <TabItem Header=”Table”> <DataGrid Name=”EmployeeGrid” FontSize=”14″ /> </TabItem> <TabItem Header=”JSON Result”> <TextBox Name=”ResultBox” IsReadOnly=”True” AcceptsReturn=”True” VerticalScrollBarVisibility=”Auto” /> </TabItem> </TabControl> </Grid> </TabItem> <TabItem Header=”Examples”> <TextBox Name=”ExamplesBox” VerticalScrollBarVisibility=”Auto” HorizontalScrollBarVisibility=”Auto” IsReadOnly=”True”/> </TabItem> </TabControl> </Grid> </Window>
<

上面的代码添加了一个TabControl,其中有一个用于用户输入的文本框和一个Evluate(评估)按钮。

WPF应用程序应该如下所示:

导入Oscova和SQLite

现在,需要将Oscova导入到WPF应用程序中,Oscova是Syn.Bot框架的一部分,我们需要使用NuGet来引用包。

点击Tools,选择NuGet Package Manager并选择Package Manager Console 选择Install-Package Syn.Bot Bot框架将与一些外部依赖项一起引用。

引用SQLite(用于数据库)

选择Install-Package System.Data.SQLite

现在您已经成功地引用了所需的库。我们会继续用一些C#代码来开发。

数据库实用类

为了让对话变得简单,我们首先创建一个数据库实用程序类。右键单击Solution Explorer并选择Class。给类命名DatabaseUtility

替换DatabaseUtility用以下方法初始化。

using System.Data.SQLite; using System.IO; namespace NLI_Database_Oscova { public class DatabaseUtility { const string DataSource = “EmployeesTable.db”; public SQLiteCommand Command { get; set; } public SQLiteConnection Connection { get; set; } public MainWindow Window { get; } public DatabaseUtility(MainWindow window) { Window = window; } public void Initialize() { if (File.Exists(DataSource)) File.Delete(DataSource); Connection = new SQLiteConnection { ConnectionString = “Data Source=” + DataSource }; Connection.Open(); ExecuteCommand(“CREATE TABLE IF NOT EXISTS EMPLOYEES (ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, Name VARCHAR(100) NOT NULL, Role VARCHAR(10), Age INTEGER NOT NULL, Salary INTEGER NOT NULL);”); ExecuteCommand(“INSERT INTO EMPLOYEES VALUES(1, Lincoln, Manager, 43, 54000)”); ExecuteCommand(“INSERT INTO EMPLOYEES VALUES(2, George, CEO, 46, 75000)”); ExecuteCommand(“INSERT INTO EMPLOYEES VALUES(3, Rick, Admin, 32, 18000)”); ExecuteCommand(“INSERT INTO EMPLOYEES VALUES(4, Jorge, Engineer, 28, 35000)”); ExecuteCommand(“INSERT INTO EMPLOYEES VALUES(5, Ivan, Tech, 23, 34000)”); ExecuteCommand(“INSERT INTO EMPLOYEES VALUES(6, Mark, Tech, 25, 34000)”); ExecuteCommand(“INSERT INTO EMPLOYEES VALUES(7, Vincent, Support, 21, 20000)”); ExecuteCommand(“INSERT INTO EMPLOYEES VALUES(8, Wang, Support, 20, 20000)”); ExecuteCommand(“INSERT INTO EMPLOYEES VALUES(9, Ahmed, Tech, 24, 34000)”); ExecuteCommand(“INSERT INTO EMPLOYEES VALUES(10, Krishna, Admin, 25, 18000)”); } private void ExecuteCommand(string commandText) { Command = new SQLiteCommand(Connection) { CommandText = commandText }; Command.ExecuteNonQuery(); } } }
<

等等,还有更多要补充的。内部DatabaseUtility类添加以下方法。

public void Evaluate(string commandText) { Window.UpdateDataGrid(commandText); } public void UpdatePropertyByName(string employeeName, string propertyName, string propertyValue) { var updateString = $”UPDATE EMPLOYEES SET {propertyName}={propertyValue} WHERE UPPER(Name) LIKE UPPER(%{employeeName}%);”; var selectString = $”SELECT * FROM EMPLOYEES WHERE UPPER(Name) LIKE UPPER({employeeName}%);”; Evaluate(updateString); Evaluate(selectString); } public void UpdatePropertyById(string employeeId, string propertyName, string propertyValue) { var updateString = $”UPDATE EMPLOYEES SET {propertyName}={propertyValue} WHERE ID={employeeId};”; var selectString = $”SELECT * FROM EMPLOYEES WHERE ID={employeeId};”; Evaluate(updateString); Evaluate(selectString); } public void PropertyByName(string employeeName, string propertyName) { var selectString = $”SELECT {propertyName} FROM Employees WHERE UPPER(Name) LIKE UPPER(%{employeeName}%);”; Evaluate(selectString); } public void PropertyByRole(string employeeRole, string propertyName) { var selectString = $”SELECT DISTINCT {propertyName} FROM Employees WHERE UPPER(Role) LIKE UPPER(%{employeeRole}%)”; Evaluate(selectString); } public void EmployeeByName(string employeeName) { var selectString = $”SELECT * FROM Employees WHERE UPPER(Name) LIKE UPPER(%{employeeName}%);”; Evaluate(selectString); } public void EmployeeByRole(string employeeRole) { var selectString = $”SELECT * FROM Employees WHERE UPPER(Role) LIKE UPPER(%{employeeRole}%);”; Evaluate(selectString); } public void Close() { Command.Dispose(); Connection.Dispose(); }
<

这个类MainWindow作为其结构参数之一。我们在以后的项目中会用到它。

这个Initialize方法帮助我们为我们的employees数据库。然后有一些帮助函数,如UpdatePropertyByName, UpdatePropertyById诸若此类。当调用某些意图时,我们的聊天机器人将使用这些函数。

您现在不必担心代码。这一切在后面的文章中都是有意义的。

主窗口

在Solution Explorer右击MainWindow.cs并选择View Code.

添加以下命名空间:

using System; using System.Data; using System.Data.SQLite; using System.Windows; using System.Windows.Input; using Syn.Bot.Oscova; using Syn.Bot.Oscova.Collection; using Syn.Bot.Oscova.Entities;

将下列属性添加到MainwWindow班级。

public OscovaBot Bot { get; } public DatabaseUtility DatabaseUtility { get; }

在构造函数中添加以下内容。

public MainWindow() { InitializeComponent(); Bot = new OscovaBot(); Bot.MainUser.ResponseReceived += (sender, args) => { ResponseLabel.Content = args.Response.Text; }; DatabaseUtility = new DatabaseUtility(this); DatabaseUtility.Initialize(); UpdateDataGrid(“SELECT * From Employees”); Bot.MainUser.Context.SharedData.Add(DatabaseUtility); Bot.CreateRecognizer(“set”, new[] { “change”, “update”, “set” }); Bot.CreateRecognizer(“property”, new[] { “id”, “name”, “job”, “age”, “salary” }); //Parsers go here //Dialogs go here //Finally Train the Bot. Bot.Train(); }
<

首先,我们使用实例化OscovaBot对象,分配聊天机器人属性。接下来我们处理ResponseReceived的事件MainUser若要显示响应的文本,使用ResponseLabel.

然后,我们创建一个新的实例DatabaseUtility类并调用Initialize()方法。可以忽略UpdateDataGrid()目前的方法。

因为我们需要DatabaseUtility在整个聊天过程中,我们接下来将它添加到MainUsers 里面

接下来,我们利用重载CreateRecognizer方法创建特定单词的识别器,如change, update诸若此类。

最后,我们添加Train()方法。

注:Oscova需要Train()方法在添加、创建或修改组件后调用一次。

有了这个,我们继续修复UpdateDataGrid()功能。将下列代码添加到MainWindow类。

public void UpdateDataGrid(string sql) { var dataSet = new DataSet(); var dataAdapter = new SQLiteDataAdapter(sql, DatabaseUtility.Connection); dataAdapter.Fill(dataSet); if (dataSet.Tables.Count > 0) { EmployeeGrid.ItemsSource = dataSet.Tables[0].DefaultView; } }

上面的方法使我们能够在每次SQL调用之后更新DataGrid。你可能已经注意到了DatabaseUtility利用这种方法。

创建自定义实体识别器

到目前一切尚好。是时候创建一些实体识别器了。实体识别器只是IEntityRecognizer接口,该接口读取normalized用户输入并返回匹配项的集合。

例如,数字识别器可能会使用正则表达式,并将所有匹配的数字作为实体的集合返回。

长话短说,我们数据库中的每一项都将被视为一个单独的实体。这允许用户输入中包含实体,从而使我们能够创建更好的表达式。

用户姓名识别器

我们将不再从头创建实体识别器,而是创建一个利用CreateRecognizer重载方法,其第二个参数接受返回实体集合的函数。即EntityCollection.

将下列方法添加到MainWindow类。

private void CreateNameParser() { Bot.CreateRecognizer(“Name”, request => { var requestText = request.NormalizedText; var entities = new EntityCollection(); DatabaseUtility.Command.CommandText = “SELECT * FROM EMPLOYEES”; var reader = DatabaseUtility.Command.ExecuteReader(); while (reader.Read()) { var name = reader[“Name”].ToString(); var wordIndex = requestText.IndexOf(name, StringComparison.OrdinalIgnoreCase); if (wordIndex != -1) { var entity = new Entity(“Name”) { Value = name, Index = wordIndex }; entities.Add(entity); } } reader.Close(); return entities; }); }
<

上面的代码创建了一个新的实体识别器。这个Name是我们希望在数据库中引用用户姓名的实体类型名称。

这个requestText保存用户请求文本的规范化值。规范化的值通常是相同的用户输入字符串,但是应用了过滤器。对此进行更多的讨论超出了本文的范围。

使用DatabaseUtility类中的所有项进行迭代。name我们数据库的列。然后,我们使用IndexOf方法,以查看用户输入中是否存在该值。如果返回的索引值不是-1,则会找到该单词。当名字创建一个新的类型实体name,并设置value的值为Index。

注:在Oscova中,所有实体都必须指定匹配值第一次出现的起始索引。

用户等级识别器

同样,我们还将为每个员工的等级创建一个实体识别器。但是,与上面的实体识别器不同,我们只创建一个空识别器,并使用Role列。

private void CreateRoleParser() { var parser = Bot.CreateRecognizer(“Role”); DatabaseUtility.Command.CommandText = “SELECT * FROM EMPLOYEES”; var reader = DatabaseUtility.Command.ExecuteReader(); while (reader.Read()) { var roleTitle = reader[“Role”].ToString(); if (parser.Entries.Contains(roleTitle)) continue; parser.Entries.Add(roleTitle); } reader.Close(); }

现在,让我们从MainWindow构造函数将以下代码放置在//Parsers go here在构造器中的注释。

//Parsers go here CreateNameParser(); CreateRoleParser();

如果到目前为止,我希望您已经对命名实体识别器有了基本的了解。

处理按钮和文本框事件

传递用户输入InputBox发送到Oscova进行Evaluate(评估),我们需要处理EvaluateButton.Click和InputBox.KeyDown事件。将下列代码添加到MainWindow类。

private void EvaluateButton_OnClick(object sender, RoutedEventArgs e) { var message = string.IsNullOrEmpty(InputBox.Text) ? “clear” : InputBox.Text; var result = Bot.Evaluate(message); ResultBox.Text = result.Serialize(); result.Invoke(); InputBox.Clear(); }

上面的代码检查InputBox.Text价值是空的还是空的。如果为空,则Clear命令被发送进行评估。

在之后评价结果返回,我们设置ResultBox.Text属性保存序列化的JSON值,该值表示评价结果然后再调用Invoke方法执行方法。

private void InputBox_OnKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Return) { EvaluateButton_OnClick(null, null); } }

上面的代码只在InputBox按动Enter键时调用EvaluateButton_OnClick方法。

创建对话框

到目前为止,我们一直在为我们的数据库机器人创建框架。现在跳出来,让我们开始实现基本dialog对话类。

dialog对话只是一个相关的集合指令集中在一起。你问我什么是指令?

指令是个指令!好吧,听起来可能不对。让我解释一下。指令是将用户输入映射到可执行操作。简单地说,在Oscova中,指令是一种在用户输入与表达式匹配时调用的方法。

Expression表达式另一方面,是一个模式或示例,取决于您如何编写它,类似于用户输入。

Oscova的评价系统将用户输入与所有输入进行比较执行。然后将表达式及其指令作为评价结果返回.

好了,代码老手,现在我们将创建我们的第一个对话框。

右键单击Solution Explorer,选择Add并选择New Folder 将文件夹命名为Dialogs 右击文件夹,选择Add并选择Class.. 给类命名DatabaseEnquiryDialog并选择Add.

为了转换DatabaseEnquiryDialog对于一个Oscova对话框,您所要做的就是从Oscova的类中派生出Dialog类,如下所示。

class DatabaseEnquiryDialog: Dialog { }

创造指令

我们的第一个指令是非常简单的。我们想要的是当用户说What is the age of Rick? (Rick(作为一个用户),我们希望聊天机器人返回相应的Age列。

我们会制定我们的指令PropertyEnquiry。为此,我们首先添加一个void方法的DatabaseEnquiryDialog类,如下所示。

public void PropertyEnquiry(Context context, Result result) { }

以上代码的一些信息。

指令方法必须始终具有public访问权限。 指令可以采用0,1(上下文或结果)或2(上下文和结果)参数。 指令必须至少有一个表达式。接下来介绍。

向指令中添加表达式

属性将表达式添加到指令的Expression属性。有两种主要的表达式类型:

示例表达式–我们只编写一个输入示例,并使用大括号对实体进行可选注释。 模板表达式–我们编写用户输入,而不是注释,而是正确地指定实体类型。

示例表达式What is the age of Rick?看起来像:

[Expression(“What is the {age} of {Rick}?”)] [Entity(“property”)] [Entity(“name”)]

第一Entity属性现在链接带注释的单词。age到实体类型property还有这个词Rick链接到实体类型name.

注:实体属性的顺序很重要,因为带注释的单词或短语的序列与Entity属性。

模板表达式What is the age of Rick?看起来像:

[Expression(“What is the @property of @name?”)]

跟表达式不一样,模板表达式更容易编写,因为通过直接指定实体类型名称(以@为前缀)来避免注释。

为了本文,我们将添加一个example在我们的PropertyEnquiry方法中。

[Expression(“What is the {age} of {Rick}?”)] [Entity(“property”)] [Entity(“name”)] public void PropertyEnquiry(Context context, Result result) { }

注:所有Oscova属性都可以在Syn.Bot.Oscova.Attributes命名空间。

现在,如果它什么也不做,它的指令又有什么用呢?这个指令必须为我们做两件事。

从数据库选择age栏Rick。 显示一条说明说明选择了这名用户

为此,我们将在方法主体中添加以下内容:

public void PropertyEnquiry(Context context, Result result) { var name = result.Entities.OfType(“name”).Value; var property = result.Entities.OfType(“property”).Value; var utility = context.SharedData.OfType<DatabaseUtility>(); utility.PropertyByName(name, property); result.SendResponse($”{property} of Employee \”{name}\”.”); }

上面的代码首先获取property实体的name的匹配值。所有提取的实体都存储在Result.Entities。结果还发现,集合中的实体通常按用户输入中发生的顺序排列。

接下来,我们获取共享DatabaseUtility对象并调用PropertyByName方法。此方法通过选择指定的Employees表里面,其中员工的名称等于指定的namevalue值。

最后,通过调用Result.SendResponse方法传递文本响应。此响应,如MainWindow构造函数更改Value的ResponseLabel.

总体指令代码应该如下所示:

[Expression(“What is the {age} of {Rick}?”)] [Entity(“property”)] [Entity(“name”)] public void PropertyEnquiry(Context context, Result result) { var name = result.Entities.OfType(“name”).Value; var property = result.Entities.OfType(“property”).Value; var utility = context.SharedData.OfType<DatabaseUtility>(); utility.PropertyByName(name, property); result.SendResponse($”{property} of Employee \”{name}\”.”); }

测试指令

在我们继续测试指令我们需要把对话框添加到Oscova。在MainWindow构造函数就在注释下面。//Dialogs go here添加以下内容。

Bot.Dialogs.Add(new DatabaseEnquiryDialog());

给你。现在按F5运行应用程序,并在输入框中输入:

What is the age of Rick?(Rick几岁了) What is the salary of Ahmed?(Ahmed的薪水多少)

如果输出一样!那么你已经成功地创造了你的第一个指令。

注:中的值。表达,我们消除了为不同属性编写冗余表达式的需要。

在附带说明中,如果您单击JSON Result选项卡,您应该会看到评价结果.

{ “query”: “WHAT IS THE AGE OF RICK?”, “sessionId”: “78a8765f-3705-442d-a4ca-fe4dbd4c2e04”, “intents”: [ { “intent”: “DatabaseEnquiryDialog.PropertyEnquiry”, “score”: 0.9985714285714286 }, { “intent”: “DatabaseEnquiryDialog.EmployeeName”, “score”: 0.59047619047619047 } ], “entities”: [ { “entity”: “AGE”, “type”: “property” }, { “entity”: “Rick”, “type”: “Name” } ], “contexts”: [] }
<

注:在不同的机器人设置中,指令的分数可能会有所不同。

更多指令

在我们进入下一个创建上下文意图的阶段之前。我们将继续增加一些指令表达式。

输入模式的意图:What is the salary of the CEO?(CEO薪水多少)

[Expression(“What is the @property of @role”)] [Expression(“@property of @role”)] public void PropertyByRole(Context context, Result result) { var role = result.Entities.OfType(“role”).Value; var property = result.Entities.OfType(“property”).Value; var utility = context.SharedData.OfType<DatabaseUtility>(); utility.PropertyByRole(role, property); result.SendResponse($”{property} of \”{role}\”.”); }

输入指令模式:Who is Wang?

[Expression(“Find employee with the name @name”)] [Expression(“Who is @name?”)] public void EmployeeName(Context context, Result result) { var name = result.Entities.OfType(“name”).Value; var utility = context.SharedData.OfType<DatabaseUtility>(); utility.EmployeeByName(name); result.SendResponse($”Employee(s) with the name {name}.”); }

输入指令模式:Who is the admin?

[Expression(“Find employee whose role is @role”)] [Expression(“Who is the @role?”)] public void EmployeeRole(Context context, Result result) { var role = result.Entities.OfType(“role”).Value; var utility = context.SharedData.OfType<DatabaseUtility>(); utility.EmployeeByRole(role); result.SendResponse($”Employee(s) with job role \”{role}\”.”); }

语境指令

在本节中,我们将学习两个新概念。

语境指令 使用预先构建的系统实体。

尽管Oscova附带了数十个预先构建的系统实体,但我们将只使用其中的两个。

右键单击Dialogs文件夹,选择Add并选择Class.. 给类命名DatabaseUpdateByNameDialog并选择Add.

就像前面的对话框一样,派生出DatabaseUpdateByNameDialog从基地Dialog类,如下所示。

class DatabaseUpdateByNameDialog : Dialog { }

此对话框中的意图结构如下:

允许用户更改员工财产价值(年龄、薪资)的意图 确定指令:如果用户说Yes提交对数据库的更改。 取消指令:如果用户说No提交操作被取消。

什么是语境?

上下文是表示用户输入的当前上下文的字符串值。在Oscova,上下文有名字和寿命。生命周期通常是上下文将持续的请求数。

为了更好的处理常量字符串值。我们将首先创建一个静态类来保存一个常量字符串值,我们将使用该值作为上下文项的名称。

向项目中添加一个新类并命名它DatabaseContext.

static class DatabaseContext { public const string ConfirmUpdateByName = “ConfirmUpdateByName”; }

现在,允许用户对数据库进行更改的第一个指令。双击DatabaseUpdateByNameDialog.cs并添加以下代码。

[Expression(“@set @property of @name to @sys.number”)] public void ChangePropertyOfName(Context context, Result result) { context.Add(DatabaseContext.ConfirmUpdateByName); var property = result.Entities.OfType(“property”); var name = result.Entities.OfType(“name”); var number = result.Entities.OfType<NumberEntity>(); context.SharedEntities.Add(property); context.SharedEntities.Add(name); context.SharedEntities.Add(number); var propertyString = property.Value.ToLower(); if (propertyString != “age” && propertyString != “salary”) { result.SendResponse($”{property} of {name} is readonly.”); return; } result.SendResponse($”Are you sure that you want to change {property} of {name} to {number}?”); }

这个Expression在上面的代码中,启用以下命令:

Change the age of Mark to 43(改变Mark的年龄为43) Set the salary of Krishna to 17000(设置Krishna的工资为17000)

在模板表达式中,值@sys.number与数字匹配的系统实体类型。有大量的系统实体可供开发人员使用。您可以阅读Oscova的API文档以获得更多细节。

注意context.Add(DatabaseContext.ConfirmUpdateByName);,通过将字符串值添加到上下文中,Bot在其下一个请求中将首先搜索指定上下文中的指令。

因为在下一次指令调用时,结果如果被清除,我们将使用Context.SharedEntities属性将当前实体传递给下一个指令。

最后,当用户发送上述命令时,我们向用户发送一个请求确认的响应。

我们处理问题的方式来自用户的后续响应No。为此,我们将创建一个指令,如下所示。

[Expression(“{no}”)] [Entity(Sys.Negative)] [Context(DatabaseContext.ConfirmUpdateByName)] public void ChangePropertyByNameDeclined(Context context, Result result) { context.SharedEntities.Clear(); result.SendResponse(“Operating canceled.”); }

在上面的意图中有两件事需要注意。

第一[Entity(Sys.Negative)]..Entity属性指定类型的系统实体。@sys.negative哪个匹配no 诸若此类。类的常量字段可以找到所有实体类型。Sys类。

第二,[Context(DatabaseContext.ConfirmUpdateByName)]显式指定此意图仅在ConfirmUpdateByName背景。

我们创造了以下指令,用来响应来自用户的后续响应yes

[Expression(“{Yes}”)] [Entity(Sys.Positive)] [Context(DatabaseContext.ConfirmUpdateByName)] public void ChangePropertyConfirmed(Context context, Result result) { var property = context.SharedEntities.OfType(“property”); var name = context.SharedEntities.OfType(“name”).Value; var number = context.SharedEntities.OfType<NumberEntity>().Value; var utility = context.SharedData.OfType<DatabaseUtility>(); utility.UpdatePropertyByName(name, property.Value, number.ToString(CultureInfo.InvariantCulture)); result.SendResponse($”{property} of {name} changed to {number}”); context.SharedEntities.Clear(); }

上述意图的表达式注释yes作为@sys.positive实体类型来捕获积极的后续响应。就像ChangePropertyByNameDeclined我们指定上述指令也必须在ConfirmUpdateByName下面。

在方法体中,我们首先检索之前添加到SharedEntities集合并将值传递给DatabaseUtility.UpdatePropertyByName函数。

提交完成后,我们发送一个文本响应,说明已进行所请求的更改,并清除SharedEntities收藏。

如果用户说yes或者类似的更改将被提交到Employees数据库。

检验指令

我们将重复对前一个对话框所做的操作,并添加DatabaseUpdateByNameDialog到Bot.Dialogs将下列代码放置在//Dialogs go here在MainWindow构造函数

Bot.Dialogs.Add(new DatabaseUpdateByNameDialog());

按下F5发送指令Change the salary of Vincent to 24000(将Vincent的薪金改为24000).

如果一切顺利,应向你提出以下问题

Are you sure you want to change the salary of Vincent to 24000?(你确定你想把Vincent的薪水改为24000吗?)

如果你说yes更改将被传递到数据库,否则操作将被取消。

好吧,这就是所有的内容。谢谢你的阅读!

有问题还是反馈?在评论中让我知道。

免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:使用Oscova的数据库的聊天机器人 https://www.yhzz.com.cn/a/13543.html

上一篇 2023-05-11 23:12:22
下一篇 2023-05-11 23:17:14

相关推荐

联系云恒

在线留言: 我要留言
客服热线:400-600-0310
工作时间:周一至周六,08:30-17:30,节假日休息。