タリンで音声アシスタント開発ワークショップに参加してきた

# 概要
今月初めにエストニア・タリンで開催された[Robotex International 2018](https://robotex.international/)（以下、Robotex）。その会場内で行われた音声アシスタント開発ワークショップに参加してきました。
本記事はその振り返りです。

### 出てくるキーワード
* Snips
* Python
* RaspberryPi

# はじめに
世界最大のロボテック関連イベントでもあるRobotex。会場の一角に専用スペースが設けられ、3日間で合計74種類ものワークショップが行われていました。
![IMG_20181201_142730357.jpg](https://qiita-image-store.s3.amazonaws.com/0/58993/3a37dfd2-a14c-6be2-8406-6b6dd583a690.jpeg)

![DSC09387.JPG](https://qiita-image-store.s3.amazonaws.com/0/58993/a04c9c6d-9a73-0c7b-bc9d-9ca84e110845.jpeg)

その中のひとつ、音声アシスト開発プラットフォームを手がける[Snips.ai](https://snips.ai/)（スニップス、以下、Snips）主催の**「Build Your Own *Private by Design* Voice Assistant（自分だけの音声アシスタントを作ってみよう）」**に参加してみました。

<img width="778" alt="スクリーンショット 2018-12-09 10.36.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/58993/dd1bdb06-56f0-2eba-8736-8dd74a00940f.png">

# Snipsとは
Snipsはコネクテッドデバイスへの組み込みに特化し、2013年にフランス・パリで立ち上げられた音声アシスタント関連のプラットフォームを提供するアーリーステージのスタートアップです。今年の春にニュースに取り上げられたり、日本語対応も始まったのでご存知の方も多いかと思います。

* [「SiriやAlexaは敵じゃない」仏ベンチャーの音声AI、日本上陸へ](https://tech.nikkeibp.co.jp/atcl/nxt/column/18/00001/00550/?ST=nnm)
* [フランスのスタートアップSnips社、プライバシーを守る音声プラットフォーム「Snips AIR」を2019年末に提供へ](https://robotstart.info/2018/07/20/snipsair.html)

# ハンズオンのゴール
ワークショップはSnipsのテクニカルエバンジェリストであるEric Bezzam氏が講師を務めるハンズオン形式。参加者は5名で、中学生、大学生、社会人といった面々です。

![DSC09546.JPG](https://qiita-image-store.s3.amazonaws.com/0/58993/8930edd2-ee38-3d99-0bab-0ee1f85e8af7.jpeg)

Snipsを使ってRaspberryPi3で動作する計算アプリ（Mental Calculations App）が作れるようになります。

実際に動作しているものを撮影した動画がこちら。
[![Mental Calculations App](http://img.youtube.com/vi/358KHUpwPVI/0.jpg)](http://www.youtube.com/watch?v=358KHUpwPVI)

簡単な足し算、引き算、掛け算、割り算といった簡単な計算問題を出題するシンプルなアプリです。

# Snipsでの開発
ハンズオンは4つのステップで構成されていました。
<img width="500" alt="スクリーンショット 2018-12-09 11.15.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/58993/5b78a6d0-3f0f-37c8-b3a8-8207a344f6b1.png">

最初にステップ1として、「音声アシスタントの基本構成について理解」します。
Snips最大の特徴は、すべてがデバイス上で行われるということ。
<img width="524" alt="スクリーンショット 2018-12-10 2.16.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/58993/355892c5-2e55-edcb-b322-caa58f6505be.png">

まずやってみよう、ということでステップ2の「Snipsでの音声アシスタント開発」に進みます。

### アシスタント作成
アカウントを取得しログインすると、アシスタント作成画面が表示されます。各アシスタントごとにアプリを開発します。
<img width="500" alt="スクリーンショット 2018-12-09 23.25.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/58993/1305ef71-bccf-7d0a-8e01-e80f6976e042.png">

アシスタントごとに言語設定ができますが、一度作成したら後から変更できないのでご注意ください。

### インテント作成
次に、計算アプリに必要なインテントを作成していきます。スタート時、回答するとき、わからないとき、途中でやめるときの4つのパターンを作成します。

<img width="500" alt="スクリーンショット 2018-12-10 0.27.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/58993/4e613e6c-02ff-5109-a8ae-bf1884c2c55d.png">

スタート時のインテントに出題数を含めることもできます。その場合は、出題数に対応するスロットを作成し紐づけます。

<img width="500" alt="スクリーンショット 2018-12-10 0.28.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/58993/4bff2192-1504-fa8a-6b5f-605d3564a82e.png">

ちなみに今回のアプリを日本語設定したのですが、ひとつだけ回答のインテント（give_mental_calculation）が英語になっています。その理由はトレーニングの事例を外部ファイルから引っ張っており、ハンズオンが英語ベースのため日本語化する時間がなかったためです。実際に開発するときはコツコツと回答集を作成していくことになります。

### アクション作成
音声アシスタントの機能が用意できたら、いよいよステップ3の「計算アプリ機能の開発」です。Snipsのアクションに該当します。

ハンズオンではサンプルプログラムを使いながら、穴埋め形式で参加者自身がPythonで音声アシスタントにどうアクションさせたいかを記述しました。
<img width="526" alt="スクリーンショット 2018-12-10 1.45.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/58993/aa225e7e-277f-44e2-e257-9c089d73f133.png">

回答ごとの場合分けが細かく、音声アシスタントに答えさせたいレスポンスの内容も考えながらなので、このパートに時間がかかってしまいました。

例えば、正解率に応じてなんと言ってもらいたいか、など。

```
def continue_lesson(response, session_id):
    SessionsStates[session_id]["step"] += 1

    if SessionsStates[session_id]["step"] == SessionsStates[session_id]["n_questions"]:
        response += "You had {} out of {} correct. ".format(SessionsStates[session_id]["good"],
                                                                             SessionsStates[session_id]["n_questions"])
        percent_correct = float(SessionsStates[session_id]["good"]) / SessionsStates[session_id]["n_questions"]
        if percent_correct == 1.:
            response += "すごくいいね！"
        elif percent_correct >= 0.75:
            response += "いい感じです。さらに上を目指しましょう。"
        elif percent_correct >= 0.5:
            response += "まだまだできるはず。もっとがんばりましょう"
        else:
            response += "たくさん練習した方がいいみたいですね"
        del SessionsStates[session_id]
        cont = False
    else:
        question, answer = create_question()
        response += question
        SessionsStates[session_id]["ans"] = answer
        cont = True

    return response, cont
```
ハンズオンの参加者は私以外に日本語がわからないのに、「いざ発話したときのセンスが問われる」と勝手にがんばってしまいました。

### ハンズオンはここまで
そして、残念ながらここで時間切れ。ステップ4の「RaspberryPiへのデプロイ」ができずに終了となりました。

12月中旬に帰国するので、実際にRoboChieで計算アプリを楽しむのは年末のお楽しみとなりました。毎年恒例の[大晦日ハッカソン](https://atnd.org/events/102652)で開発することにします。

# まとめ
今回は初めてのSnips、初めての海外ハンズオンということで、GoodとBadを列挙してみます。

#### Good
* ニュースで気になりつつ、後回しになっていたSnipsが触れて良かった
* 海外スタートアップのエバンジェリストのハンズオンが体験できた（ドキュメンテーションやどこを詳しく説明するか等）

#### Bad
* Snipsの売りであるデバイスで動作するところまで体験できなかった（5人中1名はコンプリートしていたので、主催側の時間配分の問題だけではなかった）
* 参加者同士の繋がりが薄かった（次の機会があればもっと積極的に話しかける）
* 日本語対応していると言われ、誘惑に負けてアシスタントの言語設定を日本語にしてしまったため、途中で混乱してしまった（ハンズオンのときはチュートリアルに忠実な方が効率がよい）

# 最後に
Snipsに興味を持った方は、ぜひBezzam氏のチュートリアルドキュメントを参考にして触ってみてください。
[https://github.com/ebezzam/snips-skill-mental-calculation](https://github.com/ebezzam/snips-skill-mental-calculation)

大晦日ハッカソンがうまく行ったら、来年LTにてお披露目しようと思います。