DEV Community

Cover image for Take order confirmation to a new level with conversational AI
Dasha
Dasha

Posted on

Take order confirmation to a new level with conversational AI

Today we’ll be taking a look at how to create a conversational AI app that automates order confirmation. While this app will be targeted towards confirming a food delivery order, yet the logic of this app can apply to create virtually any order confirmation app. Let’s get started!

Prep steps to create conversational AI apps with Dasha

In order to get access to the community of like-minded developers, have all your questions answered, and get help with app development the moment you need it, join Dasha Developer Community.

Once done, you’ll need to download the latest versions of:

Open VSCode, go to extensions and download the Dasha Studio extension. You use the studio to create your conversational script, it gives you syntax analysis and highlights the code. There's also a visual graph editor and it has a GUI tool for debugging.

All done with the downloads!

Now you can go ahead and download Dasha Blank Slate app source code and use it as a base to write your code. You can also refer to the source code of this order confirmation conversational AI app* that you can download here.

You would want to install the latest version of Dasha CLI. Do that by opening the Terminal in VSCode and running this command:

npm i -g "@dasha.ai/cli"
npm i

You could also run a live chat at any moment of time with the following command:

npm start chat (text chat)
npm start your_phone_number (voice chat. Instead of “your_phone_number” type the number of your phone)

With these commands, you’ll be able to converse with the AI in text form. This will not only help you test the conversational flow but also gauge whether there are any errors in the code.

Get to know the files you’ll use to create human-like conversational AI apps

There are 3 main files you need to know about and use:

  • main.dsl -- here you’ll write DashaScript Language code to create the workflow of your conversational AI app.

  • data.json -- you will set the intents and entities (/NER/Named Entity Recognition) in this file. The neural network will use intents and entities you’ll create to learn.

  • index.js -- a NodeJS file that launches the Dasha SDK. You’ll be adding any external functions you deem necessary once adapting the code to your company’s needs. External functions are needed to process data in JavaScript or to get or push data from external APIs. For example, you may need to process data, get access to databases or APIs or use it for any other purposes.

Create your order confirmation conversational AI app!

Off to creating your 2-in-1 ai food delivery and order confirmation app!

Start with importing the common library. It provides all the pre-programmed replies to common digressions such as “wait”, “are you a robot?”, etc.

// Import the commonReactions library so that you don't have to worry about coding the pre-programmed replies
import "commonReactions/all.dsl";
Enter fullscreen mode Exit fullscreen mode

Now you want to establish the context. Here you’ll write the variables, both input (the ones available at the start of the conversation) and output (the variables AI will receive, store and use throughout the conversation).

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;
// Storage variables. You'll be referring to them across the code. 
    appetizers: string="";
    drinks: string="";
    new_burger: string="";
    street: string="";
    house_num: string="";
}
Enter fullscreen mode Exit fullscreen mode

Once you’ve set the variables, write out the start node named root. In it, under the do command, you’ll let the AI know that it needs to connect to the user’s phone, wait for 1 second, and then say some kind of a welcome message and wait for the reply (wait *;).

Once the user says something, the AI will go to the next node. Under transitions you can either write directions to the specified nodes, or leave it blank in case you want the transitions to be not to any of the nodes, but to one of the digressions. In this case, we have next: goto order_confirmation_start on true; -- this means that the transition will happen despite what the user says.

// A start node that always has to be written out. Here we declare actions to be performed in the node. 
start node root
{
    do
    {
        #connectSafe($phone); // Establishing a safe connection to the user's phone.
        #waitForSpeech(1000); // Waiting for 1 second to say the welcome message or to let the user say something
        #sayText("Hi, this is Dasha, I'm calling to verify some informaton regarding your order with ABC Burgers."); // Welcome message
        wait *; // Wating for the user to reply
    }
    transitions // Here you give directions to which nodes the conversation will go
    {
        next: goto order_confirmation_start on true;
    }
}
Enter fullscreen mode Exit fullscreen mode

As we programmed the AI to go to node order_confirmation_start, let’s write it out:

node order_confirmation_start
{
    do 
    {   
        #sayText("Yeah, hi, so I see that you've ordered a cheeseburger to be delivered to 78 Washington Road. Do you want to change anything about your order?"); 
        wait*;
    }
    transitions
    {
        payment_method: goto payment_method on #messageHasIntent("no");
        edit_new_order: goto edit_new_order on #messageHasIntent("yes");
    }
}
Enter fullscreen mode Exit fullscreen mode

Note that after #sayText we wrote a random order to a random address. However, you should create an external function (you’ll be doing that in index.js file as we’ve discussed above) and connect it to your internal ordering system, that will pull the information on the order and the delivery address of the user.

Considering that the user knows the menu and wants to change the burger they are ordering, let’s write out the corresponding node and digression. The reason we should write out both is that we’ll be referring to this node in another node’s transition, and the digression will be there to get triggered at any point of the conversation should there be a need for it.

digression change_order_burger
{
    conditions {on #messageHasData("burger_kind");}
    do 
    {   
        set $new_burger = #messageGetData("burger_kind")[0]?.value??"";
        #sayText("Perfect. I've added " + $new_burger + " to your order. Would you like anything else?"); 
        wait *;
    }
    transitions
    {
        edit_new_order: goto edit_new_order on #messageHasIntent("yes") or #messageHasIntent("order_sth_else");
    }
}

node change_order_burger
{
    do 
    {   
        set $new_burger = #messageGetData("burger_kind")[0]?.value??"";
        #sayText("Perfect. I've added " + $new_burger + " to your order. Would you like anything else?"); 
        wait *;
    }
    transitions
    {
        edit_new_order: goto edit_new_order on #messageHasIntent("yes") or #messageHasIntent("order_sth_else");
    }
}
Enter fullscreen mode Exit fullscreen mode

At this point, let’s write the node we mention in the transition (+ a corresponding digression):

digression edit_new_order
{
    conditions {on #messageHasIntent("order_sth_else");}
    do
    {
        #sayText("What can I get for you?"); 
        wait *; 
    }
}

node edit_new_order
{
    do
    {
        #sayText("What can I get for you?"); 
        wait *; 
    }
    transitions
    {

    }
}
Enter fullscreen mode Exit fullscreen mode

This is a simple, yet multifunctional node in a way since we’ll be transferring to it in multiple nodes.

Another similar digression and node are the following:

node nvm
{
        do
    {
        #sayText("Is there anything else I can help you with?"); 
        wait *;
    }
    transitions
    {
        payment_method: goto payment_method on #messageHasIntent("no");
        edit_new_order: goto edit_new_order on #messageHasIntent("yes");
    }
}

digression nvm
{
    conditions {on #messageHasIntent("nvm");}
    do
    {
        #sayText("Okay! How may I help you?"); 
        wait *; 
    }
}
Enter fullscreen mode Exit fullscreen mode

We’ll also have a chance to refer to them in other nodes.

Let’s write a digression for a case when a person asks about the burger menu after deciding to change the order:

digression burgers_available
{
    conditions {on #messageHasIntent("burgers_available");}
    do 
    {
        #sayText("We've got cheeseburger, hawaiian burger, buffalo chicken burger, creamy mushroom burger, beef burger and barbeque burger. Which one would you like?"); 
        wait*;
    }
    transitions
    {
        change_order_burger: goto change_order_burger on #messageHasData("burger_kind");
    }
}
Enter fullscreen mode Exit fullscreen mode

Pretty simple!

Now, what if the user wants to change the delivery address? Let’s program the conversational AI app to be able to deal with this case scenario.

There could be 4 different paths here. Either the user states they want to change the address without specifying it, or they name the new street, or the new building number, or the full address. We should write down a digression for each of these scenarios as they can pop up at any moment during the conversation:

digression different_address
{
    conditions {on #messageHasIntent("different_address");}
    do
    {
        #sayText("Sounds good, could you tell me the building number and the street name, please?"); 
        wait *; 
    }
}

digression change_street
{
    conditions {on #messageHasIntent("change_street");}
    do 
    {
        set $street = #messageGetData("street")[0]?.value??"";
        #sayText("Okay, I changed the street to " + $street + " . Is there anything else you'd like to change?"); 
        wait *;
    }
    transitions
    {
        edit_new_order: goto edit_new_order on #messageHasIntent("yes") or #messageHasIntent("order_sth_else");
        review_full_order: goto review_full_order on #messageHasIntent("no");
    }
}

digression change_house_num
{
    conditions {on #messageHasIntent("change_house_num");}
    do 
    {
        set $house_num = #messageGetData("house_num")[0]?.value??"";
        #sayText("Gotcha, I changed the building number to " + $house_num + " . Is there anything else you'd like to change?"); 
        wait *;
    }
    transitions
    {
        edit_new_order: goto edit_new_order on #messageHasIntent("yes") or #messageHasIntent("order_sth_else");
        review_full_order: goto review_full_order on #messageHasIntent("no");
    }
}

digression change_address
{
    conditions {on #messageHasData("house_num") and #messageHasData("street");}
    do 
    {
        set $street = #messageGetData("street")[0]?.value??"";
        set $house_num = #messageGetData("house_num")[0]?.value??"";
        #sayText("Okay, changed the delivery address to " + $house_num + " " + $street + ". Is there anything else you'd like to change?"); 
        wait *;
    }
    transitions
    {
        edit_new_order: goto edit_new_order on #messageHasIntent("yes") or #messageHasIntent("order_sth_else");
        review_full_order: goto review_full_order on #messageHasIntent("no");
    }
}
Enter fullscreen mode Exit fullscreen mode

Take a look at the digression change_street the line under the do command: set $street = #messageGetData("street")[0]?.value??"";. You might recognize $street from the content that we’ve established right off the bat. This line lets the AI store the variable $street and use it throughout the chat.

Note that we can store multiple variables under the do section as seen under change_address.

We’ll use the stored variables right in the digressions to provide feedback to the user, letting them know we’ve understood them correctly and make some changes if we didn’t.

Now, let’s consider the case when the user decides to edit their order by ordering something extra that’s on our menu. Appetizers, for instance. Remember that the user might know the menu and say exactly what they want to order, or they might ask what you have on the menu appetizers-wise:

digression appetizers
{
    conditions {on #messageHasIntent("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_appetizers: goto confirm_appetizers on #messageHasData("appetizers");
    }
     onexit
    {
        confirm_appetizers: do {
        set $appetizers =  #messageGetData("appetizers", { value: true });
       }
    }
}
node confirm_appetizers
{
    do
    {
        var sentence = "Perfect. I've added ";
        set $appetizers = #messageGetData("appetizers");
        for (var item in $appetizers) {
            set sentence = sentence + (item.value ?? " and ");
        }
        set sentence = sentence + " to your order. Is there anything else you'd like?";
        #sayText(sentence); 
        wait *;
    }
     transitions 
    {
        edit_new_order: goto edit_new_order on #messageHasIntent("yes") or #messageHasIntent("drinks");
        confirm_drinks: goto confirm_drinks on #messageHasData("drinks");
        review_full_order: goto review_full_order on #messageHasIntent("no");
    }
}
Enter fullscreen mode Exit fullscreen mode

The same thing goes for the drinks menu:

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", { value: true });
       }
    }
}

node confirm_drinks
{
    do
    {
        var sentence = "Noted, I added ";
        set $drinks = #messageGetData("drinks");
        for (var item in $drinks) {
            set sentence = sentence + (item.value ?? " and "); // In case the guest desides to order multiple items of food
        }
        set sentence = sentence + " to your order. Anything else you'd like to order?";
        #sayText(sentence); 
        wait *;
    }
     transitions 
    {
        edit_new_order: goto edit_new_order on #messageHasIntent("yes") or #messageHasIntent("appetizers");
        confirm_appetizers: goto confirm_appetizers on #messageHasData("appetizers");
        review_full_order: goto review_full_order on #messageHasIntent("no");
    }
}
Enter fullscreen mode Exit fullscreen mode

Now that we’re done changing the order, we should provide the user with the final confirmation:

node review_full_order
{
    do
    {
        var sentence = "To review your order, you want to get ";
        for (var item in $new_burger) {
            set sentence = sentence + (item.value ?? "") + (", ");
        }
        for (var item in $appetizers) {
            set sentence = sentence + (item.value ?? "") + (", and ");
        }
        for (var item in $drinks) {
            set sentence = sentence + (item.value ?? "");
        }
        set sentence = sentence + ". Would you like anything else?"; 
        #sayText(sentence); 
        wait *;
    }
     transitions 
    {
        payment_method: goto payment_method on #messageHasIntent("no");
        edit_new_order: goto edit_new_order on #messageHasIntent("yes");
    }
}
Enter fullscreen mode Exit fullscreen mode

Here we write out the for statements to account for multiple food/drink items (for example, if the user says they want both calamari and fries). The + (", "); and + (", and "); so that the multiple variables are separated when the text is spoken (fries, Hawaiian burger, and Sprite vs friedHawaiian burgerSprite).

Now, a couple of simple nodes will let the AI know it needs to ask about the payment method:

node payment_method
{
    do
    {
        #sayText("Gotcha. Now, would you be paying with cash or by card?");
        wait *;
    }
     transitions 
    {
        with_cash: goto with_cash on #messageHasIntent("cash");
        by_card: goto by_card on #messageHasIntent("card");
    }
}

node with_cash
{
    do
    {
        #sayText("Sounds good, with cash it is. Your order will be ready in 15 minutes. Thank you for your order! Bye bye!");
        exit;
    }
}

node by_card
{
    do
    {
        #sayText("Sounds good, by card it is. Your order will be ready in 15 minutes. Thank you for your order! Bye bye!");
        exit;
    }
}
Enter fullscreen mode Exit fullscreen mode

It goes without saying that we need to account for the case scenario when the user wants to cancel the order altogether:

digression cancel_order
{   
    conditions {on #messageHasIntent("cancel_order");}
    do 
    {
        #sayText("Okay, just cancelled your order. Is there anything else I can help you with?");
        wait *;
    }
    transitions 
    {
        edit_new_order: goto edit_new_order on #messageHasIntent("yes");
        bye: goto bye on #messageHasIntent("no");
    }
}
Enter fullscreen mode Exit fullscreen mode

And the final touch is our bye node and digression. We don’t ever want the user to not have an option to end the conversation:

digression bye 
{
    conditions { on #messageHasIntent("bye"); }
    do 
    {
        #sayText("Thanks for your time. Have a great day. Bye!");
        #disconnect();
        exit;
    }
}

node bye 
{
    do 
    {
        #sayText("Thanks for your time. Have a great day. Bye!");
        #disconnect();
        exit;
    }
}
Enter fullscreen mode Exit fullscreen mode

Create your own conversational AI app! It’s easy :)

Try creating an order confirmation app that fits your business’ needs. Think of the questions your users could ask, plot them and write out corresponding nodes and digressions. Or improve the app and share the results in Dasha Developer Community :)

Top comments (0)