使用正则表达式引擎构建 AI 聊天机器人
本文介绍如何使用流行的、基于正则表达式的开源聊天机器人引擎:Verbots 来构建一个 AI 聊天机器人。
引言
本文介绍如何使用一个名为 Verbot 的开源、基于正则表达式的自然语言处理引擎来构建一个人工智能 (AI) 聊天机器人。聊天机器人技术并不新鲜,但随着人们尝试新的与计算机交互方式,其受欢迎程度和使用率不断提高。聊天机器人、动画角色、语音识别和语音合成正被用来促进新的人机交互 (HCI) 渠道。
背景
最初的聊天机器人 ELIZA 是由 Joseph Weizenbaum 于 1966 年开发的。ELIZA 是一款虚拟心理治疗师,它会尝试通过保持话题相关并对用户的问题表现出关心来与用户互动。1994 年,第一个 Verbot Sylvie 的创造者 Michael Mauldin 创造了“ChatterBot”一词。从那时起,Verbots 不断发展成熟,演变成了 Conversive 公司创建的当前 Verbot 4 版本。2006 年,Conversive 将 Verbot SDK 开源,以允许人们轻松创建自己的“机器人”并将其嵌入到自己的应用程序中。本文介绍 Verbot Engine SDK 的一些基本原理以及如何将 SDK 集成到另一个应用程序中。
Verbot 的工作原理
在深入研究代码之前,我认为有必要在高层次上解释 Verbot SDK 的工作原理。所有聊天机器人都有一个“知识库”或脚本的概念,它告诉机器人识别哪些关键字或短语。当找到匹配项时,相应的输出将被发送给用户。Verbot 知识库由一组规则组成,这些规则是 Verbot 对话的基本构建块。规则必须有一个或多个输入,用于识别用户所说的话。它们还必须有一个或多个输出,当规则中的输入匹配时,机器人会响应这些输出。当 Verbot 引擎加载知识库文件时,它会将脚本中的简单文本输入转换为正则表达式,然后可以基于这些正则表达式进行匹配。
例如,假设我们有一个输入是
What is your name?
引擎生成的最终正则表达式如下所示
^(|.*?\b|.*?\s)What\b.+?\bis\b.+?\byour\b.+?\bname(|\b.*?|\s.*?)$
如果您不熟悉正则表达式语法,这可能有点令人生畏。即使您熟悉,它可能仍然显得有些晦涩。基本上,引擎在单词之间以及短语的开头和结尾添加了通配符。这个正则表达式将匹配“So, what the heck is your name?”,但不会匹配“What's your name?”。为了匹配这个,我们可以使用 Verbots 中的同义词功能,您可以在其网站上了解有关此功能以及其他更高级的脚本主题的更多信息。另外,如果您想了解更多关于正则表达式的知识,可以在 dotnetcoders 找到一个很好的正则表达式语法参考。
Verbot 知识库(扩展名为 *.vkb)是定义知识库的规则、输入和输出的 XML 文件。它们还可以引用其他 Verbot 4 文件类型,如同义词、替换配置文件和代码模块。Verbots 允许您将 VKB 文件“编译”成更紧凑的二进制“已编译知识库”(扩展名为 *.ckb)文件格式。
测试应用程序
执行位于 VerbotWindowsApplicationSample\bin\Release 文件夹中的 VerbotWindowsApplicationSample.exe 文件。应用程序运行后,选择文件 -> 加载... 菜单项,然后浏览到 VerbotWindowsApplicationSample\Resources\sample.ckb 文件以打开示例知识库。文件加载到引擎后,您就可以与机器人进行交互了。尝试键入“notepad”来测试示例知识库中包含的规则之一。
请注意,程序已启动 Windows 记事本。这是示例应用程序中用于解析脚本命令的代码。我稍后会详细讨论这一点。
使用代码
要在自己的应用程序中使用 Verbot Engine SDK,只需将 Verbot4Library 引用添加到项目中,创建 Verbot4Engine 的实例,然后调用 AddCompiledKnowledgeBase 或 AddKnowledgeBase 来加载机器人的知识。要在用户输入进来时与机器人交互,请创建一个 State 对象来唯一标识您的用户。添加用户希望与之交互的知识库的路径。然后调用 Verbot4Engine 对象上的 GetReply 方法,以在已加载的脚本中找到匹配项。
让我们看一下我们 VerbotWinApp.cs 文件中的 getReply() 函数
private void getReply()
{
string stInput = this.inputTextBox.Text.Trim();
this.inputTextBox.Text = "";
Reply reply = this.verbot.GetReply(stInput, this.state);
if(reply != null)
{
this.outputTextBox.Text = reply.Text;
this.parseEmbeddedOutputCommands(reply.AgentText);
this.runProgram(reply.Cmd);
}
else
this.outputTextBox.Text = "No reply found.";
}
此方法将输入文本框中的文本发送到引擎的 GetReply 方法。它会收到一个 Reply 对象,然后我们可以对其进行处理。Reply 对象有一个名为“Text”的成员,我们将将其放入输出框中。它还有一个“AgentText”成员,这是 Text 的一个版本,用于发送给文本转语音 (TTS) 引擎。它还有一个“Cmd”(命令)成员,我们可以根据需要用于特殊处理。
最后,看看 parseEmbeddedOutputCommands 和 runEmbeddedOutputCommand 方法。这些方法根据我们的要求进行自定义处理。正如我上面提到的,“run”命令就是在这里打开记事本。
根据您自己应用程序的工作方式,您可以自定义 Reply 对象的处理方式。例如,在在线机器人引擎中,您可能希望通过打开弹出窗口等方式处理 URL。
创建知识
有一些免费工具可以帮助您创建 Verbot 知识库。Verbot GPL Editor 和 VCompiler 是两个不错的选择。您还可以使用 Verbot Editor,它需要 10 美元并提供注册码解锁。如果您想创建自己的知识库创建工具,代码相当简单。您也可以查看上面提到的 Verbot GPL Editor 的源代码作为参考。以下是创建知识库所需步骤的摘要
- 首先,创建一个 KnowledgeBase 类的实例
KnowledgeBase kb = new KnowledgeBase();
- 然后,我们将创建一个规则添加到我们的 KB 中
Rule r = kb.AddRule();
- 最后,对于您创建的每个规则,您都希望至少有一个输入和一个输出。我们可以手动创建和添加输入和输出,或者直接调用规则类中的 AddInput 和 AddOutput 方法
r.AddInput("Input Text", ""); r.AddOutput("Output Text", "", "");
现在我们有了一个 KnowledgeBase 对象,其中包含一条规则,该规则有一个输入和一个输出。当然,在实际应用程序中,我们不希望硬编码“Input Text”和“Output Text”字段,并且可能希望允许用户自己添加它们,但您明白了。接下来,我们可能想将 KB 保存到文件中。为此,我们需要一个 XMLToolbox 类的实例。然后,我们只需调用 SaveXML 方法来保存文件
XMLToolbox xmlToolbox = new XMLToolbox(typeof(KnowledgeBase));
xmlToolbox.SaveXML(kb, @"C:\mykbpath.vkb");
然后,我们希望能够将我们的知识库加载到 Verbot 引擎中并与之交互。以下是执行此操作的代码
Verbot4Engine engine = new Verbot4Engine();
KnowledgeBaseItem kbi = new KnowledgeBaseItem();
kbi.Fullpath = @"C:\";
kbi.Filename = "mykbpath.vkb";
engine.AddKnowledgeBase(kb, kbi);
State state = new State();
state.CurrentKBs.Add(@"C:\mykbpath.vkb");
最后,要与加载的知识库交互,只需调用引擎上的 GetReply 方法,如上所述。
深入阅读
如果您对了解更多关于 Verbots 的信息感兴趣,请访问 Verbot 社区论坛或浏览 Verbots wiki,以了解有关编写自己的 Verbot 脚本的更多信息。
历史
- 2007 年 3 月 22 日 -- 文章初稿。
- 2007 年 3 月 28 日 -- 为 SDK 4.1.3.2 的新版本更新了文章,该版本包含一个简单的控制台应用程序作为示例和一个新的 KnowledgeBase 方法 AddRule,该方法返回新规则。此外,对文章说明进行了一些小的修改。
- 2007 年 6 月 21 日 -- 文章已编辑并移至 CodeProject.com 的主文章库。