※ ここで書かれた内容は未だプレビュー/β版で英語用のスキルでしか使えないため、将来的に仕様が変わり、記事が古くなってしまうかもしれません。適宜公式ページを参照していただければと思います。
Name-free Interactions(無指名対話)とはなにか
長いので以下、無指名対話といいます。現状私たちはスキルを使う時、「Alexa, 〇〇を開いて」や、「Alexa, 〇〇でハンバーグのレシピを探して」のようにスキルの名前をAlexaに言う(スキルを指名する)必要があります。しかし、無指名対話用リクエストを受け取る設定にしてあるスキルが対応していれば、ユーザーはスキルの名前を言わずに(無指名で)情報を得ることができます。例えば「Alexa, ハンバーグのレシピを探して」のように。
現状はプレビュー版ですが、日本語対応もしてくれれば、Alexaとより自然な対話ができるようになると思うので期待大です
準備
無指名対話を有効にするには、ASK CLI経由でskill.jsonのinterfaces
部分に"type":"CAN_FULFILL_INTENT_REQUEST"
を追加するかデベロッパーコンソールを開いて、「ビルド」 -> 「インターフェース」から、「Can Fulfill Intent Request」を有効にします。
これで無指名のインテントを受け取った時に、Alexaから以下で説明するリクエストを受け取ることができるようになります。
リクエストとレスポンス
無指名の発話を聞いたAlexaはまず、そのインテントに対応しているスキルを選定し、リクエストを送ります。このリクエストではタイプがCanFulfillIntentRequest
となります。そのため、エンドポイントとなる関数内でこのタイプのリクエストに対するハンドラーを実装する必要があります。
canFulfillIntentRequest
はスキルが応答できるかどうかをAlexaが判断するためだけのリクエストなので、この時点で音声ファイルを再生したり、電気のON/OFFを操作することは禁じられています。
リクエスト
{
"request": {
"type": "CanFulfillIntentRequest",
"requestId": "…",
"intent": {
"name": "FindRecipeIntent",
"slots": {
"Menu": {
"name": "Menu",
"value": "hamburg"
}
},
},
"locale": "en-US",
"timestamp": "…"
},
"context": {
"System": {
"application": {
"applicationId": "amzn1.ask.skill.<skill-id-value>"
},
"user": {
"userId": "<user-id-value>"
},
"device": {
"supportedInterfaces": {}
}
}
},
"version": "1.0"
}
レスポンス
canFulfillIntentRequest
に対するレスポンスには、渡されたリクエストに含まれるスロットからユーザーの要求に応えられるかどうかをcanFulfillIntent
オブジェクトの形で含めます。canFulfillIntent
にはcanFulfill
とslots
が含まれます。レスポンスのサンプルを記載します。
{
response:{
canFulfillIntent: {
canFulfill: "YES",
slots:{
Menu: {
canUnderstand: "YES",
canFulfill: "YES"
}
}
}
}
}
canFulFill
canFulFill
には、'YES', 'NO', 'MAYBE'のいずれかを値として指定します。
{
response:{
canFulfillIntent: {
canFulfill: "YES",
}
}
}
値は下記をもとに決定します(めちゃざっくりだけど…)
- 'YES': 渡されたスロット全てを理解でき、ユーザーからのリクエストに応えられる場合
- 'NO': 渡されたどのスロットも理解できない場合
- 'MAYBE': 渡されたスロット全てを理解できるが、追加でアカウントリンクが必要だったりなど、
canFulfillIntentRequest
だけでは完了できない場合。
slots
slots
は渡されたスロットごとにcanUnderstand
とcanFulfill
を指定します。canUnderstand
には'YES', 'NO', 'MAYBE'のいずれかを、canFulfill
には'YES', 'NO'のどちらかを指定します。
canUnderstand
- 'YES': 渡されたスロットの値に完全にマッチする解答を持っている場合。
- 'NO': 渡されたどのスロットの値に対する解答を持っていない場合。
- 'MAYBE': 渡されたスロットの値に部分一致するような解答を持っている場合。
エンティティ解決を事前に設定しておけば、Alexaが判断してくれ、デフォルトで値が設定されるようです。(どこにその値が設定されるのかは謎)デフォルト値を上書きすることも可能です。(※エンティティ解決についてはこちら)
どういう場合に'YES', 'NO', 'MAYBE'を指定するかの具体例がGuidelines for slot response valuesに書いてあるので、見ると分かりやすいと思います。
canFulfill
canUnderstand
はスロットの値を理解できるかどうかを指定するのに対して、canFulFill
は実際にアクションを実行できるかどうかを示します。公式ドキュメントでは、ユーザーが言った動物の鳴き声を鳴らすサンプルを取り上げています。その動物の名前に対応する回答は持っているが、何らかの理由で音声ファイルの再生ができない場合は
canUnderstand: 'YES'
canFulfill: 'NO'
となるようです。ちなみに、
Note: You must implement Canfulfillintentrequest for all intents in your interaction model.
とあるので、無指名対話に対応する場合は実装しているインテント全てにCanfulfillintentrequest
のハンドラーを実装する必要がありそうです。(2回書いてあった)
まとめ
この機能の強力なポイントは、スキル名を言わなくていいところだけではありません。CanFulfillIntentRequest
へのハンドラーを実装していれば、ユーザーがスキルを有効化していないスキルでも、自動で有効化されるところです。(いいことなのか悪いことなのかはさておき)
また、すでにスキルを公開している場合でも、対話モデルを変更することなく、インタフェースを追加するだけなので、手軽に実装ができます。もし英語版スキルを出されている方がいれば、実装した方がよさそうですね。
インテントやスロットの名前がどのように渡されるのかテストができていないので、後程追記しようと思います。(間に合ってなくて申し訳ない。)