ลงมือปฏิบัติ: สร้างการดำเนินการสำหรับทีวีไกด์สำหรับ Google Assistant ด้วย Dialogflow และ Actions on Google

1. บทนำ

คุณกำลังดูทีวี แต่หารีโมตไม่เจอ หรืออาจไม่ต้องการไปที่ช่องทีวีแต่ละช่องเพื่อดูว่ามีรายการน่าสนใจหรือไม่ มาถาม Google Assistant กันว่ามีอะไรในทีวีบ้าง ในแล็บนี้ คุณจะได้สร้างการกระทําอย่างง่ายโดยใช้ Dialogflow และเรียนรู้วิธีผสานรวมกับการกระทําของ Google Assistant

แบบฝึกหัดจะเรียงตามลำดับเพื่อให้สอดคล้องกับประสบการณ์การใช้งานของผู้พัฒนาบนระบบคลาวด์ทั่วไป

  1. สร้าง Agent Dialogflow v2
  2. สร้างเอนทิตีที่กำหนดเอง
  3. สร้างความตั้งใจ
  4. ตั้งค่า Webhook ด้วย Firebase Functions
  5. ทดสอบแชทบ็อต
  6. เปิดใช้การผสานรวม Google Assistant

สิ่งที่คุณจะสร้าง

เราจะสร้างเอเจนต์แชทบอทคู่มือทีวีแบบอินเทอร์แอกทีฟสำหรับ Google Assistant คุณสามารถถามไกด์ทีวีว่าขณะนี้ช่องใดกำลังออกอากาศ เช่น "MTV กำลังฉายอะไร" การดำเนินการในคู่มือทีวีจะบอกให้คุณทราบว่าตอนนี้กำลังฉายอะไรและจะฉายอะไรต่อไป

สิ่งที่คุณจะได้เรียนรู้

  • วิธีสร้างแชทบอทด้วย Dialogflow v2
  • วิธีสร้างเอนทิตีที่กำหนดเองด้วย Dialogflow
  • วิธีสร้างการสนทนาแบบเชิงเส้นด้วย Dialogflow
  • วิธีตั้งค่าการดำเนินการตามคำสั่งของเว็บฮุกด้วย Dialogflow และฟังก์ชัน Firebase
  • วิธีนำแอปพลิเคชันของคุณมาใช้กับ Google Assistant ด้วย Actions on Google

ข้อกำหนดเบื้องต้น

  • คุณจะต้องมีข้อมูลประจำตัวของ Google / อีเมล Gmail เพื่อสร้าง Agent ของ Dialogflow
  • ไม่จำเป็นต้องมีความรู้พื้นฐานเกี่ยวกับ 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. เลือกภาษาเริ่มต้นเป็น English - en
  2. เลือกเขตเวลาที่ใกล้กับคุณมากที่สุดเป็นเขตเวลาเริ่มต้น
  3. คลิกสร้าง

กำหนดค่า Dialogflow

  1. คลิกไอคอนเฟืองในเมนูด้านซ้ายข้างชื่อโปรเจ็กต์

1d7c2b56a1ab95b8.png

  1. ป้อนคำอธิบาย Agent ต่อไปนี้ My TV Guide

26f262d359c49075.png

  1. เลื่อนลงไปที่การตั้งค่าบันทึก แล้วสลับทั้ง 2 สวิตช์เพื่อบันทึกการโต้ตอบของ 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. ตรวจสอบว่าได้ตั้งค่าโปรแกรมจำลองเป็นภาษาอังกฤษ แล้วคลิกคุยกับแอปทดสอบของฉัน

Action จะทักทายคุณด้วย Intent เริ่มต้นพื้นฐานของ Dialogflow ซึ่งหมายความว่าการตั้งค่าการผสานรวมกับ Action on Google สำเร็จแล้ว

3. เอนทิตีที่กำหนดเอง

เอนทิตีคือออบเจ็กต์ที่แอปหรืออุปกรณ์ของคุณดำเนินการ ให้คิดว่าพารามิเตอร์ / ตัวแปร ในผังรายการทีวี เราจะถามว่า "MTV เปิดอะไรอยู่" MTV คือเอนทิตีและตัวแปร ฉันขอช่องอื่นๆ ได้ด้วย เช่น "National Geographic" หรือ "Comedy Central" ระบบจะใช้เอนทิตีที่รวบรวมเป็นพารามิเตอร์ในคำขอของฉันไปยังเว็บเซอร์วิส TV Guide API

ดูข้อมูลเพิ่มเติมเกี่ยวกับเอนทิตี Dialogflow

การสร้างเอนทิตีของช่อง

  1. คลิกรายการเมนูเอนทิตีในคอนโซล Dialogflow
  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. Intent

Dialogflow ใช้ความตั้งใจเพื่อจัดหมวดหมู่ความตั้งใจของผู้ใช้ เจตนามีวลีการฝึก ซึ่งเป็นตัวอย่างของสิ่งที่ผู้ใช้อาจพูดกับเอเจนต์ เช่น ผู้ใช้ที่ต้องการทราบว่ามีอะไรฉายในทีวีบ้างอาจถามว่า "วันนี้มีอะไรฉายในทีวี" "ตอนนี้เปิดอะไรอยู่" หรือพูดว่า "ทีวีไกด์"

เมื่อผู้ใช้เขียนหรือพูดอะไรบางอย่าง ซึ่งเรียกว่าการแสดงออกของผู้ใช้ Dialogflow จะจับคู่การแสดงออกของผู้ใช้กับเจตนาที่ดีที่สุดในเอเจนต์ การจับคู่ความตั้งใจเรียกอีกอย่างว่าการจัดประเภทความตั้งใจ

ดูข้อมูลเพิ่มเติมเกี่ยวกับเจตนาของ Dialogflow

การแก้ไขเจตนาต้อนรับเริ่มต้น

เมื่อสร้างเอเจนต์ Dialogflow ใหม่ ระบบจะสร้าง Intent เริ่มต้น 2 รายการโดยอัตโนมัติ เจตนาต้อนรับเริ่มต้นคือโฟลว์แรกที่คุณจะได้รับเมื่อเริ่มการสนทนากับตัวแทน เจตนาสำรองเริ่มต้นคือโฟลว์ที่คุณจะได้รับเมื่อตัวแทนไม่เข้าใจคุณหรือไม่สามารถจับคู่เจตนากับสิ่งที่คุณเพิ่งพูด

  1. คลิก Default Welcome Intent

ในกรณีของ Google Assistant ระบบจะเริ่มทำงานโดยอัตโนมัติด้วยเจตนาต้อนรับเริ่มต้น เนื่องจาก Dialogflow กำลังรอเหตุการณ์ต้อนรับ แต่คุณยังเรียกใช้ Intent ได้ด้วยการพูดวลีการฝึกที่ป้อนไว้

6beee64e8910b85d.png

นี่คือข้อความต้อนรับสำหรับเจตนาต้อนรับเริ่มต้น

ผู้ใช้

Agent

"Ok Google คุยกับ your-name-tvguide"

"ยินดีต้อนรับ ฉันคือตัวแทนทีวีไกด์ ฉันบอกได้ว่าตอนนี้ช่องทีวีกำลังออกอากาศอะไรอยู่ เช่น คุณสามารถถามว่า "ตอนนี้ MTV กำลังฉายอะไร"

  1. เลื่อนลงไปที่คำตอบ
  2. ล้างคำตอบที่เป็นข้อความทั้งหมด
  3. สร้างคำตอบแบบข้อความใหม่ 1 รายการซึ่งมีคำทักทายต่อไปนี้

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. คลิกบันทึก

สร้างเจตนาทดสอบชั่วคราว

เพื่อวัตถุประสงค์ในการทดสอบ เราจะสร้าง Intent ทดสอบชั่วคราวเพื่อให้ทดสอบเว็บฮุกได้ในภายหลัง

  1. คลิกรายการเมนูเจตนาอีกครั้ง
  2. คลิกสร้างความตั้งใจ
  3. ป้อนชื่อความตั้งใจ: Test Intent (ตรวจสอบว่าคุณใช้ T และ I ตัวพิมพ์ใหญ่ - หากคุณสะกดเจตนาแตกต่างออกไป บริการแบ็กเอนด์จะทำงานไม่ได้)

925e02caa4de6b99.png

  1. คลิกเพิ่มวลีการฝึก
  • Test my agent
  • Test intent

2e44ddb2fae3c841.png

  1. คลิกการจัดการคำสั่งซื้อ > เปิดใช้การจัดการคำสั่งซื้อ

7eb73ba04d76140e.png

คราวนี้เราจะไม่ฮาร์ดโค้ดคำตอบ การตอบกลับจะมาจาก Cloud Function

  1. พลิกสวิตช์เปิดใช้การเรียกใช้ Webhook สำหรับความตั้งใจนี้

748a82d9b4d7d253.png

  1. คลิกบันทึก

สร้างความตั้งใจของแชแนล

เจตนาของช่องจะมีส่วนของการสนทนาต่อไปนี้

ผู้ใช้

Agent

"มีอะไรฉายใน Comedy Central บ้าง"

""ตอนนี้ The Simpsons กำลังฉายทาง Comedy Central ตั้งแต่เวลา 18:00 น. จากนั้นเวลา 19:00 น. จะเริ่มฉาย Family Guy""

  1. คลิกรายการเมนูเจตนาอีกครั้ง
  2. คลิกสร้างความตั้งใจ
  3. ป้อนชื่อความตั้งใจ: Channel Intent (ตรวจสอบว่าคุณใช้ T และ I ตัวพิมพ์ใหญ่ - หากคุณสะกดเจตนาแตกต่างออกไป บริการแบ็กเอนด์จะทำงานไม่ได้)
  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. คลิกการปฏิบัติตามคำสั่งซื้อ

คราวนี้เราจะไม่ฮาร์ดโค้ดคำตอบ การตอบกลับจะมาจาก Cloud Function ดังนั้น ให้พลิกสวิตช์เปิดใช้การเรียกใช้ Webhook สำหรับความตั้งใจนี้

  1. คลิกบันทึก

5. การดำเนินการตามคำสั่งผ่านเว็บฮุค

หากเอเจนต์ต้องการมากกว่าการตอบกลับตามความตั้งใจแบบคงที่ คุณต้องใช้การดำเนินการตามคำสั่งเพื่อเชื่อมต่อบริการเว็บกับเอเจนต์ การเชื่อมต่อบริการเว็บช่วยให้คุณดำเนินการตามสิ่งที่ผู้ใช้แสดงออกและส่งคำตอบแบบไดนามิกกลับไปยังผู้ใช้ได้ ตัวอย่างเช่น หากผู้ใช้ต้องการดูตารางรายการทีวีของ MTV เว็บเซอร์วิสจะตรวจสอบในฐานข้อมูลและตอบกลับผู้ใช้ด้วยตารางรายการของ MTV

  1. คลิกการจัดการคำสั่งซื้อในเมนูหลัก
  2. เปิดสวิตช์โปรแกรมแก้ไขในบรรทัด

cc84351f0d03ab6f.png

คุณสามารถใช้เครื่องมือแก้ไขในบรรทัดสำหรับการทดสอบและการติดตั้งใช้งานเว็บบุ๊กอย่างง่าย โดยใช้ 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. คลิกปุ่มติดตั้งใช้งาน ระบบจะใช้เวลาสักครู่เนื่องจากกำลังติดตั้งฟังก์ชันแบบไม่ใช้เซิร์ฟเวอร์ ป๊อปอัปจะปรากฏที่ด้านล่างของหน้าจอเพื่อแจ้งสถานะของคุณ
  2. มาทดสอบเว็บฮุกเพื่อดูว่าโค้ดใช้งานได้ไหม ในโปรแกรมจำลองทางด้านขวา ให้พิมพ์

Test my agent.

เมื่อทุกอย่างถูกต้อง คุณควรเห็นข้อความว่า "นี่คือข้อความทดสอบ"

  1. มาทดสอบความตั้งใจของช่องกัน โดยถามคำถามต่อไปนี้

What's on MTV?

เมื่อทุกอย่างถูกต้อง คุณควรเห็นข้อมูลต่อไปนี้

"MTV Unplugged กำลังเล่นทาง MTV ตั้งแต่เวลา 16:30 น. จากนั้นเวลา 17:30 น. จะเริ่มรายการ RuPaul's Drag Race"

ขั้นตอนที่ไม่บังคับ - Firebase

เมื่อทดสอบกับช่องอื่น คุณจะเห็นว่าผลลัพธ์ของทีวีเหมือนกัน เนื่องจากฟังก์ชัน Cloud ยังไม่ได้ดึงข้อมูลจากเว็บเซิร์ฟเวอร์จริง

เราจะต้องสร้างการเชื่อมต่อเครือข่ายขาออกเพื่อดำเนินการนี้

หากต้องการทดสอบแอปพลิเคชันนี้กับเว็บเซอร์วิส ให้อัปเกรดแพ็กเกจ 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 Action โดยขอให้ Google เปิดหรือพูดคุยกับแอป

การดำเนินการนี้จะเปิดการดำเนินการของคุณ เปลี่ยนเสียง และคุณจะออกจากขอบเขตของ Google Assistant "ดั้งเดิม" ซึ่งหมายความว่าทุกสิ่งที่คุณขอจากเอเจนต์นับจากนี้ไปจะต้องสร้างขึ้นโดยคุณ คุณไม่สามารถถาม Google Assistant เกี่ยวกับข้อมูลสภาพอากาศของ Google ได้ทันทีหากต้องการทราบข้อมูลดังกล่าว คุณควรออกจาก (ปิด) ขอบเขตของการดำเนินการ (แอปของคุณ) ก่อน

ทดสอบการดำเนินการในโปรแกรมจำลอง Google Assistant

มาทดสอบการสนทนาต่อไปนี้กัน

ผู้ใช้

Google Assistant

"Ok Google คุยกับyour-name-tv-guide"

"ได้เลย ขอดูyour-name-tv-guide หน่อย"

ผู้ใช้

ตัวแทน Your-Name-TV-Guide

-

"ยินดีต้อนรับ ฉันคือทีวีไกด์...."

ทดสอบ Agent ของฉัน

"นี่คือข้อความทดสอบ เมื่อคุณเห็นข้อความนี้ แสดงว่าการดำเนินการตามคำสั่งของ Webhook ทำงานแล้ว"

MTV มีรายการอะไรบ้าง

MTV Unplugged กำลังเล่นทาง MTV ตั้งแต่เวลา 16:30 น. จากนั้นเวลา 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?

ซึ่งควรแสดงผลดังนี้

ตอนนี้ The Simpsons กำลังฉายทาง Comedy Central ตั้งแต่เวลา 18:00 น. จากนั้นเวลา 19:00 น.จะเริ่มฉาย Family Guy

7. ขอแสดงความยินดี

คุณได้สร้างการทำงานของ Google Assistant รายการแรกด้วย Dialogflow แล้ว ขอแสดงความยินดีด้วย

ดังที่คุณอาจสังเกตเห็น การดำเนินการของคุณทำงานในโหมดทดสอบซึ่งเชื่อมโยงกับบัญชี Google ของคุณ หากคุณจะเข้าสู่ระบบในอุปกรณ์ Nest หรือแอป Google Assistant ในโทรศัพท์ iOS หรือ Android ด้วยบัญชีเดียวกัน คุณยังทดสอบการดำเนินการได้ด้วย

ตอนนี้เราจะมาดูการสาธิตเวิร์กช็อป แต่เมื่อสร้างแอปพลิเคชันสำหรับ Google Assistant จริงๆ คุณจะส่ง Action เพื่อขอรับการอนุมัติได้ อ่านข้อมูลเพิ่มเติมในคู่มือนี้

สิ่งที่เราได้พูดถึง

  • วิธีสร้างแชทบอทด้วย Dialogflow v2
  • วิธีสร้างเอนทิตีที่กำหนดเองด้วย Dialogflow
  • วิธีสร้างการสนทนาแบบเชิงเส้นด้วย Dialogflow
  • วิธีตั้งค่าการดำเนินการตามคำสั่งของเว็บฮุกด้วย Dialogflow และฟังก์ชัน Firebase
  • วิธีนำแอปพลิเคชันของคุณมาใช้กับ Google Assistant ด้วย Actions on Google

สิ่งต่อไปที่ควรทำ

คุณชอบโค้ดแล็บนี้ไหม ลองดูห้องทดลองที่ยอดเยี่ยมเหล่านี้

ทำตาม Codelab นี้ต่อโดยผสานรวมกับ Google Chat

สร้างแชท Google Chat สำหรับรายการทีวีด้วย G Suite และ Dialogflow