AlexaのName-free Interactions（無指名対話）について

※ ここで書かれた内容は**未だプレビュー/β版で英語用のスキルでしか使えない**ため、将来的に仕様が変わり、記事が古くなってしまうかもしれません。適宜[公式ページ](https://developer.amazon.com/ja/docs/custom-skills/understand-name-free-interaction-for-custom-skills.html)を参照していただければと思います。

# Name-free Interactions（無指名対話）とはなにか

長いので以下、無指名対話といいます。現状私たちはスキルを使う時、「Alexa, 〇〇を開いて」や、「Alexa, 〇〇でハンバーグのレシピを探して」のようにスキルの名前をAlexaに言う（スキルを指名する）必要があります。しかし、無指名対話用リクエストを受け取る設定にしてあるスキルが対応していれば、ユーザーはスキルの名前を言わずに（無指名で）情報を得ることができます。例えば「Alexa, ハンバーグのレシピを探して」のように。

現状はプレビュー版ですが、日本語対応もしてくれれば、Alexaとより自然な対話ができるようになると思うので期待大です:point_up:

## 準備
無指名対話を有効にするには、ASK CLI経由でskill.jsonの`interfaces`部分に`"type":"CAN_FULFILL_INTENT_REQUEST"`を追加するかデベロッパーコンソールを開いて、「ビルド」 -> 「インターフェース」から、「Can Fulfill Intent Request」を有効にします。

<img width="1419" alt="開発者コンソールの画面" src="https://qiita-image-store.s3.amazonaws.com/0/100937/b1dafc61-d2ed-ac9a-cadd-cba8b4e964db.png">

これで無指名のインテントを受け取った時に、Alexaから以下で説明するリクエストを受け取ることができるようになります。

## リクエストとレスポンス
無指名の発話を聞いたAlexaはまず、そのインテントに対応しているスキルを選定し、リクエストを送ります。このリクエストではタイプが`CanFulfillIntentRequest`となります。そのため、エンドポイントとなる関数内でこのタイプのリクエストに対するハンドラーを実装する必要があります。

`canFulfillIntentRequest`はスキルが応答できるかどうかをAlexaが判断するためだけのリクエストなので、この時点で音声ファイルを再生したり、電気のON/OFFを操作することは禁じられています。

### リクエスト

```request
{
  "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が判断してくれ、デフォルトで値が設定されるようです。（どこにその値が設定されるのかは謎）デフォルト値を上書きすることも可能です。（※エンティティ解決については[こちら](https://developer.amazon.com/ja/docs/custom-skills/define-synonyms-and-ids-for-slot-type-values-entity-resolution.html)）

どういう場合に'YES', 'NO', 'MAYBE'を指定するかの具体例が[Guidelines for slot response values](https://developer.amazon.com/ja/docs/custom-skills/understand-name-free-interaction-for-custom-skills.html#guidelines-for-slot-response-values)に書いてあるので、見ると分かりやすいと思います。

##### canFulfill

`canUnderstand`はスロットの値を理解できるかどうかを指定するのに対して、`canFulFill`は実際にアクションを実行できるかどうかを示します。[公式ドキュメント](https://developer.amazon.com/ja/docs/custom-skills/understand-name-free-interaction-for-custom-skills.html#canfulfill-management)では、ユーザーが言った動物の鳴き声を鳴らすサンプルを取り上げています。その動物の名前に対応する回答は持っているが、何らかの理由で音声ファイルの再生ができない場合は

```
canUnderstand: 'YES'
canFulfill: 'NO'
```

となるようです。ちなみに、

>  Note: You must implement Canfulfillintentrequest for all intents in your interaction model.

とあるので、無指名対話に対応する場合は実装しているインテント全てに`Canfulfillintentrequest`のハンドラーを実装する必要がありそうです。（2回書いてあった）

## まとめ
この機能の強力なポイントは、スキル名を言わなくていいところだけではありません。`CanFulfillIntentRequest`へのハンドラーを実装していれば、ユーザーがスキルを有効化していないスキルでも、自動で有効化されるところです。（いいことなのか悪いことなのかはさておき）

また、すでにスキルを公開している場合でも、対話モデルを変更することなく、インタフェースを追加するだけなので、手軽に実装ができます。もし英語版スキルを出されている方がいれば、実装した方がよさそうですね。

インテントやスロットの名前がどのように渡されるのかテストができていないので、後程追記しようと思います。（間に合ってなくて申し訳ない。）