Today we’ll build an automated AI receptionist. Know a small business hotel owner? Build this human-like conversational AI app, test it with them and deploy. Hook your friends up, they will probably be so thankful as to give you some free hotel stays.
The best part is that you’ll build this app in less than 2 hours. The app creation process with Dasha AI is super intuitive, even a non-developer (or a citizen developer like me) can do it.
Hotel front desk AI: why are we building this thing?
Creating a conversational AI hotel front desk receptionist
Embedded content: https://youtu.be/2Glp_HC-VHcStep 1: Prep work for creating an AI front desk receptionist app
Step 2: Your conversational AI workplace setup
Step 3: Get to know what you’ll use to create an AI front desk receptionist
Step 4: Build your conversational AI app
// Import the commonReactions library so that you don't have to worry about coding the pre-programmed replies import "commonReactions/all.dsl";
context { // Declare the input variable - phone. It's your hotel room phone number and it will be used at the start of the conversation. input phone: string; output new_time: string=""; output new_day: string=""; // Storage variables. You'll be referring to them across the code. food: {[x:string]:string;}[] = []; pizza: {[x:string]:string;}[]?=null; appetizers: {[x:string]:string;}[]?=null; main_dishes: {[x:string]:string;}[]?=null; drinks: {[x:string]:string;}[] = []; forgotten_thing: {[x:string]:string;}[]=[]; }
// A start node that always has to be written out. Here we provide instructions to the AI app on how to behave once the connection is established. start node root { do { #connectSafe($phone); // Establishing a safe connection to the hotel room's phone. #waitForSpeech(1000); // Waiting for 1 second to say the welcome message or to let the hotel guest say something #sayText("Hi, this is Butterfly Resort Hotel reception. How may I help you?"); // Welcome message wait *; // Waiting for the user to reply } transitions // Here you give directions to which nodes the conversation will go { // Transitions could be written out here, in which case you'd need to write out corresponding nodes. Otherwise, the conversation will go to a digression triggered by specific intent. In this case, we are routing the conversation with digressions. } }
digression cleaning // Digressions can be triggered at any moment of the conversation. { conditions {on #messageHasIntent("cleaning");} // This digression is triggered when a person says something that is related to the room cleaning service. The intents are written out in the data.json file. do // Once this digression is triggered, here's what Dasha AI will do { #sayText("Absolutely, someone will come up to your room in approximately 10 minutes. Is there anything else I can help you with?"); wait *; // Waiting for the person to either end the call, proceed to ask more questions, etc. The AI doesn't say anything before hears a human speak. } }
digression order { conditions {on #messageHasIntent("order");} do { #sayText("Sure thing. What would you like to order?"); wait *; } transitions { menu: goto menu on #messageHasIntent("menu") or #messageHasIntent("unsure"); // In this case we expect the hotel guest not knowing what's on the hotel restaurant's menu, therefore we will make a transition to the menu node } }
node menu { // Note that you don't write conditions for nodes (compared to digressions), because a node always has another node (or digression) directly leading into it. do { #sayText("We have various appetizers, pizza, main dishes and drinks. What would you like to get?"); wait *; } transitions // 4 options of different types of food/drinks. { appetizers: goto appetizers on #messageHasIntent("appetizers"); pizza: goto pizza on #messageHasIntent("pizza"); main_dishes: goto main_dishes on #messageHasIntent("main_dishes"); drinks: goto drinks on #messageHasIntent("drinks"); } }
node appetizers { do { #sayText("We've got fried calamari, french fries, spring salad, and a soup of the day. What of these would you like to order?"); wait *; } transitions { confirm_food_order: goto confirm_food_order on #messageHasData("food"); // We have an entity here - food. It's written out in the data.json file under entities. } onexit // Specifies an action that Dasha AI should take, as it exits the node. The action must be mapped to a transition { confirm_food_order: do { set $appetizers = #messageGetData("food", { value: true }); // Dasha AI will remember what has been ordered and will update the "food" variable. "value: true" will return all results that have a value field } } } digression appetizers { conditions {on #messageHasIntent("pizza_kind");} do { #sayText("We've got fried calamari, french fries, spring salad, and a soup of the day. What of these would you like to order?"); wait *; } transitions { confirm_food_order: goto confirm_food_order on #messageHasData("food"); } onexit { confirm_food_order: do { set $appetizers = #messageGetData("food", { value: true }); } } }
node confirm_food_order { do { var sentence = "Perfect. Let me just make sure I got that right. You want "; set $food = #messageGetData("food"); for (var item in $food) { set sentence = sentence + (item.value ?? " and "); // In case the guest decides to order multiple items of food } set sentence = sentence + ". Is that right?"; #sayText(sentence); wait *; } transitions { order_confirmed: goto order_confirmed on #messageHasIntent("yes"); repeat_order: goto repeat_order on #messageHasIntent("no"); } }
node order_confirmed { do { #sayText("Your order will be ready in 15 minutes. We'll bring it straight to your room! Anything else I can help you with? "); wait *; } transitions { can_help: goto can_help on #messageHasIntent("yes"); bye: goto bye on #messageHasIntent("no"); } } node repeat_order { do { #sayText("Let's try this again. What can I get for you today?"); wait *; } transitions { confirm_food_order: goto confirm_food_order on #messageHasData("food"); confirm_drinks: goto confirm_drinks on #messageHasData("drinks"); } }
node drinks { do { #sayText("We have orange juice, Sprite, and vanilla milkshakes. What would you like to get?"); wait *; } transitions { confirm_drinks: goto confirm_drinks on #messageHasData("drinks"); } onexit { confirm_drinks: do { set $drinks = #messageGetData("drinks"); } } } digression drinks { conditions {on #messageHasIntent("drinks");} do { #sayText("We have orange juice, Sprite, and vanilla milkshakes. What would you like to get?"); wait *; } transitions { confirm_drinks: goto confirm_drinks on #messageHasData("drinks"); } onexit { confirm_drinks: do { set $drinks = #messageGetData("drinks"); } } }
"drinks": { "open_set": false, "values": [ { "value": "orange juice", "synonyms": ["OJ", "juice", "orange drink"] }, { "value": "vanilla milkshake", "synonyms": ["milkshake", "vanilla drink", "vanilla one"] }, { "value": "Sprite", "synonyms": ["soda"] } ]
"entities": { "food": { "open_set": true, "values": [ { "value": "Pepperoni", "synonyms": ["pepperoni", "pepperoni pizza", "a pepperoni", "the pepperoni pizza"] }, { "value": "Margherita", "synonyms": ["Margherita pizza", "a margherita pizza", "a margherita", "margherita"] }, { "value": "Veggie", "synonyms": ["vegan pizza", "vegan", "vegans", "vegeterian", "with vegetables", "without meat"] }, { "value": "fried calamari", "synonyms": ["calamari", "the fried calamari", "the calamari"] }, { "value": "french fries", "synonyms": ["fries", "the french fries", "the fries"] }, { "value": "spring salad", "synonyms": ["the salad", "a salad", "spring one"] }, { "value": "soup of the day", "synonyms": ["the soup", "soup", "whatever soup", "a soup"] }, { "value": "mushroom tortellini", "synonyms": ["tortellini", "the tortellini", "the mushroom thingy"] }, { "value": "baked honey mustard chicken", "synonyms": ["the honey mastard one", "honey mustard", "honey one", "chicken", "baked chicken", "baked honey chicken", "baked mustard chicken", "mustard one"] }, { "value": "pasta carbonara", "synonyms": ["pasta", "carbonara"] }, { "value": "vietnamise porkchops", "synonyms": ["vietnamese dish", "pork", "porkchops"] } ], "includes": [ "I'd like a (pepperoni)[food] please", "I'll take a (veggie pizza)[food] now", "I'll like to get a (margherita)[food]", "I'll like a (margherita)[food]", "I'll have a (Pepperoni)[food] please", "I'll order the (soup of the day)[food]", "I'll have some (french fries)[food]", "I'll order a (spring salad)[food]", "I'll take (french fries)[food]", "I'll take the (mushroom tortellini)[food]", "I'll get the (muchroom thingy)[food]", "I'll take the (soup)[food]", "I'll take the (honey one)[food]", "I'll take the (huney mastard)[food]", "order the (pasta)[food]", "get a (pasta carbonara)[food]", "take that (vietnamese dish)[food]" ] },
digression forgot_sth { conditions {on #messageHasIntent("forgot_sth");} do { #sayText("That happens, don't worry. I'm sure we have whatever you need. What did you forget to bring?"); wait *; } transitions { forgotten_thing: goto forgotten_thing on #messageHasData("forgotten_thing"); } } node forgotten_thing { do { var sentence = "Okay, we're about to bring "; set $forgotten_thing = #messageGetData("forgotten_thing"); for (var item in $forgotten_thing) { set sentence = sentence + (item.value ?? "and"); } set sentence = sentence + " to you. Did I get that right?"; #sayText(sentence); wait *; } transitions { confirm_forgotten: goto confirm_forgotten on #messageHasIntent("yes"); repeat_forgotten: goto repeat_forgotten on #messageHasIntent("no"); } } node confirm_forgotten { do { #sayText("We're gonna bring it to to your room in 5 to 10 minutes. May I help with any other questions?"); wait *; } transitions { can_help: goto can_help on #messageHasIntent("yes"); repeat_forgotten: goto repeat_forgotten on #messageHasIntent("no"); } } node repeat_forgotten { do { #sayText("Let's try this again. What was it that we can bring you?"); wait *; } transitions { forgotten_thing: goto forgotten_thing on #messageHasData("forgotten_thing"); } onexit { forgotten_thing: do { set $forgotten_thing = #messageGetData("forgotten_thing"); } } }
Taking a request to take clothes to the dry cleaner shop
digression dry_cleaning { conditions {on #messageHasIntent("dry_cleaning");} do { #sayText("Absolutely, we'll pick your clothes up soon and send it to the dry cleaning service. We'll bring your clothes back to you in 1 day. Is there anything else I can help you with?"); wait *; } }
Navigating the hotel guests on what to do and what to see
digression vicinity { conditions {on #messageHasIntent("vicinity");} do { #sayText("There are parks, cinemas, restauntants and an amusement park in the area. What interests you the most at this moment?"); wait *; } } digression park { conditions {on #messageHasIntent("park");} do { #sayText("We have two parks nearby: sunrise valley park and oak tree park, both are super beautiful and open twenty four seven. Both are located right outside the hotel within a two minute walking distance. Is there anything else I can tell you about?"); wait *; } } digression cinemas { conditions {on #messageHasIntent("cinemas");} do { #sayText("There’s ABA cinema that's located just 5 minutes away to the south of the hotel. It's open from 9 AM to 1 AM. Is there anything else I can tell you about?"); wait *; } } digression restaurants { conditions {on #messageHasIntent("restaurants");} do { #sayText("The 2 amazing restaurants around are Kimchi One restaurant, which is open from 9 AM to 9 PM and Bonjorno restaurant, open from 8 AM to 11 PM. Is there anything else I can help with?"); wait *; } } digression amusement_park { conditions {on #messageHasIntent("amusement_park");} do { #sayText("There's an amusement park which is within a 15 minute drive. You can take the free shuttle that's located right outside the hotel entrance to get there. But make sure to go there within its working hours, it closes at 4pm these days. Is there anything else I can help with?"); wait *; } }
Changing the checkout day
node check_out_diff_day { do { #sayText("What day would you like to check out?"); wait *; } transitions { new_checkout_day: goto new_checkout_day on #messageHasData("day_of_week"); } onexit { new_checkout_day: do { set $new_day = #messageGetData("day_of_week")[0]?.value??""; } } } digression check_out_diff_day { conditions {on #messageHasIntent("check_out_diff_day");} do { #sayText("What day would you like to check out?"); wait *; } transitions { new_checkout_day: goto new_checkout_day on #messageHasData("day_of_week"); } onexit { new_checkout_day: do { set $new_day = #messageGetData("day_of_week")[0]?.value??""; } } } node new_checkout_day { do { #sayText("Just changed your checkout day to " + $new_day + ". Is that right?"); wait *; } transitions { can_help: goto can_help on #messageHasIntent("yes"); repeat_new_checkout_day: goto repeat_new_checkout_day on #messageHasIntent("no"); } } node repeat_new_checkout_day { do { #sayText("Let's do it one more time. What day would you like to check out?"); wait *; } transitions { new_checkout_day: goto check_out_diff_day on #messageHasData("day_of_week"); } onexit { new_checkout_day: do { set $new_day = #messageGetData("day_of_week")[0]?.value??""; } } }
Changing the checkout hour
node check_out_diff_hour { do { #sayText("What time would you like to check out?"); wait *; } transitions { new_checkout_hour: goto new_checkout_hour on #messageHasData("time"); } onexit { new_checkout_hour: do { set $new_time = #messageGetData("time")[0]?.value??""; } } } digression check_out_diff_hour { conditions {on #messageHasIntent("check_out_diff_hour");} do { #sayText("What time would you like to check out?"); wait *; } transitions { new_checkout_hour: goto new_checkout_hour on #messageHasData("time"); } onexit { new_checkout_hour: do { set $new_time = #messageGetData("time")[0]?.value??""; } } } node new_checkout_hour { do { #sayText("You got it. I just changed your checkout time to " + $new_time + ". Did I get that correctly?"); wait *; } transitions { can_help: goto can_help on #messageHasIntent("yes"); repeat_new_checkout_hour: goto repeat_new_checkout_hour on #messageHasIntent("no"); } } node repeat_new_checkout_hour { do { #sayText("Let's do it one more time. What hour would you like to check out?"); wait *; } transitions { check_out_diff_hour: goto check_out_diff_hour on #messageHasData("time"); } onexit { check_out_diff_hour: do { set $new_time = #messageGetData("time")[0]?.value??""; } } }
Answering questions about the things to do inside of the hotel
digression hotel_restautant { conditions {on #messageHasIntent("hotel_restautant");} do { #sayText("We do have a restaurant on the first floor. It's open from 7am to 11pm and we're looking forward to seeing you there. May I help with anything else?"); wait *; } }