整合 Vision API 與 Dialogflow

1. 事前準備

在本程式碼研究室中,您會將 Vision API 與 Dialogflow 整合,以針對使用者提供的圖片輸入內容提供豐富的動態機器學習技術回應。您將建立一個聊天機器人應用程式,以圖片做為輸入內容,並在 Vision API 中進行處理,然後將已辨識的地標傳回給使用者。舉例來說,如果使用者上傳泰姬瑪哈陵的圖片,則聊天機器人會傳回泰姬瑪哈陵做為回應。

這項功能很實用,因為您可以分析圖片中的項目,並對取得的資訊採取行動。您也可以建立退款處理系統,協助使用者上傳收據、擷取收據中的購買日期,以及在適當日期處理退款。

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

使用者:您好:

聊天機器人:嗨!你可以上傳相片,探索地標

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

聊天機器人:檔案正在處理中,結果如下:泰姬瑪哈陵、泰姬瑪哈陵、泰姬瑪哈陵。

15a4243e453415ca.png

必要條件

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

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

您也需要瞭解 Dialogflow 的基本概念和建構,請參考以下「使用 Dialogflow 建構聊天機器人」課程的影片:

課程內容

  • 如何建立 Dialogflow 虛擬服務專員
  • 如何更新 Dialogflow 代理程式來上傳檔案
  • 如何透過 Dialogflow 執行要求設定 Vision API 連線
  • 如何設定及執行 Dialogflow 的 Django 前端應用程式
  • 如何在 App Engine 中將 Django 前端應用程式部署至 Google Cloud
  • 如何透過自訂前端測試 Dialogflow 應用程式

建構項目

  • 建立 Dialogflow 虛擬服務專員
  • 實作 Django 前端以上傳檔案
  • 實作 Dialogflow 執行要求,以便針對上傳的圖片叫用 Vision API

軟硬體需求

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

2. 架構總覽

您將透過自訂的 Django 前端打造全新的對話體驗,並擴充該介面以與 Vision API 整合。您將使用 Django 架構建構前端、在本機執行和測試,然後將其部署至 App Engine。前端應如下所示:

5b07e09dc4b84646.png

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

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

153725eb50e008d4.png

以下是整體架構的樣貌。

a2fcea32222a9cb4.png

3. 什麼是 Vision API?

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

4. 建立 Dialogflow 虛擬服務專員

  1. 前往 Dialogflow 主控台
  2. 登入即可(如果您是初次使用,請使用電子郵件地址註冊)。
  3. 接受條款及細則後,您就會進入控制台。
  4. 按一下「d9e90c93fc779808.png」並捲動至底部,然後按一下「Create new agent」3b3f9677e2a26d93.png
  5. 輸入「VisionAPI」做為代理程式名稱
  6. 按一下「建立」

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

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

目前您有一個功能機器人,會問候使用者。不過,您必須更新機器人,使用者才能上傳圖片探索地標。

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

  1. 點選 [Default Welcome Intent] (預設的歡迎意圖)。
  2. 前往「回應」>預設 >Text 或 SSML Response (文字或 SSML 回應),然後輸入「Hi!你可以上傳相片,探索地標。」

f9cd9ba6917a7aa9.png

建立實體

  1. 按一下「實體」

432fff294b666c93.png

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

602d001d684485de.png

建立新意圖

  1. 按一下「Intents」>建立意圖
  2. 輸入「探索上傳的圖片」意圖名稱
  3. 按一下「訓練詞組」>新增訓練詞組,然後輸入「file is demo.jpg」,「檔案為 taj.jpeg」做為使用者運算式,並以 @filename 做為實體

dd54ebda59c6b896.png

  1. 按一下「回覆」>新增回應 >預設 >文字或 SSML 回應。輸入「評估檔案」然後按一下「新增回應」
  2. 按一下「執行要求」>啟用執行要求,然後開啟「為這個意圖啟用 Webhook 呼叫」

b32b7ac054fcc938.png

5. 設定執行要求以與 Vision API 整合

  1. 按一下「執行要求」
  2. 啟用「Inline Editor」(內嵌編輯器)

c8574c6ef899393f.png

  1. 使用下列程式碼更新 index.js,並將 YOUR-BUCKET-NAME 更新為 Cloud Storage 值區名稱。
'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. 按一下 [儲存]

6. 下載並執行前端應用程式

  1. 將這個存放區複製到本機電腦:
https://github.com/priyankavergadia/visionapi-dialogflow.git
  1. 變更為包含程式碼的目錄。您也可以透過 ZIP 格式下載範例,然後解壓縮。
cd visionapi-dialogflow

7. 設定本機環境

部署完成後,應用程式會使用 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]

或者,您也可以點選控制台中的執行個體,取得「執行個體連線名稱」

c11e94464bf4fcf8.png

初始化 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 控制台,為名為 polls-instance 的 Cloud SQL 執行個體建立新資料庫。例如,您可以輸入「polls」(意見調查)做為名稱a3707ec9bc38d412.png
  2. 使用 Cloud 控制台,為名為 polls-instance 的 Cloud SQL 執行個體建立新使用者。f4d098fca49cccff.png

進行資料庫設定

  1. 開啟 mysite/settings-changeme.py 進行編輯。
  2. 將檔案重新命名為 setting.py
  3. [YOUR-USERNAME][YOUR-PASSWORD] 兩處,替換為您在上一節建立的資料庫使用者名稱和密碼。這有助於為 App Engine 部署和本機測試設定連至資料庫的連線。
  4. ‘HOST': ‘cloudsql/ [PROJECT_NAME]:[REGION_NAME]:[INSTANCE_NAME] 行將 [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

8. 設定服務帳戶

  1. 在 Dialogflow 的主控台中,按一下 21a21c1104f5fdf3.png。在「General」分頁中,前往「Google Project」>「專案 ID」,然後按一下「Google Cloud」圖示 7b2236f5627c37a0.png 來開啟 Cloud 控制台。a4cfb880b3c8e789.png
  2. 依序點選「導覽選單」圖示 ⋮ >身分與存取權管理與管理 >按一下「服務帳戶」,然後點選「Dialogflow 整合」旁的「796e7c9e65ae751f.png」,然後點選「建立金鑰」

3d72abc0c184d281.png

  1. JSON 檔案會下載到您的電腦,您在下列設定章節中會用到這個檔案。

9. 設定要從應用程式呼叫的 Dialogflow 偵測意圖端點

  1. 在聊天資料夾中,將 key-sample.json 替換為憑證 JSON 檔案,並將其命名為 key.json
  2. 在聊天資料夾的 views.py 中,將 GOOGLE_PROJECT_ID = "<YOUR_PROJECT_ID>" 變更為您的專案 ID。

10. 建立 Cloud Storage 值區

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

  1. 在 Cloud 控制台中,按一下「導覽」選單 >儲存空間

87ff9469db4eb77f.png

  1. 按一下「建立值區」
  2. 請提供全域不重複的名稱。

a15a6612e92a39d3.png

  1. 選擇資料的儲存位置。選擇「區域」,然後選取最符合需求的位置。
  2. 選取「Standard」做為預設儲存空間級別。

9c56abe632cf61db.png

  1. 選擇「Set permissions uniformly at bucket-level (Bucket Policy Only)」(統一設定值區層級的權限 (僅值區政策)),然後按一下「Continue」(繼續) 以建立值區。

f175ac794049df04.png

  1. 建立值區後,點選「導覽選單」圖示 ⋮ >儲存空間 >Browser (瀏覽器) 並找出您建立的值區。

9500ee19b427158c.png

  1. 按一下對應值區旁的 796e7c9e65ae751f.png,然後點選「編輯值區權限」

fd0a310bc3656edd.png

  1. 點選「新增成員」,點選「新成員」並輸入「allUsers」然後按一下「請選擇角色」>Storage 物件檢視者。這個外掛程式能向 allUsers 授予靜態前端檔案的檢視存取權。這不是理想的檔案安全性設定,但可在本程式碼研究室中派上用場。

7519116abd56d5a3.png

建立 Cloud Storage 值區以儲存使用者上傳的圖片

按照相同操作說明建立單獨的值區來上傳使用者圖片。將權限設為「allUsers」再次選取「Storage 物件建立者」和「Storage 物件檢視者」角色。

11. 設定前端應用程式中的 Cloud 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 值區來挑選檔案並進行預測。

12. 在本機建構並執行應用程式

若要在本機電腦上執行 Django 應用程式,您必須設定 Python 開發環境,包括 Python、pip 和 virtualenv。如需操作說明,請參閱「設定 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/。您應該會看到類似下方的簡易網頁:

8f986b8981f80f7b.png

範例應用程式頁面是由在您電腦上執行的 Django 網路伺服器提供。當您準備好繼續時,請按下 Control+C (在 Macintosh 上為 Command+C) 停止本機網路伺服器。

使用 Django 管理控制台

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

13. 將應用程式部署至 App Engine 標準環境

執行下列指令,將所有靜態內容收集到一個資料夾,這個指令會將應用程式的所有靜態檔案移至 settings.pySTATIC_ROOT 指定的資料夾:

python3 manage.py collectstatic

app.yaml 檔案所在的應用程式目錄執行下列指令,即可上傳應用程式:

gcloud app deploy

等候更新完成通知訊息。

14. 測試前端應用程式

透過網路瀏覽器前往 https://<您的專案 ID>.appspot.com

這次您的要求是由在 App Engine 標準環境執行的網路伺服器提供。

app deploy 指令會依照 app.yaml 中的說明部署應用程式,並將新部署的版本設為預設版本,藉此提供所有新流量。

15. 正式環境

如果您已準備好在實際工作環境提供內容,請將 mysite/settings.py 中的 DEBUG 變數變更為 False

16. 測試聊天機器人

你可以使用模擬器測試聊天機器人,或使用先前建構的網路或 Google Home 整合功能。

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

請下載並使用這張圖片並命名為 demo.jpg

c3aff843c9f132e4.jpeg

  1. 聊天機器人:「檔案正在處理中,結果如下:金門大橋, 金門大橋國家休閒區, 金門大橋, 金門大橋, 金門大橋」。

整體而言,它看起來會像這樣:

228df9993bfc001d.png

17. 清除所用資源

如果您想完成其他 Dialogflow 程式碼研究室,請略過本部分,之後再返回查看。

刪除 Dialogflow 虛擬服務專員

  1. 按一下現有服務專員旁邊的 ca4337eeb5565bcb.png

520c1c6bb9f46ea6.png

  1. 在「General」分頁中,向下捲動並點選 [Delete this Agent]
  2. 在隨即出現的視窗中輸入 Delete,然後按一下「Delete」(刪除)

18. 恭喜

您已在 Dialogflow 中建立聊天機器人,並將其與 Vision API 整合。你已成為聊天機器人開發人員!

瞭解詳情

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