איך משלבים את Vision API עם Dialogflow

ב-codelab הזה תלמדו איך לשלב את Vision API עם Dialogflow כדי לספק תשובות עשירות ודינמיות שמבוססות על למידת מכונה, בתגובה לקלט של תמונות שסופק על ידי המשתמש. תצרו אפליקציית צ'אטבוט שמקבלת תמונה כקלט, מעבדת אותה ב-Vision API ומחזירה למשתמש ציון דרך מזוהה. לדוגמה, אם המשתמש יעלה תמונה של הטאג' מהאל, הצ'אטבוט יחזיר את התשובה 'טאג' מהאל'.

זה שימושי כי אפשר לנתח את הפריטים בתמונה ולפעול לפי המידע שמתקבל. אפשר גם ליצור מערכת לעיבוד החזרים כספיים שתעזור למשתמשים להעלות קבלות, לחלץ את תאריך הרכישה מהקבלה ולעבד את ההחזר הכספי אם התאריך מתאים.

הנה דוגמה לתיבת דו-שיח:

משתמש: שלום

צ'אט בוט: שלום! אפשר להעלות תמונה כדי לחפש ציוני דרך

משתמש: תעלה תמונה עם הטאג' מהאל.

צ'אטבוט: הקובץ נמצא בתהליך עיבוד, אלה התוצאות: טאג' מהאל, גן טאג' מהאל, טאג' מהאל.

דרישות מוקדמות

לפני שממשיכים, צריך להשלים את ה-codelabs הבאים:

  1. יצירת כלי לתזמון פגישות באמצעות Dialogflow
  2. שילוב של צ'אטבוט של Dialogflow עם Actions on Google
  3. הסבר על ישויות ב-Dialogflow
  4. איך יוצרים לקוח Django בחזית לאפליקציית Dialogflow

כדאי גם להבין את המושגים והמבנים הבסיסיים של Dialogflow. אפשר ללמוד עליהם מהסרטונים הבאים במסלול יצירת צ'אטבוט באמצעות Dialogflow:

מה תלמדו

  • איך יוצרים נציג ב-Dialogflow
  • איך מעדכנים סוכן Dialogflow כדי להעלות קבצים
  • איך מגדירים את החיבור ל-Vision API באמצעות Dialogflow fulfillment
  • איך מגדירים ומריצים אפליקציית frontend של Django ל-Dialogflow
  • איך פורסים את אפליקציית הקצה הקדמי של Django ב-Google Cloud ב-App Engine
  • איך בודקים את אפליקציית Dialogflow מחזית אתרים בהתאמה אישית

מה תפַתחו

  • יצירת נציג ב-Dialogflow
  • הטמעה של ממשק קצה ב-Django להעלאת קובץ
  • הטמעה של Dialogflow fulfillment כדי להפעיל את Vision API על התמונה שהועלתה

מה נדרש

  • ידע בסיסי ב-Python
  • הבנה בסיסית של Dialogflow
  • הבנה בסיסית של Vision API

תצרו ממשק צ'אט חדש עם קצה קדמי מותאם אישית של Django, ותוסיפו לו שילוב עם Vision API. תבנו את חזית האתר באמצעות מסגרת Django, תריצו ותבדקו אותה באופן מקומי, ואז תפרסו אותה ב-App Engine. ממשק הקצה ייראה כך:

תהליך הבקשה יפעל באופן הבא, כפי שמוצג בתמונה הבאה:

  1. המשתמש ישלח בקשה דרך ממשק הקצה.
  2. הפעולה הזו תפעיל קריאה ל-Dialogflow detectIntent API כדי למפות את האמירה של המשתמש לכוונת הרכישה הנכונה.
  3. אחרי שמזוהה כוונת החיפוש של ציון דרך, מנגנון מילוי הבקשות של Dialogflow שולח בקשה אל Vision API, מקבל תשובה ושולח אותה למשתמש.

כך ייראה הארכיטקטורה הכוללת.

‫Vision API הוא מודל ML שעבר אימון מראש ומפיק תובנות מתמונות. הוא יכול לספק לכם תובנות רבות, כולל הוספת תוויות לתמונות, זיהוי של פנים וציוני דרך, זיהוי תווים אופטי (OCR) ותיוג של תוכן בוטה. מידע נוסף זמין במאמר בנושא Vision AI.

  1. עוברים אל מסוף Dialogflow.
  2. מתחברים לחשבון. (אם אתם משתמשים בפלטפורמה בפעם הראשונה, עליכם להשתמש בכתובת האימייל שלכם כדי להירשם).
  3. מאשרים את התנאים וההגבלות, ואז נכנסים למסוף.
  4. לוחצים על , גוללים לתחתית ולוחצים על יצירת סוכן חדש.

5. מזינים VisionAPI בתור שם הסוכן.

  1. לוחצים על יצירה.

מערכת Dialogflow יוצרת את שתי כוונות ברירת המחדל הבאות כחלק מהסוכן:

  1. כוונת ברירת המחדל של הודעת הפתיחה היא לברך את המשתמשים.
  2. כוונת ברירת המחדל לגיבוי מזהה את כל השאלות שהבוט לא מבין.

בשלב הזה יש לכם בוט פונקציונלי שמברך את המשתמשים, אבל אתם צריכים לעדכן אותו כדי ליידע את המשתמשים שהם יכולים להעלות תמונה כדי לחקור ציוני דרך.

עדכון כוונת ברירת המחדל של הודעת הפתיחה כדי להודיע למשתמש להעלות תמונה

  1. לוחצים על Default Welcome Intent (כוונת הפתיחה שמוגדרת כברירת מחדל).
  2. עוברים אל תגובות > ברירת מחדל > תגובה בטקסט או ב-SSML ומזינים את הטקסט 'שלום! אפשר להעלות תמונה כדי לחקור ציוני דרך".

יצירת ישות

  1. לוחצים על ישויות.

  1. לוחצים על Create Entity (יצירת ישות), נותנים לה את השם filename (שם הקובץ) ולוחצים על Save (שמירה).

יצירת כוונת משתמש חדשה

  1. לוחצים על Intents > Create Intent.
  2. מזינים Explore uploaded image (חיפוש תמונה שהועלתה) כשם הכוונה.
  3. לוחצים על משפטי אימון > הוספת משפטי אימון ומזינים את הביטויים "הקובץ הוא demo.jpg" ו "הקובץ הוא taj.jpeg" כביטויי משתמש עם @filename כיישות.

  1. לוחצים על תגובות > הוספת תגובה > ברירת מחדל> תגובה בטקסט או ב-SSML. מזינים את הטקסט "Assessing file" (בדיקת הקובץ) ולוחצים על הוספת תגובות.
  1. לוחצים על Fulfillment (השלמת בקשה) > Enable fulfillment (הפעלת השלמת בקשה) ומפעילים את האפשרות Enable webhook call for this intent (הפעלת קריאה ל-webhook עבור הכוונה הזו).

  1. לוחצים על הזמנות.
  2. מפעילים את העורך המוטבע.

  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. לוחצים על שמירה.
  1. משכפלים את המאגר הזה למחשב המקומי:
https://github.com/priyankavergadia/visionapi-dialogflow.git
  1. עוברים לספרייה שמכילה את הקוד. אפשרות נוספת היא להוריד את הדוגמה כקובץ ZIP ולחלץ אותה.
cd visionapi-dialogflow

כשפורסים את האפליקציה, היא משתמשת ב-Cloud SQL Proxy שמוטמע בסביבה הרגילה של App Engine כדי לתקשר עם מופע Cloud SQL. עם זאת, כדי לבדוק את האפליקציה באופן מקומי, צריך להתקין ולהשתמש בעותק מקומי של Cloud SQL Proxy בסביבת הפיתוח. מידע נוסף זמין במאמר מידע על Cloud SQL Proxy.

כדי לבצע משימות אדמין בסיסיות במופע Cloud SQL, אפשר להשתמש בלקוח Cloud SQL ל-MySQL.

התקנת 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. יוצרים מכונה של Cloud SQL ל-MySQL מהדור השני. מזינים את השם polls-instance או שם דומה. יכול להיות שיעברו כמה דקות עד שהמכונה תהיה מוכנה. אחרי שהיא תהיה מוכנה, היא תופיע ברשימת המופעים.
  2. עכשיו משתמשים בכלי gcloud CLI כדי להריץ את הפקודה הבאה, כאשר [YOUR_INSTANCE_NAME] מייצג את השם של מכונת Cloud SQL. רושמים את הערך שמוצג בשדה connectionName כדי להשתמש בו בשלב הבא. הוא מוצג בפורמט [PROJECT_NAME]:[REGION_NAME]:[INSTANCE_NAME].
gcloud sql instances describe [YOUR_INSTANCE_NAME]

לחלופין, אפשר ללחוץ על המופע במסוף כדי לקבל את שם החיבור של המופע.

הפעלת המכונה של Cloud SQL

מפעילים את Cloud SQL Proxy באמצעות connectionName מהקטע הקודם.

./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 עבור מופע Cloud SQL בשם polls-instance. לדוגמה, אפשר להזין את השם 'סקרים'.
  2. יוצרים משתמש חדש באמצעות Cloud Console עבור מופע Cloud SQL בשם polls-instance.

הגדרת ההגדרות של מסד הנתונים

  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 Project (פרויקט Google) > Project ID (מזהה פרויקט) ולוחצים על Google Cloud (פרויקט Google) כדי לפתוח את Cloud Console.
  2. לוחצים על תפריט הניווט ☰ > IAM & Admin > Service accounts, ואז לוחצים על לצד Dialogflow integrations ועל Create key.

  1. קובץ JSON יורד למחשב. תצטרכו אותו בשלבי ההגדרה הבאים.
  1. בתיקיית הצ'אט, מחליפים את key-sample.json בקובץ ה-JSON של פרטי הכניסה ונותנים לו את השם key.json.
  2. בתיקיית הצ'אט views.py, משנים את GOOGLE_PROJECT_ID = "<YOUR_PROJECT_ID>" למזהה הפרויקט.

יצירת קטגוריה של Cloud Storage לאובייקטים סטטיים של חזית האתר

  1. ב-Cloud Console, לוחצים על תפריט הניווט ☰> Storage.

  1. לוחצים על Create Bucket.
  2. צריך להזין שם ייחודי בהיקף גלובלי.

  1. בוחרים את המיקום לאחסון הנתונים. בוחרים באפשרות אזור ובוחרים את המיקום שהכי מתאים לצרכים שלכם.
  2. בוחרים באפשרות Standard כסוג האחסון שמוגדר כברירת מחדל.

  1. בוחרים באפשרות Set permissions uniformly at bucket-level (Bucket Policy Only) (הגדרת הרשאות באופן אחיד ברמת הקטגוריה (מדיניות הקטגוריה בלבד)) ולוחצים על Continue (המשך) כדי ליצור את הקטגוריה.

  1. אחרי שיוצרים את הדלי, לוחצים על תפריט הניווט ☰ > Storage > Browser ומאתרים את הדלי שיצרתם.

  1. לוחצים על ליד הקטגוריה הרלוונטית ואז על Edit bucket permissions (עריכת הרשאות הקטגוריה).

  1. לוחצים על Add Members (הוספת חברים), לוחצים על New members (חברים חדשים), מזינים allUsers ולוחצים על Select a role (בחירת תפקיד) > Storage Object Viewer (צפייה באובייקט אחסון). ההרשאה הזו מאפשרת גישת צפייה בקבצי ה-frontend הסטטיים ל-allUsers. זו לא הגדרת אבטחה אידיאלית לקבצים, אבל היא מתאימה למטרה של ה-codelab הזה.

יצירת קטגוריה של Cloud Storage לתמונות שהמשתמשים מעלים

פועלים לפי אותן הוראות כדי ליצור קטגוריה נפרדת להעלאת תמונות של משתמשים. מגדירים שוב את ההרשאות ל-allUsers, אבל בוחרים בתפקידים Storage Object Creator ו-Storage Object Viewer.

הגדרת הקטגוריה של Cloud Storage בקובץ settings.py

  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>'

הגדרת קטגוריה של Cloud Storage בקובץ home.html

  • פותחים את תיקיית הצ'אטים, פותחים את 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 (Command+C ב-Macintosh) כדי להפסיק את שרת האינטרנט המקומי.

שימוש במסוף Admin של Django

  1. יוצרים משתמש על.
python3 manage.py createsuperuser
  1. מפעילים שרת אינטרנט מקומי.
python3 manage.py runserver
  1. בדפדפן האינטרנט, עוברים לכתובת http://localhost:8000/admin/. כדי להתחבר לאתר האדמין, מזינים את שם המשתמש והסיסמה שיצרתם כשביצעתם את הפקודה createsuperuser.

מריצים את הפקודה הבאה כדי לאסוף את כל התוכן הסטטי לתיקייה אחת. הפקודה מעבירה את כל הקבצים הסטטיים של האפליקציה לתיקייה שצוינה על ידי STATIC_ROOT ב-settings.py:

python3 manage.py collectstatic

כדי להעלות את האפליקציה, מריצים את הפקודה הבאה מהספרייה של האפליקציה שבה נמצא הקובץ app.yaml:

gcloud app deploy

מחכים להודעה שהעדכון הסתיים.

בדפדפן האינטרנט, עוברים אל https://<your_project_id>.appspot.com

הפעם, הבקשה שלכם מטופלת על ידי שרת אינטרנט שפועל בסביבה הרגילה של App Engine.

הפקודה app deploy פורסת את האפליקציה כמו שמתואר במאמר app.yaml ומגדירה את הגרסה החדשה שנפרסה כגרסת ברירת המחדל, כך שהיא תציג את כל התנועה החדשה.

כשמוכנים להציג את התוכן בסביבת הייצור, משנים את המשתנה DEBUG ל-False ב-mysite/settings.py.

אתם יכולים לבדוק את הצ'אטבוט בסימולטור, או להשתמש באינטגרציה עם האינטרנט או עם Google Home שיצרתם קודם.

  1. משתמש: "היי"
  2. צ'אט בוט: "היי! אפשר להעלות תמונה כדי לחקור ציוני דרך".
  3. המשתמש מעלה תמונה.

מורידים את התמונה הזו, נותנים לה את השם demo.jpg ומשתמשים בה.

  1. צ'אטבוט: "הקובץ נמצא בתהליך עיבוד, אלה התוצאות: גשר שער הזהב,אזור הנופש הלאומי גולדן גייט,גשר שער הזהב,גשר שער הזהב,גשר שער הזהב".

בסך הכול, זה אמור להיראות כך:

אם רוצים להשלים עוד סדנאות קוד של Dialogflow, אפשר לדלג על הקטע הזה ולחזור אליו מאוחר יותר.

מחיקת סוכן Dialogflow

  1. לוחצים על לצד הסוכן הקיים.

  1. בכרטיסייה כללי, גוללים למטה ולוחצים על מחיקת הסוכן הזה.
  2. מקלידים מחיקה בחלון שמופיע ולוחצים על מחיקה.

יצרתם צ'אטבוט ב-Dialogflow ושילבתם אותו עם Vision API. הוגדרת כמפתח/ת של צ'אטבוטים.

מידע נוסף

למידע נוסף, אפשר לעיין בדוגמאות הקוד בדף Dialogflow Github.