將 Vision API 與 Dialogflow 整合

在這個程式碼研究室中,您將將 Vision API 與 Dialogflow 整合,以針對使用者提供的圖片輸入提供豐富且動態的機器學習回應。您將建立一個聊天機器人應用程式,以在圖片中進行輸入、在 Vision API 中處理圖片,並將識別出的地標傳回給使用者。例如,如果使用者上傳泰姬瑪哈陵的圖片,聊天機器人就會傳回泰姬瑪哈陵的回覆。

這很有用,因為您可以對圖片中的項目進行分析,並對取得的資訊採取行動。您也可以建構退款處理系統,協助使用者上傳收據、擷取收據中的購買日期,並視情況處理退款。

請查看下列範例對話方塊:

使用者:您好

聊天機器人:嗨!您可以上傳圖片來探索地標

使用者:上傳含有泰姬瑪哈陵的圖片。

Chatbot:檔案正在處理中,結果為:Taj Mahal、Taj Mahal Garden、Taj Mahal。

必要條件

如要繼續操作,請先完成下列程式碼研究室:

  1. 使用 Dialogflow 建立預約時間表
  2. 將 Dialogflow 聊天機器人與 Actions on Google 整合
  3. 瞭解 Dialogflow 中的實體
  4. 為 Dialogflow 應用程式建構前端 Ruby 用戶端

您也必須瞭解 Dialogflow 的基本概念和結構。如有需要,您可以觀看下方透過 Dialogflow 建構聊天機器人課程影片:

課程內容

  • 如何建立 Dialogflow 代理程式
  • 如何更新 Dialogflow 代理程式以上傳檔案
  • 如何設定與 Dialogflow 履行的 Vision API 連線
  • 如何設定及執行 Dialogflow 的 Ruby 前端應用程式
  • 如何在 App Engine 上將 Ruby 前端應用程式部署至 Google Cloud
  • 如何從自訂前端測試 Dialogflow 應用程式

建構項目

  • 建立 Dialogflow 代理程式
  • 實作 Ruby 前端以上傳檔案
  • 實作 Dialogflow 的實作,以對上傳的圖片叫用 Vision API

軟硬體需求

  • Python 基本知識
  • 對 Dialogflow 有基本瞭解
  • 瞭解 Vision API 的基本知識

您將透過自訂的 Ruby 前端建立新的對話體驗,並將這些服務應用程序與 Vision API 整合。您將使用 Ruby 架構建構前端,在本機執行並進行測試,然後將它部署至 App Engine。前端看起來會像這樣:

要求流程的運作方式如下圖所示:

  1. 使用者會透過前端傳送要求。
  2. 這樣就會觸發 Dialogflow 偵測意圖 API 的呼叫,將使用者的語音內容對應至正確的意圖。
  3. 偵測到探索地標意圖後,Dialogflow 執行要求就會傳送要求至 Vision API,接收回應並傳送給使用者。

以下是整體架構的外觀。

Vision API 是預先訓練的機器學習模型,從圖片取得深入分析資訊。應用程式提供多項深入分析,包括圖片標籤、臉部和地標偵測、光學字元辨識,以及為煽情露骨內容加上標記等。詳情請參閱 Vision AI

  1. 前往 Dialogflow 主控台
  2. 登入即可(如果你是初次使用,請用電子郵件申請帳戶)。
  3. 接受條款及細則,您就會在主控台中看到。
  4. 按一下 [],捲動至底部,然後按一下 [Create newagent]

5. 在 [Agent name] (代理程式名稱) 中輸入「quos;VisionAPI&hlt;」

  1. 按一下「Create」(建立)

Dialogflow 會在代理程式中建立以下兩個預設意圖:

  1. 預設的歡迎意圖會歡迎使用者。
  2. 預設備用意圖會擷取機器人不瞭解的所有問題。

此時,您開發的機器人能滿足使用者的需求,但您需要更新機器人,讓使用者知道他們可以上傳圖片來探索地標。

更新預設的歡迎意圖,通知使用者上傳圖片

  1. 點選 [Default Welcome Intent] (預設的歡迎意圖)。
  2. 瀏覽至 Responses > Default > Text or SSML Response,然後輸入 "Hi!您可以上載相片來探索地標。」

建立實體

  1. 按一下 [實體]

  1. 按一下 [建立實體],將其命名為「檔案名稱」,然後按一下 [儲存]

建立新意圖

  1. 按一下 [Intents] (意圖) > [Create Intent] (建立意圖)
  2. 輸入「探索已上傳的圖片」做為「意圖名稱」。
  3. [訓練詞組] > [新增訓練詞組],然後輸入「file」為 demo.jpg,且「file 是 taj.jpeg」;以 @filename 為實體的使用者運算式。

  1. 按一下 [Responses] > [Add Response] > Default > Text or SSML Response。輸入「評估檔案」,然後按一下 [新增回應]。
  1. 點選 [Fulfillment] (執行要求) > [Enable fulfillment] (啟用執行要求),然後開啟 [Enable Webhook call for thisIntent] (啟用這個意圖的 Webhook 呼叫)

  1. 按一下 [執行要求]
  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 執行個體上執行基本管理員工作,您可以使用 MySQL 適用的 Cloud SQL 用戶端。

安裝 Cloud SQL Proxy

使用下列指令下載並安裝 Cloud SQL Proxy。在本機執行時,Cloud SQL Proxy 可用來連線至 Cloud SQL 執行個體。

下載 Proxy:

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

將 Proxy 設為可執行。

chmod +x cloud_sql_proxy

建立 Cloud SQL 執行個體

  1. 建立 MySQL 適用的 Cloud SQL 第二代執行個體。輸入 "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 為名為 polls-instance 的 Cloud SQL 執行個體建立新資料庫。舉例來說,你可以輸入「polls」做為名稱。
  2. 使用 Cloud Console 為名為 polls-instance 的 Cloud SQL 執行個體建立新使用者。

進行資料庫設定

  1. 開啟「mysite/settings-changeme.py」進行編輯。
  2. 將檔案重新命名為 setting.py
  3. 在兩個地方,將 [YOUR-USERNAME][YOUR-PASSWORD] 替換為您在上一節建立的資料庫使用者名稱和密碼。這有助於設定資料庫連線,以便進行 App Engine 部署和本機測試。
  4. ‘HOST': ‘cloudsql/ [PROJECT_NAME]:[REGION_NAME]:[INSTANCE_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 中,按一下 。在 [一般] 分頁中,前往 [Google 專案] > [專案 ID],然後按一下 [Google Cloud] 開啟 Cloud Console。
  2. 按一下 [導覽] 選單 ☰ > [IAM 與管理]

  1. JSON 檔案會下載到您的電腦,在以下的設定部分中需要您下載該檔案。
  1. 在即時通訊資料夾中,將 key-sample.json 替換為您的憑證 JSON 檔案,並命名為 key.json
  2. 在即時通訊資料夾的「views.py」中,將「GOOGLE_PROJECT_ID = "<YOUR_PROJECT_ID>"」改成您的專案 ID。

為前端靜態物件建立 Cloud Storage 值區

  1. 在 Cloud Console 中,依序按一下 [導覽選單] ☰ > [儲存空間]

  1. 按一下 [Create Bucket] (建立值區)
  2. 輸入全域專屬的名稱。

  1. 選擇資料的儲存位置。選取 [地區],然後選取最符合需求的位置。
  2. 選擇 [Standard] (標準) 做為預設的儲存空間級別。

  1. 選擇 [在值區層級設定統一權限 (僅值區政策)],然後按一下 [繼續] 來建立值區。

  1. 建立值區後,請依序按一下 [導覽選單 ☰ ] > [儲存空間] > [瀏覽器],然後找出您建立的值區。

  1. 在對應的值區旁邊按一下 ,然後點選 [編輯值區權限]

  1. 按一下 [Add Members] (新增成員),然後點選 [New members] (新增成員),輸入「&alltallall,」,然後再點選 [Select a role] (選取角色) > [Storage Object Viewer] (儲存空間物件檢視者)。如此一來,您就能存取 allUsers 的靜態前端檔案。對檔案來說,這並不是理想的安全設定,但適合用於這個特定程式碼研究室。

為使用者上傳的映像檔建立 Cloud Storage 值區

如要建立使用者圖片,請依相同指示建立個別的值區。再次將權限設為「allUsers」,但請選取 [Storage Object Creator] 和 [Storage Object Viewer] 做為角色。

在 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 值區來擷取檔案並進行預測。

如要在本機電腦上執行 Ruby 應用程式,您必須設定 Python 開發環境,包括 Python、pip 及 virtualenv。如需操作說明,請參閱設定 Python 開發環境

  1. 建立獨立的 Python 環境並安裝依附元件。
virtualenv env
source env/bin/activate
pip install -r requirements.txt
  1. 執行 Ruby 遷移作業以設定模型。
python3 manage.py makemigrations
python3 manage.py makemigrations polls
python3 manage.py migrate
  1. 啟動本機網路伺服器。
python3 manage.py runserver
  1. 在您的網路瀏覽器中,瀏覽至 http://localhost:8000/。您應該會看到如下的簡單網頁:

範例應用程式的網頁是由您電腦上的 Ruby 網路伺服器所傳送。當你準備好繼續瀏覽時,請按下 Control+C (Macintosh 上的 Command+C) 以停止本機網路伺服器。

使用 Django 管理控制台

  1. 建立超級使用者。
python3 manage.py createsuperuser
  1. 啟動本機網路伺服器。
python3 manage.py runserver
  1. 透過網路瀏覽器前往 http://localhost:8000/admin/。如要登入管理員網站,請輸入您在執行 createsuperuser 時建立的使用者名稱和密碼。

執行下列指令,將所有靜態內容收集到一個資料夾中,方法是將所有的應用程式靜態檔案移入 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.py 中將 DEBUG 變數變更為 False

您可以在模擬工具中測試聊天機器人,或使用原先建立的 Google Home 網頁版或 Google Home 整合功能。

  1. 使用者:「hi」
  2. 聊天機器人:“嗨!您可以上載相片來探索地標。」
  3. 使用者上傳圖片。

下載這張圖片並命名為 demo.jpg,然後開始使用。

  1. Chatbot: “檔案正在處理中,以下是結果:Gold Gate Bridge, Golden Gate National Recreation Area, Golden Gate Bridge, Golden Gate Bridge, Golden Gate Bridge.”

整體來說,這看起來應該像這樣:

如果您想要完成其他 Dialogflow 程式碼研究室,請略過這個部分,稍後再回來查看。

刪除 Dialogflow 代理程式

  1. 按一下現有代理程式旁邊的 []。

  1. 在「一般」分頁中向下捲動,然後按一下 [刪除這個代理程式]
  2. 在顯示的視窗中輸入 Delete,然後按一下 [Delete]

您在 Dialogflow 中建立了一個聊天機器人,並將其與 Vision API 整合。你現在是聊天機器人開發人員了!

瞭解詳情

如要瞭解詳情,請前往 Dialogflow Github 頁面查看程式碼範例。