将 Vision API 与 Dialogflow 集成

1. 准备工作

在此 Codelab 中,您会将 Vision API 与 Dialogflow 集成,以便为用户提供的图片输入提供基于机器学习的丰富响应。您将创建一个聊天机器人应用,该应用将图片作为输入,在 Vision API 中对其进行处理,然后向用户返回已识别的地标。例如,如果用户上传泰姬陵的图片,聊天机器人将返回“泰姬陵”作为响应。

这非常有用,因为您可以分析图片中的项,并根据获得的信息采取行动。您还可以构建一个退款处理系统来帮助用户上传收据、在收据中提取购买日期,并在日期适当的情况下处理退款。

请查看以下示例对话框:

用户:嗨

聊天机器人:嗨!您可以上传图片以探索地标

用户:上传一张展现泰姬陵的图片。

聊天机器人:正在处理文件,以下是结果:Taj Mahal、Taj Mahal Garden、Taj Mahal。

15a4243e453415ca

前提条件

在继续操作之前,您需要完成以下 Codelab:

  1. 使用 Dialogflow 构建预约安排程序
  2. 将 Dialogflow 聊天机器人与 Actions on Google 集成
  3. 了解 Dialogflow 中的实体
  4. 为 Dialogflow 应用构建前端 Django 客户端

您还需要了解 Dialogflow 的基本概念和结构,您可以从使用 Dialogflow 构建聊天机器人在线课程的以下视频中获得这些信息:

学习内容

  • 如何创建 Dialogflow 代理
  • 如何更新 Dialogflow 代理以上传文件
  • 如何设置 Vision API 与 Dialogflow 执行方式的连接
  • 如何为 Dialogflow 设置和运行 Django 前端应用
  • 如何将 Django 前端应用部署到 App Engine 上的 Google Cloud
  • 如何从自定义前端测试 Dialogflow 应用

构建内容

  • 创建 Dialogflow 代理
  • 实现 Django 前端以上传文件
  • 实现 Dialogflow fulfillment 以针对上传的图片调用 Vision API

所需条件

  • Python 基础知识
  • 对 Dialogflow 有基本的了解
  • 对 Vision API 有基本的了解

2. 架构概览

您将使用自定义 Django 前端打造新的对话体验,并将其扩展为与 Vision API 集成。您将使用 Django 框架构建前端,在本地运行和测试该前端,然后将其部署到 App Engine。前端如下所示:

5b07e09dc4b84646

请求流程的运作方式如下图所示:

  1. 用户将通过前端发送请求。
  2. 这将触发对 DialogflowdetectIntent API 的调用,以将用户话语映射到正确的意图。
  3. 检测到探索地标 intent 后,Dialogflow fulfillment 会向 Vision API 发送请求,接收响应并将其发送给用户。

153725eb50e008d4

整体架构如下所示。

a2fcea32222a9cb4.png

3. 什么是 Vision API?

Vision API 是一种预训练的机器学习模型,可从图片中提取实用信息。它可以帮助您获取多种数据洞见,包括图片标记、人脸和地标检测、光学字符识别以及露骨内容的标记。如需了解详情,请参阅 Vision AI

4. 创建 Dialogflow 代理

  1. 转到 Dialogflow 控制台
  2. 登录。(如果您是首次使用,请使用您的电子邮件地址注册。)
  3. 接受条款及条件,即可进入控制台。
  4. 点击 d9e90c93fc779808.png,滚动到底部,然后点击创建新代理3b3f9677e2a26d93
  5. 输入“VisionAPI”作为代理名称
  6. 点击创建

Dialogflow 会创建以下两个默认意图作为代理的一部分:

  1. 默认欢迎 intent 用于向用户发出问候。
  2. 默认后备 intent 可捕获聊天机器人不能理解的所有问题。

至此,您已经有一个可欢迎用户的功能型聊天机器人,但您需要对其进行更新,让用户知道他们可以上传图片来探索地标。

更新默认欢迎 intent 以通知用户上传图片

  1. 点击默认欢迎意图 (Default Welcome Intent)。
  2. 转到响应 >默认 >文本或 SSML 响应并输入“Hi!您可以上传图片以探索地标。"

f9cd9ba6917a7aa9.png

创建实体

  1. 点击实体

432fff294b666c93

  1. 点击创建实体,将其命名为“filename”。然后点击保存

602d001d684485de

创建新意图

  1. 点击意图 >创建 intent
  2. 输入“探索上传的图片”用作意图名称
  3. 点击训练短语 >添加训练短语并输入“file is demo.jpg”“file is taj.jpeg”以 @filename 作为实体的用户表达式。

dd54ebda59c6b896.png

  1. 点击回复 >添加回复 >默认 >文本或 SSML 响应。输入“正在评估文件”然后点击添加回复
  2. 点击 Fulfillment >启用 fulfillment 并开启为此意图启用 webhook 调用

b32b7ac054fcc938.png

5. 设置 fulfillment 以与 Vision API 集成

  1. 点击 Fulfillment
  2. 启用内嵌编辑器

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 代理,与您的 Cloud SQL 实例进行通信。但是,如需在本地测试应用,您必须在开发环境中安装和使用 Cloud SQL 代理的本地副本。如需了解详情,请参阅 Cloud SQL 代理简介

如需在 Cloud SQL 实例上执行基本管理任务,您可以使用 Cloud SQL for MySQL 客户端。

安装 Cloud SQL 代理

使用以下命令下载并安装 Cloud SQL 代理。Cloud SQL 代理用于在本地运行时连接到您的 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 第二代实例。输入 "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 代理。

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

[YOUR_INSTANCE_CONNECTION_NAME] 替换为您在上一部分中记录的值。这将建立从本地计算机到 Cloud SQL 实例的连接,以进行本地测试。在您对应用进行本地测试的整个过程中,请确保 Cloud SQL 代理一直运行。

接下来,创建一个新的 Cloud SQL 用户和数据库。

  1. 使用 Google Cloud 控制台为 Cloud SQL 实例创建一个名为 polls-instance 的新数据库。例如,您可以输入“polls”作为名称。a3707ec9bc38d412.png
  2. 使用 Cloud Console 为您的 Cloud SQL 实例创建一个名为 polls-instance 的新用户。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。在常规标签页中,前往 Google 项目 >项目 ID,然后点击 Google Cloud7b2236f5627c37a0 打开 Cloud 控制台。a4cfb880b3c8e789.png
  2. 点击导航菜单 ☰ >IAM 和管理 >服务账号,然后点击 Dialogflow 集成旁边的 796e7c9e65ae751f,再点击创建密钥

3d72abc0c184d281

  1. 系统会将 JSON 文件下载到您的计算机上,您在后续设置部分需要用到此文件。

9. 设置要从应用中调用的 DialogflowdetectIntent 端点

  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

  1. 点击创建存储桶
  2. 提供全局唯一的名称。

a15a6612e92a39d3.png

  1. 选择数据存储位置。选择区域,然后选择最符合您需求的位置。
  2. 选择标准作为默认存储类别。

9c56abe632cf61db

  1. 选择在存储分区级统一设置权限(仅限存储分区政策),然后点击继续以创建存储分区。

f175ac794049df04.png

  1. 创建存储分区后,点击导航菜单 ☰ >存储 >浏览器 (Browser),然后找到您创建的存储分区。

9500ee19b427158c

  1. 点击相应存储分区旁边的 796e7c9e65ae751f,然后点击修改存储分区权限

fd0a310bc3656edd.png

  1. 点击添加成员,点击新成员,输入“allUsers”。然后点击选择角色 >Storage Object Viewer。这将为 allUsers 提供对静态前端文件的查看权限。这不是文件理想的安全设置,但适用于此特定 Codelab。

7519116abd56d5a3

为用户上传的图片创建 Cloud Storage 存储分区

按照相同的说明创建一个单独的存储分区来上传用户图片。将权限设置为“allUsers”但要选择 Storage Object CreatorStorage Object Viewer 作为角色。

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”

示例应用页面由您的计算机上运行的 Django Web 服务器提供。准备好继续操作后,请按 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.py 中的 STATIC_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. 测试聊天机器人

您可以在模拟器中测试聊天机器人,也可以使用之前构建的 Web 或 Google Home 集成。

  1. 用户:“hi”
  2. 聊天机器人:“Hi!您可以上传图片以探索地标。"
  3. 用户上传图片。

下载此图片,将其命名为 demo.jpg 并使用它。

c3aff843c9f132e4.jpeg

  1. 聊天机器人:“文件正在处理中,以下是结果:金门大桥,金门国家休闲区,金门大桥,金门大桥,金门大桥。”

总体而言,它应如下所示:

228df9993bfc001d

17. 清理

如果您想完成其他 Dialogflow Codelab,请跳过此部分,稍后再回来查看。

删除 Dialogflow 代理

  1. 点击现有代理旁边的 ca4337eeb5565bcb.png

520c1c6bb9f46ea6

  1. 常规标签页中,向下滚动并点击删除此代理
  2. 在出现的窗口中输入 Delete,然后点击删除

18. 恭喜

您在 Dialogflow 中创建了一个聊天机器人,并将其与 Vision API 集成。您现在已经是聊天机器人开发者了!

了解详情

如需了解详情,请查看 Dialogflow GitHub 页面上的代码示例。