ai端到端_如何使用行为树构建端到端的对话式AI系统

ai端到端

by Lior Messinger

由Lior Messinger

如何使用行为树构建端到端的对话式AI系统 (How to Build an End-to-End Conversational AI System using Behavior Trees)

At their core, AI projects can be depicted as a simple pipeline of a few building blocks. The diagram above explains that pretty nicely: Unstructured content, usually in huge amounts of data, comes in from the left, and is fed into AI classifiers. These pre-trained machine- or deep- learning models separate the wheat from the chaff and reduce the input to a few numerical or string output values.

从本质上讲,AI项目可以描述为包含几个构建块的简单管道。 上图很好地说明了这一点:非结构化内容(通常包含大量数据)是从左侧传入的,并被馈送到AI分类器中。 这些经过预训练的机器学习或深度学习模型将小麦与谷壳分离,并将输入减少为几个数字或字符串输出值。

For example, megas of pixels and colors in an image are reduced to a label: this is a giraffe. Or a zebra. In audio, millions of wave frequencies produce a sentence through Speech To Text models. And in conversational AI, that sentence can be reduced further to a few strings representing the intent of the speaker and the entities in the sentences.

例如,图像中的数百万像素和彩色被缩小为标签:这是一只长颈鹿。 或斑马。 在音频中,数百万个波频率通过“语音转文本”模型产生一个句子。 在对话式AI中,该句子可以进一步简化为一些代表说话者意图和句子中实体的字符串。

Once the input has been recognized, we need to do things, and generate some meaningful output. For example, a car recognized too close should turn the wheel in an autonomous car. A request to book a flight should produce some RESTFul database queries and POST calls, and issue a confirmation, or a denial, to the user.

识别输入后 我们需要做一些事情,并产生一些有意义的输出。 例如,识别出太近的汽车应该转动自动驾驶汽车的车轮。 预订航班的请求应产生一些RESTFul数据库查询和POST调用,并向用户发出确认或拒绝。

This last part, shown in the diagram as rule-based logic, is an inseparable part of any AI system, and there’s no change in sight to that. It has usually been done by coding, thousands and thousands of lines of code — if it’s a serious system — or a couple of scripts if it’s a toy chatbot.

最后一部分,在图中显示为基于规则的逻辑,是任何AI系统不可分割的一部分,对此没有任何改变。 通常是通过编码,成千上万的代码行(如果是一个严肃的系统)或几个脚本(如果是一个玩具聊天机器人)来完成的。

行为树 (Behavior Trees)

A Behavior Tree is a programming paradigm that emerged in video games to create human-like behaviors in non-player characters. They form an excellent visual language with which a software architect, a junior developer and even a non-coder, technical designer can all create complex scripts. In fact, since Behavior trees (BTs) allow logic operations like AND and OR, loops and conditions, any program that can be created by code, can be created with BTs.

行为树是一种编程范例,出现在视频游戏中,用于在非玩家角色中创建类人的行为。 它们形成了一种出色的视觉语言,软件架构师,初级开发人员甚至是非编码人员,技术设计师都可以使用它们来创建复杂的脚本。 实际上,由于行为树(BT)允许进行逻辑运算(如AND和OR),循环和条件,因此可以使用BT创建可以由代码创建的任何程序。

Servo is an open-source AI conversational framework built on top of a JavaScript behavior tree framework called Behavior3. It’s designed to do the needed orchestration of inputs and outputs for conversational AI systems. It’s what is called “low-code” framework: you only need to code a little, and most of the tasks can be done in the visual editor.

Servo是一个开放源代码的AI对话框架,建立在一个名为Behavior3JavaScript行为树框架之上。 它旨在进行对话式AI系统所需的输入和输出编排。 这就是所谓的“低代码”框架:您只需要编写一点代码,并且大多数任务都可以在可视化编辑器中完成。

It’s not your usual newbie's toy: it was designed to be extended using real-life, debuggable JS source files and classes, and abide by any team project-management methodologies. Moreover, it’s suitable for teams that grow in size, allowing the introduction and reuse of new modules through abstracted and decoupled sub-processes.

它不是您通常的新手玩具:它被设计为使用实际的,可调试的JS源文件和类进行扩展,并遵守任何团队的项目管理方法。 而且,它适合于规模不断扩大的团队,允许通过抽象和解耦的子流程引入和重用新模块。

I’m the main developer of Servo. After 30-something years of coding, feeling the pain in long-delayed projects and watching legacy systems break under their own weight, I wanted to achieve maximum flexibility with minimum coding. Here I’m going to explain the magic that can be done when one combines Behavior Trees with NLU/NLP engines, using Servo and Wit.ai.

我是Servo的主要开发人员。 经过30多年的编码,经历了长时间拖延的项目带来的痛苦,并看着遗留系统承受了自己的负担,我希望以最少的编码获得最大的灵活性。 在这里,我将解释使用Servo和Wit.ai将行为树与NLU / NLP引擎结合使用时可以实现的神奇效果 。

Any developer can benefit from this tutorial, but it’s best if you are a developer with experience in building chat- or voice-bots and have knowledge working with NLU/NLP engines like LUIS, Wit.AI, Lex (the Alexa engine), or Dialogflow. If you do not, it’s ok, but I’ll be covering some subjects a bit briefly.

任何开发人员都可以从本教程中受益,但是,如果您是具有构建聊天机器人或语音机器人的经验并且具有与LUIS,Wit.AI,Lex(Alexa引擎)之类的NLU / NLP引擎合作的知识,那么这是最好的选择。对话流。 如果您不这样做,则可以,但是我将简要介绍一些主题。

If you want to learn about NLU and NLP engines, there are excellent resources all over the Internet — just search for ‘Wit tutorial’. If you want to learn how to build a heavyweight assistant, then just continue reading.

如果您想了解NLU和NLP引擎,则Internet上有大量优秀的资源-只需搜索“ Wit教程”。 如果您想学习如何构建重量级助手,请继续阅读。

伺服入门 (Getting Started with Servo)

I won’t get into details of installing Servo here, but just say that getting started with Servo is really easy. You can read about it here. In essence, you clone the Github repo, npm-install it according to the readme, and run it locally. Then, every New Project would start you off with a small ready-made bot to get things going:

我不会在这里介绍安装Servo的细节,只是说开始使用Servo确实很容易。 你可以在这里阅读。 本质上,您可以克隆Github存储库 ,根据自述文件进行npm-install安装,然后在本地运行。 然后,每个新项目都将以一个小型现成的机器人开始,以使事情进展:

You can notice here the green hexagons named ‘chit-chat’, ‘cancel’ and others. By the end of this article, you’ll have a clear idea of what they are and how they work. But first, let’s tackle the first challenges.

您会在这里注意到绿色的六边形,分别为“聊天”,“取消”和其他。 到本文结尾,您将对它们是什么以及它们如何工作有一个清晰的认识。 但是首先,让我们解决第一个挑战。

建立NLU模型 (Building An NLU Model)

Let’s talk about building a banking assistant, and specifically, one that works for the money transfer department. Had it been a web application, we would have a form with few fields, among which the amount and the transferee’s (also called beneficiary) account are the most important. Let’s use these here for this tutorial. Actually, when using NLU engines, we can still think of it as forms, with the fields now called entities (also slots, in Alexa lingo). The NLU engines also produce an intent, which can be viewed as the name of the form that will guide the assistant to the area of that functionality of the user’s intent.

让我们谈谈建立银行助理,特别是为汇款部门工作的助理。 如果它是一个Web应用程序,我们将拥有一个字段很少的表格,其中金额和受让人(也称为受益人)帐户是最重要的。 让我们在这里使用这些作为本教程。 实际上,当使用NLU引擎时,我们仍然可以将其视为表单,这些字段现在称为实体 (在Alexa术语中也称为插槽 )。 NLU引擎还会产生一个意图,该意图可以看作是表单的名称,它将指导助手到达用户意图的功能区域。

We should train the NLU engine with a few sentences, such as:

我们应该用一些句子来训练NLU引擎,例如:

  • “I’d like to send some money”

    “我想寄一些钱”

  • “I’d like to send $100 “

    “我想寄100美元”

  • “Please transfer $490 to account #01–10099988”

    “请转移$ 490到帐户#01–10099988”

And for these, we need to tell the engine to output the following:

对于这些,我们需要告诉引擎输出以下内容:

  • a TransferIntent intent for such sentences

    这些句子的TransferIntent意图

  • A wit/number for the amount

    金额的机智/数字

  • An accountNumberEntity for the beneficiary account

    受益人帐户的accountNumberEntity

Let’s do that on Wit.ai. Again, I won’t get into a Wit tutorial — there are plenty of guides. Servo comes with a general Wit model which you can take from Servo’s Github here. Then, open your own Wit app and import it.

让我们在Wit.ai上进行操作。 同样,我不会进入Wit教程-有很多指南。 伺服器带有通用的Wit模型,您可以在此处从伺服器的Github中获取。 然后,打开您自己的Wit应用程序并将其导入。

I created a free-text entity for the account numbers (as account number might include other symbols), and a wit/number entity for the amount. I found composite entities work pretty well, too, although they need some training. For simplicity, for account numbers, I trained the model to be a # followed by 8 digits.

我为帐号创建了一个自由文本实体(因为帐号可能包含其他符号),并为金额创建了一个机智/数字实体。 我发现复合实体也很不错,尽管它们需要一些培训。 为简单起见,对于帐号,我将模型训练为#后跟8位数字。

In general, it’s always better to experiment with different entity models. In our case, we might get two numbers in the same sentence (account number and amount) and we need a way to tell them apart, so it’s best if it’s two different entity names. But you can try other types: AI is still a very empirical science…

通常,尝试使用不同的实体模型总是更好。 在我们的例子中,我们可能在同一个句子中得到两个数字(帐号和金额),我们需要一种区分它们的方法,因此最好是两个不同的实体名称。 但是您可以尝试其他类型:人工智能仍然是一门非常经验的科学……

We then trained it with a few sentences and let Wit build the bank-transfer model. For convenience, I added it here, and also set the whole banking bot tutorial bot to come along with the pre-loaded examples.

然后,我们用几句话对其进行了训练,然后让Wit建立了银行转帐模型。 为了方便起见,我在此处添加了它,还设置了整个银行bot机器人教程bot以及预加载的示例。

Last, we need to connect the NLU to the assistant. Go to Settings in Wit, and copy the access token. We need to paste it in our tree root’s properties. We do this by opening Servo’s editor, selecting the root, opening its properties, and pasting it under nlu. As you can see, Servo supports multi-language assistants and different NLU engines:

最后,我们需要将NLU连接到助手。 转到机智中的设置 ,然后复制访问令牌 。 我们需要将其粘贴到树根的属性中。 为此,请打开Servo的编辑器,选择根,打开其属性,然后将其粘贴到nlu下。 如您所见,Servo支持多语言助手和不同的NLU引擎:

启动银行助理 (Start The Bank Assistant)

Now, we can turn to Servo. We should construct a small tree with a question for each entity and intent.

现在,我们来谈谈Servo。 我们应该构建一棵小树,为每个实体和意图提出一个问题。

As a reminder, the basic rules of Servo behavior-trees is as follows

提醒一下,伺服行为树的基本规则如下

  1. The main loop of the tree is executing the root continuously

    树的主循环正在连续执行根
  2. Each node executes its children

    每个节点执行其子级
  3. An AskAndMap node (the “Age” node in the diagram above) outputs a question to the user and waits for an answer

    AskAndMap节点(上图中的“ Age”节点)向用户输出问题并等待答案
  4. Once an answer comes in, the flow is routed to the appropriate child according to the intent and entities that the NLU engine gave it

    一旦有答案,流程就会根据NLU引擎给它的意图和实体被路由到适当的孩子

Let’s first change the main, topmost question from “Age?” into “What would you like to do?”. Also, let’s delete the first (that is, left-most) child and its nodes, as we are not going to use them anymore:

让我们首先从“年龄?”中更改最主要的主要问题 变成“您想做什么?” 。 另外,让我们删除第一个(即最左边的)子节点及其节点,因为我们将不再使用它们:

Why are we seeing the red dashes around the node? Hover over it and you’ll see the error:

为什么在节点周围看到红色虚线? 将鼠标悬停在它上面,您将看到错误:

Count of contexts number should be equal to the number of children

上下文数应等于子项数

We will fix that in a minute.

我们将在一分钟内解决该问题。

Now let’s build the transfer flow. We’ll assume that once the user says “I’d like to wire money”, we want to descend into the first, leftmost child. For that, we’ll select the “How can I help you” node and go into its properties. There, change the first context to have an intentId of “TransferIntent”:

现在,让我们构建传输流程。 我们假设一旦用户说出“我想电汇”,我们就想进入第一个最左边的孩子。 为此,我们将选择“如何为您提供帮助”节点,然后进入其属性。 在那里,将第一个上下文更改为具有intentId“ TransferIntent”

This will cause any sentence that the Wit determines to have a TransferIntent, to be routed there.

这将导致机智确定具有TransferIntent的所有句子被路由到那里。

映射实体 (Mapping an entity)

Now, once the NLU has recognized our intent to transfer money, we should get all the different “fields”, or entities. Let’s add a node for the amount:

现在,一旦NLU意识到我们的汇款意图,我们就应该获得所有不同的“领域”或实体。 让我们为数量添加一个节点:

We added an AskAndMap node, and set its prompt to a question about the amount. We also changed its title — it’s always a good practice. Last, don’t forget to save your work using the Save button or Ctrl-S.

我们添加了一个AskAndMap节点,并将其提示设置为关于数量的问题。 我们还更改了标题-这始终是一个好习惯。 最后,不要忘记使用“保存”按钮或Ctrl-S保存您的工作。

You can also notice the red warning disappeared from the How can I help you node.

您还会注意到红色警告从“ 我如何帮助您”节点中消失了。

Last, let’s add a number entity to one of the child contexts of the Amount node, and map the value into a field called amount.

最后,让我们将一个数字 实体添加到Amount节点的一个子上下文中,并将该值映射到一个名为amount的字段中

“contexts”: [ {   “entities”: [    {      “contextFieldName”: “amount”,      “entityName”: “number”,      “expectedValue”: “”,      “entityIndex”: 0    }    ] }

All this seems very simple, and it is: if a user says something like “I need to send some money”, they will be asked, “What is the amount?”. Once they enter the amount, the number will be extracted by the NLU and mapped to the context.amount in Servo. Then, we can use it later in the game. Visually, the flow started from the root:

所有这一切似乎非常简单,而且是:如果用户说“我需要寄钱”之类的内容,则会询问他们“金额是多少?”。 输入金额后, 数字将由NLU提取并映射到Servo中的context.amount 。 然后,我们可以在游戏后期使用它。 从视觉上看,流程从根开始:

And the assistant would ask:

助手会问:

“How can I help you?”

“我怎么帮你?”

If the user answered:

如果用户回答:

“I’d like to transfer some money”

“我想转移一些钱”

the NLU engine would output a TransferIntent and the flow would continue downstream to the context it identified — the leftmost child — and ask the next question, about the amount:

NLU引擎将输出TransferIntent ,并且流程将继续向下游移动到它标识的上下文(最左边的孩子),并询问下一个有关数量的问题:

But what if the user doesn’t enter an amount?

但是,如果用户不输入金额怎么办?

建筑助手 (Building Helpers)

AskAndMap nodes support another type of a context child, called a Helper. This context is selected when the user answered something that couldn’t be mapped to any other context. Let’s add one into our What’s the amount AskAndMap:

AskAndMap节点支持另一种类型的上下文子代,称为Helper 。 当用户回答了无法映射到任何其他上下文的内容时,将选择此上下文 。 让我们添加一个到AskAndMap中的数量是多少:

"contexts":[     {        "entities":[           {              "contextFieldName":"amount",            "entityName":"number",            "expectedValue":"",            "entityIndex":0         }      ]   },   {        "helper":true   }]

Let’s now add a right-most child with a message help. Something like:

现在让我们添加最右边的一个带有消息帮助的孩子。 就像是:

Of course, there can be only one helper context child for the AskAndMap.

当然,AskAndMap只能有一个辅助上下文子级。

One could imagine an example of the flow:

可以想象一个流程示例:

User: “I’d like to transfer some money”

用户: “我想转移一些钱”

Assistant: “What is the amount?

助手:“ 多少钱?

User: “You think I’d know. But I’m not sure

用户:“ 你以为我知道。 但我不确定

Assistant: “Please provide the amount to transfer

助理:“ 请提供转账金额

That looks simple: obviously, the assistant didn’t understand the “You think I’d know. But I’m not sure” and went on with the helper message “Please provide the amount to transfer”.

这看起来很简单:显然,助手不理解“ 您认为我会知道。 但是我不确定”,并继续显示帮助消息“ 请提供转账金额 ”。

But in fact, if you’ll run the bot, you will get a surprising sentence after that last line:

但实际上,如果您要运行该机器人,那么在最后一行之后,您会得到一个令人惊讶的句子:

User: “You think I’d know. But I’m not sure

用户:“ 你以为我知道。 但我不确定

Assistant: “Please provide the amount to transfer

助理:“ 请提供转账金额

Assistant: “How can I help you?”

助手: “我能为您提供什么帮助?”

What happened here? Where did the “How can I help you?” come from?

这里发生了什么? “我如何帮助您?”在哪里 来自?

Here’s the flow. The helper node said its line and returned SUCCESS to its parent, the AskAndMap. This, in turn, returned SUCCESS too, and so on, until the root was reached. At which point, the whole tree was restarted, and we get the initial How can I help you?” question.

这是流程。 帮助程序节点说了一行,然后将SUCCESS返回给其父级AskAndMap。 反过来,这也返回SUCCESS,依此类推,直到到达根目录为止。 此时,整个树已重新启动,我们得到了初始的“我如何帮助您?” 题。

So, to avoid that, we need to put a loop before the AskAndMap, so that it won’t return until it really succeeded. That is done with something called a decorator.

因此,为避免这种情况,我们需要在AskAndMap之前放置一个循环,以使它在真正成功之前不会返回。 这是通过称为装饰器的东西完成的

添加重复装饰器 (Adding a repeat decorator)

Behavior Trees implement loops using decorators, which are nodes that have one parent and one child. Depicted as a rhombus ⧫, we will use here the RepeatUntillSuccess decorator to loop the AskAndMap until it is successfully completed. Receiving a help message would not complete it, so we need to return a FAILURE after the help message. We do that by sequencing a Failer node right after the message. All in all, that’s the decoration we add to the AskAndMap construct:

行为树使用装饰器实现循环, 装饰器是具有一个父级和一个子级的节点。 描述为菱形⧫,我们将在这里使用RepeatUntillSuccess装饰器循环AskAndMap,直到成功完成。 收到帮助消息将无法完成它,因此我们需要在帮助消息之后返回一个FAILURE。 我们通过在消息之后对Failer节点进行排序来实现。 总而言之,这就是我们添加到AskAndMap构造中的修饰:

Now it’s the time to add the next node that would map the beneficiary account number. Again, pretty straight-forward: as before, we add an an AskAndMap with the question for the account number and a map from accountNumberEntity to an accountNumber member on the context. We set it as a child of a RepeatUntilSuccess decorator, and a helper child that explains what’s needed for this entity.

现在是时候添加下一个映射受益人帐号的节点了。 再次,非常简单:与以前一样,我们添加一个带有帐号问题的AskAndMap和上下文中从accountNumberEntity到accountNumber成员的映射。 我们将其设置为RepeatUntilSuccess装饰器的子级,并将其解释为该实体所需的帮助器子级。

Then, we should add the actual business logic to do the transfer. This would probably mean several API calls with the entities collected. We would simulate this with a message: we are going to transfer $X to account #Y. For that, you need to drag in a GeneralMessage as the first child of the accountNumberEntity, and make its properties as follows:

然后,我们应该添加实际的业务逻辑来进行传输。 这可能意味着要对收集到的实体进行几次API调用。 我们将通过一条消息模拟这一点: 我们将$ X转移到帐户#Y 。 为此,您需要将GeneralMessage作为accountNumberEntity的第一个子项拖入,并使其属性如下:

“debug-log”:””, “runningTimeoutSec”:600, “maxRetriesNumber”:5, “replayActionOnReturnFromContextSwitch”:true, “view”:false, “prompt”:[  “About to transfer <%=context.amount%> to account <%=context.accountNumber%>”],…

This is how the tree looks like now:

这是现在树的样子:

The tree comes with Servo. It’s files are under server/convocode/anonymous/drafts/bank-bot.

该树随伺服系统一起提供。 它的文件在server / convocode / anonymous / drafts / bank-bot下。

运行和测试 (Running and testing)

Let’s test the bot and see what happens with various inputs. Click on the Debugger tab, then the play button ▶️. On the right hand the simulator will pop:

让我们测试一下机器人,看看各种输入会发生什么。 单击“调试器”选项卡,然后单击播放按钮▶️。 模拟器将在右侧弹出:

You can enter a sentence like:

您可以输入类似以下的句子:

I’d like to send money.

我想汇款。

That would be answered, as expected, with

正如预期的那样,

What is the amount?

多少钱?

And you can put in the amount, and continue.

您可以输入金额,然后继续。

But what if we say

但是如果我们说

I’d like to send $14141??

我想寄14141美元

Test it, and you’ll see how the assistant nicely jumps over the amount question straight to the account number:

测试一下,您将看到助手如何将金额问题直接跳过到帐号:

What is the account number?

帐号是多少?

Now, let’s make its life even harder:

现在,让我们的生活变得更加艰难:

I’d like to send money to account #87654321

我想汇款到帐户#87654321

Nicely enough, it asks only for the amount. Say you enter $3400, it would then skip the account number (since it knows it already) into the final confirmation sentence:

很好,它只要求金额。 假设您输入$ 3400,然后它将跳过帐号(因为它已经知道了)到最后一个确认语句中:

About to transfer 3400 to account #87654321.

即将将3400转移到帐户#87654321。

How does it know to do all that magic?

它怎么知道做所有的魔术?

上下文流 (The Context Flow)

Servo comes equipped with a powerful context-recognition set of algorithms that helps it do all that. What happened here shows a bit of it. Let’s take the last example. After the assistant asked:

Servo配备了功能强大的上下文识别算法集,可帮助其完成所有任务。 这里发生的事情显示了一部分。 让我们来看最后一个例子。 助手问后:

“How can I help you?”

“我怎么帮你?”

And the user answered:

用户回答:

I’d like to send money to account #87654321

我想汇款到帐户#87654321

The NLU engine output a TransferIntent and the flow continued downstream to the next question, about the amount:

NLU引擎输出一个TransferIntent ,并且流程继续向下游移动到下一个关于数量的问题:

But the NLU also returned an accountNumberEntity! So before descending, this entity is saved on the ‘How can I help you’ context. And, every AskAndMap defines its own context.

但是NLU还返回了一个accountNumberEntity! 因此,在下降之前,此实体保存在“我如何为您提供帮助”上下文中。 并且,每个AskAndMap都定义了自己的上下文。

That’s actually an important remark, so I’ll repeat it: every AskAndMap defines its own context.

这实际上是一个重要的说明,因此我将重复一遍: 每个AskAndMap都定义了自己的上下文。

At any point in the flow, when an entity is mentioned, Servo searches back (read: upwards) in the conversation to find it. If it hasn’t, it would ask for it.

在流程中的任何时候,当提到一个实体时,Servo都会在对话中向后搜索(阅读:向上)以找到它。 如果没有,它将要求它。

So after the amount is entered, once we continue to the account number node, Servo finds that the accountNumberEntity was already mentioned, and uses it.

因此,在输入金额之后,一旦我们转到帐号节点,Servo就会发现已经提到了accountNumberEntity并使用它。

By the way, a process of similar characteristics happens also when we get to the last confirming GeneralMessage node. Its prompt reads:

顺便说一句,当我们到达最后一个确认的GeneralMessage节点时,也会发生类似特征的过程。 其提示为:

About to transfer <%=context.amount%> to account <%=context.accountNumber%>

即将转移<%= context.amount%>到帐户<%= context.accoun tNumber%>

To resolve that, Servo searches up the context tree to find the needed entities, or context members.

为了解决这个问题,Servo在上下文树中向上搜索以找到所需的实体或上下文成员。

Does this remind you of something? Folks familiar with JavaScript prototypical inheritance would see that it basically uses the same design. In Servo, we implemented that since we need more control over the variables. But it’s always interesting to see how object-oriented concepts are actually applied to real life, natural conversations.

这是否使您想起某些事情? 熟悉JavaScript原型继承的人们会看到它基本上使用相同的设计。 在伺服系统中,我们实现了这一点,因为我们需要对变量进行更多的控制。 但是,将面向对象的概念实际应用于现实生活中自然对话总是很有趣的。

But what if the user asks something much more unrelated, like:

但是,如果用户要问更不相关的问题,例如:

“How much money do I have in my account?”

“我的帐户里有多少钱?”

Or more so

或更多

“Who are you, for heaven’s sake??”

“为了天堂,你是谁?”

To which to bot responds:

机器人响应的对象:

“I’m an artificial intelligence assistant built by Servo Labs.”

“我是由Servo Labs建立的人工智能助手。”

Whaaaaaaaaaat?? Where did this come from?

哇啊啊啊啊? 这个是从哪里来的?

上下文和子树 (Context and sub-trees)

Almost all of the structural designs architects use to build manageable large systems can be divided into one of two categories:

建筑师用于构建可管理的大型系统的几乎所有结构设计都可以分为两类之一:

  • Reuse

    重用
  • Modularize

    模块化

If Servo is to stand as the infrastructure of large AI systems, it must provide some mechanism for allowing developers to achieve these goals. And that’s where sub-trees come into play.

如果要使Servo成为大型AI系统的基础架构,则它必须提供某种机制来允许开发人员实现这些目标。 这就是子树起作用的地方。

We mentioned before the green hexagons:

我们在绿色六边形之前提到过:

This is a sub-tree. Double-click it, and you’ll enter a new tree, with that name. To create a new sub-tree, hover over the Trees on the left pane and select New:

这是一个子树。 双击它 ,您将输入一个具有该名称的新树。 要创建新的子树,请将鼠标悬停在左窗格的“ 树”上,然后选择“ 新建”:

A tree with a unique GUID name would appear. Change its name to something meaningful, and build it using any node from the left pane. Once built, you can drag, drop and connect it at any point in any other tree (including itself, by the way, but be very careful about that). Since sub-trees can have many leaf nodes, you can connect them only as leaves, too.

将显示具有唯一GUID名称的树。 将其名称更改为有意义的名称,然后使用左窗格中的任何节点进行构建。 构建完成后,您可以将其拖放,连接到任何其他树的任何位置(顺便说一下,包括它本身,但要非常小心)。 由于子树可以具有许多叶节点,因此您也只能将它们连接为叶。

What happened when the user asked the assistant “Who are you”?

当用户问助手“你是谁”时会发生什么?

First, the NLU, already trained for such questions, returned a WhoAreYouIntent. Then context search was activated. If the conversation was somewhere down in the middle of a transfer conversation, the search went upwards, trying to find a context with WhoAreYouIntent. This context is found: it sits on the 4th context, in the How can I help you node. The flow then was redirected there, meaning, that route was made the active route. The flow here continued downstream into the chit-chat subtree, answered the question, returned up with a SUCCESS and the routing was returned to its previous context, the transfer one.

首先,已经接受过此类问题培训的NLU返回了WhoAreYouIntent 。 然后激活上下文搜索。 如果对话在转接对话的中间处于某个位置,则搜索向上,尝试使用WhoAreYouIntent查找上下文。 找到此上下文:它位于“ 我如何帮助您”节点中的第4个上下文中。 然后将流重定向到那里,这意味着该路由已成为活动路由。 此处的流程继续向下游进入chit-chat子树,回答了问题,并以SUCCESS返回,并且路由返回到其先前的上下文,即传输域。

Here we learned something actually very important. The conversation flows down, but context is searched up. Never forget that:

在这里,我们学到了非常重要的东西。 对话不畅,但上下文却被搜索。 永远别忘了:

连接到Messenger客户端 (Connecting to a messenger client)

Until now, we have used the internal simulator and debugger as our messaging client. Let’s connect our small assistant to a real Facebook messenger. There is one big important change on the root properties of our tree, and that is to change the channel name from the default channel “chatsim” to “facebook”:

到目前为止,我们已经使用内部模拟器和调试器作为消息传递客户端。 让我们将我们的小助手连接到一个真正的Facebook Messenger。 我们树的根属性有一个重要的大变化,那就是将频道名称从默认频道“ chatsim”更改为“ facebook”

"channels":"facebook"

On the Facebook side, these are the main high-level steps that one needs to take:

在Facebook方面,这些是人们需要采取的主要高级步骤:

  1. Open a Facebook page under your Facebook account

    在您的Facebook帐户下打开Facebook页面
  2. Create a new Facebook app in the Facebook developer center

    在Facebook开发人员中心创建一个新的Facebook应用

  3. Add a messenger functionality to your app

    向您的应用程序添加Messenger功能
  4. Subscribe the app to listen to events in the page

    订阅该应用以收听页面中的事件
  5. Set the assistant callback address as the webhook to post to. Servo always publish its bot with the format of

    将助手回调地址设置为要发布到的Webhook。 Servo始终以以下格式发布其bot:

/entry//

/条目/ <通道ID> / <助理名称>

So for a bank-bot assistant, running on www.mydomain.com, the address would be:

因此,对于运行在www.mydomain.com上的银行自动助理,该地址为:

https:///entry/fb/bank-bot

https:// / ent ry / fb / bank-bot

You should set it in the page subscription section of the Facebook app, at the developer’s portal. You need to select at least messages, messaging_postbacks, and to match the verify token with the validation token you set in the bot’s root properties:

您应该在开发人员门户的Facebook应用程序的页面订阅部分中进行设置。 您至少需要选择messagemessaging_postbacks ,并将验证令牌与在机器人的根属性中设置的验证令牌进行匹配:

By the way, https://serveo.net is a great tunneling system (another alternative is ngrok), if you are developing your assistants, like me, on localhost.

顺便说一句,如果您正在本地主机上像我一样开发助手,则https://serveo.net是一个很棒的隧道系统(另一个替代方法是ngrok)。

On the assistant root properties, set the same verify token and re-publish it:

在助手根属性上,设置相同的验证令牌并重新发布:

"facebook": {    "validationToken": "mytoken123",    "accessToken": ""  },

The access token should be set too, taken from Facebook’s messenger area:

访问令牌也应该设置,取自Facebook的Messenger区域:

Last, select a page to subscribe your webhook to the page events:

最后,选择一个页面以将您的Webhook订阅到页面事件:

and… once you connect all these ends, you should have, at last, a full, orchestrated, end-to-end conversational AI system!

并且…一旦连接了所有这些末端,您最终应该拥有一个完整的,精心策划的,端到端的对话式AI系统!

连接后端 (Connecting Backends)

Real life connections vary, but luckily, most of them these days are done by using RESTFul API. For these, check out the documentation on RetrieveJSONAction and PostAction. Once data is retrieved, or a response is received, it is set into a memory field (context/global/volatile). You probably would want to query it. This is done using ArrayQueryAction, which implements an in-memory Mongo-like query language. For direct MongoDB queries, use the MongoQuery action.

现实生活中的连接各不相同,但幸运的是,这些天中的大多数连接都是使用RESTFul API完成的。 对于这些内容,请查看RetrieveJSONActionPostAction上的文档 。 检索到数据或接收到响应后,将其设置到存储字段(上下文/全局/易失性)中 。 您可能想要查询它。 这是使用ArrayQueryAction完成的该方法实现了类似于Mongo的内存查询语言 对于直接MongoDB查询,请使用MongoQuery操作。

综上所述 (In Summary)

Servo is an open-source IDE and framework that uses a context-recognition search to place the user on the right conversation and output the right questions. We learned how to construct a simple conversation, and how to wrap such conversations in sub-trees for decoupling and re-use. Servo has many other features that are worth exploring, among which you could find

Servo是一个开放源代码的IDE和框架,它使用上下文识别搜索将用户置于正确的对话中并输出正确的问题。 我们学习了如何构造一个简单的对话,以及如何将这些对话包装在子树中以进行解耦和重用。 伺服还有许多其他功能值得探索,其中您可以找到

  • Connectors to Facebook, Alexa, Twilio and Angular

    Facebook,Alexa,Twilio和Angular的连接器
  • Connectors to MongoDB, Couchbase and LokiJS databases

    连接到MongoDB,Couchbase和LokiJS数据库的连接器
  • Harness for automated conversation testing

    利用自动化对话测试
  • A Conversation debugger

    会话调试器
  • More actions, conditions and decorators

    更多动作,条件和装饰器
  • Flow control mechanisms

    流量控制机制
  • Field assignment and compare

    现场分配和比较
  • Context manipulation

    上下文操纵
  • Validation

    验证方式
  • In-memory mongo-like queries

    内存中类似于mongo的查询
  • And any customized action you come up with

    以及您提出的任何自定义操作

Feel free to check it out and ask questions on the Github forum or at my @lmessinger Github name. Enjoy!

随时检查它并在Github论坛上或以我的@lmessinger Github名称提问。 请享用!

翻译自: https://www.freecodecamp.org/news/how-to-build-an-end-to-end-conversational-ai-system-using-behavior-trees-658a7122e794/

ai端到端

你可能感兴趣的:(python,人工智能,java,编程语言,机器学习)