Vision API를 Dialogflow와 통합

1. 시작하기 전에

이 Codelab에서는 Vision API를 Dialogflow와 통합하여 사용자가 제공한 이미지 입력에 풍부하고 동적인 머신러닝 기반 응답을 제공합니다. 이미지를 입력으로 받아 Vision API에서 처리하고 식별된 랜드마크를 사용자에게 반환하는 챗봇 앱을 만듭니다. 예를 들어 사용자가 타지마할 이미지를 업로드하면 챗봇은 타지마할을 응답으로 반환합니다.

이미지에 있는 항목을 분석하고 얻은 정보에 따라 조치를 취할 수 있으므로 유용합니다. 또한 사용자가 영수증을 업로드하고, 영수증에서 구매 날짜를 추출하고, 적절한 경우 환불을 처리할 수 있도록 환불 처리 시스템을 구축할 수 있습니다.

다음 샘플 대화를 살펴보세요.

사용자: 안녕하세요.

챗봇: 안녕하세요. 사진을 업로드하여 명소를 탐색할 수 있습니다.

사용자: 타지마할이 포함된 이미지를 업로드하세요.

챗봇: 파일이 처리되고 있습니다. 결과는 타지마할, 타지마할 정원, 타지마할입니다.

15a4243e453415ca.png

기본 요건

계속하기 전에 다음 Codelab을 완료해야 합니다.

  1. Dialogflow로 약속 스케줄러 빌드
  2. Actions on Google과 Dialogflow 챗봇 통합
  3. Dialogflow의 항목 이해
  4. Dialogflow 앱을 위한 프런트엔드 Django 클라이언트 빌드

또한 Dialogflow의 기본 개념과 구성도 이해해야 합니다. 이러한 내용은 Dialogflow로 챗봇 빌드 과정의 다음 동영상에서 얻을 수 있습니다.

학습할 내용

  • Dialogflow 에이전트를 만드는 방법
  • Dialogflow 에이전트를 업데이트하여 파일을 업로드하는 방법
  • Dialogflow fulfillment와 Vision API 연결을 설정하는 방법
  • Dialogflow용 Django 프런트엔드 앱 설정 및 실행 방법
  • App Engine에서 Google Cloud에 Django 프런트엔드 앱을 배포하는 방법
  • 커스텀 프런트엔드에서 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 fulfillment가 Vision API에 요청을 전송하고 응답을 수신한 후 사용자에게 전송합니다.

153725eb50e008d4.png

전체 아키텍처는 다음과 같습니다.

a2fcea32222a9cb4.png

3. Vision API란 무엇인가요?

Vision API는 이미지에서 유용한 정보를 도출하는 선행 학습된 ML 모델입니다. 이를 통해 이미지 라벨 지정, 얼굴 및 랜드마크 인식, 광학 문자 인식, 선정적인 콘텐츠 태그 등 다양한 정보를 얻을 수 있습니다. 자세한 내용은 Vision AI를 참조하세요.

4. Dialogflow 에이전트 만들기

  1. Dialogflow 콘솔로 이동합니다.
  2. 로그인합니다. 처음 사용하는 경우 이메일을 사용하여 가입합니다.
  3. 이용약관에 동의하면 콘솔로 이동합니다.
  4. d9e90c93fc779808.png를 클릭하고 하단으로 스크롤하여 새 에이전트 만들기를 클릭합니다. 3b3f9677e2a26d93.png
  5. 'VisionAPI'를 입력합니다. Agent name(에이전트 이름)으로 입력합니다.
  6. 만들기를 클릭합니다.

Dialogflow는 에이전트의 일부로 다음 두 개의 기본 인텐트를 만듭니다.

  1. 기본 시작 인텐트는 사용자에게 인사합니다.
  2. 기본 대체 인텐트는 봇이 이해하지 못하는 모든 질문을 포착합니다.

이 시점에서 사용자에게 인사하는 작동하는 봇이 있지만 이미지를 업로드하여 랜드마크를 탐색할 수 있음을 사용자에게 알려야 합니다.

사용자에게 이미지를 업로드하도록 알리도록 기본 시작 인텐트를 업데이트합니다.

  1. 기본 시작 인텐트를 클릭합니다.
  2. 응답 >으로 이동합니다. 기본값 > 텍스트 또는 SSML 응답을 클릭하고 'Hi! 사진을 업로드하여 명소를 탐험할 수 있습니다.'

f9cd9ba6917a7aa9.png

항목 만들기

  1. 항목을 클릭합니다.

432fff294b666c93.png

  1. 항목 만들기를 클릭하고 '파일 이름'으로 이름을 지정합니다. 저장을 클릭합니다.

602d001d684485de.png

새 인텐트 만들기

  1. 인텐트 >를 클릭합니다. 인텐트 만들기
  2. '업로드된 이미지 탐색'을 입력합니다. 인텐트 이름으로 사용합니다.
  3. 학습 문구를 클릭합니다. 학습 문구를 추가하고 'file is demo.jpg'를 입력합니다. '파일이 taj.jpeg임' @filename을 항목으로 갖는 사용자 표현으로 제공합니다.

dd54ebda59c6b896.png

  1. 응답을 클릭합니다. 응답 추가 > 기본값 > 텍스트 또는 SSML 응답. '파일 평가 중'을 입력하세요. 응답 추가를 클릭합니다.
  2. fulfillment를 클릭합니다. fulfillment 사용 설정이 인텐트에 웹훅 호출 사용 설정을 설정합니다.

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 인스턴스에 대한 기본적인 관리 작업을 수행하려면 MySQL용 Cloud SQL 클라이언트를 사용하면 됩니다.

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. MySQL 2세대용 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 프록시를 시작합니다.

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

[YOUR_INSTANCE_CONNECTION_NAME]을 이전 섹션에서 기록한 값으로 바꿉니다. 그러면 로컬 테스트를 위해 로컬 컴퓨터에서 Cloud SQL 인스턴스로 연결이 설정됩니다. 앱을 로컬에서 테스트하는 동안 Cloud SQL 프록시를 계속 실행합니다.

다음으로 새 Cloud SQL 사용자 및 데이터베이스를 만듭니다.

  1. polls-instance라는 Cloud SQL 인스턴스용 Google Cloud 콘솔을 사용하여 새 데이터베이스를 만듭니다. 예를 들어 'polls'를 입력할 수 있습니다. 을 이름으로 사용하겠습니다. a3707ec9bc38d412.png
  2. polls-instance라는 Cloud SQL 인스턴스용 Cloud 콘솔을 사용하여 새 사용자를 만듭니다. <ph type="x-smartling-placeholder">f4d098fca49cccff.png</ph>

데이터베이스 설정 구성

  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 Cloud 7b2236f5627c37a0.png를 클릭하여 Cloud 콘솔을 엽니다. a4cfb880b3c8e789.png
  2. 탐색 메뉴 ❯를 클릭합니다. IAM 및 관리 > 서비스 계정을 선택한 다음 Dialogflow 통합 옆에 있는 796e7c9e65ae751f.png를 클릭하고 키 만들기를 클릭합니다.

3d72abc0c184d281.png

  1. JSON 파일이 컴퓨터에 다운로드되며 다음 설정 섹션에서 필요합니다.

9. 앱에서 호출되도록 Dialogflow DetectionIntent 엔드포인트를 설정합니다.

  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. 기본 스토리지 클래스로 표준을 선택합니다.

9c56abe632cf61db.png

  1. 버킷 수준에서 균일하게 권한 설정 (버킷 정책 전용)을 선택한 다음 계속을 클릭하여 버킷을 만듭니다.

f175ac794049df04.png

  1. 버킷이 만들어지면 탐색 메뉴 ❯ >를 클릭합니다. 스토리지 > 브라우저로 이동하고 앞서 만든 버킷을 찾습니다.

9500ee19b427158c.png

  1. 해당 버킷 옆에 있는 796e7c9e65ae751f.png를 클릭하고 버킷 권한 수정을 클릭합니다.

fd0a310bc3656edd.png

  1. 구성원 추가를 클릭하고 새 구성원을 클릭한 다음 'allUsers'를 입력합니다. 역할 선택을 클릭합니다. 스토리지 객체 뷰어. 이렇게 하면 allUsers에게 정적 프런트엔드 파일에 대한 보기 액세스 권한이 제공됩니다. 이 설정은 파일에 이상적인 보안 설정은 아니지만 이 Codelab의 목적에 맞게 작동합니다.

7519116abd56d5a3.png

사용자가 업로드한 이미지를 위한 Cloud Storage 버킷 만들기

동일한 안내에 따라 사용자 이미지를 업로드할 별도의 버킷을 만듭니다. 권한을 'allUsers'로 설정 스토리지 객체 생성자스토리지 객체 뷰어를 역할로 선택합니다.

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, 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/으로 이동합니다. 다음과 같은 간단한 웹페이지가 표시됩니다.

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://<your_project_id>.appspot.com으로 이동합니다.

이번에는 App Engine 표준 환경에서 실행되는 웹 서버에서 요청을 처리합니다.

app deploy 명령어는 app.yaml에 설명된 대로 앱을 배포하고 새로 배포된 버전을 기본 버전으로 설정하여 모든 새 트래픽을 처리합니다.

15. 프로덕션

프로덕션에 콘텐츠를 제공할 준비가 되면 mysite/settings.py에서 DEBUG 변수를 False로 변경합니다.

16. 챗봇 테스트

시뮬레이터에서 챗봇을 테스트하거나 이전에 구축한 웹 또는 Google Home 통합을 사용할 수 있습니다.

  1. 사용자: "안녕하세요"
  2. 챗봇: "안녕하세요. 사진을 업로드하여 명소를 탐험할 수 있습니다.'
  3. 사용자가 이미지를 업로드합니다.

이 이미지를 다운로드하고 이름을 demo.jpg로 지정하고 사용하세요.

c3aff843c9f132e4.jpeg

  1. 챗봇: "파일이 처리되고 있습니다. 결과는 금문교, 금문교,금문교,금문교,금문교,금문교입니다."

전체적으로 다음과 같이 표시됩니다.

228df9993bfc001d.png

17. 삭제

다른 Dialogflow Codelab을 완료하려면 이 섹션을 건너뛰고 나중에 다시 확인하세요.

Dialogflow 에이전트 삭제

  1. 기존 에이전트 옆에 있는 ca4337eeb5565bcb.png를 클릭합니다.

520c1c6bb9f46ea6.png

  1. General 탭에서 아래로 스크롤하여 Delete This Agent를 클릭합니다.
  2. 나타나는 창에 삭제를 입력하고 삭제를 클릭합니다.

18. 축하합니다

Dialogflow에서 챗봇을 만들어 Vision API와 통합했습니다. 챗봇 개발자가 되셨습니다!

자세히 알아보기

자세한 내용은 Dialogflow GitHub 페이지의 코드 샘플을 확인하세요.