iansltx/api-ai-bridge

此包已被废弃,不再维护。作者建议使用 iansltx/dialogflow-bridge 包。

一组中间件和辅助工具,用于响应 Dialogflow 网络钩子

0.3 2017-11-13 17:51 UTC

This package is auto-updated.

Last update: 2022-02-01 13:09:34 UTC


README

中间件和辅助对象,用于响应 Dialogflow 网络钩子。

需求 + 安装

为了充分利用这个库,您需要

  1. 一个兼容 PSR-11 (以前称为容器互操作性) 的容器,用于拉取依赖项。
  2. 一个使用双遍历中间件(例如 Slim 3)或建议的 PSR-15 中间件(例如 Zend Expressive 2.0+),使用 PSR-7 请求和响应来使用中间件组件的框架。

要安装,请使用 Composer

composer require iansltx/dialogflow-bridge

入门

将此库集成到支持(微)框架中最简单的方法是将它添加为路由中间件。例如,使用 Slim 3

<?php

use iansltx\DialogflowBridge\{Middleware, Router, Question, Answer};

// require Composer autoloader here

$app = new Slim\App();
$app->post('/hook', new Middleware\DoublePass(Router::buildFromClosureArray([
    'hello' => function(Question $question, Answer $answer) : Answer {
        return $answer->withSpeechAndText("Hello {$question->getParam('name', 'world')}!");
    }
])));
$app->run();

要查看您的应用程序,请将 Dialogflow 的网络钩子配置指向您托管应用程序的 /hook,创建一个带有(或没有)name 参数的意图,将动作名称设置为 hello,勾选使用 Web Hook 进行满足的框,然后调用您的新意图。

现在,让我们分析一下刚刚发生的事情

  1. Dialogflow 调用我们的网络钩子,Slim 将其路由到 DoublePass 中间件。
  2. 该中间件将请求交给 Router,它编组了 QuestionAnswer 类。
  3. Router 看到有一个动作 helloQuestion,它与它传递的处理程序之一匹配,因此它调用了处理程序,返回一个 Answer
  4. RouterAnswer 返回给中间件,中间件使用正确的 JSON 负载更新了 HTTP Response

您可以在本文件的稍后部分了解有关这些组件的更多信息。

添加回退

此库包含一个内置的、尽管是通用的、处理程序,用于处理传入的网络钩子请求上的动作与您的路由映射中没有任何匹配的情况。函数签名与正常动作处理程序相同,可以使用任何可调用(具有 __invoke() 的类、闭包等)在这里。只需在创建您的 Router 时传递可调用作为额外的参数。调整之前的示例

<?php

use iansltx\DialogflowBridge\{Middleware, Router, Question, Answer};

// require Composer autoloader here

$app = new Slim\App();
$app->post('/hook', new Middleware\DoublePass(Router::buildFromClosureArray([
    'hello' => function(Question $question, Answer $answer) : Answer {
        return $answer->withSpeechAndText("Hello {$question->getParam('name', 'world')}!");
    }
], function (Question $question, Answer $answer) : Answer {
    return $answer->withSpeechAndText("Sorry, I'm not sure what to do here.");
})));
$app->run();

随着您的应用程序变得更加复杂,您将想要开始...

管理处理程序依赖项

一个匿名函数数组是开始处理网络钩子请求的快速方法,但随着您项目的增长,您可能希望将处理程序放在主应用程序 DI 容器中。在这种情况下,您将想要使用 Router::build() 而不是 Router::buildFromClosureArray()build() 接受三个参数

  1. 实现 PSR-11 ContainerInterface 的对象(例如 Slim 3 的容器)
  2. 一个动作名称(作为键)和容器键(作为值)之间的映射数组。这提供了一个白名单,以便 incoming 请求不会从容器中拉取随机的服务,并允许您将多个动作名称映射到单个依赖项,如果您愿意的话。
  3. 可选的回退可调用对象。

考虑上一个示例,但假设我们现在已经将“hello”处理器移动到容器中作为“helloHandler”,我们最终会得到

<?php

use iansltx\DialogflowBridge\{Middleware, Router, Question, Answer};

// require Composer autoloader here

$app = new Slim\App();
$app->post('/hook', new Middleware\DoublePass(Router::build($app->getContainer(), [
    'hello' => 'helloHandler'
], function (Question $question, Answer $answer) : Answer {
    return $answer->withSpeechAndText("Sorry, I'm not sure what to do here.");
})));
$app->run();

当您切换到基于类的动作处理器时,您可以选择(但不是必须)实现 HandlerInterface,以确保您的处理器方法具有正确的签名。

中间件详解

DoublePass 类可以用作实际的中间件,而不仅仅是作为 Slim 路由可调用对象;它的第三个参数未使用,并且未进行类型提示,以允许这样做。

如果您更愿意使用依赖于提议的 PSR-15 中间件规范的框架,请设置 PSR15 类的一个实例。在这种情况下,您需要一个 Router 实例(就像 DoublePass 一样)和一个可调用对象,该对象接受一个 JSON 序列化的唯一参数,并返回一个带有参数 JSON 编码的 PSR-7 ResponseInterface,以及正确的 Content-Type 头部。如果您使用 Zend Diactoros,构建中间件将看起来像

$middleware = new Middleware\PSR15($router, function($data) {
    return new \Zend\Diactoros\JsonResponse($data);
});

对象

此库提供了一些 不可变 对象,使与 Dialogflow Webhook 的交互更加容易。

问题

问题封装了 Dialogflow 的 webhook 请求 JSON,允许更干净地访问参数、上下文和其他 webhook 请求的方面。通常您将由路由器提供问题,但您也可以独立构建一个问题

/** @var \Psr\Http\Message\ServerRequestInterface $request */
$question = Question::fromRequest($request); // from a PSR-7 request

/** @var array $data */
$question = new Question($data); // from an array, e.g. by JSON-decoding the web hook request body

有关更多信息,请参阅 Question 类中的方法文档。

答案

可以将答案直接传递给 json_decode() 来生成 Dialogflow webhook 调用所需的响应体。通常这将通过在问题上调用 getBaseAnswer() 来生成。这样做会告知答案当前设置了哪些上下文,如果需要可以丢弃它们。这是路由器处理问题和答案的方式,但您也可以直接调用 new Answer()

有关更多信息,请参阅 Answer 类中的方法文档。