DialogflowとNode.js Webhookで、賢いチャットボットを作る方法

あらすじ

これはDialog Flow(旧API.AI)を利用してチャットボットを作成するシリーズの最初の記事です。

まずこの記事ではNode.jsのWebhookを作成します。

以下、2番目の記事では、そのWebhookをDialogFlowエージェントの性能を高めるために活用します。

Movie ChatBotDialogFlowの用語と使い方を解説

以下、3番目の記事では、そのDialogFlowエージェントをAngular4 チャットボットアプリ開発のために活用します。

DialogFlow Angular4 AppDialogFlowを活用したAngular4アプリの開発方法

DialogFlow(旧API.AI)はあなたのアプリと統合できるチャットボットを作るのにとても適したツールです。

DialogFlowエージェントはユーザーの質問を理解し関連情報を回答することにおいてとても賢いです。

各DialogFlowエージェントにはデフォルトのインテントと、エージェントがユーザーの質問を理解できなかったときに機能するフォールバック(代替)インテントがあります。

概して自然言語処理(NLP)に大変適しているのです。

しかし限界もあり、それだけでは対応できないこともあります。

それだけでは、あなたが指定したある都市の現在の気象情報も、あなたが知りたい映画の情報も提供することができません。

基本的に、外部のデータソース(例えば天気API)との連携が必要な質問には正確な回答ができないのです。

しかし、そのような質問には答えることができないと言いましたが、Webhookを活用することによってに必要な情報を回答することができるようになります。

Webhookとは何か?

Wikipediaによれば

Webhooksはユーザー定義のHTTPコールバックである。通常、レポジトリにコードをプッシュしたり、ブログにコメントが投稿されたり等のイベントによりトリガーされる。

もっと簡単に言えば、あなたのエージェントが誰かのところに行き、なにかデータを取ってくるものと思ってください。

例えばあなたはある映画についての情報が必要でDialogFlow エージェントに問い合わせます。

DialogFlowはそれ単体ではその情報を得ることができません。

インテントを使い、あなたが知りたい映画(Entity)があるという事を決定するだけです。

さて、あなたが興味ある映画の名前がわかったら詳しい情報を得るために他の人を呼びます。

誰を呼ぶか?それが、Webhookです。

これは下記の様に表示されます。

User’s Query <-> DialogFlow Agent <-> Webhook <-> API To Get Details

それでは、 Node.js を使用しWebhookを作成してみましょう。

始める前に、いくつかの必要条件があります

  • Node.js をインストールしPathに加えてあること。もしインストールしていなかったらこのリンクから Node.js をダウンロードしインストールして下さい。
  • 私はIDEにVS codeを使用しますが、あなたの好きなものを使ってください。特に好みがなければ上記のリンクをクリックしてVS codeをダウンロードして下さい。無料で素晴らしいツールです。
  • Movie Dataとしては我々はOMDb APIを使用します。2017年11月に無料のAPI Key Provisionが再登場しました。このリンクからAPI Keyを生成することができます。このAPI Keyを使い、Webhook を介してOBDb API にGETコールをします。

今回はWindowsでの設定手順を解説します。

もしあなたの環境が、MAC/Linux 等であれば、それらの環境に置き換えて対応してください。

それでは下記の順序で進めて頂ければと思います。

1.Windowsエクスプローラを起動し、Webhookプロジェクトを保存するフォルダに移動してください。今回は Node.js プロジェクトを以下に作成します。C:\Development\Node.

2.プロジェクトのために新しいフォルダを作成してください(Ctrl + Shift + N)。何か良い名前を付けて(MovieDBWebhook 等) enter を押しフォルダに移動してください。

3.Windows エクスプローラのアドレスバーをクリックし、Cmdと入力してください。

4.対象のパスでCommand Promptを起動します。 (C:\Development\Node\MovieDBWebhook).

5.npm init で新しいnode モジュールをイニシャライズしますいくつか質問されるので、回答して終わらせます。全て済んだらpackage.jsonというファイルがいくつかの情報と一緒に作成されます。このファイルは何を意味しているか考えてみましょう。

6.このWebhookと依存関係のあるパッケージをインストールします。
npm install express body-parser

7.これにより、Express と body-parser という名前のパッケージがnode_modules.という名前のフォルダにインストールされます。

8.終了したら、このロケーションにIDEを開いてください(VS Codeを使用しているなら code.)

9.Webhook Codeを含むファイルを作成してください。私は普通にindex.js と名付けます。

10.ではコードを見てみましょう。

Node.js Webhookのソースコード

const API_KEY = 'YOUR_API_KEY_HERE';
module.exports = API_KEY;
const express = require('express');
const bodyParser = require('body-parser');
const http = require('http');
const API_KEY = require('./apiKey');
const server = express();
server.use(bodyParser.urlencoded({
    extended: true
}));

server.use(bodyParser.json());
server.post('/get-movie-details', (req, res) => {

    const movieToSearch = req.body.result && req.body.result.parameters && req.body.result.parameters.movie ? req.body.result.parameters.movie : 'The Godfather';
    const reqUrl = encodeURI(`http://www.omdbapi.com/?t=${movieToSearch}&apikey=${API_KEY}`);
    http.get(reqUrl, (responseFromAPI) => {
        let completeResponse = '';
        responseFromAPI.on('data', (chunk) => {
            completeResponse += chunk;
        });
        responseFromAPI.on('end', () => {
            const movie = JSON.parse(completeResponse);
            let dataToSend = movieToSearch === 'The Godfather' ? `I don't have the required info on that. Here's some info on 'The Godfather' instead.\n` : '';
            dataToSend += `${movie.Title} is a ${movie.Actors} starer ${movie.Genre} movie, released in ${movie.Year}. It was directed by ${movie.Director}`;

            return res.json({
                speech: dataToSend,
                displayText: dataToSend,
                source: 'get-movie-details'
            });
        });
    }, (error) => {
        return res.json({
            speech: 'Something went wrong!',
            displayText: 'Something went wrong!',
            source: 'get-movie-details'
        });
    });
});

Postリクエストの一部としてリクエストデータでヒットするルート(get-movie-details )を定義しました。

ルート・ハンドラーはリクエストボディからmovie の名前を抽出します。

もし映画の名前が何も見つからなければ、The Godfatherを検索のデフォルトムービーとして設定します。

映画の名前にスペースが入っているかもしれないのでOMDb API URL をエンコードしなければなりません。

最後にAPIにGETコールします。これによりデータが以下のフォーマットの様になります。

{
  "Title": "The Godfather",
  "Year": "1972",
  "Rated": "R",
  "Released": "24 Mar 1972",
  "Runtime": "175 min",
  "Genre": "Crime, Drama",
  "Director": "Francis Ford Coppola",
  "Writer": "Mario Puzo (screenplay by), Francis Ford Coppola (screenplay by), Mario Puzo (based on the novel by)",
  "Actors": "Marlon Brando, Al Pacino, James Caan, Richard S. Castellano",
  "Plot": "The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.",
  "Language": "English, Italian, Latin",
  "Country": "USA",
  "Awards": "Won 3 Oscars. Another 24 wins & 27 nominations.",
  "Poster": "https://images-na.ssl-images-amazon.com/images/M/MV5BY2Q2NzQ3ZDUt[email protected]._V1_SX300.jpg",
  "Ratings": [
    {
      "Source": "Internet Movie Database",
      "Value": "9.2/10"
    },
    {
      "Source": "Rotten Tomatoes",
      "Value": "98%"
    },
    {
      "Source": "Metacritic",
      "Value": "100/100"
    }
  ],
  "Metascore": "100",
  "imdbRating": "9.2",
  "imdbVotes": "1,313,968",
  "imdbID": "tt0068646",
  "Type": "movie",
  "DVD": "09 Oct 2001",
  "BoxOffice": "N/A",
  "Production": "Paramount Pictures",
  "Website": "http://www.thegodfather.com",
  "Response": "True"
}

そしてリクエストURLとコールバック関数とともにhttp.getメソッドを呼び出します。

コールバック関数はdata やendなどのイベントにより呼び出され、応答データの塊(チャンク)を返すdataイベントを待ちます。

作成した、completeResponse変数へ全てのチャンクを加えていきます。

APIからの応答が終了したとき、The end eventがトリガーされ、それがcompleteResponse変数の中からレスポンスを得ます。

しかしこれはStringですので初めにこれをパースしてからmovie変数へ必要な映画情報を割り当てます。

私はそこから必要なフィールドを抜き出して、応答の一部として送るデータを用意し、私のresへのjsonコールを返すことにより送信します。

いくつかの基本的なエラーハンドリングもあります。

最後にサーバーを、特定のポートか 8000上のリクエストを待機する様に設定します。

server.listen((process.env.PORT || 8000), () => {
    console.log("Server is up and running...");
});

コマンドプロンプトのnode index.js でサーバーを起動させましょう。

そしてPostmanを使いこのエンドポイントをテストしましょう。

Postman

または、HerokuにWebhookをデプロイすることもできます。

HerokuにWebhookがデプロイされたら、Postmanを使い動作に問題ないかローカルでテストできます。

Postman

これでこの記事は終わりです、この投稿がお役に立つことを祈ります。

なにか改良できる点があればご提案ください。

コードはGithub にありますので、ご自由に使用したり修正したりしてください。

以下、次の記事では、このWebhookを使ってDialogFlow エージェントに必要なデータを受け取ります。

Movie ChatBotDialogFlowの用語と使い方を解説

原文

https://chatbotslife.com/creating-a-nodejs-based-webhook-for-intelligent-bots-a91ecbe33402

チャットボットライフとの提携により、翻訳し掲載しています。
チャットボットライフとは、最新のボット、AI、NLP、ツール等を扱うメディアです。