これは Lex ベースのチャットボットで、さまざまなファーストフード レストランへの旅行によって得られるカロリーを計算します。これは、Facebook ページからアクセスできる FB メッセンジャー チャットボットから、または携帯電話のメッセンジャー アプリを通じて有効になります。
目次
このボットは AWS Lex を使用します。これは、ユーザーのリクエストを解読し、モデルで提供されたデータに基づいてインテントをトリガーできるインテリジェンスを含むサービスです。次に、インテントは、インテントに固有のビジネス ロジックを含むラムダ関数を呼び出します。
現在、NLU プロセスで分類されるさまざまなインテントが多数あります。ボットの「コア機能」は次のとおりです。
コア機能を補完するインテントもあります。
次に、ボットの「個性」を形成するインテントがあります。これらは実際のユーザーの使用状況に基づいて作成されており、一般的なエラー メッセージが応答に使用されるのを防ぎます。
各インテント内には、ユーザーが提供する可能性のあるセンテンスを構成するサンプル発話が提供されます。スロットの値 (つまり、Large Fry) は、一意の属性としてラムダ関数に渡されます。
次のコマンドを実行すると、AWS CLI から概要情報を取得できます。
aws lex-models get-bot --name FastFoodChecker --version-or-alias PROD
これは、NLU モデルがどのインテントを呼び出すかを決定するサンプル発話とスロットの組み合わせです。これらは Lex で維持され、モデルのトレーニングに使用されます。
現在、インテントによって使用されるカスタム スロットは次のとおりです。
NLU が値を配置するためにスロットに項目を指定する必要はありません。ただし、データがまばらな場合、NLU がユーザー要求を解釈する方法が低下する可能性があります。
チャットボットを使いやすくするには、ユーザーとの自然な対話が必要です。重要な概念の 1 つは、複数のスロットを 1 つのインテントに組み込む方法に関するものです。たとえば、ユーザーは「ビッグマック、フライドポテト、コーラのカロリーは何杯ですか?」と尋ねることができます。これは 3 つの異なる項目であり、それぞれを解析する必要があります。このチャットボット内のメイン処理には、インテントにマップされるさまざまなスロットが多数あります。たとえば、GetCalories インテントにマップされるスロットは次のとおりです。
この中で注意すべき点がいくつかあります。
上記のリクエストの例では、NLU モデルは発話からのデータを 3 つの異なるスロット (食べ物、追加、飲み物) に解析します。
スロットの順序は解析には関係ありませんが、次の応答 (スロット 1 - どのレストランにいますか?) を決定します。
このインテントでは必要のない 2 つのスロット (Ketchup と PacketsKetchup) があります。このオプションの情報は、フライドポテトをサイドアイテムとして要求する場合に要求されます。これは、検証コードフックで呼び出される Lambda 関数のコードによって制御されます。
さまざまなインテントへの応答を定式化するロジックはすべて、一連のラムダ関数で処理されます。どのラムダ関数を呼び出すかは Lex 内で管理され、インテント レベルで設定されます。これにより、アプリケーション内でモジュール性を構築でき、機能を軽量に保つことができます。
Lex 内には、ラムダ関数を呼び出すことができる 2 つの異なる場所があります。 1 つ目は基本的な検証であり、それを識別する属性名は invocationSource と呼ばれます。これには、DialogCodeHook と FulfillmentCodeHook という 2 つの値が考えられます。 Lex Bot でこれらの Lambda 関数が指定される場所は次のとおりです。
最初のドロップダウンは検証であり、ボットが呼び出されるたびにラムダ関数を呼び出します。渡される属性は DialogCodeHook と呼ばれます。 2 番目のドロップダウンはフルフィルメントで、必須スロットが完了し、最初の呼び出しからの検証が完了した場合にのみ呼び出されます。これにより、機能を異なるものにすることができ、ボットを構築する際の拡張性が向上します。
現在作成されている各関数の概要を以下に示します。
lambda.js - クエリの基本的な検証を処理するメイン関数であり、DialogCodeHook モードでのみソースされます。
Calculate.js - 食事の実際のカロリーに対する応答の計算は、この関数によって処理され、FulfillmentCodeHook によって取得されます。
zza.js - WhatPizzaTypes のインテントを含む、ピザのカロリー計算に関するインテントを処理します。
misc.js - ヘルプ、紹介、食事に関する詳細などの単純なインテントを処理します。
chinese.js - 中華料理に関するインテントを処理し、さまざまなスロットを結合して食事を形成します。
このボットの中心的な機能は、さまざまな食事のカロリー数に関する質問に答えられることです。 Lex が使用するスロットは NLU モデルのトレーニングには役立ちますが、ルックアップ ファイルとして機能する機能はありません。ここで、/src/data/ フォルダーに保存されている json オブジェクトが登場します。
以下はフォーマットのサンプルです。
[
{
" restaurant " : " Chipotle " ,
" foodItems " :[
{ " foodName " : " Chicken Burrito " , " foodType " : " Burrito " , " protein " : " chicken " , " calories " :975},
{ " foodName " : " Steak Burrito " , " foodType " : " Burrito " , " protein " : " steak " , " calories " :945},
{ " foodName " : " Carnitas Burrito " , " foodType " : " Burrito " , " protein " : " carnitas " , " calories " :1005},
ラムダ関数はこれらのオブジェクトを参照して、さまざまなクエリに応答し、ユーザーのカロリー消費量を計算します。
各食品項目は、検索に使用されるさまざまなスペルやフレーズで複製される場合があります。例えば。
{ " foodName " : " Fries " , " calories " :340},
{ " foodName " : " Fry " , " calories " :340},
{ " foodName " : " Frys " , " calories " :340},
{ " foodName " : " French Fries " , " calories " :340},
{ " foodName " : " French Fry " , " calories " :340},
{ " foodName " : " Medium Fries " , " calories " :340},
{ " foodName " : " Medium Fry " , " calories " :340},
ソース、ドレッシング、および個々の項目の調整に関する参照テーブルもあります。例えば。
[
{
" dressingName " : " Ranch " ,
" calories " :200,
" carbs " :11,
" restaurantNames " :[ " McDonalds " ]
},
{
" dressingName " : " French " ,
" calories " :300,
" carbs " :22,
" restaurantNames " :[ " McDonalds " ]
},
NLU モデルはユーザーが指定したスペルを修正しないため、ロジックのこの部分を処理するのは Lambda 関数次第です。
特にデータが動的である場合、大規模なカスタム スロットの管理は困難になることがあります。メインの食品ルックアップには数百の一意の値が含まれており、ユーザーの使用状況に基づいて増加します。このスロットを作成するプロセスは自動化されており、カスタム スロットのデータは food.json データ オブジェクトから取得されます。これは、コマンドラインからこれらを直接ロードできる AWS CLI を通じて行われます。すべてのファイルは参照用に [slots}(https://github.com/terrenjpeterson/カロリーカウンター/tree/master/src/slots) ディレクトリに含まれています。作成に使用した手順は次のとおりです。
構文は次のようになります。
# foods.json is the data object that will be passed to the lambda function
request= $( < foods.json )
# invoke the lambda function from the command line and write the output to output.json
aws lambda invoke --function-name convertFoodsObjForSlot --payload " $request " output.json
data= $( < output.json )
# invoke lex to create a new version of the FoodEntreeNames custom slot using the data from output.json
aws lex-models put-slot-type --name FoodEntreeNames --checksum < enter latest checksum here > --enumeration-values " $data " >> sysout.txt
また、チェックサム値は、カスタム スロットの以前の展開からのものです。スロットの現在のチェックサムは、get-slot-type コマンドで確認できます。
# find the latest information about a custom slot
aws lex-models get-slot-type --name FoodOptions --slot-type-version ' $LATEST '
ユーザーとボットの間で長時間にわたる効果的な会話を実現する鍵は、会話のコンテキストを管理することにあります。たとえば、ダイアログは数分間継続し、多くのインテントを呼び出す可能性があります。
これを促進するには、会話の流れをデザインすることが重要です。エラー メッセージは唐突すぎてはならず、ユーザーを別のクエリに誘導する必要があります。また、インテント間でデータをやり取りする必要があります。これは、インテントの完了時にセッション データを保存することで実現できます。これにより、次のインテントが情報を取得できるようになり、ユーザーがリクエストごとに情報を繰り返す必要がなくなります。
上の例では、会話はユーザーがどのレストランで食事をしているかを示すことから始まります。これは、FoodTypeOptions インテントによってセッション内に保持されます。ダイアログは食事の詳細に移りますが、レストラン名は保存されます。また、カロリー計算に関する最初の応答は短いですが、ユーザーが「もっと詳しく」と言えば、より詳細な説明が提供されます。もう一度、データはセッション データに保存され、Lex フレームワークの一部として返されます。以下はオブジェクトの 1 つの例です。
{
" messageVersion " : " 1.0 " ,
" invocationSource " : " FulfillmentCodeHook " ,
" userId " : " 1712299768809980 " ,
" sessionAttributes " : {
" restaurantName " : " Burger King " ,
" foodName " : " Whopper " ,
" foodCalories " : " 660 " ,
" extraName " : " Onion Rings " ,
" extraCalories " : " 410 " ,
" drinkCalories " : " 310 " ,
" drinkName " : " 32 oz. Large Coke " ,
" totalCalories " : " 1380 "
},
" bot " : {
" name " : " FastFoodChecker " ,
" alias " : " PROD " ,
" version " : " 42 "
},
" outputDialogMode " : " Text " ,
" currentIntent " : {
" name " : " DailyIntakeAnalysis " ,
" slots " : {},
" slotDetails " : {},
" confirmationStatus " : " None "
},
" inputTranscript " : " Analyze my meal "
}
このボットのラムダ関数は完全にステートレスであるため、以前の呼び出しからのデータはすべてリクエスト オブジェクトを介して送信される必要があります。
主要なチャットボット ユーザー インターフェイス (メッセンジャー、Slack など) の機能の 1 つはボタンです。これらは、このような一連のオプションを提供することでユーザーの労力を軽減します。
各メッセージング プラットフォームにはこのパターンの独自の実装があり、メッセンジャーが使用するものは次のとおりです。 Lex はボタンを正しい形式に変換するための変換を処理します。Lex 内では、responseCard 属性にボタンの詳細の詳細を指定する必要があります。
Lex の変更は完全にコンソールから行われます。ビジネス ロジックを提供するラムダ関数は AWS ラムダでホストされ、EC2 ホストからデプロイされます。
完全な展開スクリプトは /src/build.sh ですが、簡単な概要は次の手順に記載されています。
# this creates the build package as a zip file containing the code and relevant data objects
zip -r foodbot.zip lambda.js data/restaurants.json data/foods.json data/drinks.json
# this CLI command copies the build package to an s3 bucket for staging
aws s3 cp foodbot.zip s3://fastfoodchatbot/binaries/
# this CLI command takes the package from the s3 bucket, and overlays the lambda function 'myCalorieCounterGreen'
aws lambda update-function-code --function-name myCalorieCounterGreen --s3-bucket fastfoodchatbot --s3-key binaries/foodbot.zip
# this CLI command invokes the lambda function with the data object read into request, and writes out a response to the testOutput data object.
aws lambda invoke --function-name myCalorieCalculatorGreen --payload " $request " testOutput.json
このプロセスは、Lex によって呼び出されるラムダ関数ごとに繰り返されます。これには、デプロイが正しく行われたことを確認するために、ラムダ関数ごとに少なくとも 1 つのテスト条件を設定することが含まれます。
ボット設計のトピックの 1 つは、個性を持つことです。インテントを設計するときに考慮すべきことは、ユーザーが尋ねる可能性のあるすべての質問は何なのかということです。これには、「あなたの名前は何ですか」などの本題から外れた質問や、「ああ、だめだ」や「最低だ」などの感情的な反応が含まれる必要があります。これらはコーディングが簡単です。通常は、スロットが関与しない単純なリクエストと応答だけであり、ダイアログがより自然になる傾向があります。
例として、誰かがボットの名前を尋ねた場合に応答する、misc.js 関数でコーディングされた短い応答を次に示します。モデルでは、「あなたの名前は何ですか」という発話は、この意図に応じて解決されます。
if (intentName === ' MyName ' ) {
console.log( " user requested bot name " ) ;
return getBotName(intentRequest, callback) ;
}
...
function getBotName(intentRequest, callback) {
const sessionAttributes = intentRequest.sessionAttributes || {} ;
var botResponse = " My name is Chuck. I'm a chatbot that helps people sort out " +
" fast food options. Talking about food all day makes me hungry!!! " ;
callback(close(sessionAttributes, ' Fulfilled ' ,
{ contentType: ' PlainText ' , content: botResponse })) ;
}
初期の取り組みの一環として、私はこのチャットボットを Slack ストアに公開しようとしました。その一環として、アプリを公的にサポートするための Web サイトを構築する必要がありました。これは現在開発中のもので、「カロリーカウントボット.com」と呼ばれています。これは s3 によってホストされており、ソースは /website フォルダーにあります。