kun432's blog

Alexaなどスマートスピーカーの話題中心に、Voiceflowの日本語情報を発信してます。たまにAWSやkubernetesなど。

〜スマートスピーカーやVoiceflowの記事は右メニューのカテゴリからどうぞ。〜

#VUIchallenge #008 - Use cases with lists

f:id:kun432:20210711001052p:plain

#VUIchallengeの第8回です。テーマは「Use cases with lists」。

過去の#VUIchallengeの記事はこちら

お題

The challenge

Create a list of use cases where lists of items are crucial. Pay special attention to use cases where presenting more that 5 elements in a row might be mandatory

Jesús' Tips

There's this general rule of thumb that says that lists should have from 3 to 5 items, but there are some use cases that will require special treatment...

DeepLによる日本語訳

課題

アイテムのリストが重要となるユースケースのリストを作成してください。特に、5つ以上の要素を連続して提示することが必須となるユースケースに注意してください。

Jesúsのヒント

リストには3~5個の項目があるべきだという一般的な経験則がありますが、特別な扱いを必要とするユースケースもあります。

デザイン

第3回でやったリストの続きですね。

お題にもあり、前回もお伝えしたとおり、音声インタフェースにおいては、リストのような大量の項目を列挙するのは認知的過負荷の観点であまり向いていません。せいぜい3個程度、個人的には5個でも多いかなぁという気がしています。画面付きデバイスなどを使ったビジュアル的なアシストがあったほうが望ましいでしょう。

それはおいといて、ユースケースによってはリストが必要になるケースもあるかもしれませんね。少し考えてみましょう。

クイズ

最初に思いつくのは、クイズですかね。問題に対して複数の選択肢が与えられるような場合は選択肢を列挙せざるを得ません。

クイズ「世界の首都」へようこそ。このスキルは、世界各国の首都をあてるクイズゲームです。ある国の首都を4つの選択肢から答えてください。

では第1問!ジャンジャン!

アメリカの首都はどこでしょう?1番、ニューヨーク、2番、ロサンゼルス、3番、ワシントン、4番、シアトル。答えはどれでしょう?

うーん、ワシントン!

パンパカパーン!正解です!

それでは次の問題です!・・・

こういう感じですね。わかりやすい例だと思います。ただ、この場合でも、画面によるアシストがあったほうがやっぱりわかりやすいのは間違いないです。

クイズ「世界の首都」へようこそ。このスキルは、世界各国の首都をあてるクイズゲームです。ある国の首都を4つの選択肢から答えてください。

では第1問!ジャンジャン!

アメリカの首都はどこでしょう?1番、ニューヨーク、2番、ロサンゼルス、3番、ワシントン、4番、シアトル。 f:id:kun432:20210721023723p:plain 答えはどれでしょう?

このほうが断然わかりやすいですね。とはいえ「画面から選んでください」というのはちょっと味気ないです。テレビのクイズ番組などでも回答は読み上げるのは一般的ですし、読み上げている間も考える時間になりますしね。

曜日を扱うもの

曜日を扱うものも列挙が必要になるケースがあるかなぁと思います。例えば、ゴミ出しスキルとかですね。

「ゴミ出し」スキルへようこそ。このスキルでは、あなたのお住いの地域で、ゴミの種類ごとにゴミ出しの日をお伝えします。お住まいの地域を言ってください。

◯◯市

◯◯市では、燃えるゴミは毎週月曜日と木曜日、プラスチックは毎週火曜日、缶・ビン・ペットボトルは毎週水曜日、燃えないゴミは第1・第3木曜日です。

これ以外にも、スケジュールやリマインダ等で必要になるような気がします。

サブウェイの注文(笑)

これは常々思っていましたw。サブウェイの注文ってパターンが多くて難しいですよね?何回か体験してみないとアレはなかなか慣れません。やってみましょう。

サブウェイにようこそ。サンドイッチのご注文をどうぞ。

ローストチキンのレギュラーで

ローストチキンのレギュラーですね。パンの種類を次の5つからお選びください。ウィート、ホワイト、セサミ、ハニーオーツ、フラットブレッドのどれにしますか?

ハニーオーツで

ハニーオーツですね。パンは焼きますか?

はい

わかりました。次に野菜でお嫌いなものはありますか?レタス、トマト、ピーマン、オニオン、オリーブ、ピクルス、ホットペッパーからお嫌いなものがあれば言ってください。

オリーブとホットペッパーは抜いてほしいな

わかりました。では、オリーブとホットペッパー以外は全部入れますね。次にドレッシングは何になさいますか?・・・

長い!www

慣れてしまえばどうってことないのですが、最初はどう注文してよいかわからないですよね。そして、店頭ならばカウンターで実際に見ながら注文できますが、音声だけだとかなり辛いです。これも画面のアシストは必要かなと思います。

このように、選択肢がたくさんあるものは一見自由度は高く思えますが(他のファーストフードに比べると自由度が高いのは間違いないです)、ただ、それでも選択できる範囲は決まっているので、その選択肢を列挙してユーザに選ばせる必要が出てきてしまいます。

サブウェイはそれがウリになっているので許容されるかもしれませんが、自分が作るスキルでこのような選択をユーザに強いる場合は、本当に必要なユースケースかどうかをきちんと考える必要がありますね。

まとめ

選択型のリストは基本的にVUIと相性は悪いと思いますが、上記のようにユースケースによっては必要になる場合があるかもしれません。ただその場合でも、

  • 本当にそれが必要でユーザが求めているものなのか?
  • 必要だとしても、ビジュアルも組み合わせることで、ユーザの認知的負荷を下げる努力をしているか?

あたりは十分に検討すべきかなと思います。

#VUIchallenge #007 - Welcome back Message

f:id:kun432:20210711001052p:plain

#VUIchallengeの第7回です。テーマは「Welcome back Message」。

過去の#VUIchallengeの記事はこちら

お題

The challenge

Create a welcome back message for a returning user in a TV guide voice experience. It needs to have a clear final call to action but also include a hint for a different feature you provide.

Jesús' Tips

Two interesting things in the challenge today:

  1. Returning visitors. We can create different experiences for users that already know how our service works. We can also ask our selves questions like: When can we assume that our interaction scope is clear and limit the amount of information we provide?
  2. Hints. Hints are great and can help us teach our users abour services we provide that are not part of the main experience. As always, use them wisely.

DeepLによる日本語訳

課題

テレビガイドの音声体験で、戻ってきたユーザーに向けたウェルカムバックメッセージを作成します。最終的な行動を明確に促すだけでなく、スキルが提供する別の機能のヒントも含まれている必要があります。

Jesúsのヒント

今日の課題には2つの興味深いことがあります。

  1. 再訪問者
    私たちのサービスがどのように機能するかをすでに知っているユーザーに対して、異なる体験を提供することができます。また、「私たちの対話の範囲が明確、かつ、提供できる情報量がを制限できるのは度のタイミングからですか?」ということについて自問自答することもできます。
  2. ヒント
    ヒントは素晴らしいもので、私達が提供するサービスのメインの体験「以外」についてユーザーに教えるのに役立ちます。いつものように、賢く利用しましょう。

デザイン

パーソナライゼーションの基礎ですね。初回ユーザと2回目以降のユーザで応答を変えるというものです。

第1回でお題に上がっていたTVガイドスキルのときに、実はもうやっています。

初回

初めて起動するときのポイントは以下です。

  • ユーザは、スキルで何ができるのかをあまりわかっていない
  • ユーザは、スキルに対して、どう発話すればいいのかあまりわかっていない

つまり、スキルについて、そしてスキルの使い方についてある程度の説明が必要だということですね。したがって、以下のような感じになると思います。(スキルの機能については例なのであまり深く考えないことにします)

はじめまして、TVガイドスキルをご利用いただきありがとうございます。※スキルのあいさつ
このスキルでは、今放送されているテレビ番組名とその情報をお伝えします。※スキルでできること
例えば「今やっている番組をおしえて」とか「今◯チャンネルでやっている番組をおしえて」と言ってみてください。※呼びかけ例

2回目以降

初回に対して2回目以降のポイントは、ユーザはすでにスキルの使い方をある程度理解している、ということです。この場合は、

  • 無駄なく目的をスピーディーに達成できる事が重要
  • ワンパターンなやり取りを回避するための工夫も必要

が重要になると思います。


〜略〜

そして、同じやり取りの繰り返しは、機械的になってしまってマンネリ化を生みます。ここは簡潔にするというところとのバランスも難しいと思うのですが、

  • パーソナライズ的な要素を組み込む
    • ユーザの名前をどこかで取得しておいて、発話に含める
    • 時間ごとに挨拶を変える
    • ユーザの過去の発話履歴からユーザが求めそうなものを解析して先んじて提案する(かなり大変だとは思いますが・・・)

ことで、いかにも機械が応答しているという感を減らすのが良いかと思います。
〜略〜

アレクサ、TVガイドをひらいて

◯◯さん、こんばんは、TVガイドスキルです。午後9時現在、4チャンネルで放送中の番組は「クイズ◯◯◯」です。ちなみに8チャンネルで「プロ野球◯◯対△△」もやっていますよ(過去の履歴からプロ野球をよく見ている場合)

あくまでも一例なので、やり方はいろいろあると思います。

基本的な考え方はこれで良いと思いますが、すこしお題にあるヒントについて考えてみましょう。

異なる体験を提供する

スキルが提供する機能にもよりますが、例えば、

  • 複数の機能を持つ場合、ユーザが使っていない機能を提案してみる
  • メインの機能をより便利に使える付加機能を提案してみる

ということで、ユーザに新たなスキルの魅力を提案することができます。例えば後者の場合だと、こういうのが考えられますね。

アレクサ、TVガイドをひらいて

◯◯さん、こんばんは、TVガイドスキルです。午後9時現在、4チャンネルで放送中の番組は「クイズ◯◯◯」です。ちなみに8チャンネルで「プロ野球◯◯対△△」もやっていますよ(過去の履歴からプロ野球をよく見ている場合)

8チャンネルについて詳しく教えて

8チャンネルでは東京ドームで行われている「プロ野球 ◯◯対△△」の10回戦をやっています。今日の先発は☆☆と★★、現在3回表 〇○の攻撃中で、2対3で△△がリードしています。

これまでのご利用からはプロ野球がお好きのようですね。プロ野球の放送日時にあわせてリマインダーでお伝えすることができますよ。リマインダーをセットしますか?

利用傾向からユーザが興味を持っていると推測される番組について、その放送日時に合わせたリマインダーを設定することで、いちいち自主的にスキルを起動して調べることなく、見たい番組を教えてくれるというような感じですね。ユーザはいちいちスキルを起動しなくていいのでとても楽ちんです。

ただし、こういった「より便利な使い方」、初めて使うユーザにとっては、

  • スキルの使い方がまだわかっていないのに、リマインダーの設定まで頭が回らない(これもまた認知的過負荷)
  • スキルの使い方がまだわかっていないのに、リマインダーの許可をしてもいいのか不安になる。

ということがあるかもしれません。第1回でも記載しましたが、初回起動時は、ユーザにスキルの使い方をシンプル・簡潔に体験・理解してもらうということが重要だと思います。より便利な使い方や他の機能については、ある程度利用回数が増えた段階タイミングを図って提案するのが良いと思います。

いつから慣れたユーザだと判断するか?

ではどのタイミングから「ユーザはスキルの利用に慣れた」と判断すればよいでしょうか?ここはいくつかの考え方があると思います。

  • 利用(起動)回数
  • 利用頻度

利用回数が多く、頻度が高ければ、ユーザは使い方に慣れていると判断する事はできると思います。ただ、

  • 過去の累積利用回数は多いが、久々に使った
    • 以前はよく使っていたが、何らかの理由で使うのをやめて、久々にまた使い始めた
    • 使い方を忘れているかもしれない
  • 利用頻度は高いものの、初回起動からあまり時間が経っていない
    • エラー等が多く発生して何度も起動していたりしないか?
    • 使い方をうまく伝えれていないかもしれない

というようなケースもあると思いますので、一概には判断は難しいかなと思います。ここはケースバイケースで判断するしかないかなと思いますが、例えば、

  • スキルの利用状況を確認
  • ログ等でエラーが発生していないか

なども確認した上で、トライアンドエラーで継続的に改善していくしかないかなと思います。

ヒントを提供する

使いかたのヒントをうまく盛り込むのも新しい効果的です。例えば、以下などが考えられます。

  • 別の言い方を提案する
  • エラーになったときやヘルプ
  • サジェスチョンチップ(Googleの場合)

例えばこういう感じでしょうか。

別の言い方を提案する

チャンネル名を指定するのがメインの使い方ですが、人によっては放送局で指定するほうが自然かもしれませんね。

アレクサ、TVガイドをひらいて

◯◯さん、こんばんは、TVガイドスキルです。見たいチャンネルを言ってください。

4チャンネル

午後9時現在、4チャンネルで放送中の番組は「クイズ◯◯◯」です。出演者は✕✕✕、△△△、ゲストは▲▲▲です。

ちなみに、チャンネルの代わりに放送局でも調べることができますよ。放送局で指定する場合は「〇〇放送でやっている番組を教えて」と言ってみてくださいね。

エラーになったときやヘルプ

エラーになった場合、ユーザに正しい使い方が伝わっていない可能性がありますね。単に間違っている、というところで留めるのではなく、正しい使い方の例とともにうまく誘導してあげるのは重要ですね。

アレクサ、TVガイドをひらいて

◯◯さん、こんばんは、TVガイドスキルです。見たいチャンネルを言ってください。

料理番組がみたいな

ごめんなさい、よくわかりませんでした。見たいチャンネル名か、放送局を言ってみてください。または「今やっている番組を教えて」といってみてください。

サジェスチョンチップやヒント

Googleの場合、画面付きデバイスおよびスマホアプリでサジェスチョンチップというものを使えます。

画面イメージとしてはこういう感じですね。

f:id:kun432:20210720005728p:plain

ユーザの発話例が表示され、音声で発話することもできますし、タップで選択することも可能です。ここでメインでよく使われる発話以外の例などを入れておくと、ユーザにとっても試しやすいですね。

Alexaの場合は、APLのFooterを使うと、発話例をヒントを表示することができます。何気なく表示しておくことで、あまりプレッシャーを与えることなくユーザに別の使い方を提案できるのではないかと思います。

まとめ

「おかえりなさい」というのは、ユーザエンゲージメントを高める方法で最も基本になりますね。ユーザの利用習熟度を踏まえて応答を変えることはもちろんですが、その中でスキルの新たな魅力を提案・体験してもらうようにできると良いですね。

HerokuでRedisを使う

f:id:kun432:20210704194211p:plain

前回の続き。

セッションストレージとして使うために、Redisを追加してみようと思います。

Redisアドオンの追加

前回のHello Worldアプリが動いている状態から進めます。

heroku addons:createでアドオンを作成します。Redisの場合は、heroku-redis:プランで指定します。hobby-devが無料のプランです。

$ heroku addons:create heroku-redis:hobby-dev
Creating heroku-redis:hobby-dev on ⬢ foo-bar-11111... free
Your add-on should be available in a few minutes.
! WARNING: Data stored in hobby plans on Heroku Redis are not persisted.
redis-foobar-22222 is being created in the background. The app will restart when complete...
Use heroku addons:info redis-foobar-22222 to check creation progress
Use heroku addons:docs heroku-redis to view documentation

これでRedisのデータベースが作成されます。作成中の進捗はheroku addons:infoで確認できます。

$ heroku addons:info redis-foobar-22222
=== redis-foobar-22222
Attachments:  foo-bar-11111::REDIS
Installed at: Mon Jul 19 2021 01:31:15 GMT+0900 (GMT+09:00)
Owning app:   foo-bar-11111
Plan:         heroku-redis:hobby-dev
Price:        free
State:        creating

State: creatingになっていて作成中なことがわかります。作成が完了すると以下のようにState: createdになります。

$ heroku addons:info redis-foobar-22222
=== redis-foobar-22222
Attachments:  foo-bar-11111::REDIS
Installed at: Mon Jul 19 2021 01:31:15 GMT+0900 (GMT+09:00)
Owning app:   foo-bar-11111
Plan:         heroku-redis:hobby-dev
Price:        free
State:        created

Herokuの管理画面でもRedisが上がっていることが確認できます。

f:id:kun432:20210719000134p:plain

作成されたRedisにアクセスするためのURLはheroku config:get REDIS_URLで確認。RedisはAWSに立つんですね。

アプリからRedisを参照する

Expressのセッションを管理する"express-session"で、セッションストレージにRedisを使ってみます。

ライブラリを追加します。

$ npm install --save express
$ npm install --save express-session
$ npm install --save redis
$ npm install --save connect-redis

コードを修正します。

const express = require('express');

const session = require("express-session");
const redis = require("redis");
const RedisStore = require("connect-redis")(session);

const app = express();

app.set('port', (process.env.PORT || 3000));

app.use(
    session({
        secret: 'secret',
        cookie: { maxAge: 3600 * 1000 },
        resave: false,
        saveUninitialized: false,
        store: new RedisStore({
            url: process.env.REDIS_URL,
            client: redis.createClient({
                url: process.env.REDIS_URL
            })
        })
    }),
);

app.get('/', function(request, response) {
  let session = request.session;
  console.log(JSON.stringify(session));
  if (!!session.count) {
    session.count += 1;
  } else {
    session.count = 1;
  }

  response.send(`Hello World! count: ${session.count}\n`);
});

app.listen(app.get('port'), function() {
  console.log("Node app is running at localhost:" + app.get('port'));
});

デプロイします。

git add .
git commit -m "add redis"
git push heroku master

アプリを開いてみましょう。

$ heroku open

カウントアップしていくのがわかります。

f:id:kun432:20210719015008p:plain

f:id:kun432:20210719015018p:plain

違うブラウザで試してみると、カウントが別になっているのがわかります。

f:id:kun432:20210719015057p:plain

Redisにアクセスする

Herokuの管理画面は、Redisのデータにアクセスするインタフェースを持っていません。管理画面からはパフォーマンス状況とRedisに接続するための認証情報を確認できます。

管理画面の"Installed add-ons"にある"Heroku Redis"をクリックします。

f:id:kun432:20210719015932p:plain

Overviewタブでパフォーマンス等のグラフが見れます。

f:id:kun432:20210719020039p:plain

Settingsタブでは、Redisに接続するための認証情報が確認できます。"View Credetials..."をクリックすると表示されます。

f:id:kun432:20210719020332p:plain

f:id:kun432:20210719020548p:plain

認証情報はHeroku CLIからも確認できます。

$ heroku config:get REDIS_URL
redis://:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX@ec2-XXX-XXX-XXX-XXX.compute-1.amazonaws.com:XXXX

スクリプトなどから接続する場合にはこの情報を使えばよさそうですね、知らんけど(やったことない)。

で、Heroku CLIを使えばかんたんに接続することができます。

$ heroku redis:cli
Connecting to redis-foobar-22222 (REDIS_TLS_URL, REDIS_URL):
ec2-XXX-XXX-XXX-XXX.compute-1.amazonaws.com:XXXXX>

試しに中身を見てみましょう。登録されているキーの一覧を見ます。

ec2-XXX-XXX-XXX-XXX.compute-1.amazonaws.com:XXXXX> keys *
1) sess:fjEX37i5mbXimKCdO3iL8xvyt1v8k6uX
2) sess:Yc4nUn37PbJ9SRVD7JKxIFc_w8SI_HI-
3) sess:TpIhPEM_b8JKJ_po6KCX9lgfEVlDzo9i
4) sess:l6CMK6hdnA2rECYoiO8rJXg9UB9KloTi
5) sess:hHrkwrg-a-IAzd0BCCNe2O8Cb7jgYmBo

いくつか入っていますね。個々のキーの中身を見てます。Redisではキーが保持している値の種類というか型によって参照の仕方がことなるみたいなので、typeを実行してます。

ec2-XXX-XXX-XXX-XXX.compute-1.amazonaws.com:XXXXX> type sess:fjEX37i5mbXimKCdO3iL8xvyt1v8k6uX
string
ec2-XXX-XXX-XXX-XXX.compute-1.amazonaws.com:XXXXX> get sess:fjEX37i5mbXimKCdO3iL8xvyt1v8k6uX
{"cookie":{"originalMaxAge":3600000,"expires":"2021-07-18T17:47:16.442Z","httpOnly":true,"path":"/"},"count":2}

カウンタらしき値が見えていますね。

おまけ

試しているときにInternal Server Errorとか出てて、ログみたいなーとか思ったら、これもHeroku CLIで見るみたい。-tはtailオプション。

$ heroku logs -t
2021-07-18T17:20:06.523883+00:00 heroku[router]: at=info method=GET path="/" host=foo-bar-11111.herokuapp.com request_id=8717856c-58c2-4b92-a407-a477ff497a9d fwd="XXX.XXX.XXX.XXX" dyno=web.1 connect=1ms service=44ms status=200 bytes=385 protocol=https
2021-07-18T17:20:06.496788+00:00 app[web.1]: {"cookie":{"originalMaxAge":3600000,"expires":"2021-07-18T17:48:22.464Z","httpOnly":true,"path":"/"},"count":1}
...

まとめ

とりあえずざっくり使い方がわかったので、次こそはVoiceflowSDKでセッション管理と、Heroku Buttonでadd-onまで設定できるようにしたい。

※参考