Help us understand the problem. What is going on with this article?

スマートスピーカープログラミング(1)

書籍「やさしくはじめる スマートスピーカープログラミング」は、とても親切に書いていてわかりやすいのですが、2019年5月に出版したにも関わらず、すでに現在の内容と相違があります。
それだけ、Googleのバージョンアップが早くてお気の毒なのですけれども。

それで、現在の内容を調べつつ、自分なりに実現出来た事を書きます。
但し、この記事でさえ、すぐに陳腐化する恐れがありますが、いちいちついていくのは面倒なので、たぶん直しません。
あくまでも2020年2月8日の情報です。

ここでは、Capter4-4「どっちの手ゲームを作ろう」を取り上げます。
なので、詳しい内容は、上記書籍を見比べてください。
この記事は、あくまでも差分です。

新規プロジェクトを作成しよう

Action Consoleを開いて新規プロジェクトを作成します。
1.jpg

プロジェクト名、言語と地域を設定し、CREATE PROJECTボタンを押します
2.jpg

すると、色々出てきますが、「Conversational」を選びます
3.jpg

本と違っていますが、めげちゃいけません。「Decide how your Action invoked」を選びます。
4.jpg

書籍ではDisplay nameは「どっちの手」になっていますが、これはすでにアプリとして存在しているようで、間違っていても、すでにある方が起動されますので、名前を変えて「どの手にあるかな」にしました。
Display nameを設定したら、SAVEを押します
6.jpg

「Don't forget to update sample invocations in the directory information page」とか言われるたら、左メニューの「Actions」を選びます

「ADD Your First Action」ボタンを押します
7.jpg

「Custom intent」が選択されているので、そのまま「BUILD」ボタンを押します
8.jpg

暫く時間がかかってから、Dialogflowの画面が出ます
DEFAULT LANGUAGEを「Japanese-ja」に変更して「CREATE」ボタンを押します。
9.jpg

また暫く時間がかかります
「Default Welcome Intent」を選びます。
10.jpg

Text Responseに、ウェルカムメッセージを入れて「SAVE」ボタンを押します
11.jpg

「Intent saved OK」と出たら、左メニュの「Intents」ボタンを押し「CREATE INTENT」ボタンを押します
12.jpg

「Intent Name」を設定し「ADD TRAINING PHASES」を押します
13.jpg

「Add user expression」に、受け付けるユーザーの答えのフレーズを入れていきます。
書籍では「右手」と「左手」だけですが、ここで色々入れておくと、言い方を変えても反応してくれる、、、はずです
14.jpg

** ここで一回SAVEボタンを押しておきます **

SAVEされたら、左メニューからEntitiesを押します
24.jpg

まだエンティティはなにもないので、「CREATE ENTITY」ボタンを押します
25.jpg

ここでは、エンティティ名をhandとします
26.jpg

Enter reference valueに「左手」Enter synonymに「左」と「左手」を登録します。
これで、言い方にブレが有っても、「左手」と認識するようになります
右手も同じ様に登録し「SAVE」ボタンを押します
28.jpg
「Agent Training completed」が表示されたら、左メニューの「Intents」を選択してインテントに戻り、先程つくった「右手左手インテント」を選択します
18.jpg

Training phrasesの「左」「左手」「右」「右手」の部分を選択すると、エンティティ一覧が表示されます。今作成した「hand」は一番したに追加されていますので、選択します
29.jpg

全ての「左」「左手」「右」「右手」について、同様に処理しますが、2回目以降は「@hand:hand」を選べるようになっています
30.jpg
全て選択し終えたら「SAVE」ボタンを押します

次にFullfillmentを選んで、「Enable Fulfillment」ボタンを押します
31.jpg

「Enable webhook call for this intent」のスイッチをオンにして、「SAVE]ボタンを押し、左メニューのFullfillmentを押します
32.jpg

「Inline Editor」のDISABLEスイッチを押して、編集可能にします
33.jpg

予め設定されているプログラムは下記の通りです

index.js
// See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
// for Dialogflow fulfillment library docs, samples, and to report issues
'use strict';

const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');

process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
  const agent = new WebhookClient({ request, response });
  console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
  console.log('Dialogflow Request body: ' + JSON.stringify(request.body));

  function welcome(agent) {
    agent.add(`Welcome to my agent!`);
  }

  function fallback(agent) {
    agent.add(`I didn't understand`);
    agent.add(`I'm sorry, can you try again?`);
  }

  // // Uncomment and edit to make your own intent handler
  // // uncomment `intentMap.set('your intent name here', yourFunctionHandler);`
  // // below to get this function to be run when a Dialogflow intent is matched
  // function yourFunctionHandler(agent) {
  //   agent.add(`This message is from Dialogflow's Cloud Functions for Firebase editor!`);
  //   agent.add(new Card({
  //       title: `Title: this is a card title`,
  //       imageUrl: 'https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png',
  //       text: `This is the body text of a card.  You can even use line\n  breaks and emoji! 💁`,
  //       buttonText: 'This is a button',
  //       buttonUrl: 'https://assistant.google.com/'
  //     })
  //   );
  //   agent.add(new Suggestion(`Quick Reply`));
  //   agent.add(new Suggestion(`Suggestion`));
  //   agent.setContext({ name: 'weather', lifespan: 2, parameters: { city: 'Rome' }});
  // }

  // // Uncomment and edit to make your own Google Assistant intent handler
  // // uncomment `intentMap.set('your intent name here', googleAssistantHandler);`
  // // below to get this function to be run when a Dialogflow intent is matched
  // function googleAssistantHandler(agent) {
  //   let conv = agent.conv(); // Get Actions on Google library conv instance
  //   conv.ask('Hello from the Actions on Google client library!') // Use Actions on Google library
  //   agent.add(conv); // Add Actions on Google library responses to your agent's response
  // }
  // // See https://github.com/dialogflow/fulfillment-actions-library-nodejs
  // // for a complete Dialogflow fulfillment library Actions on Google client library v2 integration sample

  // Run the proper function handler based on the matched Dialogflow intent name
  let intentMap = new Map();
  intentMap.set('Default Welcome Intent', welcome);
  intentMap.set('Default Fallback Intent', fallback);
  // intentMap.set('your intent name here', yourFunctionHandler);
  // intentMap.set('your intent name here', googleAssistantHandler);
  agent.handleRequest(intentMap);
});

ここに、右手や左手を発話された時の処理を書きます。
これについては、Dialogflowのドキュメントのfulfillmentの章を参考にしました。

インテントの追加はapp.intent()ではなく、
intentMap.set(インテント名, 対応する処理関数);
で行います。

対応する処理関数でやることは、書籍の中の、app.intent()と内容は一緒ですが、方法が変わります。

先程、右手か左手かは、エンティティで指定するようにしましたので、
 agent.parameters.hand
で取得します。

また、ユーザーへの応答は
 agent.add(msg);
で返します。

それらを反映したソースは下記の通りです

index.js
// See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
// for Dialogflow fulfillment library docs, samples, and to report issues
'use strict';

const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');

process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements

// 定数の宣言 --- (*2)
const HAND_STR = ['右手', '左手'];

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
  const agent = new WebhookClient({ request, response });
  console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
  console.log('Dialogflow Request body: ' + JSON.stringify(request.body));

  function welcome(agent) {
    agent.add(`Welcome to my agent!`);
  }

  function fallback(agent) {
    agent.add(`I didn't understand`);
    agent.add(`I'm sorry, can you try again?`);
  }
  function selectHand(agent) {
    // 隠した手を決める
    const   answer = Math.floor(Math.random()*2);
    // ユーザーの入力を得る
    var word = agent.parameters.hand;
    console.log( 'hand:', word);
    // 右手なら0、左手なら1とする
    const hand = (word ==='右手') ? 0 : 1;
    // 結果判定とメッセージの作成
    let msg = HAND_STR[hand] + 'を開きます。';
    if (hand === answer) {
        msg += 'すると、あめ玉が手のひらにありました。' +
          '当たりです!おめでとうございます。';
    } else {
        msg += 'すると、空っぽでした。残念。';
    }
    msg += '再び遊びましょう。' +
      '「右手」と「左手」どちらの手でしょうか?';
    agent.add(msg);
  }

  // // Uncomment and edit to make your own intent handler
  // // uncomment `intentMap.set('your intent name here', yourFunctionHandler);`
  // // below to get this function to be run when a Dialogflow intent is matched
  // function yourFunctionHandler(agent) {
  //   agent.add(`This message is from Dialogflow's Cloud Functions for Firebase editor!`);
  //   agent.add(new Card({
  //       title: `Title: this is a card title`,
  //       imageUrl: 'https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png',
  //       text: `This is the body text of a card.  You can even use line\n  breaks and emoji! 💁`,
  //       buttonText: 'This is a button',
  //       buttonUrl: 'https://assistant.google.com/'
  //     })
  //   );
  //   agent.add(new Suggestion(`Quick Reply`));
  //   agent.add(new Suggestion(`Suggestion`));
  //   agent.setContext({ name: 'weather', lifespan: 2, parameters: { city: 'Rome' }});
  // }

  // // Uncomment and edit to make your own Google Assistant intent handler
  // // uncomment `intentMap.set('your intent name here', googleAssistantHandler);`
  // // below to get this function to be run when a Dialogflow intent is matched
  // function googleAssistantHandler(agent) {
  //   let conv = agent.conv(); // Get Actions on Google library conv instance
  //   conv.ask('Hello from the Actions on Google client library!') // Use Actions on Google library
  //   agent.add(conv); // Add Actions on Google library responses to your agent's response
  // }
  // // See https://github.com/dialogflow/fulfillment-actions-library-nodejs
  // // for a complete Dialogflow fulfillment library Actions on Google client library v2 integration sample

  // Run the proper function handler based on the matched Dialogflow intent name
  let intentMap = new Map();
  intentMap.set('Default Welcome Intent', welcome);
  intentMap.set('Default Fallback Intent', fallback);
  intentMap.set('右手インテント', selectHand);

  // intentMap.set('your intent name here', yourFunctionHandler);
  // intentMap.set('your intent name here', googleAssistantHandler);
  agent.handleRequest(intentMap);
});

これらの変更が出来たら「DEPLOY」ボタンを押しますが、デプロイには時間がかかります。
デプロイ中の表示が出ている間は、待ちましょう。
34.jpg

終わったらテストします
Action Consoleに戻ってテストタブを選択し、左下に、今回作ったものの起動ワードを入れます。
35.jpg

起動されたら「右手だよ」など、ユーザーの回答となる文章を入れます
36.jpg

これで、終了インテントの手前までの処理を作成できました。

ちなみにインテント名を「右手左手インテント」にしなきゃいけないところを「右手インテント」と間違ってしまいました。ごめんなさい。

ShimantoAkira
元組み込み系のプログラマーだった農家です。 組み込み系だったけど、今は趣味や農業管理用にアプリ書く事が時々あるくらい。 元だし組み込み系なので、アプリ書くには勉強が必要で、その為のノート代わりに、ここに書いています。 なので、知識は中途半端です。あんまり信用しないように。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした