将 Vision API 与 Dialogflow 集成

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

这非常有用,因为您可以分析图片中的内容,并对获得的信息执行操作。您还可以构建退款处理系统,帮助用户上传收据,在收据中提取购买日期,并在适当的日期处理退款。

我们来看看以下示例对话框:

用户:Hi.

聊天机器人:Hi!You can upload a picture to explore landmarks

用户:Upload an image with Taj Mahal in it.

聊天机器人:File is being processed, here are the results: Taj Mahal, Taj Mahal Garden, Taj Mahal.

前提条件

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

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

还需要了解 Dialogflow 的基本概念和结构,您可以从使用 Dialogflow 构建聊天机器人路径中的以下视频中获取这些内容:

要学习的内容

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

要构建的内容

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

所需条件

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

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

请求流将按照下图所示的方式工作:

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

整体架构如下所示。

Vision API 是一个预训练的机器学习模型,可从图片中提取数据洞见。它可为您提供多项数据洞见,包括为图片加标签、人脸和地标检测、光学字符识别和露骨内容标记。如需了解详情,请参阅 Vision AI

  1. 转到 Dialogflow 控制台
  2. 登录(如果您是首次使用,请使用您的电子邮件地址注册)。
  3. 接受条款及条件,然后您就可以进入控制台。
  4. 点击 ,滚动到底部,然后点击创建新代理 (Create new agent)。

5. 输入“VisionAPI”作为代理名称

  1. 点击创建

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

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

此时,您拥有了一个问候用户的功能聊天机器人,但您需要将其更新,让用户知道他们可以通过上传图片来探索地标。

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

  1. 点击默认欢迎意图 (Default Welcome Intent)。
  2. 依次转到响应 (Responses) > 默认 (Default) > 文本或 SSML 响应 (Text or SSML Response),然后输入“Hi!You can upload a picture to explore landmarks.”

创建实体

  1. 点击实体 (Entities)。

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

创建新的意图

  1. 依次点击意图 (Intents) > 创建意图 (Create Intent)。
  2. 输入“Explore uploaded image”作为意图名称
  3. 点击训练短语 (Training phrases) > 添加训练短语 (Add Training Phrases),然后输入“file is demo.jpg”和“file is taj.jpeg”作为用户表达式,并输入 @filename 作为实体。

  1. 依次点击响应 (Responses) > 添加响应 (Add Response) > 默认 (Default) > 文本或 SSML 响应 (Text or SSML Response)。输入“Assessing file”,然后点击添加回复 (Add Responses)。
  1. 依次点击 Fulfillment > 启用 fulfillment (Enable fulfillment) 并开启为此意图启用 Webhook 调用 (Enable webhook call for this intent)。

  1. 点击 Fulfillment
  2. 启用内嵌编辑器 (Inline Editor)。

  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. 点击保存 (Save)。
  1. 将此代码库克隆到本地机器:
https://github.com/priyankavergadia/visionapi-dialogflow.git
  1. 切换到包含该代码的目录。或者,您也可以下载该示例的 zip 文件并将其解压缩。
cd visionapi-dialogflow

部署后,您的应用会使用 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]

或者,您可以在控制台中点击实例以获取实例连接名称

初始化您的 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 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] 行,将“[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 项目 (Google Project) > 项目 ID (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 中,点击导航菜单 ☰> 存储

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

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

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

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

  1. 点击相应存储桶旁边的 ,然后点击修改存储桶权限

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

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

按照相同的说明创建单独的存储桶以上传用户图片。再次将权限设置为“allUsers”,但选择 Storage Object CreatorStorage 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 存储桶以获取文件并进行预测。

要在本地计算机上运行 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/。您应该会看到如下所示的简单网页:

示例应用页面由您的计算机上运行的 Django 网络服务器提供。准备好继续操作后,请按 Control+C(Macintosh 上为 Command+C)以停止本地网络服务器。

使用 Django 管理控制台

  1. 创建超级用户。
python3 manage.py createsuperuser
  1. 启动本地网络服务器。
python3 manage.py runserver
  1. 在网络浏览器中导航到 http://localhost:8000/admin/。要登录管理网站,请输入您在运行 createsuperuser 时创建的用户名和密码。

通过运行以下命令将所有静态内容收集到一个文件夹中,该命令会将应用的所有静态文件移动到由 settings.py 中的 STATIC_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

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

  1. 用户:"hi"
  2. 聊天机器人:"Hi! You can upload a picture to explore landmarks.”
  3. 用户会上传图片。

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

  1. 聊天机器人:“File is being processed, here are the results: Golden Gate Bridge,Golden Gate National Recreation Area,Golden Gate Bridge,Golden Gate Bridge,Golden Gate Bridge.”

总体上应如下所示:

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

删除 Dialogflow 代理

  1. 点击现有代理旁边的

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

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

了解详情

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