איך משלבים את Dialogflow עם BigQuery

1. מבוא

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

תרשים הרצף הבא מציג את האירועים מהמשתמש ועד לביצוע ההזמנה ול-BigQuery.

538029740db09f49.png

מה תלמדו

  • איך יוצרים מערך נתונים וטבלה ב-BigQuery
  • איך מגדירים את פרטי החיבור ל-BigQuery ב-Dialogflow fulfillment.
  • איך בודקים את תהליך השלמת ההזמנה

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

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

2. יצירת מערך נתונים וטבלה ב-BigQuery

  1. עוברים אל מסוף Google Cloud.
  2. במסוף Cloud, לוחצים על סמל התפריט ☰ > Big Data > BigQuery.
  3. בקטע 'Resources' (משאבים) בחלונית הימנית, לוחצים על מזהה הפרויקט. אחרי הבחירה, האפשרות 'CREATE DATASET' (יצירת מערך נתונים) תופיע בחלונית השמאלית.
  4. לוחצים על CREATE DATASET (יצירת מערך נתונים) ונותנים לו שם.

be9f32a18ebb4a5b.png

  1. אחרי שיוצרים את מערך הנתונים, לוחצים עליו בחלונית הימנית. בצד שמאל יופיע CREATE TABLE.
  2. לוחצים על CREATE TABLE (יצירת טבלה), מציינים שם לטבלה ולוחצים על Create table (יצירת טבלה) בתחתית המסך.

d5fd99b68b7e62e0.png

  1. אחרי שיוצרים את הטבלה, לוחצים על הטבלה בחלונית הימנית. בצד שמאל יופיע הלחצן עריכת סכימה.
  2. לוחצים על הלחצן 'עריכת סכימה' ואז על הלחצן 'הוספת שדה'. מוסיפים את השדה date (תאריך) וחוזרים על הפעולה עבור השדות time (שעה) ו-type (סוג).
  3. חשוב לשים לב לערכים של DatasetID ו-tableID

e9d9abbe843823df.png

3. הוספת פרטי החיבור ל-BigQuery ל-Dialogflow Fulfillment

  1. פותחים את נציג Dialogflow ומפעילים את הכלי לעריכת Fulfillment בתוך הדף. אם אתם צריכים עזרה, אפשר לעיין במעבדה הקודמת .
  1. מוודאים שהקובץ package.json בעורך המובנה של קוד ה-fulfillment ב-Dialogflow מכיל תלות ב-BigQuery. ‫"@google-cloud/bigquery": "0.12.0". חשוב לוודא שאתם משתמשים בגרסה העדכנית ביותר של BigQuery בזמן שאתם קוראים את המאמר הזה.
  2. ב-index.js יוצרים את הפונקציה addToBigQuery כדי להוסיף את התאריך, השעה וסוג הפגישה לטבלה ב-BigQuery.
  3. מוסיפים את projectID, ‏ datasetID ו-tableID בקטע TODO בקובץ index.js כדי לחבר את הטבלה ב-BigQuery ואת מערך הנתונים לביצוע ההזמנה.
{
  "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.5.0",
    "@google-cloud/bigquery": "^0.12.0"
  }
}
'use strict';

const functions = require('firebase-functions');
const {google} = require('googleapis');
const {WebhookClient} = require('dialogflow-fulfillment');
const BIGQUERY = require('@google-cloud/bigquery');


// Enter your calendar ID below and service account JSON below
const calendarId = "XXXXXXXXXXXXXXXXXX@group.calendar.google.com";
const serviceAccount = {}; // Starts with {"type": "service_account",...

// Set up Google Calendar Service account credentials
const serviceAccountAuth = new google.auth.JWT({
  email: serviceAccount.client_email,
  key: serviceAccount.private_key,
  scopes: 'https://www.googleapis.com/auth/calendar'
});

const calendar = google.calendar('v3');
process.env.DEBUG = 'dialogflow:*'; // enables lib debugging statements

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);
  const appointment_type = agent.parameters.AppointmentType;

// Function to create appointment in calendar  
function makeAppointment (agent) {
    // Calculate appointment start and end datetimes (end = +1hr from start)
    const dateTimeStart = new Date(Date.parse(agent.parameters.date.split('T')[0] + 'T' + agent.parameters.time.split('T')[1].split('-')[0] + timeZoneOffset));
    const dateTimeEnd = new Date(new Date(dateTimeStart).setHours(dateTimeStart.getHours() + 1));
    const appointmentTimeString = dateTimeStart.toLocaleString(
      'en-US',
      { month: 'long', day: 'numeric', hour: 'numeric', timeZone: timeZone }
    );
  
// Check the availability of the time, and make an appointment if there is time on the calendar
    return createCalendarEvent(dateTimeStart, dateTimeEnd, appointment_type).then(() => {
      agent.add(`Ok, let me see if we can fit you in. ${appointmentTimeString} is fine!.`);

// Insert data into a table
      addToBigQuery(agent, appointment_type);
    }).catch(() => {
      agent.add(`I'm sorry, there are no slots available for ${appointmentTimeString}.`);
    });
  }

  let intentMap = new Map();
  intentMap.set('Schedule Appointment', makeAppointment);
  agent.handleRequest(intentMap);
});

//Add data to BigQuery
function addToBigQuery(agent, appointment_type) {
    const date_bq = agent.parameters.date.split('T')[0];
    const time_bq = agent.parameters.time.split('T')[1].split('-')[0];
    /**
    * TODO(developer): Uncomment the following lines before running the sample.
    */
    //const projectId = '<INSERT your own project ID here>'; 
    //const datasetId = "<INSERT your own dataset name here>";
    //const tableId = "<INSERT your own table name here>";
    const bigquery = new BIGQUERY({
      projectId: projectId
    });
   const rows = [{date: date_bq, time: time_bq, type: appointment_type}];
  
   bigquery
  .dataset(datasetId)
  .table(tableId)
  .insert(rows)
  .then(() => {
    console.log(`Inserted ${rows.length} rows`);
  })
  .catch(err => {
    if (err && err.name === 'PartialFailureError') {
      if (err.errors && err.errors.length > 0) {
        console.log('Insert errors:');
        err.errors.forEach(err => console.error(err));
      }
    } else {
      console.error('ERROR:', err);
    }
  });
  agent.add(`Added ${date_bq} and ${time_bq} into the table`);
}

// Function to create appointment in google calendar  
function createCalendarEvent (dateTimeStart, dateTimeEnd, appointment_type) {
  return new Promise((resolve, reject) => {
    calendar.events.list({
      auth: serviceAccountAuth, // List events for time period
      calendarId: calendarId,
      timeMin: dateTimeStart.toISOString(),
      timeMax: dateTimeEnd.toISOString()
    }, (err, calendarResponse) => {
      // Check if there is a event already on the Calendar
      if (err || calendarResponse.data.items.length > 0) {
        reject(err || new Error('Requested time conflicts with another appointment'));
      } else {
        // Create event for the requested time period
        calendar.events.insert({ auth: serviceAccountAuth,
          calendarId: calendarId,
          resource: {summary: appointment_type +' Appointment', description: appointment_type,
            start: {dateTime: dateTimeStart},
            end: {dateTime: dateTimeEnd}}
        }, (err, event) => {
          err ? reject(err) : resolve(event);
        }
        );
      }
    });
  });
}

הסבר על רצף האירועים מהקוד

  1. מפת הכוונות קוראת לפונקציה makeAppointment כדי לקבוע פגישה ביומן Google
  2. באותה פונקציה מתבצעת קריאה לפונקציה addToBigQuery כדי לשלוח את הנתונים לרישום ב-BigQuery.

4. בדיקה של הצ'אטבוט ושל הטבלה ב-BigQuery

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

  • משתמש: "Set an appointment for vehicle registration at 2pm tomorrow"
  • תשובת הצ'אטבוט: "בסדר, בוא נראה אם יש לנו מקום בשבילך. ‫August 6, 2 PM is fine!."

96d3784c103daf5e.png

  • בודקים את הטבלה ב-BigQuery אחרי קבלת התגובה. שימוש בשאילתה 'SELECT * FROM projectID.datasetID.tableID'

dcbc9f1c06277a21.png

5. הסרת המשאבים

אם אתם מתכננים לבצע את שאר שיעורי ה-Lab בסדרה הזו, אל תבצעו את הניקוי עכשיו, אלא אחרי שתסיימו את כל שיעורי ה-Lab בסדרה.

מחיקת הנציג ב-Dialogflow

  • לוחצים על סמל גלגל השיניים 30a9fea7cfa77c1a.png לצד הסוכן הקיים.

520c1c6bb9f46ea6.png

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

6. מעולה!

יצרתם צ'אטבוט ושילבתם אותו עם BigQuery כדי לקבל תובנות. הוגדרת כמפתח/ת צ'אטבוטים.

כדאי לעיין במקורות המידע הבאים:

1217326c0c490fa.png