Ini adalah chatbot berbasis Lex yang akan menghitung kalori yang dihasilkan oleh perjalanan ke berbagai restoran cepat saji. Ini diaktifkan dari Chatbot FB Messenger yang dapat diakses dari Halaman Facebook, atau melalui Aplikasi Messenger di ponsel Anda.
Daftar isi
Bot ini menggunakan AWS Lex - layanan yang berisi kecerdasan untuk dapat menguraikan permintaan pengguna dan memicu maksud berdasarkan data yang disediakan dalam model. Maksud tersebut kemudian memanggil fungsi lambda yang berisi logika bisnis khusus untuk maksud tersebut.
Saat ini ada banyak maksud berbeda yang disortir oleh proses NLU. Berikut adalah "fungsi inti" bot.
Ada juga maksud yang melengkapi fitur inti.
Lalu ada maksud yang membentuk 'kepribadian' bot tersebut. Ini dibuat berdasarkan penggunaan pengguna sebenarnya, dan mencegah pesan kesalahan umum digunakan untuk merespons.
Dalam setiap maksud, contoh ucapan disediakan untuk membangun kalimat potensial yang mungkin diberikan pengguna. Nilai slot (yaitu Goreng Besar) diteruskan ke fungsi lambda sebagai atribut unik.
Anda bisa mendapatkan informasi ringkasan dari AWS CLI dengan menjalankan perintah berikut.
aws lex-models get-bot --name FastFoodChecker --version-or-alias PROD
Ini adalah kombinasi dari contoh ucapan dan slot yang menentukan maksud mana yang akan dipanggil oleh model NLU. Ini dipertahankan di Lex, dan digunakan untuk melatih model.
Saat ini, berikut adalah slot khusus yang digunakan oleh tujuan.
Suatu item tidak perlu ditentukan dalam slot agar NLU dapat memberikan nilai ke dalamnya. Namun, jika datanya sedikit, hal ini dapat menurunkan cara NLU menafsirkan permintaan pengguna.
Kegunaan chatbot membutuhkan interaksi alami dengan pengguna. Salah satu konsep utamanya adalah bagaimana menggabungkan beberapa slot ke dalam satu tujuan. Misalnya, pengguna dapat bertanya "Berapa banyak kalori dalam Big Mac, Kentang Goreng, dan Coke?" Itu adalah tiga item berbeda yang masing-masing perlu diuraikan. Dalam chatbot ini, pemrosesan utama memiliki banyak slot berbeda yang dipetakan ke dalam maksud. Misalnya, berikut adalah slot yang dipetakan ke dalam maksud GetCalories.
Ada beberapa hal yang perlu diperhatikan dalam hal ini.
Dalam contoh permintaan di atas, model NLU akan mengurai data ucapan ke dalam tiga slot berbeda (Makanan, Ekstra, dan Minuman).
Urutan slot tidak menjadi masalah dalam penguraian, namun menentukan respons selanjutnya (slot 1 - Di Restoran manakah Anda berada?)
Ada dua slot yang tidak diperlukan dalam maksud ini - Ketchup dan PacketsKetchup. Informasi opsional ini ditanyakan jika kentang goreng diminta sebagai makanan sampingan. Hal ini didorong oleh kode dalam fungsi Lambda yang dipanggil di kait kode Validasi.
Seluruh logika dalam merumuskan respons terhadap maksud yang berbeda diproses dalam serangkaian fungsi lambda. Fungsi lambda mana yang akan dipanggil dikelola dalam Lex, dan ditetapkan pada tingkat maksud. Hal ini memungkinkan modularitas dibangun dalam aplikasi, menjaga fungsinya tetap ringan.
Ada dua tempat berbeda di dalam Lex yang dapat menjalankan fungsi lambda. Yang pertama adalah melalui validasi dasar, dan nama atribut yang mengidentifikasinya disebut invocationSource. Ada dua nilai potensial untuk ini - DialogCodeHook dan FulfillmentCodeHook. Di sinilah fungsi Lambda ditentukan di Lex Bot.
Dropdown pertama adalah Validasi, dan memanggil fungsi lambda setiap kali bot dipanggil. Atribut yang diteruskannya disebut DialogCodeHook. Dropdown kedua adalah Pemenuhan, dan hanya dipanggil setelah slot wajib telah selesai, dan validasi dari panggilan awal selesai. Hal ini memungkinkan fungsinya berbeda, memungkinkan skalabilitas yang lebih baik dalam membangun bot.
Berikut adalah ikhtisar dari setiap fungsi yang sedang ditulis.
lambda.js - fungsi utama yang menangani validasi dasar untuk kueri, hanya bersumber dalam mode DialogCodeHook.
kalkulasi.js - penghitungan respons kalori sebenarnya dalam makanan ditangani oleh fungsi ini, dan bersumber dari FulfillmentCodeHook.
pizza.js - menangani maksud seputar penghitungan kalori dalam pizza, termasuk maksud - WhatPizzaTypes.
misc.js - menangani maksud sederhana seperti bantuan, perkenalan, dan detail lebih lanjut seputar makanan.
chinese.js - menangani maksud seputar makanan Cina, dan menggabungkan slot yang berbeda untuk membentuk makanan.
Fungsi inti dari bot ini adalah untuk dapat menjawab pertanyaan tentang berapa banyak kalori dalam makanan yang berbeda. Meskipun slot yang digunakan Lex berguna dalam melatih model NLU, slot tersebut tidak memiliki kemampuan untuk berfungsi sebagai file pencarian. Di situlah masuknya objek json yang disimpan di folder /src/data/.
Berikut adalah contoh formatnya.
[
{
" 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},
Fungsi lambda merujuk ke objek ini untuk merespons kueri yang berbeda, dan untuk menghitung konsumsi kalori bagi pengguna.
Setiap item makanan dapat diduplikasi untuk ejaan dan frasa berbeda yang digunakan untuk mengambil. Misalnya.
{ " 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},
Ada juga tabel pencarian seputar saus, dressing, dan penyesuaian item individual. Misalnya.
[
{
" dressingName " : " Ranch " ,
" calories " :200,
" carbs " :11,
" restaurantNames " :[ " McDonalds " ]
},
{
" dressingName " : " French " ,
" calories " :300,
" carbs " :22,
" restaurantNames " :[ " McDonalds " ]
},
Mengingat model NLU tidak memperbaiki ejaan yang diberikan oleh pengguna, fungsi Lambda bertanggung jawab untuk menangani bagian logika ini.
Mengelola slot khusus yang besar bisa jadi sulit, terutama jika datanya dinamis. Pencarian makanan utama memiliki beberapa ratus nilai unik di dalamnya, dan terus bertambah berdasarkan penggunaan pengguna. Proses pembuatan slot ini telah diotomatisasi, dan data untuk slot khusus diambil dari objek data food.json. Hal ini dilakukan melalui AWS CLI yang dapat memuatnya langsung dari baris perintah. Semua file terdapat di direktori [slots}(https://github.com/terrenjpeterson/kaloricounter/tree/master/src/slots) untuk referensi. Berikut langkah-langkah yang digunakan untuk membuat.
Sintaksnya terlihat seperti ini.
# 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
Selain itu, nilai checksum berasal dari penerapan slot khusus sebelumnya. Anda dapat menemukan checksum saat ini untuk sebuah slot dengan perintah get-slot-type.
# find the latest information about a custom slot
aws lex-models get-slot-type --name FoodOptions --slot-type-version ' $LATEST '
Kunci percakapan jangka panjang yang efektif antara pengguna dan bot adalah seputar pengelolaan konteks percakapan. Misalnya, dialog bisa berlangsung selama beberapa menit, dan memunculkan banyak maksud.
Salah satu upaya untuk memfasilitasi hal ini adalah dengan merancang alur percakapan. Pesan kesalahan tidak boleh terlalu mendadak, dan harus mengarahkan pengguna ke kueri alternatif. Niatnya juga harus meneruskan data satu sama lain. Hal ini dapat dicapai dengan menyimpan data sesi saat menyelesaikan suatu maksud. Hal ini memungkinkan maksud berikutnya mengambil informasi dan tidak mengharuskan pengguna mengulanginya pada setiap permintaan.
Pada contoh di atas, percakapan dimulai dengan pengguna menunjukkan di restoran mana mereka makan. Hal ini dipertahankan dalam sesi dengan maksud FoodTypeOptions. Dialog beralih ke detail makanan, tetapi nama restoran disimpan. Selain itu, respons awal mengenai jumlah kalori juga singkat, namun menawarkan penjelasan yang lebih detail jika pengguna mengatakan 'lebih detail'. Sekali lagi data disimpan dalam data sesi, dan diteruskan kembali sebagai bagian dari kerangka Lex. Berikut adalah contoh salah satu objeknya.
{
" 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 "
}
Fungsi lambda di bot ini sepenuhnya tanpa kewarganegaraan, sehingga data apa pun dari pemanggilan sebelumnya harus datang melalui objek permintaan.
Salah satu fitur di antarmuka pengguna chatbot utama (Messenger, Slack, dll.) adalah tombol. Ini mengurangi upaya pengguna dengan menyediakan serangkaian opsi seperti itu.
Setiap platform perpesanan memiliki penerapan pola ini masing-masing, dan inilah yang digunakan Messenger. Lex menangani terjemahan untuk memasukkan tombol ke dalam format yang benar, dan di dalam Lex, atribut responsiveCard perlu diberikan dengan rincian detail tombol.
Memodifikasi Lex dilakukan sepenuhnya melalui konsol. Fungsi lambda yang melayani logika bisnis dihosting di lambda AWS, dan diterapkan dari host EC2.
Skrip penerapan lengkapnya adalah /src/build.sh tetapi ikhtisar singkatnya dapat ditemukan dalam petunjuk berikut.
# 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
Proses ini diulangi untuk setiap fungsi lambda yang dipanggil oleh Lex. Hal ini termasuk memiliki setidaknya satu kondisi pengujian untuk setiap fungsi lambda guna memastikan bahwa penerapan dilakukan dengan benar.
Salah satu topik dalam desain bot adalah seputar kepribadian. Sesuatu yang perlu dipertimbangkan saat merancang maksud adalah pertanyaan apa saja yang mungkin diajukan pengguna. Ini harus mencakup pertanyaan di luar topik, seperti 'siapa namamu' atau respons emosional seperti 'oh-tidak' atau 'kamu payah'. Ini mudah untuk dikodekan - biasanya hanya berupa permintaan-respons sederhana tanpa melibatkan slot, dan cenderung membuat dialog lebih alami.
Sebagai contoh, berikut adalah respon singkat yang dikodekan dalam fungsi misc.js yang merespon jika seseorang menanyakan nama botnya. Dalam model, ucapan 'siapa namamu' menunjukkan maksud ini.
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 })) ;
}
Sebagai bagian dari upaya awal, saya mencoba mempublikasikan chatbot ini ke slack store. Sebagai bagian dari itu, saya perlu membangun situs web untuk dukungan publik terhadap aplikasi tersebut. Ini sedang dalam proses, dan disebut Caloricountbot.com. Itu di-host oleh s3, dan sumbernya terletak di folder /website.