Amazon Web Services ブログ

Amazon Lex で会話型ビジネスインテリジェンスボットを構築する

会話型インターフェースの登場で、ソフトウェアアプリケーションやサービスとのやり取りの方法が激変しています。インターフェースをより自然なやり取りの仕方、つまり会話に置き換えることで、キーボードやスマートフォンを使っての意思表示方法から人々を開放したのです。質問に対する回答が必要な時、リマインダーを設定する時、あるいは製品やサービスを調達したい時に、ボットとの対話を利用する人々がますます増えています。

Amazon Lex では、これと同じレベルの利便性をデータにもたらすことが可能です。一連の質問を尋ね、会話コンテキストを維持し、ユーザーがデータセットを検索できるようにすることで、全く新しいエクスペリエンスとデータとの関係が実現しました。

このブログ記事では Amazon Lex を使用して、ビジネスインテリジェンス (BI) チャットボットを実装する方法を紹介します。このチャットボットを「BIBot」と呼んでいますが、別の名前を使うようカスタマイズできます。BIBot は、質問をバックエンドデータベースクエリに変換し、さらに結果セットを自然言語応答に変換することによって、データベース内のデータに関するユーザーの質問に答えることができます。例えば、「先月の在庫の増加を教えてください」というリクエストは、「month(received_date) = 10 の在庫から sum(item_qty) を選択する」に変換します。

BIBot は、ビジネスインテリジェンスとレポートアプリケーション向けの一般的なリレーショナルデータベースと統合されています。サンプルデータベースは Amazon Redshift TICKIT データベースです。これは、ユーザーが音楽コンサートや劇場でのショーのチケットをオンラインで購入したり販売できる架空のウェブサイトでの売り上げを追跡するものです。データベースは、2 つのファクトテーブル (販売、リスト) と 5 つのディメンションテーブル (イベント、日付、会場、カテゴリ、ユーザー) を持つスタースキーマです。詳細については、「Amazon Redshift」 » 「サンプルデータベース」を参照してください。

BIBot とのやりとりの例をいくつか紹介します。

これらの例から分かるように、BIBot は 6 月にヒューストンについて聞いたことと、何枚のチケットが売れたか聞いたことを覚えており、そのため、質問のコンテキストを把握することができます。会話は、データの「言葉」を利用します。つまりこの場合、チケット販売、都市、月、イベントなどです。これらは、サンプルチケット販売データベースのファクトとディメンションです。レポートデータベースを使用するように BIBot を調整すると、ボットとの会話はデータの言葉で行われます。

アーキテクチャ

BIBot のアーキテクチャはシンプルです。Amazon Lex ボットは、ユーザーの各質問をインテントに送り、質問をスロットでパースします。次に、Amazon Lex ボットはインテントとスロットのデータを AWS Lambda 関数に渡します。この関数はデータを使用して、SQL クエリを構築し、Amazon Athena データベースに対して実行します。Athena は、Amazon S3 バケットに格納されている一連の CSV ファイルからクエリ結果を取得し、結果セットを Lambda 関数に返し、その時 Lambda 関数が自然言語応答に変換します。

シンプルで使いやすいという理由で Athena を使用しましたが、このアーキテクチャは SQL ベースのデータベースで動作するため、NoSQL データベースなど他の種類のデータソースにも適用できます。

BIBot をインストールする

初めに、Amazon Lex ボットのサンプルを、AWS アカウントにインストールしてみましょう。BIBot のインストールを容易にし、さらにその後の変更を行うために、AWS CodeBuild で Amazon Lex ボット、Lambda インテントハンドラ関数、および Athena データベースを作成し更新できる AWS CodePipeline を使用して、パイプラインを実装しました。

ステップ 1: GitHub アカウントに公開 amazon-lex-bi-bot をフォークする。

自身の BIBot コードベースのコピーを作成すれば、ボットを変更して実験したり、自分のデータを使えるようにすることもできます。リポジトリに変更をコミットするたびに、パイプラインが自分のボットを再構築します。

: まだ GitHub アカウントをお持ちでない場合は、https://github.com で、無料でアカウントを作成できます。

ステップ 2: AWS Systems Manager パラメータストアに AWS API 認証情報を保存する

CodeBuild プロジェクトは、Amazon Lex ボット、Lambda 関数、Athena データベースを構築するための AWS API 呼び出しを行います。これを行うには、AWS API の認証情報が必要になります。ご使用の環境に AWS CLI をまだ設定していない場合は、こちらの指示に従ってください。AWS CLI を設定する。AWS マネジメントコンソールで、AWS Systems Manager コンソールに移動し、[Shared Resources] を選択し、次に [Parameter Store] を選択します。次のパラメータ名と値を持つ 2 つのパラメータを作成します。

  • ACCESS_KEY_ID – paste in the value of your aws_access_key_id from your AWS credentials file
  • SECRET_ACCESS_KEY – paste in the value of your aws_secret_access_key from your credentials file

これらの機密キーを保護するには、パラメータストアで値が暗号化されるように、各パラメータに Secure String 型を必ず選択してください。

ステップ 3: AWS CloudFormation を使用してパイプラインを作成する

このボタンを使用して、米国東部 (バージニア北部) リージョン (us-east-1) で AWS CloudFormation スタックを起動します。

[Stack Name] に bibot と入力します。[Owner] フィールドに GitHub ユーザー名を入力し、[Personal Access Token] で GitHub の Repo スコープを使用してトークンを生成します

他のパラメータのデフォルト値を受け入れ、[Next] を 2 度選択して、[Review] ページを表示します。確認チェックボックスを選択し、[Create] を選択します。

CloudFormation テンプレートは 1 〜 2 分で終了し、次のリソースが作成されます。

CodePipeline コミットするたびに GitHub リポジトリからソースを取得し、CodeBuild を呼び出す、「bibot-pipeline」AWS CodePipeline
CodeBuildProject Amazon Lex ボットを構築 (または再構築) する CodeBuild プロジェクト「bibot-build」
ArtifactStore CodePipeline が CodeBuild のコードを格納する S3 バケット
AthenaBucket TICKIT サンプルデータのコピーを保存する S3 バケット
AthenaOutputLocation Athena がクエリからの出力を保存するための S3 バケット
CodePipelineRole CodePipeline が Amazon S3 と CodeBuild にアクセスできるようにする IAM サービスロール
CodeBuildServiceRole CodeBuild が Amazon S3 および CloudWatch ログにアクセスできるようにする IAM サービスロール
LambdaExecutionRole Lambda 関数に必要な IAM サービスロール

AWS マネジメントコンソールで、CodePipeline コンソールに移動し、「bibot-pipeline」を開きます。[Source][Build] の 2 つの段階が表示されます。両段階が成功すると、Amazon Lex ボットが構築されます。

次に、CodeBuild コンソールに進み、[Build history] を選択します。「bibot-build」プロジェクトのエントリが表示されます。[Build run] リンクを選択し、[Build details][Environment variables]、および [Build logs] を調べます。

ステップ 4: サンプル TICKIT データを AthenaBucket S3 バケットにコピーする

CloudFormation スタックの起動が完了すると、[Output] タブに、Amazon Redshift サンプル TICKIT データベースから新しい AthenaBucket S3 バケットにデータファイルをコピーするための AWS CLI コマンドが含まれます。以下に例を挙げます。

$ aws s3 cp s3://awssampledbuswest2/tickit/allevents_pipe.txt s3://bibot-athenabucket-xxxxxxxxxxxxx/event/allevents_pipe.txt --source-region us-west-2

これらの AWS CLI コマンドをそれぞれコピーして実行し、サンプルデータのコピーを作成します。CloudFormation によって作成された Athena データベースは、このデータを使用します。AWS マネジメントコンソールで、Athena コンソールに移動し、「tickit」データベースを選択して、SQL クエリを実行します。以下に例を挙げます。

SELECT DISTINCT event_name from event ORDER BY event_name

ステップ 5: Lex ボットをテストし、データベースから「event_name」スロットを更新する

次に、Amazon Lex に移動し、BIBot を開きます。Amazon Lex にあなたの Lambda 関数を呼び出す権限を与えようとしているという警告が表示されますが、これは分かっているので、[OK] を選択してください。

「Event_name」 [Slot type] を選択すると、このスロットには 2 つのエントリしかないことが分かります (「Sample Event 1」と「Another Sample Event」)。次に、[Test Chatbot] を選択して Lex シミュレーターを開き、「refresh yourself」と入力します (または言う)。BIBot はデータベースからイベントリストを読み込み、「event_name」 [Slot type] を更新します。イベントを見るには、再度「event_name」 [Slot type] を選択します。「Joshua Radin」、「Jessica Simpson」、「Nine Inch Nails」などのイベント名のリストが表示されます。

今すぐ、ボットを再構築してください。Amazon Lex コンソールに戻り、BIBot Lex ボットを選択し、[Build] を選択します。BIBot はテスト準備が整いました。Lex シミュレーターを開き、BIBot にいくつか質問してみましょう。

Lex ボットの設計

BIBot Lex ボットには 8 つのインテントがあります。

インテント 目的
Hello BIBot に、こんにちはと言う
Top 既定のディメンションの上位 n の集計値を尋ねる (、ショー、会場、都市、月)
Compare 2 つのディメンション集計値 (3 月対 4 月) の比較を尋ねる
Count 現在のディメンションセットのファクト (販売したチケット 3 月) の合計を尋ねる
Switch 以前のクエリを、新しいディメンション値 (5 月はどうですか) に切り替える
Reset 検索結果を拡張するため、クエリパラメータの一部またはすべてを消去する、または最初からやり直す
Refresh データベースからのディメンションデータを使用してスロットタイプを更新し、NLU エンジンを再トレーニングします。
GoodBye さようならと言って、セッションを終了する

HelloGoodBye のインテントはシンプルで、主に文字を追加するためだけに含まれています。「こんにちは」、「ねえ」、「ハロー」などと言っても、BIBot は応答します。最後に「ありがとう」、「さよなら」、「よくできました」、「また後で」などを言うと、BIBot はセッションを終了します。

TopCompareCount、Switch、、および Reset は、もっとおもしろいです。これらのインテントは、特定の型のデータベースクエリに会話型の自然言語インターフェースを実装するように設計されています。これらのインテントは、データベース内のどのディメンションとも連携できるので、柔軟性があります。また、ユーザーは長め会話の一環の中で質問をするため、そのコンテキストを覚えておいて共有するので、会話が噛み合うのです。

Refresh インテントは、データベースのディメンションデータを含む Lex スロットタイプの定義を更新します (この例では、サンプル TICKIT データベースの EVENT テーブルのイベント名のリスト)。

Top インテントを見てみましょう。

このインテントを使って、「ボストンでの売上トップ 3 のイベントを教えて」、または「3 月に Dave Matthews Band 売上トップ 3 の都市は?」などの質問ができます。

このインテントは、次のスロットを使用しています。

  • {count} – ビルトインの AMAZON.NUMBER スロットタイプを使用します。
  • {dimension} – サンプルデータベースのディメンションを識別するカスタムスロットタイプ。「イベント」、「月」、「会場」、「都市」、「州」、および「カテゴリ」が含まれます。 このスロットタイプではシノニムも使うため、例えば、「会場」の代わりに「場所」と言うことができます。

サンプルデータベースの各ディメンションも、スロットとして表されます。

  • {event_name} – サンプルの TICKIT データベース「EVENT」テーブルに存在する一連のイベントを識別するカスタムスロットタイプ。このスロットタイプは、Refresh で更新されます。
  • {event_month} – ビルトインの AMAZON.Month スロットタイプを使用します。
  • {venue_name} – ビルトインの AMAZON.MusicVenue スロットタイプを使用します。
  • {venue_city} – ビルトインの AMAZON.US_CITY スロットタイプを使用します。
  • {venue_state} – ビルトインの AMAZON.US_STATE スロットタイプを使用します
  • {cat_desc} – サンプルの TICKIT データベースの「CATEGORY」テーブルに存在する、カテゴリセットを識別するカスタムスロットタイプ。

ドメイン特化型の自然言語を構築する

BIBot のクエリインテント – TopCompareCountSwitch、および Reset – これらはすべて、基礎となるデータセットに関連する文構造を構築するのに必要な「ボキャブラリー」としてスロットを使用します。実際に、BIBot のインテントは、ドメイン特化型の自然言語を実装しています。Amazon Lex の強力な自然言語理解の機能により、これを簡単に行うことができます。

例として、Count インテントからいくつかのサンプル発話を見てみましょう。

BIBot に「2 月のアーリントンで Allman Brothers のチケットを何枚販売しましたか?」と聞くと、Lex 自然言語処理エンジンはいくつかのサンプル発話のコンポーネントを使って、質問を正確にパースすることができます。サンプル発話でのすべての質問の全順列を、指定する必要はありません。

会話コンテキストを維持する

BIBot に質問をすると、Lambda フルフィルメント関数は回答で応答しますが、インテント全体で共有するセッション属性のスロット値の一部も保持します。これで、BIBot は会話を継続することができ、実際に、以前に尋ねられたことを覚えています。このように会話コンテキストを維持することは、より自然なユーザーエクスペリエンスを提供し、一連の関連する質問を行うことによってユーザーがデータセットを検索する機能を簡素化するための鍵となります。

例えば、このブログの初めのサンプルのやり取りで、ユーザーが 6 月のヒューストンでの上位の売上のコンサートについて質問し、BIBot が上位 5 つのイベントを特定しました。ユーザーが Allman Brothers と Goo Goo Dolls の売上を比較するように頼んだ際、BIBot は、これが継続した質問であること、そして本当のところユーザーは 6 月にヒューストンでのこれらのイベントの売上を比較したいのだということを「理解」したのです。このアプローチを使用すると、必要な情報が見つかるまで結果をドリルダウンできます。

ユーザーがバックアップを取ったり、ギアを切り替えたり、検索結果を拡張したり、最初からやり直したい場合があります。BIBot の TopCompare、および Count クエリインテントは、Reset インテントから追加の補助を受けて、これをサポートしています。以下に例を挙げます。

やり取り インテント – 結果

6 月のヒューストンでの売上トップのコンサートは何でしたか?

ヒューストン市の 6 月の売上上位 5 つのイベントは、1、Allman Brothers Band、2、Girl Talk、3、Goo Goo Dolls、4、Commodores、5、Dropkick Murphys でした。

Top – BIBot は都市を覚えています : ヒューストンと月 : クエリパラメータとして 6 月

Goo Goo Dolls のトップ都市

2 つしかありません。6 月の Goo Goo Dolls の上位 2 都市は、1、ヒューストン、2、シンシナティでした。

Top – BIBot はイベントを覚えています : Goo Goo Dolls、でも都市を忘れています : ヒューストンクエリパラメータ

6 月はいいです

了解、6 月をリセットしました。

Reset – BIBot は月を忘れています : 6 月

上位の都市

Goo Goo Dolls の上位 5 都市は、1、トロント、2、ヒューストン、3、ボストン、4、オークランド、5、シンシナティでした。

Top – BIBot は覚えているイベントを使用します : Goo Goo Dolls のリクエストを完了します。

ボストンで売られたチケットの数は?

ボストン市での Goo Goo Dolls のコンサートには、46 枚のチケットを販売しました。

Count – BIBot は覚えているイベントを使用します : Goo Goo Dolls のリクエストを完了しましたが、都市を覚えています : ボストン

やり直す

了解、すべてをリセットしました。

Reset – BIBot はイベントを忘れています : Goo Goo Dolls と都市 : ボストン

データからスロットを調達する

前述のように、BIBot は、ビルトインの Amazon スロットタイプを使用して、月、都市、州、会場名などディメンションの一部を表します。イベント名ディメンションの場合、Refresh インテントはデータベースからデータを読み取り、aws.lex-models.put-slot-type API コールを使用して対応するスロットタイプを更新します。これで、Amazon Lex NLU エンジンが、TICKIT データベースに固有のイベント名を認識するようにトレーニングします。頻繁に変更するデータセットの場合、Refresh インテントロジックは、スケジュールに従って自動的にトリガーされます。

Amazon Lex は、次の例に示すように、他のスロットタイプにも存在する可能性のある値を含む場合でも、意図するスロットを正しく識別できます。Amazon Lex は、同じリクエストであっても、「ボストン」や「シカゴ」を都市と同様にバンド名として認識することができます。

AWS Lambda の実装および拡張性

BIBot の Python をベースした Lambda フルフィルメント関数は、インテントハンドラ、ヘルパー関数、構成データ、およびユーザー出口関数で構成されています。インテントハンドラ関数は 8 つあります。

  • hello_intent.py
  • count_intent.py
  • compare_intent.py
  • top_intent.py
  • switch_intent.py
  • reset_intent.py
  • refresh_intent.py
  • goodbye_intent.py

ヘルパー関数は次を含みます。

  • get_slot_values(slot_values, intent_request)
  • remember_slot_values(slot_values, session_attributes)
  • get_remembered_slot_values(slot_values, session_attributes)
  • execute_athena_query(query_string)
  • close(session_attributes, fulfillment_state, message)

これらの機能はどれもデータベースに依存せず、異なるデータベーススキーマで動作するように構成することができます。

構成パラメータには、スロット構成、ディメンション情報、および SQL クエリ文字列が含まれ、これらは基礎となるデータベースに固有のものです。スロットは、インテントに対して定義されたスロットタイプに一致するよう設定されています。

SLOT_CONFIG = {
  'event_name':  {'type': TOP_RESOLUTION, 'remember': True, 
                  'error': 'I did not find an event called "{}".'},
  'event_month': {'type': ORIGINAL_VALUE, 'remember': True},
  'venue_name':  {'type': ORIGINAL_VALUE, 'remember': True},
  'venue_city':  {'type': ORIGINAL_VALUE, 'remember': True},
  'venue_state': {'type': ORIGINAL_VALUE, 'remember': True},
   ...
}

BIBot は、データベースのディメンションとデータベース列へのマッピング方法も理解する必要があります。

DIMENSIONS = {
  'events':     {'slot': 'event_name',  'column': 'e.event_name',  'singular': 'event'},
  'months':     {'slot': 'event_month', 'column': 'd.month',       'singular': 'month'},
  'venues':     {'slot': 'venue_name',  'column': 'v.venue_name',  'singular': 'venue'},
  'cities':     {'slot': 'venue_city',  'column': 'v.venue_city',  'singular': 'city'},
  'states':     {'slot': 'venue_state', 'column': 'v.venue_state', 'singular': 'state'},
  'categories': {'slot': 'cat_desc',    'column': 'c.cat_desc',    'singular': 'category'}
}

クエリインテントハンドラは、データベースに固有の SQL クエリが必要です。例えば、サンプル TICKIT データベースの Top インテントハンドラの構成パラメータは次のとおりです。

TOP_SELECT  = "SELECT {}, SUM(s.amount) ticket_sales FROM sales s, event e, venue v, " \           
              "category c, date_dim d " 
TOP_JOIN    = " WHERE e.event_id = s.event_id AND v.venue_id = e.venue_id AND " \ 
              " c.cat_id = e.cat_id AND d.date_id = e.date_id "
TOP_WHERE   = " AND LOWER({}) LIKE LOWER('%{}%') " 
TOP_ORDERBY = " GROUP BY {} ORDER BY ticket_sales desc" 

「{ }」パラメータは、実行時にユーザーのリクエストに基づいて、列名と値に置き換えられます。

構成パラメータに加えて、ユーザー出口関数もあります。

  • pre_process_query_value(key, value)
  • post_process_slot_value(key, value)
  • post_process_dimension_output(key, value)
  • get_state_name(value)
  • get_month_name(value)
  • post_process_venue_name(venue)

これらの関数は、人間が判読可能な値とデータベースに格納された値との間のマッピングを可能にするために、クエリパラメータに値を挿入する前、または結果セットから値を抽出した後に呼び出されます。これらの関数にカスタムコードを挿入して、データベース固有のマッピングを実装することができます。

例えば、ユーザーがカリフォルニアで上位 5 つのイベントを尋ねると、preprocess_query_value() はその値をデータベースのデータに対応する「CA」に変換します。Post_process_dimension_output() は逆関数を実行し、データベースから返された値「CA」を「California」に戻します。

結論

自然言語インターフェースは、人々がデータとやり取りする方法を新しくします。従来のビジネスインテリジェンスのダッシュボード、視覚化、およびアラートを、ビジネスユーザーが単に尋ねるだけでデータに関する質問に回答するという、会話型インターフェースが強化するのです。

BIBot は、ビジネスデータ用の会話インターフェースを実装するための、拡張可能なフレームワークを備えています。これは、スタースキーマやスノーフレークスキーマなどの従来のレポートデータベース構造と統合するように設計されていますが、NoSQL データベースなどの他の種類のデータソースにも適用が可能です。サンプルの実装には、ディメンション別の上位集計、2 つのディメンションの集計の比較、および集計のカウントという 3 つのシンプルな分析が含まれています。これらはすべて共有会話コンテキスト内でシームレスに共有されます。単純なクエリから複雑なシミュレーションや予測モデルに至るまで、このフレームワークには、さらなる分析機能を追加することができます。

ビジネスデータに BIBot を試してみて、組織内でどう機能したか、ぜひ教えてください。


著者について

Brian Yost は、AWS プロフェッショナルサービスのシニアコンサルタントです。マウンテンバイク、自家製ビール醸造、テクノロジーのティンカリングが趣味です。