C#によるAlexaスキル実装:スロットとセッションを活用した対話の実現特集:はじめてのAlexaスキル開発(1/3 ページ)

「スロット」を使い、ユーザーとの対話から必要な情報を取得したり、その情報を1つのセッションで保持して使い回したりする方法を解説する。

» 2018年03月22日 05時00分 公開
[かわさきしんじInsider.NET編集部]
「特集:はじめてのAlexaスキル開発」のインデックス

「特集:はじめてのAlexaスキル開発」

 前回はAWS Toolkit for Visual Studioを使用して、Alexaのスキルから呼び出されるAWS Lambda関数をC#で実装した。今回は、もう少し実践的な話として、ユーザーとの対話の中で、いわゆる「変数」に相当する「スロット」を使う方法と、1つのセッションの中で情報を保持して、使い回す方法を取り上げる*1

*1 前回の最後に「おもしろネタを」と書いたのだが、なかなか難しいこともあり、次回に期待ということにしていただければと思う。


 なお、スロットとセッションはAlexaスキルで一般的に使われる概念で、C#におけるAlexaスキル開発に特有の事項ではないのだが、今回もAWS Toolkit for Visual Studio(以下、AWS Toolkit)とAlexa.NETパッケージを使って、Visual Studio(以下、VS)とC#でAWS Lambda関数(以下、Lambda関数)を実装している。

 まずは簡単にスロットの概要と、1つのセッションの中で情報を保持する方法の概要をまとめてから、個々の要素について見ていくことにしよう。

スロットとセッションの概要

 「スロット」とはAlexaとユーザーとの間で行われる定型的なやりとりの中で、変化する要素を取り扱うための機構だ。通常のプログラミング言語における変数に相当する。

  • 「東京」の「明日」の天気を教えて
  • 「あさって」の「札幌」の天気は?
  • 「名古屋」の天気はどう?

 上に書いたようなフレーズをユーザーがAlexaに投げかけて、「特定の日時」の「特定の都市」の天気を知りたいとすると、これは「{day} の {city} の天気」のようなフレーズにまとめることができる(実際にはAlexaのサンプル発話として、さらに多くの会話パターンを登録していくことになる)。この「{day}」「{city}」のように、パラメーター化された要素のことを、Alexaでは「スロット」と呼ぶ。

 スロットに格納されるデータは「タイプ」(データ型)を持つ。例えば、日付(AMAZON.DATEタイプ)や都市(AMAZON.Cityタイプ)などがある(これらはAlexa Skills Kitに組み込みのタイプ)。開発者が独自にスロットのタイプを定義することもできる(Google Homeアプリ開発におけるエンティティの定義と似たもの)。

 スロットを使うことで、Alexaのスキルはユーザーから送信されたフレーズを解析して、日付や都市などの情報を取り出して、それが意図するところ(インテント)をより明確なものにでき、Lambda関数ではその情報を基に特定の日、特定の都市など、ユーザーが望んだ処理を実現できるようになる。スロット情報は、Lambda関数へと渡されるリクエスト情報(Alexa.NETではSkillRequest型のオブジェクト)に含まれる。

 一方、Lambda関数に渡されるSkillRequest型のパラメーターには、セッションに関連する情報も含まれる(LaunchRequest/IntentRequestなど、標準的なリクエストの場合)。これに含まれる情報としては、セッションIDやセッション内で保持したい情報を格納するためのattributesプロパティ、アプリID、ユーザー情報などがある。今回はこのうちのattributesプロパティの使い方を見てみる。

 では、それぞれについて、もう少し詳しく見ていこう。

スロット

 既に述べたように、スロットとはユーザーがしたいこと(インテント)をより具体的なものとする「何らかの処理の対象」のことだ。スロットはインテントと深く結び付いているので、その作成はAlexaのコンソールで行うことになる。以下では、上で例示したような「指定した日の指定した都市の天気」を予想する「ふり」をするAlexaスキルを作りながら、スロットの使い方を見てみよう(天気予報APIの使い方自体は難しいものではないので、ここでは割愛する)。

 「実際には予想をしない天気予報」スキルを作成して、インテントを定義したところを以下に示す。

「実際には予想をしない天気予報」スキル 「実際には予想をしない天気予報」スキル

 余談だが、AlexaコンソールのUIが前回までとは大きく変わってしまったが、基本的な構成要素は同様だ。ただし、Lambda関数の設定で必要となるスキルIDの表示位置が分かりづらいので注意しよう。上の画面で[あなたのAlexaコンソール]にマウスカーソルを合わせるとメニューがポップアップされるので、そこで[スキル(新しいコンソール)]を選択すると、作成したスキルが一覧表示される。この画面の[SKILL NAME]列に表示されたスキル名の直下に小さく表示されているのがスキルIDだ(Lambda関数にスキルIDを指定するときには、この画面でIDをコピーしておく)。

スキルIDは[SKILL NAME]列に表示されている(マウスカーソルに注目) スキルIDは[SKILL NAME]列に表示されている(マウスカーソルに注目)

スロットの作成

 本題に戻ると、最初に示した画面では「WeatherForecastIntent」インテントを作成して、そこに「サンプル発話」としていくつかのフレーズを入力している。それらの中にある「{city}」「{day}」が「スロット」だ。サンプル発話に「{}」で囲んで識別子を入力していけば、それが自動的にスロットとして認識される。

 ページ左側には「WeatherForecastIntent」の下に「city」「day」が表示されていて、このインテントではこれらのスロットを使用することが分かるようになっている。スロットタイプの指定など、簡単な設定は画面下部にあるセクションで行える。

WeatherForecastIntentインテントで使用するスロットの情報 WeatherForecastIntentインテントで使用するスロットの情報

 この画像を見れば分かる通り、cityスロットのタイプには「AMAZON.City」を指定し、dayスロットのタイプには「AMAZON.DATE」を指定している。既に述べた通り、これはAlexa Skills Kitが組み込みで提供するいわば「標準データ型」のようなものだ。他にどのようなスロットタイプが提供されているかについては「スロットタイプリファレンス」ページを参照のこと。

 重要なのは、一番右の[ACTION]列にある[Edit Dialog]リンクだ。これをクリックすると、対応するスロットが必須であるかどうか、必須の場合には対話の中でユーザーがその情報を提示しなかった場合に、どんなプロンプトをユーザーに表示(発話)するか、そのプロンプトに対して想定されるユーザーの入力を指定できる。以下にcityスロットの[Edit dialog]リンクをクリックしたところを示す(おおよその情報が含まれるように、画面をスケールしているので、少し見にくいかもしれない)。

cityスロットは必須の情報 cityスロットは必須の情報

 [Slot Filling]にあるスライドスイッチをオンにすると、そのスロットへの情報の入力が必須になる。その下にある「どこの天気ですか」は、cityスロット情報の入力をユーザーに促すプロンプトで、「{city}」「{city} です」というのは、それに対するユーザー入力の例となる。ユーザーが「新宿」「新宿です」などと返答すると、「新宿」がcityスロットに格納されるということだ。

 ここではcityスロットだけを必須の情報とした。日付を指定しなかった場合には、今日の日付をデフォルト値として使用する。

 このようにインテントの実行に必須な情報を得るためのユーザーとのやりとりを「ダイアログモデル」と呼ぶ。

注意点

 ただし、注意したい点が2つある。1つは「上の画面のように、あるスロットが必須であることを示し、それを得るためのダイアログモデルを作成しても、必要な情報がない場合に自動的にダイアログモデルを基にした会話が発動されるわけではない」ということだ。ダイアログモデルを使って、情報を得るには少々のコーディングが必要になる(後述)。

 もう1つは、ダイアログモデルを利用するには、今回表示している新しいコンソール画面か、古いコンソールではスキルビルダーを使っている必要があることだ。

古いコンソールでスキルビルダーを使っていない場合はダイアログモデルは使えない 古いコンソールでスキルビルダーを使っていない場合はダイアログモデルは使えない

 新しいコンソールでダイアログモデルを利用している場合、ページ左側にある[JSON Editor]をクリックすることで、そのスキルを定義するJSONを表示できる。例えば、「実際には予想をしない天気予報」スキルを定義するJSONは次のようになる。深く理解する必要はない。単に「長いそうだねぇ」と思ってくれれば十分だ。

{
  "languageModel": {
    "invocationName": "ドットネット天気予報",
    "intents": [
      {
        "name": "AMAZON.CancelIntent",
        …… 省略 ……
      },
      …… 省略 ……
      {
        "name": "WeatherForecastIntent",
        "slots": [
          {
            …… 省略 ……
          },
          …… 省略 ……
        ],
        "samples": [
          "WeatherForecastIntent {city}",
          …… 省略 ……
        ]
      }
    ],
    "types": []
  },
  "dialog": {
    "intents": [
      {
        "name": "WeatherForecastIntent",
        …… 省略 ……
        "slots": [
          …… 省略 ……
        ]
      }
    ]
  },
  "prompts": [
    {
      "id": "Elicit.Intent-WeatherForecastIntent.IntentSlot-city",
      …… 省略 ……
    }
  ]
}


「実際には予想をしない天気予報」インテントを定義するJSON

 このJSONにはインテントやスロットの定義、スロットが必須かどうか、必須のスロットに情報を得るためのプロンプトなどが記されている。古いコンソールでスキルビルダーを使用していない場合には、これらの情報が以下のようにバッサリと落とされてしまう。

{
  "intents": [
    {
      "intent": "AMAZON.CancelIntent"
    },
    {
      "intent": "AMAZON.HelpIntent"
    },
    {
      "intent": "AMAZON.StopIntent"
    },
    {
      "slots": [
        {
          "name": "city",
          "type": "AMAZON.City"
        },
        {
          "name": "day",
          "type": "AMAZON.DATE"
        }
      ],
      "intent": "WeatherForecastIntent"
    }
  ]
}


古いコンソールのインテント定義ではダイアログモデル情報がなくなってしまう

 従って、ダイアログモデルを利用したいのであれば、新しいコンソールか古いコンソールでスキルビルダーを使用するようにしよう。

 次にこのインテントを処理するLambda関数を実装する。

       1|2|3 次のページへ

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。