Contor de calorii Chatbot

Acesta este un chatbot bazat pe Lex, care va calcula caloriile făcute de călătorii la diferite restaurante de fast-food. Este activat de pe un chat FB Messenger care poate fi accesat de pe pagina de Facebook sau prin intermediul aplicației Messenger de pe telefon.

Cuprins

Utilizarea modelelor NLU

Acest bot folosește AWS Lex - un serviciu care conține informații pentru a putea descifra cererile utilizatorilor și a declanșa intenții pe baza datelor furnizate în modele. Intențiile invocă apoi funcții lambda care conțin logică de afaceri specifică intenției.

github

În prezent, există multe intenții diferite în care sortează procesul NLU. Iată „funcțiile de bază” ale botului.

  • FoodTypeOptions (Exemplu de enunț - Care sunt opțiunile mele alimentare?)
  • GetCalories (Exemplu de enunț - Câte calorii într-un Big Mac?)
  • GetMexicanFoodCalories (Exemplu de enunț - Câte calorii într-un pui Burrito?)
  • GetNuggetsCalories (Exemplu de enunț - Câte calorii din 20 de pepite de pui?)
  • GetPizzaCalories (Exemplu de enunț - Câte calorii din 2 felii de pizza Pepperoni la Papa Johns?)
  • GetChineseCalories (Exemplu de enunț - Câte calorii într-un pui Kung Pao?)
  • GetChickenCalories (Exemplu de enunț - Câte calorii într-o bucată de pui de rețetă originală?)

Există, de asemenea, intenții care completează caracteristicile de bază.

  • MoreDetails (Exemplu de enunț - Mai multe detalii. Notă: acest lucru poate fi invocat numai după ce solicitările anterioare sunt făcute în conversație, deoarece citesc date din sesiune).
  • DailyIntakeAnalysis (Exemplu de enunț - analizați masa mea. Similar cu mai multe detalii, acest lucru folosește datele sesiunii, deci trebuie să urmați una dintre solicitările anterioare.
  • WhatPizzaTypes (Exemplu de enunț - Ce tipuri de pizza există?)
  • WhichRestaurants (Exemplu de enunț - Listă de restaurante.)
  • CalculateBMR (Exemplu de enunț - Care este aportul meu zilnic de calorii recomandat?)
  • GetCarbs (Exemplu de enunț - Câți carbohidrați din asta?)

Apoi, există intenții care formează „personalitatea” botului. Acestea au fost create pe baza utilizării reale a utilizatorilor și împiedică utilizarea mesajului de eroare generic pentru a răspunde.

  • EndConversation (intenție încorporată - folosește exemple de enunțuri AWS ca - Stop)
  • Introducere (Exemple de enunțuri - Bună ziua, Începeți, trimiteți un mesaj)
  • Mulțumesc (Exemple de enunțuri - Mulțumesc, la revedere, la revedere)
  • Complement (Exemple de enunțuri - Te iubesc)
  • Critic (Exemple de enunțuri - U suge)
  • Șoc (Exemple de enunțuri - wow, ouch)
  • MyName (Exemple de enunțuri - care este numele tău)
  • HelpRequest (intenție încorporată - folosește exemple de enunțuri AWS cum ar fi - Ajutor)
  • NewRestaurant (Exemplu de enunț - Restaurant nou. Aceasta șterge sesiunea.)

În cadrul fiecăruia dintre intenții, sunt furnizate exemple de enunțuri care construiesc sentențele potențiale pe care le poate furniza un utilizator. Valoarea slotului (adică Large Fry) este transmisă funcției lambda ca un atribut unic.

Puteți obține informații rezumative din AWS CLI executând următoarea comandă.

Este o combinație a exemplelor de enunțuri și sloturi care determină ce intenție vor invoca modelele NLU. Acestea sunt întreținute în Lex și sunt utilizate pentru instruirea modelelor.

În prezent, aici sunt sloturile personalizate care sunt utilizate de intenții.

Nu este necesar să fie specificat un element în slot pentru ca NLU să-i plaseze o valoare. Cu toate acestea, dacă datele sunt rare, se poate degrada modul în care NLU interpretează solicitările utilizatorului.

Mai multe sloturi într-o singură intenție

Utilizarea unui chatbot necesită o interacțiune naturală cu un utilizator. Un concept cheie este acela de a încorpora mai multe sloturi într-o singură intenție. De exemplu, un utilizator ar putea întreba „Câte calorii într-un Big Mac, cartofi prăjiți și o Cola?” Este vorba de trei elemente diferite care trebuie analizate fiecare. În cadrul acestui chatbot, procesarea principală are multe sloturi diferite care se mapează în intenții. De exemplu, aici sunt sloturile care se încorporează în intenția GetCalories.

Există câteva elemente de menționat în acest sens.

În cererea de exemplu de mai sus, modelele NLU ar analiza datele din enunț în trei sloturi diferite (Alimente, Extra și Băutură).

Ordinea sloturilor nu contează pentru analiză, dar determină care ar fi următorul răspuns (slotul 1 - La ce restaurant sunteți?)

Există două sloturi care nu sunt necesare în acest scop - Ketchup și PacketsKetchup. Aceste informații opționale sunt solicitate dacă cartofii prăjiți sunt solicitați ca element secundar. Acest lucru este condus de codul din funcția Lambda care este invocat în cârligul codului de validare.

Logica regulilor în lambda

Toată logica formulării răspunsurilor la diferite intenții este procesată într-o serie de funcții lambda. Funcția lambda pe care o invocăm este gestionată în cadrul Lex și setată la nivelul intenției. Aceasta permite construirea modularității în cadrul aplicației, menținând funcțiile ușoare.

Există două puncte diferite în Lex care pot invoca o funcție lambda. Primul este prin validarea de bază, iar numele atributului care îl identifică se numește invocationSource. Există două valori potențiale pentru acest lucru - DialogCodeHook și FulfillmentCodeHook. Aici sunt specificate aceste funcții Lambda în Lex Bot.

Primul meniu derulant este Validarea și apelează funcția lambda de fiecare dată când este apelat botul. Atributul pe care îl trece se numește DialogCodeHook. Al doilea meniu derulant este Îndeplinirea și este apelat numai după ce sloturile obligatorii au fost finalizate și validarea de la apelul inițial este finalizată. Acest lucru permite ca funcțiile să fie diferite, permițând o scalabilitate mai bună în construirea botului.

Iată o prezentare generală a fiecărei funcții scrise în prezent.

lambda.js - funcția principală care gestionează validarea de bază pentru interogări, obținută numai în modul DialogCodeHook.

calculate.js - calcularea răspunsului pentru caloriile reale dintr-o masă este gestionată de această funcție și este obținută de un FulfillmentCodeHook.

pizza.js - tratează intențiile privind calcularea caloriilor dintr-o pizza, inclusiv intenția - WhatPizzaTypes.

misc.js - gestionează intenții simple, cum ar fi ajutorul, introducerea și mai multe detalii despre o masă.

chinese.js - tratează intențiile în jurul mâncării chinezești și cuplează diferitele sloturi împreună pentru a forma o masă.

Tabelele de căutare a datelor

Funcționalitatea de bază a acestui bot este să puteți răspunde la întrebări despre câte calorii sunt în diferite mese. Deși sloturile pe care le folosește Lex sunt utile în instruirea modelelor NLU, acestea nu au capacitatea de a servi ca fișiere de căutare. Acolo intră obiectele json care sunt stocate în folderul/src/data /.

Iată un exemplu de format.

Funcțiile lambda se referă la aceste obiecte pentru a răspunde la diferite întrebări și pentru a calcula consumul de calorii pentru utilizator.

Fiecare produs alimentar poate fi duplicat pentru diferite ortografii și fraze utilizate pentru recuperare. De exemplu.

Există, de asemenea, tabele de căutare în jurul sosurilor, pansamentelor și ajustărilor individuale ale articolelor. De exemplu.

Având în vedere că modelele NLU nu corectează ortografia furnizată de utilizator, depinde de funcțiile Lambda să se ocupe de această parte a logicii.

Sloturi personalizate mari

Gestionarea sloturilor personalizate mari poate fi dificilă, mai ales dacă datele sunt dinamice. Căutarea principală a alimentelor conține câteva sute de valori unice și crește în funcție de utilizarea utilizatorilor. Procesul de creare a acestui slot a fost automatizat, iar datele pentru slotul personalizat sunt preluate din obiectul de date foods.json. Acest lucru se face prin AWS CLI care le poate încărca direct de pe linia de comandă. Toate fișierele sunt conținute în directorul [slots> (https://github.com/terrenjpeterson/caloriecounter/tree/master/src/slots) pentru referință. Iată pașii utilizați pentru a crea.

  1. Obiectul de date foods.json este trecut la o funcție lambda numită convertFoodsObjForSlot.
  2. Funcția sortează datele, elimină duplicatele, apoi datele sunt formatate într-o matrice simplă cu doar numele de intrare.
  3. Matricea este returnată și apoi transmisă în AWS CLI utilizând comanda put-slot-type.
  4. Modelul este apoi reconstruit manual prin consolă și implementat la fel ca orice altă activitate de formare.

Sintaxa arată astfel.

De asemenea, valoarea sumei de control provine de la implementarea prealabilă a slotului personalizat. Puteți găsi suma de control curentă pentru un slot prin comanda get-slot-type.

Partajarea datelor despre sesiune între intenții

Cheia conversațiilor eficiente de lungă durată între un utilizator și un robot este gestionarea contextului conversației. De exemplu, un dialog ar putea continua câteva minute și ar putea invoca multe intenții.

O parte din facilitarea acestui lucru este proiectarea unui flux al conversației. Mesajele de eroare nu ar trebui să fie prea bruste și ar trebui să conducă utilizatorul la o interogare alternativă. Intențiile ar trebui, de asemenea, să transmită date între ele. Acest lucru poate fi realizat prin salvarea datelor sesiunii la finalizarea unei intenții. Aceasta permite următoarea intenție de a prelua informațiile și nu impune utilizatorului să le repete cu fiecare cerere.

În exemplul de mai sus, conversația începe cu utilizatorul care indică la ce restaurant mănâncă. Acest lucru este persistat în sesiune de intenția FoodTypeOptions. Dialogul trece la detaliile mesei, dar numele restaurantului este salvat. De asemenea, răspunsul inițial la numărul de calorii este scurt, dar oferă o explicație mai detaliată dacă utilizatorul spune „mai multe detalii”. Din nou, datele sunt stocate în datele sesiunii și sunt transmise înapoi ca parte a cadrului Lex. Iată un exemplu al unuia dintre obiecte.

Funcțiile lambda din acest bot sunt complet fără stare, astfel încât orice date din invocații anterioare trebuie să vină prin obiectul cererii.

Crearea butoanelor în interfața cu utilizatorul

Una dintre caracteristicile principalelor interfețe de utilizator chatbot (Messenger, Slack etc.) sunt butoanele. Acestea reduc efortul utilizatorului oferind o serie de opțiuni de genul acesta.

Fiecare platformă de mesagerie are propria implementare a acestui model și iată ce folosește Messenger. Lex gestionează traducerea pentru a obține butoanele în formatul corect, iar în Lex, atributul responseCard trebuie să fie furnizat cu specificul detaliilor butonului.

Modificarea Lex se face complet prin consolă. Funcțiile lambda care servesc logicii de afaceri sunt găzduite în AWS lambda și sunt implementate de la o gazdă EC2.

Scriptul complet de implementare este /src/build.sh, dar o prezentare generală rapidă poate fi găsită în următoarele instrucțiuni.

  1. Creați un fișier zip pe gazdă care acționează ca server de compilare. De la serverul de compilare sunt manipulate atât codul sursă, cât și fișierele de date. Fișierele de date sunt apoi citite local și, ori de câte ori se schimbă, se creează o nouă implementare.
  2. Încărcați fișierul zip într-o bucket s3 folosind comenzile AWS CLI corespunzătoare.
  3. Actualizați funcția lambda existentă cu noul pachet și, utilizând comanda AWS CLI, furnizați locația fișierului zip care conține pachetul de construire.
  4. Executați un test al funcției lambda direct cu date de eșantion valide. Obiectul de răspuns este returnat și scris în consolă, precum și un fișier local.

Acest proces se repetă pentru fiecare dintre funcțiile lambda care sunt apelate de Lex. Aceasta include cel puțin o condiție de testare pentru fiecare funcție lambda pentru a se asigura că implementarea a fost efectuată corect.

Adăugați personalitate la bot

Unul dintre subiectele în proiectarea botului este acela de a avea personalitate. Ceva de luat în considerare la proiectarea intențiilor este care sunt toate întrebările posibile pe care le poate pune un utilizator. Aceasta ar trebui să includă întrebări în afara subiectului, cum ar fi „cum te cheamă” sau răspunsuri emoționale, cum ar fi „oh-nu” sau „tu suge”. Acestea sunt ușor de codat - de obicei, doar o simplă solicitare-răspuns fără sloturi implicate și tind să facă dialogurile mai naturale.

Pentru un exemplu, iată un scurt răspuns codat în funcția misc.js care răspunde dacă cineva întreabă care este numele botului. În modele, o enunțare a „care este numele tău” rezolvă această intenție.

Site în desfășurare

Ca parte a efortului inițial, am încercat să public acest chatbot în magazinul slack. Ca parte a acestui lucru, am avut nevoie să construiesc un site web pentru sprijinul public al aplicației. Este o lucrare în curs și numită caloriecountbot.com. Este găzduit de s3, iar sursa se află în folderul/website.

Despre

Chatbot bazat pe AWS Lex care calculează caloriile pe baza diferitelor restaurante de tip fast-food. Aceasta a fost o intrare pentru o provocare de codare pe DevPost și este utilizată activ pe Facebook Messenger. Lista de probleme este gestionată în mod activ ca defecte sau îmbunătățiri care sunt găsite de utilizarea din lumea reală.