今回は音声アプリケーション(Alexaスキルや Google アクション)のログを取得し、分析するまでの環境構築手順を説明します。また、Amazon/Google のプラットフォーム(PF)が提供しているデータを利用した分析について一例を紹介したいと思います。

分析する前に

ヤフーのスキルプロジェクトでは、分析する際に以下の2つのデータを利用しています。

初めにお伝えしますが、プロジェクトは独自に収集したログデータのみで分析をしているわけではありません。PFが提供しているデータは非常に有益です。まずは、それらのデータを確認することをおすすめします。プロジェクトでは、基本的な指標(ユニークユーザー数や会話数など)を確認しています。PFが提供しているデータは利用ユーザー全体の利用状況を俯瞰的に確認できるという強みがあります。

一方で、ユーザーの属性データと合わせた分析をしたい場合は独自でデータを取得する必要があります。例えば、アカウントリンク済みと、そうでないユーザーで利用状況の差異や特定デバイスでの利用状況を確認したい場合などです。 重要なことはPFが提供しているものと独自で取得するものは、違った強みがあるということを認識することです。それを理解した上でどういう分析がしたく、どういったデータが必要になるのか、といった設計をすることが重要です。 以下に簡単ですが、それぞれの強みをまとめました。

強み/データ 強み データ
PF 利用ユーザー全体の利用状況が俯瞰的に確認できる、すぐに利用可能、開発/運用コストなし 発話数、ユニークユーザー数、Amazon AlexaではアカウントリンクのCVR、Actions on Google ではアプリケーションの評価
独自 利用ユーザーの属性と照らし合わせた分析 利用デバイスの種類、アカウントリンクの有無、レスポンス内容

ログのデータストア先

Amazon Elasticsearch Service をデータストア先として利用します。選択した理由は以下の2点です。

  • Kibanaを利用した可視化が容易
  • CloudWatch LogsからAmazon Elasticsearch Serviceへのストリーミングが利用できる

Elasticsearch Serviceにデータを登録

では、具体的に手順を説明します。

1. Amazon Elasticsearch Serviceドメイン作成

https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/es-createupdatedomains.html

2. Amazon CloudWatch設定

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/CWL_ES_Stream.html

3. コード実装

実装でしなければならないことは、登録するデータをconsoleするのみです。一部省略しておりますが、以下が実際のコードです。

module.exports.index = async function (userEntity, options) {
  const document = {
    body: {
      status: {
        // ユーザーの情報(ディスプレイ付き、アカウントリンク済みかなど)
        userId: userEntity.userId,
        pf: options.isAlexa ? ‘alexa' : ‘google',
        device: userEntity.device,
        hasDisplay: userEntity.hasDisplay,
        isAccountLink: userEntity.isAccountLink,
        sessionsCount: userEntity.sessionsCount,
        lastUsedAt: userEntity.lastUsedAt
      },
      permission: {
        // ユーザーが許可している権限情報
        notification: userEntity.isPermitNotification,
        location: userEntity.isPermitLocation
      },
      request: {
        // リクエスト情報
        skillName: SKILL_NAME,
        type: 'talk',
        intent: options.fromIntent ? options.fromIntent : options.intent
      },
      redirect: {
        // 実際に処理した情報
        intent: options.intent
      },
      params: {
        // 利用した路線情報
        railCode: _get(options, 'railCode') ? options.railCode : [],
        railRangeCode: _get(options, 'railRangeCode') ? options.railRangeCode : []
      },
      response: {
        // ユーザーへの発話内容
        speech: options.responses.speech,
        reprompt: options.responses.reprompt
      }
    }
  }
  // consoleで表示させてCloudWatch経由でElastisearchに登録させる
  console.info(JSON.stringify(document))
}

上記の3つの手順を行うことで、Elasticsearch Serviceに日時のついたindexが作成され、データが登録されます。

  • スマートスピーカーアプリ開発 虎の巻 最終回

Kibanaを利用して可視化

Elasticsearch Serivceにデータを登録したので、Kibanaを利用して可視化します。

1. Management で、Index Patternsを作成

(1)ManagementからIndex Patternsのリンクをクリックします。

  • スマートスピーカーアプリ開発 虎の巻 最終回

(2)index patternを作成(可視化するために扱うデータの決定)するため、「cwl-*」と正規表現を用いて入力します。下図は、3月22、25、26、4月3、5日の5日間のデータを利用するという意味になります。

  • スマートスピーカーアプリ開発 虎の巻 最終回

(3)Time Filter field name に「@timestamp」を指定し、CloudWatch機能を利用して自動で登録されるので選択します。こちらを選択することでグラフを時系列に作成できます。

  • スマートスピーカーアプリ開発 虎の巻 最終回

2. Discoverで専用クエリを作成

(1)検索条件を入力します。下図の例では、Google アシスタント対応となり、端末を利用しているユーザーのデータのみを扱う検索クエリです。

  • スマートスピーカーアプリ開発 虎の巻 最終回

(2)検索クエリを保存します。

  • スマートスピーカーアプリ開発 虎の巻 最終回

3. Visulalizeでグラフを作成

今回は円グラフで各PFのスキルのIntentの利用状況を可視化します。

(1)VisualizeからPieを選択します。

  • スマートスピーカーアプリ開発 虎の巻 最終回

(2)可視化するデータを選択し、手順2で作成した専用クエリ「google端末利用ユーザー」を選択します。

  • スマートスピーカーアプリ開発 虎の巻 最終回

(3)Split Slicesの設定を行います。 ①Aggregation に「Terms」を選択
②Field に「$event.body.request.intent.keyword」を選択
③「▷」ボタンを押下して反映

  • スマートスピーカーアプリ開発 虎の巻 最終回

(4)作成したグラフを保存します。

  • スマートスピーカーアプリ開発 虎の巻 最終回

4. Dashboardで、手順3で作成したグラフを並べる

手順3で作成したグラフを一つの画面で確認できるようにし、事前に、Alexa端末利用ユーザーのインテント可視化というグラフを作成します。

(1)「+」ボタン、もしくは「Create a dashboard」ボタンを押下します。

  • スマートスピーカーアプリ開発 虎の巻 最終回

(2)「Add」をクリックします。

  • スマートスピーカーアプリ開発 虎の巻 最終回

(3)手順2で作成したグラフのリンク2つをクリックします。

  • スマートスピーカーアプリ開発 虎の巻 最終回

(4)Titleをつけて保存します。

  • スマートスピーカーアプリ開発 虎の巻 最終回

これで作成したグラフをいつでも確認できる状態となります。もし可視化したいデータにフィルターをかける必要がない場合は、手順2の「専用クエリを作成」を省略し、手順3でIndex Pattersを選択することもできます。プロジェクトでは、ユニークユーザーでデータを確認するニーズが多く、グラフを作成する際には、Metricsの設定を以下にするケースが多くあります。

  • Aggregationを「UniqueCount」を指定
  • Fieldにユーザー毎に発行されるユニークな識別子の「status.userId.keyword」を指定
  • スマートスピーカーアプリ開発 虎の巻 最終回

Elasticsearchの運用

Elasticsearchで気になるのはコストです。どれくらいの容量を保持するのかという点に気をつける必要があります。現状、2週間分のデータを保持し、それ以前のデータは削除する運用をしています。CloudWatchのElasticsearch Serviceへのストリーミング機能を利用すると日付のついたindexが作成されます。

  • スマートスピーカーアプリ開発 虎の巻 最終回

2週間以上前のデータを削除するときは、index名についている日時を元に削除します。Elasticsearchでは、2週間以上前のデータを対象にして個別に削除するより、index全体を削除する方が効率的です。そのため、特別な理由がない限りはCloudWatchの機能を利用すると良いと思います。プロジェクトでは開発言語をNode.jsで統一しているため、Lambdaで実装しCloudWatchのイベント設定で定期実行させています。除処理はcuratorを利用してindex管理するのも良い手段です。

インテント履歴から施策を考える

プロジェクトは独自で取得したログだけで分析していないと冒頭で説明しました。ここでは、インテント履歴を利用した分析の例も紹介します。インテント履歴ではユーザーが発話した内容とAlexaがどう解釈したかの履歴が確認できます。

  • スマートスピーカーアプリ開発 虎の巻 最終回

インテント履歴のデータを確認すると、Yahoo!路線スキル(路線スキル)から、天気情報を取得しようとする発話が一定数あることに気づき、我々は1つの仮説を立てました。路線スキルから天気情報を取得しようとして、その後Yahoo!天気スキル(天気スキル)を起動せず、ドロップしてしまっているユーザーがいるのではないか?ということです。そのようなユーザーに対して、天気スキルの利用方法を伝え、訴求をする施策を考えました。

なお、UXを考慮すると路線スキルで路線情報を聞いた後に、天気情報を回答する方が好ましいです。現状、特定のスキルから別のスキルを呼び出すSkill Connections機能は開発プレビューのため利用はできません。これと同等の機能を独自で実装しようとするとコードの肥大化を招き、バグの発生確率が高くなる可能性があります。

まとめ

わたしたちのプロジェクトでは、コンソールから確認できるデータと独自に収集したログを分析することでUXの向上などに努めております。今後は、弊社に保有されているユーザーの情報と掛け合わせ、さらなるUX向上に注力しようと考えています。

プロジェクトの環境

今回で最終回となるため、最後にプロジェクトで行っている取り組みについても記載します。VUIは技術の進歩が非常に早いです。プロジェクトではモブプログラミングを積極的に取り入れ、知見のシェア、属人化を防止しています。時には、非エンジニアの方にも参加していただき、プロダクションコードにコミットしたケースもあります。常に最新の情報を追い、知見をシェアする文化が根付いた環境となっています。

著者紹介

Yahoo! JAPAN スキルプロジェクトチーム
サイエンス統括本部のスマートデバイス本部に所属するプロジェクトチーム。スマートデバイス本部は、IoTや今回のテーマである音声アプリケーション開発など、ちょっとだけ未来の技術に挑戦する部署。

今回の執筆者:藤田 和秀(ふじたかずひで)/エンジニア
スキルプロジェクト エンジニア。ヤフーでは、スマートスピーカー向け音声アプリケーションVUI設計、フロントエンド、バックエンド開発等を担当。それ以前の経験は、ヤフオク!やYahoo!ショッピング、Yahoo!ウォレット、ウェブ通知PF、ワイキューのバックエンド開発、システム運用を経験。