מעשית: יצירת פעולה במדריך הטלוויזיה ל-Google Assistant באמצעות Dialogflow ו-Actions on Google

1. מבוא

אתם צופים בטלוויזיה, אבל לא מוצאים את השלט, או שאולי אתם לא רוצים להיכנס לכל ערוץ טלוויזיה כדי לראות אם יש משהו מעניין לצפות בו? בואו נשאל את Google Assistant מה משודר בטלוויזיה! בשיעור ה-Lab הזה תלמדו איך ליצור פעולה פשוטה באמצעות Dialogflow ואיך לשלב אותה עם Google Assistant.

התרגילים מסודרים לפי סדר שמשקף את חוויית המפתחים בענן:

  1. יצירת סוכן Dialogflow v2
  2. יצירת ישות בהתאמה אישית
  3. יצירת כוונות
  4. הגדרת webhook באמצעות פונקציות Firebase
  5. בדיקת הצ'אט בוט
  6. הפעלת השילוב עם Google Assistant

מה תפַתחו

אנחנו ניצור סוכן צ'אטבוט אינטראקטיבי של מדריך טלוויזיה ל-Google Assistant. אתם יכולים לשאול את מדריך הערוצים מה משודר כרגע בערוץ מסוים. לדוגמה: "What's on MTV?‎" (מה משודר בערוץ MTV?). פעולת מדריך הטלוויזיה תגיד לכם מה משודר כרגע ומה ישודר בהמשך.

מה תלמדו

  • איך יוצרים צ'אט בוט באמצעות Dialogflow v2
  • איך יוצרים ישויות מותאמות אישית באמצעות Dialogflow
  • איך יוצרים שיחה ליניארית באמצעות Dialogflow
  • איך מגדירים מילויים של webhook באמצעות Dialogflow ו-פונקציות Firebase
  • איך להוסיף את האפליקציה שלכם ל-Google Assistant באמצעות Actions on Google

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

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

2. תהליך ההגדרה

הפעלת פעילות באינטרנט בדפדפן

  1. לוחצים על: http://myaccount.google.com/activitycontrols

  1. מוודאים שההגדרה 'פעילות באינטרנט ובאפליקציות' מופעלת:

bf8d16b828d6f79a.png

יצירת נציג של Dialogflow

  1. פותחים את https://console.dialogflow.com

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

1d7c2b56a1ab95b8.png

  1. צריך לציין שם לסוכן: your-name-tvguide (צריך להשתמש בשם שלכם)

35237b5c5c539ecc.png

  1. שפת ברירת המחדל היא: אנגלית – en
  2. כאזור זמן שמוגדר כברירת מחדל, בוחרים את אזור הזמן שהכי קרוב למיקום שלכם.
  3. לחץ על צור.

הגדרת Dialogflow

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

1d7c2b56a1ab95b8.png

  1. מזינים את התיאור הבא של הסוכן: My TV Guide

26f262d359c49075.png

  1. גוללים למטה אל Log Settings (הגדרות יומן) ומעבירים את שני המתגים למצב 'מופעל' כדי לתעד את האינטראקציות של Dialogflow ולתעד את כל האינטראקציות ב-Google Cloud Stackdriver. נצטרך את זה בהמשך, אם נרצה לנפות באגים בפעולה.

e80c17acc3cce993.png

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

הגדרת Actions on Google

  1. בחלונית השמאלית, לוחצים על הקישור Google Assistant בקטע איך זה עובד ב-Google Assistant.

5a4940338fc351e3.png

הכתובת http://console.actions.google.com תיפתח.

אם אתם חדשים ב-Actions on Google, אתם צריכים קודם למלא את הטופס הזה:

3fd4e594fa169072.png

  1. מנסים לפתוח את הפעולה בסימולטור** על ידי לחיצה על שם הפרויקט.**
  2. בסרגל התפריטים, לוחצים על בדיקה.

6adb83ffb7adeb78.png

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

הפעולה תברך אתכם, עם כוונת ברירת המחדל הבסיסית של Dialogflow. זה אומר שההגדרה של השילוב עם Action on Google עבדה.

3. ישויות מותאמות אישית

ישויות הן אובייקטים שהאפליקציה או המכשיר מבצעים עליהם פעולות. אפשר לחשוב על זה כפרמטרים או משתנים. במדריך התוכניות שלנו נשאל: "What's on MTV". ‫MTV היא הישות והמשתנה. אפשר גם לבקש ערוצים אחרים, כמו: ‫National Geographic או Comedy Central. הישות שנאספה תשמש כפרמטר בבקשה שלי לשירות האינטרנט של API מדריך הערוצים.

מידע נוסף על ישויות ב-Dialogflow

יצירת ישות של ערוץ

  1. לוחצים על פריט התפריט Entities (ישויות) ב-Dialogflow Console.
  2. לוחצים על יצירת ישות.
  3. שם הישות: channel (חשוב לוודא שכל האותיות קטנות)
  4. מעבירים שם של ערוץ. (חלק מהערוצים יצטרכו מילה נרדפת למקרה ש-Google Assistant תבין משהו אחר). אפשר להשתמש במקשים Tab ו-Enter בזמן ההקלדה. מזינים את מספר הערוץ כערך הפניה. ושמות הערוצים כמילים נרדפות, למשל:
  • 1 - 1, Net 1, Net Station 1

ee4e4955aa77232d.png

‫5**.** עוברים למצב עריכה גולמית בלחיצה על לחצן התפריט לצד לחצן השמירה הכחול.

e294b49b123e034f.png

  1. מעתיקים ומדביקים את הישויות האחרות בפורמט CSV:
"2","2","Net 2, Net Station 2"
"3","3","Net 3, Net Station 3"
"4","4","RTL 4"
"5","5","Movie Channel"
"6","6","Sports Channel"
"7","7","Comedy Central"
"8","8","Cartoon Network"
"9","9","National Geographic"
"10","10","MTV"

ed78514afd5badef.png

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

4. כוונות

Dialogflow משתמש בכוונות כדי לסווג את הכוונות של המשתמש. לכוונות יש ביטויי אימון, שהם דוגמאות למה שהמשתמש עשוי לומר לסוכן. לדוגמה, משתמש שרוצה לדעת מה משודר בטלוויזיה יכול לשאול "What is on TV today?‎" ‫"What's currently playing?‎" (מה משודר עכשיו?) או פשוט אומרים "tvguide" (מדריך טלוויזיה).

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

מידע נוסף על כוונות ב-Dialogflow

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

כשיוצרים סוכן חדש ב-Dialogflow, נוצרות באופן אוטומטי שתי כוונות ברירת מחדל. כוונת הפתיחה שמוגדרת כברירת מחדל היא התהליך הראשון שמתחיל כשמתחילים שיחה עם הסוכן. Default Fallback Intent הוא התהליך שתקבלו אם הסוכן לא יבין אתכם או לא יתאים כוונה למה שאמרתם.

  1. לוחצים על Default Welcome Intent (כוונת ברירת המחדל של הודעת הפתיחה).

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

6beee64e8910b85d.png

זו הודעת הפתיחה של כוונת ברירת המחדל לקבלת פנים:

משתמש

Agent

‫"Ok Google, talk to your-name-tvguide" (אוקיי Google, תתחבר ל-your-name-tvguide).

"שלום, אני סוכן מדריך הטלוויזיה. אני יכול להגיד לך מה מוצג כרגע בערוץ טלוויזיה. לדוגמה, אפשר לשאול אותי: 'מה משודר בערוץ MTV?'

  1. גוללים למטה אל תגובות.
  2. מחיקת כל התשובות הטקסטואליות.
  3. תצור תגובה חדשה בטקסט, שתכלול את הפתיח הבא:

Welcome, I am the TV Guide agent. I can tell you what's currently playing on a TV channel. For example, you can ask me: What's on MTV?

84a1110a7f7edba2.png

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

יצירת כוונת בדיקה זמנית

לצורך בדיקה, ניצור כוונת בדיקה זמנית כדי שנוכל לבדוק את ה-webhook בהמשך.

  1. לוחצים שוב על פריט התפריט Intents.
  2. לוחצים על יצירת כוונת חיפוש.
  3. מזינים את שם הכוונה: Test Intent (חשוב להשתמש באות T גדולה ובאות I גדולה. ‫- אם תאייתו את הכוונה בצורה שונה, שירות ה-Back-end לא יעבוד!)

925e02caa4de6b99.png

  1. לוחצים על הוספת ביטויי אימון.
  • Test my agent
  • Test intent

2e44ddb2fae3c841.png

  1. לוחצים על הזמנות > הפעלת ניהול הזמנות.

7eb73ba04d76140e.png

הפעם לא נגדיר תגובה קבועה מראש. התשובה תגיע מפונקציה ב-Cloud Functions.

  1. מעבירים את המתג הפעלת קריאה ל-Webhook עבור הכוונה הזו.

748a82d9b4d7d253.png

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

יצירת כוונת הערוץ

הכוונה של הערוץ תכלול את החלק הזה של השיחה:

משתמש

Agent

"What's on Comedy Central?"

""Currently on Comedy Central from 6 PM, The Simpsons is playing. אחרי זה, בשעה 19:00, תתחיל הסדרה 'איש משפחה'״.

  1. לוחצים שוב על פריט התפריט Intents.
  2. לוחצים על יצירת כוונת חיפוש.
  3. מזינים את שם הכוונה: Channel Intent (חשוב להשתמש באותיות גדולות T ו-I. ‫- אם תאייתו את הכוונה בצורה שונה, שירות ה-Back-end לא יעבוד!)
  4. לוחצים על הוספת ביטויי אימון ומוסיפים את הביטויים הבאים:
  • What's on MTV?
  • What's playing on Comedy Central?
  • What show will start at 8 PM on National Geographic?
  • What is currently on TV?
  • What is airing now.
  • Anything airing on Net Station 1 right now?
  • What can I watch at 7 PM?
  • What's on channel MTV?
  • What's on TV?
  • Please give me the tv guide.
  • Tell me what is on television.
  • What's on Comedy Central from 10 AM?
  • What will be on tv at noon?
  • Anything on National Geographic?
  • TV Guide

6eee02db02831397.png

  1. גוללים למטה אל פעולה ופרמטרים.

b7e917026760218a.png

שימו לב לישויות @channel ו-@sys.time שמוכרות ל-Dialogflow. בהמשך, שם הפרמטר וערך הפרמטר יישלחו לשירות האינטרנט שלכם ב-webhook. לדוגמה:

channel=8

time=2020-01-29T19:00:00+01:00

  1. סימון הערוץ כחובה

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

מזינים את ההנחיה:

  • For which TV channel do you want to hear the tv guide information?
  • In which TV channel are you interested?

cdb5601ead9423f8.png

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

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

  1. לוחצים על הזמנות.

הפעם לא נגדיר תגובה קבועה מראש. התשובה תגיע מפונקציית הענן. לכן, מעבירים את המתג Enable Webhook call for this intent (הפעלת קריאת Webhook לכוונת המשתמש הזו).

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

5. ניהול אספקה באמצעות תגובה לפעולה מאתר אחר (webhook)

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

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

cc84351f0d03ab6f.png

כדי לבדוק ולהטמיע בקלות webhook, אפשר להשתמש בכלי לעריכה בשורה. הוא משתמש ב-Cloud Functions for Firebase, פונקציות ללא שרת.

  1. לוחצים על הכרטיסייה index.js בעורך ומעתיקים ומדביקים את קטע ה-JavaScript הזה לקוד Node.js:
'use strict';

process.env.DEBUG = 'dialogflow:debug';

const {
  dialogflow,
  BasicCard,
  Button,
  Image,
  List
 } = require('actions-on-google');

const functions = require('firebase-functions');
const moment = require('moment');
const TVGUIDE_WEBSERVICE = 'https://tvguide-e4s5ds5dsa-ew.a.run.app/channel';
const { WebhookClient } = require('dialogflow-fulfillment');
var spokenText = '';
var results = null;


/* When the Test Intent gets invoked. */
function testHandler(agent) {
    let spokenText = 'This is a test message, when you see this, it means your webhook fulfillment worked!';

    if (agent.requestSource === agent.ACTIONS_ON_GOOGLE) {
        let conv = agent.conv();
        conv.ask(spokenText);
        conv.ask(new BasicCard({
            title: `Test Message`,
            subTitle: `Dialogflow Test`,
            image: new Image({
                url: 'https://dummyimage.com/600x400/000/fff',
                alt: 'Image alternate text',
            }),
            text: spokenText,
            buttons: new Button({
                title: 'This is a button',
                url: 'https://assistant.google.com/',
            }),
        }));
        // Add Actions on Google library responses to your agent's response
        agent.add(conv);
    } else {
        agent.add(spokenText);
    }
}

/* When the Channel Intent gets invoked. */
function channelHandler(agent) {
    var jsonResponse = `{"ID":10,"Listings":[{"Title":"Catfish Marathon","Date":"2018-07-13","Time":"11:00:00"},{"Title":"Videoclips","Date":"2018-07-13","Time":"12:00:00"},{"Title":"Pimp my ride","Date":"2018-07-13","Time":"12:30:00"},{"Title":"Jersey Shore","Date":"2018-07-13","Time":"13:00:00"},{"Title":"Jersey Shore","Date":"2018-07-13","Time":"13:30:00"},{"Title":"Daria","Date":"2018-07-13","Time":"13:45:00"},{"Title":"The Real World","Date":"2018-07-13","Time":"14:00:00"},{"Title":"The Osbournes","Date":"2018-07-13","Time":"15:00:00"},{"Title":"Teenwolf","Date":"2018-07-13","Time":"16:00:00"},{"Title":"MTV Unplugged","Date":"2018-07-13","Time":"16:30:00"},{"Title":"Rupauls Drag Race","Date":"2018-07-13","Time":"17:30:00"},{"Title":"Ridiculousness","Date":"2018-07-13","Time":"18:00:00"},{"Title":"Punk'd","Date":"2018-07-13","Time":"19:00:00"},{"Title":"Jersey Shore","Date":"2018-07-13","Time":"20:00:00"},{"Title":"MTV Awards","Date":"2018-07-13","Time":"20:30:00"},{"Title":"Beavis & Butthead","Date":"2018-07-13","Time":"22:00:00"}],"Name":"MTV"}`;
    var results = JSON.parse(jsonResponse);
    var listItems = {};
    spokenText = getSpeech(results);

    for (var i = 0; i < results['Listings'].length; i++) {
        listItems[`SELECT_${i}`] = {
            title: `${getSpokenTime(results['Listings'][i]['Time'])} - ${results['Listings'][i]['Title']}`,
            description: `Channel: ${results['Name']}`
        }
    }
    if (agent.requestSource === agent.ACTIONS_ON_GOOGLE) {
        let conv = agent.conv();
        conv.ask(spokenText);
        conv.ask(new List({
            title: 'TV Guide',
            items: listItems
        }));
        // Add Actions on Google library responses to your agent's response
        agent.add(conv);
    } else {
        agent.add(spokenText);
    }
}

/**
 * Return a text string to be spoken out by the Google Assistant
 * @param {object} JSON tv results
 */
var getSpeech = function(tvresults) {
    let s = "";
    if(tvresults['Listings'][0]) {
        let channelName = tvresults['Name'];
        let currentlyPlayingTime = getSpokenTime(tvresults['Listings'][0]['Time']);
        let laterPlayingTime = getSpokenTime(tvresults['Listings'][1]['Time']);
        s = `On ${channelName} from ${currentlyPlayingTime}, ${tvresults['Listings'][0]['Title']} is playing.
        Afterwards at ${laterPlayingTime}, ${tvresults['Listings'][1]['Title']} will start.`
    }

    return s;
}

/**
 * Return a natural spoken time
 * @param {string} time in 'HH:mm:ss' format
 * @returns {string} spoken time (like 8 30 pm i.s.o. 20:00:00)
 */
var getSpokenTime = function(time){
    let datetime = moment(time, 'HH:mm:ss');
    let min = moment(datetime).format('m');
    let hour = moment(datetime).format('h');
    let partOfTheDay = moment(datetime).format('a');

    if (min == '0') {
        min = '';
    }

    return `${hour} ${min} ${partOfTheDay}`;
};

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
    var agent = new WebhookClient({ request, response });

    console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
    console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
   
    let channelInput = request.body.queryResult.parameters.channel;
    let requestedTime = request.body.queryResult.parameters.time;
    let url = `${TVGUIDE_WEBSERVICE}/${channelInput}`;

    var intentMap = new Map();
    intentMap.set('Test Intent', testHandler);
    intentMap.set('Channel Intent', channelHandler);
    agent.handleRequest(intentMap);
});

cc84351f0d03ab6f.png

  1. לוחצים על הכרטיסייה package.json בעורך ומעתיקים ומדביקים את קטע קוד ה-JSON הזה, שמייבא את כל הספריות של Node.js Package Manager ‏ (NPM):
{
  "name": "tvGuideFulfillment",
  "description": "Requesting TV Guide information from a web service.",
  "version": "1.0.0",
  "private": true,
  "license": "Apache Version 2.0",
  "author": "Google Inc.",
  "engines": {
    "node": "8"
  },
  "scripts": {
    "start": "firebase serve --only functions:dialogflowFirebaseFulfillment",
    "deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment"
  },
  "dependencies": {
    "actions-on-google": "^2.2.0",
    "firebase-admin": "^5.13.1",
    "firebase-functions": "^2.0.2",
    "request": "^2.85.0",
    "request-promise": "^4.2.5",
    "moment" : "^2.24.0",
    "dialogflow-fulfillment": "^0.6.1"
  }
}

af01460c2a023e68.png

  1. לוחצים על הלחצן Deploy (פריסה). הפעולה תימשך כמה רגעים כי המערכת פורסת את הפונקציה ללא שרת. בתחתית המסך יופיע חלון קופץ עם הסטטוס שלכם.
  2. כדי לבדוק אם הקוד פועל, נבדוק את ה-webhook. בסימולטור בצד שמאל, מקלידים:

Test my agent.

אם הכל תקין, תופיע ההודעה: "This is a test message".

  1. בואו נבדוק את הכוונה של הערוץ. עכשיו נשאל את השאלה:

What's on MTV?

אם הכל נכון, אמור להופיע:

‫"On MTV from 4 30 pm, MTV Unplugged is playing. אחרי זה, בשעה 17:30, תתחיל התוכנית RuPaul's Drag Race".

שלבים אופציונליים – Firebase

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

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

אם רוצים לבדוק את האפליקציה הזו באמצעות שירות אינטרנט, צריך לשדרג את המינוי ל-Firebase לתוכנית Blaze. הערה: השלבים האלה הם אופציונליים. אפשר גם לעבור לשלבים הבאים במעבדה הזו כדי להמשיך לבדוק את האפליקציה ב-Actions on Google.

  1. עוברים אל מסוף Firebase: https://console.firebase.google.com

  1. בתחתית המסך, לוחצים על הלחצן שדרוג.

ad38bc6d07462abf.png

בחלון הקופץ, בוחרים בתוכנית Blaze.

  1. עכשיו אנחנו יודעים שה-webhook פועל, ולכן אפשר להמשיך ולהחליף את הקוד של index.js בקוד שמופיע בהמשך. כך תוכלו לוודא שתוכלו לבקש מידע על מדריך התוכניות משירות האינטרנט:
'use strict';

process.env.DEBUG = 'dialogflow:debug';

const {
  dialogflow,
  BasicCard,
  Button,
  Image,
  List
 } = require('actions-on-google');

const functions = require('firebase-functions');
const moment = require('moment');
const { WebhookClient } = require('dialogflow-fulfillment');
const rp = require('request-promise');

const TVGUIDE_WEBSERVICE = 'https://tvguide-e4s5ds5dsa-ew.a.run.app/channel';
var spokenText = '';
var results = null;


/* When the Test Intent gets invoked. */
function testHandler(agent) {
    let spokenText = 'This is a test message, when you see this, it means your webhook fulfillment worked!';

    if (agent.requestSource === agent.ACTIONS_ON_GOOGLE) {
        let conv = agent.conv();
        conv.ask(spokenText);
        conv.ask(new BasicCard({
            title: `Test Message`,
            subTitle: `Dialogflow Test`,
            image: new Image({
                url: 'https://dummyimage.com/600x400/000/fff',
                alt: 'Image alternate text',
            }),
            text: spokenText,
            buttons: new Button({
                title: 'This is a button',
                url: 'https://assistant.google.com/',
            }),
        }));
        // Add Actions on Google library responses to your agent's response
        agent.add(conv);
    } else {
        agent.add(spokenText);
    }
}

/* When the Channel Intent gets invoked. */
function channelHandler(agent) {
    var listItems = {};
    spokenText = getSpeech(results);

    for (var i = 0; i < results['Listings'].length; i++) {
        listItems[`SELECT_${i}`] = {
            title: `${getSpokenTime(results['Listings'][i]['Time'])} - ${results['Listings'][i]['Title']}`,
            description: `Channel: ${results['Name']}`

        }
    }
    if (agent.requestSource === agent.ACTIONS_ON_GOOGLE) {
        let conv = agent.conv();
        conv.ask(spokenText);
        conv.ask(new List({
            title: 'TV Guide',
            items: listItems
        }));
        // Add Actions on Google library responses to your agent's response
        agent.add(conv);
    } else {
        agent.add(spokenText);
    }
}

/**
 * Return a text string to be spoken out by the Google Assistant
 * @param {object} JSON tv results
 */
var getSpeech = function(tvresults) {
    let s = "";
    if(tvresults && tvresults['Listings'][0]) {
        let channelName = tvresults['Name'];
        let currentlyPlayingTime = getSpokenTime(tvresults['Listings'][0]['Time']);
        let laterPlayingTime = getSpokenTime(tvresults['Listings'][1]['Time']);
        s = `On ${channelName} from ${currentlyPlayingTime}, ${tvresults['Listings'][0]['Title']} is playing.
        Afterwards at ${laterPlayingTime}, ${tvresults['Listings'][1]['Title']} will start.`
    }

    return s;
}

/**
 * Return a natural spoken time
 * @param {string} time in 'HH:mm:ss' format
 * @returns {string} spoken time (like 8 30 pm i.s.o. 20:00:00)
 */
var getSpokenTime = function(time){
    let datetime = moment(time, 'HH:mm:ss');
    let min = moment(datetime).format('m');
    let hour = moment(datetime).format('h');
    let partOfTheDay = moment(datetime).format('a');

    if (min == '0') {
        min = '';
    }

    return `${hour} ${min} ${partOfTheDay}`;
};

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
    var agent = new WebhookClient({ request, response });

    console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
    console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
   
    let channelInput = request.body.queryResult.parameters.channel;
    let requestedTime = request.body.queryResult.parameters.time;
    let url = `${TVGUIDE_WEBSERVICE}/${channelInput}`;

    if (requestedTime) {
        console.log(requestedTime);
        let offsetMin = moment().utcOffset(requestedTime)._offset;
        console.log(offsetMin);
        let time = moment(requestedTime).utc().add(offsetMin,'m').format('HH:mm:ss');
        url = `${TVGUIDE_WEBSERVICE}/${channelInput}/${time}`;
      }
    
      console.log(url);
  
      var options = {
          uri: encodeURI(url),
          json: true
      };
       
      // request promise calls an URL and returns the JSON response.
      rp(options)
        .then(function(tvresults) {
            console.log(tvresults);
            // the JSON response, will need to be formatted in 'spoken' text strings.
            spokenText = getSpeech(tvresults);
            results = tvresults;
        })
        .catch(function (err) {
            console.error(err);
        })
        .finally(function(){
            // kick start the Dialogflow app
            // based on an intent match, execute
            var intentMap = new Map();
            intentMap.set('Test Intent', testHandler);
            intentMap.set('Channel Intent', channelHandler);
            agent.handleRequest(intentMap);
        });
});

6. Actions on Google

Actions on Google היא פלטפורמת פיתוח ל-Google Assistant. היא מאפשרת לצד שלישי לפתח 'פעולות' – אפלטונים ל-Google Assistant שמספקים פונקציונליות מורחבת.

תצטרכו להפעיל פעולה ב-Google, ולבקש מ-Google לפתוח אפליקציה או לדבר איתה.

הפעולה הזו תפתח את הפעולה שלכם, תשנה את הקול ותוציא אתכם מההיקף 'המקורי' של Google Assistant. כלומר, כל מה שתבקשו מהסוכן מכאן ואילך צריך להיווצר על ידכם. אי אפשר לבקש מ-Google Assistant מידע על מזג האוויר של Google אם זה מה שרוצים. קודם צריך לצאת (לסגור) את ההיקף של הפעולה (האפליקציה).

בדיקת הפעולה בסימולטור של Google Assistant

בואו נבדוק את השיחה הבאה:

משתמש

Google Assistant

‫"Ok Google, talk to your-name-tv-guide."

"בטח. אני רוצה להציג את your-name-tv-guide".

משתמש

Your-Name-TV-Guide Agent

-

"שלום, אני מדריך התוכניות..."

בדיקת הסוכן שלי

"זו הודעת בדיקה. אם אתם רואים אותה, סימן שה-webhook שלכם פועל!"

מה משודר ב-MTV?

ב-MTV החל מ-16:30, מוצגת התוכנית MTV Unplugged. אחרי כן, בשעה 17:30, תתחיל התוכנית RuPaul's Drag Race.

  1. חזרה לסימולטור של Google Assistant

פותחים את הכתובת: https://console.actions.google.com

  1. לוחצים על סמל המיקרופון ושואלים את השאלה הבאה:

c3b200803c7ba95e.png

  • Talk to my test agent
  • Test my agent

‫Google Assistant אמורה להגיב עם:

5d93c6d037c8c8eb.png

  1. עכשיו נשאל:
  • What's on Comedy Central?

הפלט צריך להיות:

משפחת סימפסון משודרת כרגע ב-Comedy Central החל מ-18:00. אחרי כן, בשעה 19:00, תתחיל התוכנית 'איש משפחה'.

7. מזל טוב

יצרת את הפעולה הראשונה שלך ב-Google Assistant באמצעות Dialogflow. כל הכבוד!

יכול להיות ששמת לב שהפעולה שלך רצה במצב בדיקה שמקושר לחשבון Google שלך. אם תיכנסו למכשיר Nest או לאפליקציית Google Assistant בטלפון Android או iOS, באמצעות אותו חשבון. אפשר גם לבדוק את הפעולה.

זוהי הדגמה של סדנה. אבל כשמפתחים אפליקציות ל-Google Assistant לשימוש אמיתי, אפשר לשלוח את הפעולה לאישור. מידע נוסף זמין במדריך הזה.

מה נכלל

  • איך יוצרים צ'אט בוט באמצעות Dialogflow v2
  • איך יוצרים ישויות מותאמות אישית באמצעות Dialogflow
  • איך יוצרים שיחה ליניארית באמצעות Dialogflow
  • איך מגדירים מילויים של webhook באמצעות Dialogflow ו-פונקציות Firebase
  • איך להוסיף את האפליקציה שלכם ל-Google Assistant באמצעות Actions on Google

מה השלב הבא?

נהניתם מה-Code Lab הזה? כדאי לבדוק את המעבדות הנהדרות האלה!

כדי להמשיך את ה-Code Lab הזה, צריך לשלב אותו עם Google Chat:

איך יוצרים מדריך טלוויזיה ב-Google Chat באמצעות G Suite ו-Dialogflow