Alexaスキル「業界用語変換」でAPL部分を作りました

# はじめに
今年も[Alexa Developerスキルアワード](https://amazonalexaskillawards2019.splashthat.com/)に参加しました。
社内有志３人で、ハッカソンのような短期集中開発を行い、[「業界用語変換」](https://www.amazon.co.jp/HANDS-LAB-INC-%E6%A5%AD%E7%95%8C%E7%94%A8%E8%AA%9E%E5%A4%89%E6%8F%9B/dp/B07WW4S8GL)というスキルができました。

＿人人人人人人人人人人＿
＞　ザギンでシースー:sushi:　＜
￣Y^Y^Y^Y^Y^Y^Y^Y^Y^Y￣


#### 担当パートざっくり
スキル全体 @daisukeArk 
形態素解析部分 @ryosukeeeee 
APL部分 @sr-mtmt 

技術的なキャッチアップの機会にしようということで、私はAPLを触ってみることにしました。
さらに、以前Alexaスキルを作ったときはNode.js（TypeScript）で書いていたけれど、
今回はPythonで書いてみようということに。

# APLとは
Alexaを始めとする音声アシスタントたちにいよいよ当たり前に画面が付き始め、
視覚情報も提供できるようになりました。

Alexa Presentation Language（APL)は、
アニメーション、グラフィック、画像、スライドショー、ビデオを含んだ視覚要素を
スキルのやりとりに合わせて変えていくことで様々な演出をすることができます。

例としてAlexaのイベントで展示されていたりするのは[PIZZA SALVATORE CUOMO](https://www.amazon.co.jp/Ys-table-corporation-PIZZA-SALVATORE/dp/B07JW9QPSN)のスキルですね。
体験版で実際には購入しなくてもスキルの操作だけ試すことができます。

# つくってみた
ちなみにNode.js版はこちらのシリーズを参考にさせていただきました。
https://qiita.com/Mount/items/72d9928ff2c0ae5de737

スキル開発コンソール画面の使い方やJSONの話とかはPythonも同じなので割愛します。


```python
# Launch Requestのhandle
def handle(self, handler_input):
    # type: (HandlerInput) -> Response

    session_attr = AttributesManager.session_attributes
    logger.info(session_attr)

    speak_output = "いらっしゃいませ。\nあなたの言葉を業界人の言葉に変換します。\n「”銀座で寿司”ってなんていうの」というふうに聞いてください"

    builder = (
        handler_input.response_builder
        .speak(speak_output)
        .ask(speak_output)
    )

    # APL対応デバイスのときだけbuilderにAPL情報を追加
    if(is_apl_supported(handler_input.request_envelope)):
        builder.add_directive(
            RenderDocumentDirective(
                document=GetAplJsonDocument.get_apl_json("launch"),
                datasources=GetAplJsonDatasources.get_apl_json("launch")
            )
        )

    return builder.response
```
```python
# APL情報の入ってるJSONファイルを取ってくる
class GetAplJsonBase(object):
    _document_type = None

    @classmethod
    def get_apl_json(cls, intent_name):
        # このファイルの場所からの相対パスではなくLambdaから見た絶対パス指定なので注意
        file_path_base = '/var/task/'

        with open(file_path_base + cls._document_type + '/' + intent_name + '.json', 'r', encoding="utf-8") as f:
            return json_load(f)


class GetAplJsonDocument(GetAplJsonBase):
    _document_type = 'document'


class GetAplJsonDatasources(GetAplJsonBase):
    _document_type = 'datasources'


def is_apl_supported(request):
    apl_interface = request.context.system.device.supported_interfaces.alexa_presentation_apl
    return apl_interface is not None
```

APL情報のJSONはテキストファイルじゃなくて、jsで定義したほうが使い勝手が良いかも、という指摘もあったのですが
色々試していて形式が定まらなかったこともあり、今回はテキストファイルからJSONを読み込んで渡しています。

jsで定義する場合の参考はこちら

```javascript
function createDatasource(attributes) {
  return {
    "riddleGameData": {
        "properties": {
            "currentQuestionSsml": "<speak>" 
                + attributes.currentRiddle.question
                + "<speak>",
            "currentLevel": attributes.currentLevel,
            "currentQuestionNumber": (attributes.currentIndex + 1),
            "numCorrect": attributes.correctCount,
            "currentHint": attributes.currentRiddle.hints[attributes.currentHintIndex]
        },
        "transformers": [
            {
                "inputPath": "currentQuestionSsml",
                "outputName": "currentQuestionSpeech",
                "transformer": "ssmlToSpeech"
            },
            {
                "inputPath": "currentQuestionSsml",
                "outputName": "currentQuestionText",
                "transformer": "ssmlToText"
            }
        ]
    }
  };
}
```
参考元）https://github.com/alexa-labs/skill-sample-nodejs-level-up-riddles/blob/master/Step%203%20-%20Add%20APL/lambda/custom/index.js#L461-L487

## 終わり
これであとはJSONを工夫すればいろいろ出せるはず

VUIの個性を活かしながら視覚情報とタッチパネルにも対応していくことを考えるのはむずかしいなと感じています。
スマホとどう使い分けていくのか、エンジニアだけでなくいろいろなひととコラボレーションして模索していきたいと思いました。

[スマートスピーカー Advent Calender 2019](https://qiita.com/advent-calendar/2019/smart-speaker) 空き枠ありますので、興味のある方ぜひご投稿ください:sunny: