Vision API を Dialogflow と統合する

この Codelab では、Vision API を Dialogflow と統合し、ユーザー指定の画像入力にリッチで動的な機械学習ベースのレスポンスを提供します。入力として画像を取得し、Vision API で処理して、特定のランドマークをユーザーに戻す chatbot アプリを作成します。たとえば、ユーザーがタージマハルの画像をアップロードすると、chatbot はタージマハルをレスポンスとして返します。

画像内の項目を分析して、得られた情報を基にアクションを実行できるので、これは便利です。また、ユーザーが領収書をアップロードし、領収書内の購入日を抽出し、日付が適切な場合は払い戻しを処理できるように、払い戻し処理システムを作成することもできます。

次のサンプル ダイアログをご覧ください。

お客様:

チャットボット: こんにちは画像をアップロードしてランドマークを探すことができます

ユーザー: タージマハルが含まれる画像をアップロードします。

Chatbot: ファイルを処理中です。結果は、Taj Mahal、Taj Mahal Garden、Taj Mahal です。

Prerequisites

続行する前に、次の Codelab を完了する必要があります。

  1. Dialogflow で予約スケジューラを作成する
  2. Dialogflow の chatbot を Actions on Google と統合する
  3. Dialogflow のエンティティについて
  4. Dialogflow アプリ用のフロントエンド Django クライアントを構築する

また、Dialogflow の基本コンセプトと構造についても理解する必要があります。これは、Dialogflow で chatbot を構築するパスで次の動画から取得できます。

学習内容

  • Dialogflow エージェントを作成する方法
  • Dialogflow エージェントを更新してファイルをアップロードする方法
  • Dialogflow フルフィルメントを使用して Vision API 接続を設定する方法
  • Dialogflow の Django フロントエンド アプリを設定して実行する方法
  • Django フロントエンド アプリを App Engine 上の Google Cloud にデプロイする方法
  • カスタム フロントエンドから Dialogflow アプリをテストする方法

作成するアプリの概要

  • Dialogflow エージェントを作成する
  • ファイルをアップロードする Django フロントエンドを実装する
  • Dialogflow フルフィルメントを実装して、アップロードした画像に対して Vision API を呼び出す

必要なもの

  • Python の基本的な知識
  • Dialogflow の基本的な理解
  • Vision API に関する基礎知識

ここでは、カスタムの Django フロントエンドを使用して新しい会話体験を作成し、Vision API と統合するために拡張します。Django フレームワークでフロントエンドを構築して、ローカルで実行、テストしてから、App Engine にデプロイします。フロントエンドは次のようになります。

次の図のように、リクエスト フローが動作します。

  1. ユーザーはフロントエンド経由でリクエストを送信します。
  2. これにより、Dialogflow DetectionIntent API への呼び出しがトリガーされ、ユーザーの発話が正しいインテントにマッピングされます。
  3. Explore ランドマーク インテントが検出されると、Dialogflow フルフィルメントが Vision API にリクエストを送信し、レスポンスを受信して、ユーザーに送信します。

アーキテクチャ全体は次のようになります。

Vision API は、画像から分析情報を抽出する事前トレーニング済み ML モデルです。画像のラベル付け、顔やランドマークの検出、光学式文字認識、露骨な表現のコンテンツへのタグ付けなど、さまざまな分析情報が得られます。詳細については、Vision AI をご覧ください。

  1. Dialogflow コンソールに移動します。
  2. いつものデータに(初めて使用する場合は、メールを使用して登録します)。
  3. 利用規約に同意すると、コンソールに表示されます。
  4. をクリックし、一番下までスクロールして [Create new agent] をクリックします。

5. エージェント名として「VisionAPI」と入力します。

  1. [作成] をクリックします。

Dialogflow は、エージェントの一部として次の 2 つのデフォルト インテントを作成します。

  1. デフォルトのウェルカム インテントはユーザーに挨拶する
  2. デフォルト フォールバック インテントは、bot が理解できないすべての質問を捕捉します。

この時点で、ユーザーに挨拶する機能的な bot ができましたが、これを更新して、ランドマークを探索するために画像をアップロードできることをユーザーに伝える必要があります。

デフォルトのウェルカム インテントを更新して、画像をアップロードするようユーザーに通知する

  1. [Default Welcome Intent] をクリックします。
  2. [Responses > Default > Text or SSML Response] に移動して「Hi!画像をアップロードしてランドマークを探すことができます。

エンティティを作成

  1. [エンティティ] をクリックします。

  1. [エンティティを作成] をクリックし、「<ファイル名>」という名前を付けて [保存] をクリックします。

新しいインテントを作成する

  1. [Intents] > [Create Intent] の順にクリックします。
  2. [Intent name] に、「Explore Upload image」と入力します。
  3. [トレーニング フレーズ] > [Add Training Phrases] をクリックし、「demo.jpg」はエンティティとして「@<ファイル名>」を含む「&」は「demo.jpg」で、「file は taj.jpeg」と入力します。

  1. [Responses] > [Add Response] > [Default] > [Text or SSML Response] をクリックします。「ファイルを評価しています」と入力し、[回答を追加] をクリックします。
  1. [Fulfillment] > [Enable fulfillment] をクリックし、[Enable webhook call for this intent] をオンにします。

  1. [Fulfillment] をクリックします。
  2. インライン エディタを有効にします。

  1. 次のコードで index.js を更新し、Cloud Storage バケットの名前を使用して YOUR-BUCKET-NAME を更新します。
'use strict';

const functions = require('firebase-functions');
const {google} = require('googleapis');
const {WebhookClient} = require('dialogflow-fulfillment');
const vision = require('@google-cloud/vision');
  /**
   * TODO(developer): Uncomment the following lines before running the sample.
   */
const bucketName = 'YOUR-BUCKET-NAME';
const timeZone = 'America/Los_Angeles';
const timeZoneOffset = '-07:00';

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
  const agent = new WebhookClient({ request, response });
  console.log("Parameters", agent.parameters);

  function applyML(agent){
    const filename = agent.parameters.filename;
    console.log("filename is: ", filename);

    // call vision API to detect text
    return callVisionApi(agent, bucketName, filename).then(result => {
                      console.log(`result is ${result}`);
                      agent.add(`file is being processed, here are the results:  ${result}`);
            //agent.add(`file is being processed ${result}`);
        }).catch((error)=> {
            agent.add(`error occurred at apply ml function`  + error);
        });
  }

  let intentMap = new Map();
  intentMap.set('Explore uploaded image', applyML);
  agent.handleRequest(intentMap);
});


async function callVisionApi(agent, bucketName, fileName){
    // [START vision_text_detection_gcs]
  // Imports the Google Cloud client libraries
  // Creates a client
  
  const client = new vision.ImageAnnotatorClient();
    try {
        // Performs text detection on the gcs file
        const [result] = await client.landmarkDetection(`gs://${bucketName}/${fileName}`);
        const detections = result.landmarkAnnotations;
        var detected = [];
        detections.forEach(text => {
            console.log(text.description);
            detected.push(text.description);
        });
        return detected;
    }
    catch(error) {
        console.log('fetch failed', error);
        return [];
    }
}
  1. 次の内容を package.json に貼り付けて、内容を置き換えます。
{
  "name": "dialogflowFirebaseFulfillment",
  "description": "Dialogflow fulfillment for the bike shop sample",
  "version": "0.0.1",
  "private": true,
  "license": "Apache Version 2.0",
  "author": "Google Inc.",
  "engines": {
    "node": "6"
  },
  "scripts": {
    "lint": "semistandard --fix \"**/*.js\"",
    "start": "firebase deploy --only functions",
    "deploy": "firebase deploy --only functions"
  },
  "dependencies": {
    "firebase-functions": "2.0.2",
    "firebase-admin": "^5.13.1",
    "actions-on-google": "2.2.0", 
    "googleapis": "^27.0.0",
    "dialogflow-fulfillment": "^0.6.1",
    "@google-cloud/bigquery": "^1.3.0",
    "@google-cloud/storage": "^2.0.0",
    "@google-cloud/vision": "^0.25.0"
  }
}
  1. [保存] をクリックします。
  1. ローカルマシンにこのリポジトリのクローンを作成します。
https://github.com/priyankavergadia/visionapi-dialogflow.git
  1. コードが含まれているディレクトリに移動します。または、zip 形式でサンプルをダウンロードして展開することも可能です。
cd visionapi-dialogflow

デプロイ時に、アプリは App Engine スタンダード環境に組み込まれている Cloud SQL Proxy を使用して Cloud SQL インスタンスと通信します。ただし、アプリをローカルでテストするには、開発環境で Cloud SQL Proxy のローカルコピーをインストールして使用する必要があります。詳細については、Cloud SQL Proxy についてをご覧ください。

Cloud SQL インスタンスで基本的な管理タスクを行うには、Cloud SQL for MySQL クライアントを使用します。

Cloud SQL プロキシをインストールする

次のコマンドを使用して Cloud SQL Proxy をダウンロードしてインストールします。Cloud SQL Proxy は、ローカルで実行するときに Cloud SQL インスタンスに接続するために使用されます。

プロキシをダウンロードします。

curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64

プロキシを実行可能にする。

chmod +x cloud_sql_proxy

Cloud SQL インスタンスを作成する

  1. Cloud SQL for MySQL 第 2 世代のインスタンスを作成します。「polls-instance"」などの名前を付けます。インスタンスの準備が完了するまでに数分かかることがあります。準備が整うと、インスタンス リストに表示されます。
  2. gcloud コマンドライン ツールを使用して次のコマンドを実行します。[YOUR_INSTANCE_NAME] は Cloud SQL インスタンスの名前を表します。次のステップのために、connectionName に表示された値をメモします。[PROJECT_NAME]:[REGION_NAME]:[INSTANCE_NAME] の形式で表示されます。
gcloud sql instances describe [YOUR_INSTANCE_NAME]

または、コンソールでインスタンスをクリックしてインスタンス接続名を取得できます。

Cloud SQL インスタンスを初期化する

前のセクションの connectionName を使用して Cloud SQL Proxy を起動します。

./cloud_sql_proxy -instances="[YOUR_INSTANCE_CONNECTION_NAME]"=tcp:3306

[YOUR_INSTANCE_CONNECTION_NAME] は、前のセクションで記録した値に置き換えます。これにより、ローカル テストのためにローカル コンピュータから Cloud SQL インスタンスへの接続を確立します。ローカルでアプリをテストしている間、Cloud SQL Proxy を実行し続ける。

次に、新しい Cloud SQL ユーザーとデータベースを作成します。

  1. Google Cloud Console を使用して、Cloud SQL インスタンスに polls-instance という名前の新しいデータベースを作成します。たとえば、名前として「polls」と入力できます。
  2. Cloud Console で、polls-instance という名前の Cloud SQL インスタンスに新しいユーザーを作成します。

データベース設定を構成する

  1. mysite/settings-changeme.py を編集用に開きます。
  2. ファイルの名前を setting.py に変更します。
  3. [YOUR-USERNAME][YOUR-PASSWORD] を 2 か所で、前のセクションで作成したデータベースのユーザー名とパスワードに置き換えます。これは、App Engine のデプロイとローカルテストのためにデータベースとの接続を設定するのに役立ちます。
  4. ‘HOST': ‘cloudsql/ [PROJECT_NAME]:[REGION_NAME]:[INSTANC_E_NAME]&#39 の [PROJECT_NAME]:[REGION_NAME]:[INSTANCE_NAME] を、前のセクションで取得したインスタンス名に置き換えます。
  5. 次のコマンドを実行し、出力された connectionName 値を次のステップ用にコピーします。
gcloud sql instances describe [YOUR_INSTANCE_NAME]
  1. [YOUR-CONNECTION-NAME] は、前のステップで記録した値で置き換えます。
  2. [YOUR-DATABASE] は、前のセクションで選択した名前に置き換えます。
# [START db_setup]
if os.getenv('GAE_APPLICATION', None):
    # Running on production App Engine, so connect to Google Cloud SQL using
    # the unix socket at /cloudsql/<your-cloudsql-connection string>
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'HOST': '/cloudsql/[PROJECT_NAME]:[REGION_NAME]:[INSTANCE_NAME]',
            'USER': '[YOUR-USERNAME]',
            'PASSWORD': '[YOUR-PASSWORD]',
            'NAME': '[YOUR-DATABASE]',
        }
    }
else:
    # Running locally so connect to either a local MySQL instance or connect to
    # Cloud SQL via the proxy. To start the proxy via command line:
    #     $ cloud_sql_proxy -instances=[INSTANCE_CONNECTION_NAME]=tcp:3306
    # See https://cloud.google.com/sql/docs/mysql-connect-proxy
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'HOST': '127.0.0.1',
            'PORT': '3306',
            'NAME': '[YOUR-DATABASE]',
            'USER': '[YOUR-USERNAME]',
            'PASSWORD': '[YOUR-PASSWORD]'
        }
    }
# [END db_setup]
  1. settings.pyを閉じて保存します。
  1. Dialogflow のコンソールで、[] をクリックします。[General] タブで [Google Project] > [Project ID] に移動し、[Google Cloud] をクリックして Cloud Console を開きます。
  2. ナビゲーション メニュー ▾ > IAM と管理者 > [サービス アカウント] をクリックし、[Dialogflow の統合] の横にある をクリックして、[キーを作成] をクリックします。

  1. JSON ファイルがパソコンにダウンロードされます。このファイルは、以降のセットアップ セクションで必要になります。
  1. チャット フォルダで、key-sample.json を認証情報の JSON ファイルに置き換え、key.json という名前を付けます。
  2. チャット フォルダの views.py で、GOOGLE_PROJECT_ID = "<YOUR_PROJECT_ID>" をプロジェクト ID に変更します。

フロントエンドの静的オブジェクトに対応する Cloud Storage バケットを作成する

  1. Cloud Console で、ナビゲーション メニュー BlobInfo &[ストレージ] をクリックします。

  1. [バケットを作成] をクリックします。
  2. グローバルに一意の名前を指定します。

  1. データの保存場所の選択[リージョン] を選択して、ニーズに最適なロケーションを選択します。
  2. デフォルトのストレージ クラスとして [Standard] を選択します。

  1. [バケットレベルで均一な権限を設定する(バケット ポリシーのみ)] をオンにし、[続行] をクリックしてバケットを作成します。

  1. バケットを作成したら、ナビゲーション メニュー BlobInfo > [ストレージ] > [ブラウザ] をクリックし、作成したバケットを見つけます。

  1. 対応するバケットの横にある をクリックし、[バケットの権限を編集] をクリックします。

  1. [メンバーを追加] をクリックし、[新しいメンバー] をクリックして「allUsers」と入力します。次に、[ロールを選択] > [Storage オブジェクト閲覧者] をクリックします。allUsers に静的フロントエンド ファイルへのアクセス権を付与します。これはファイルにとって理想的なセキュリティ設定ではありませんが、この Codelab には向いています。

ユーザーがアップロードした画像用の Cloud Storage バケットを作成する

同じ手順で、ユーザー画像をアップロードするバケットを別途作成します。権限を再度「allUsers」に設定します。ただし、ロールとして [Storage オブジェクト作成者] と [Storage オブジェクト閲覧者] を選択します。

settings.py で Cloud Storage バケットを構成する

  1. mysite/setting.py を開きます。
  2. GCS_BUCKET 変数を見つけて、‘<YOUR-GCS-BUCKET-NAME>' を Cloud Storage の静的バケットに置き換えます。
  3. GS_MEDIA_BUCKET_NAME 変数を見つけて、‘<YOUR-GCS-BUCKET-NAME-MEDIA>' を画像の Cloud Storage バケット名に置き換えます。
  4. GS_STATIC_BUCKET_NAME 変数を見つけて、‘<YOUR-GCS-BUCKET-NAME-STATIC>' を静的ファイルの Cloud Storage バケット名に置き換えます。
  5. ファイルを保存します。
GCS_BUCKET = '<YOUR-GCS-BUCKET-NAME>'
GS_MEDIA_BUCKET_NAME = '<YOUR-GCS-BUCKET-NAME-MEDIA>'
GS_STATIC_BUCKET_NAME = '<YOUR-GCS-BUCKET-NAME-STATIC>'

home.html で Cloud Storage バケットを構成する

  • チャット フォルダを開き、templates を開いて home-changeme.html の名前を home.html に変更します。
  • <YOUR-GCS-BUCKET-NAME-MEDIA> を探し、ユーザーがアップロードしたファイルを保存するバケット名に置き換えます。これにより、ユーザーがアップロードしたファイルをフロントエンドに保存し、静的アセットを Cloud Storage バケットに保持することがなくなります。Vision API は Cloud Storage バケットを呼び出して、ファイルを取得し、予測を行います。

ローカル コンピュータ上で Django アプリを実行するには、Python、pip、virtualenv などの Python 開発環境をセットアップする必要があります。手順については、Python 開発環境の設定をご覧ください。

  1. 分離された Python 環境を作成し、依存関係をインストールする。
virtualenv env
source env/bin/activate
pip install -r requirements.txt
  1. Django の移行を実行して、モデルを設定します。
python3 manage.py makemigrations
python3 manage.py makemigrations polls
python3 manage.py migrate
  1. ローカルのウェブサーバーを起動します。
python3 manage.py runserver
  1. ウェブブラウザで http://localhost:8000/ に移動します。次のようなシンプルなウェブページが表示されます。

サンプルアプリのページは、パソコン上で実行されている Django ウェブサーバーによって配信されます。次に進む準備ができたら、Control+C(Macintosh では Command+C)を押してローカル ウェブサーバーを停止します。

Django 管理コンソールを使用する

  1. スーパーユーザーを作成します。
python3 manage.py createsuperuser
  1. ローカルのウェブサーバーを起動します。
python3 manage.py runserver
  1. ウェブブラウザで http://localhost:8000/admin/ に移動します。管理サイトにログインするには、createsuperuser を実行したときに作成したユーザー名とパスワードを入力します。

次のコマンドを実行して、すべての静的コンテンツを 1 つのフォルダにまとめます。これにより、アプリのすべての静的ファイルが settings.pySTATIC_ROOT で指定されたフォルダに移動します。

python3 manage.py collectstatic

app.yaml ファイルがあるアプリのディレクトリから次のコマンドを実行して、アプリをアップロードします。

gcloud app deploy

更新が完了したことを通知するメッセージが表示されるまで待ちます。

ウェブブラウザで、https://<your_project_id>.appspot.com に移動します。

今回は、App Engine スタンダード環境で実行されているウェブサーバーによってリクエストが処理されます。

app deploy コマンドは、app.yaml で説明しているようにアプリをデプロイし、新しくデプロイされたバージョンをデフォルト バージョンとして設定して、すべての新しいトラフィックを処理できるようにします。

本番環境でコンテンツを配信する準備ができたら、mysite/settings.pyDEBUG 変数を False に変更します。

シミュレータでチャットボットをテストしたり、以前作成したウェブまたは Google Home の統合機能を使用したりできます。

  1. ユーザー: "hi"
  2. Chatbot: 「こんにちは!画像をアップロードしてランドマークを探すことができます。
  3. ユーザーが画像をアップロードします。

このイメージをダウンロードして、demo.jpg という名前を付け、使用します。

  1. Chatbot: ファイルを処理しています。結果は次のとおりです。ゴールデン ゲート ブリッジ、ゴールデン ゲート ナショナル レクリエーション エリア、ゴールデン ゲート ブリッジ、ゴールデン ゲート ブリッジ、ゴールデン ゲート ブリッジ。"

以下のようになります。

他の Dialogflow Codelab を完了するには、このセクションをスキップして後で行ってください。

Dialogflow エージェントを削除する

  1. 既存のエージェントの横にある をクリックします。

  1. [General] タブで下にスクロールし、[Delete This Agent] をクリックします。
  2. 表示されたウィンドウに「削除」と入力し、[削除] をクリックします。

Dialogflow で chatbot を作成し、Vision API と統合しました。あなたは chatbot デベロッパーになりました

詳細

詳細については、Dialogflow GitHub のコードサンプルをご覧ください。