In this blog post we’ll discuss how we built a Bot for ParkAround using Microsoft Bot Framework and hosted it in Azure platform.
ParkAround is a prominent startup in Greece which allows you to book your place in hundreds of car parks in the cities of Athens/Thessaloniki as well as the airports of Barcelona and Malaga. We worked with ParkAround to build a Bot that allows the user to book a parking spot at the airports of Athens and Thessaloniki. You can currently chat with the Bot on Facebook’s Messenger platform, whereas support for other channels (e.g. Skype) will be rolled out in the next few weeks.
Bot has the name of “Mitsaras, the parking assistant” (“Mitsaras” being the folk/friendly name for “Dimitris”) and you can chat with it here: https://www.messenger.com/t/parkaroundbot. Beware, bot currently uses Greek language only since it targets Greek audience for now. So, don’t get confused if it’s all Greek to you!
To develop the bot, we used Microsoft’s Bot Framework which allows you to create a bot that will interact with various conversation channels, such as Messenger, Skype, Slack and other services. Bot Framework supports a REST API and has two SDKs, one for .NET and one for Node.js. As most Microsoft SDKs nowadays, both of them are open source. If you aren’t acquainted with Bot Framework SDK, please take a look at the extensive documentation in order to better understand the code segments listed below. Also, ParkAround is a BizSpark startup, so we naturally chose Azure App Service PaaS platform to host the bot, so we can easily scale up/out if needed.
Last but definitely not least, before we continue with bot’s internals, we should mention that this work is a collaboration between myself, my colleague Sophia Chanialaki and ParkAround’s CEO, John Katsiotis.
Bot request/response data flow
So, how does the bot accomplish its goal?
Bot follows the steps listed below, in an effort to acquire the necessary data from the user
- Bot displays a welcome message to the user, as soon as she speaks to it
- User selects the airport location she wishes to park her car
- User selects the date/time she will arrive at the airport
- User selects the date/time she will come back from her trip and pick the car
- Bot searches in the available parking lots to find an empty booking. If successful, it continues to next step. Otherwise, it returns to step 1. User is presented with a carousel displaying the available parking lots along with their prices and the distance from the airport.
- Now, user has to enter the necessary details for the booking to be performed. Bot starts by asking user to enter their full name, suggesting the one taken by the conversation channel used (e.g. Facebook given name)
- Bot sequentially asks for user’s email, phone and car’s license plate
- Bot asks for a final confirmation before it performs the actual booking
- If user confirms, the bot calls the ParkAround web service to perform the actual booking and user receives the necessary details in her e-mail address. Bot presents a receipt to the user
Steps can be represented with the following diagram
Bot core code
In the beginning, we built a small prototype using Bot SDK’s FormFlow. FormFlow is a great tool that you can use to develop a bot using minor effort. Specifically, you can “feed” it a C# class and it can generate required request (input) questions. FormFlow searches your class for public fields which can be either a simple data type or enum and will build a sequential series of questions that the bot will ask the user. Add to this the fact that you can add C# attributes to filter and validate the answers given by the user and you’ve got yourself a great mechanism which you can use to build a powerful bot with minimal effort and few lines of code.
However, we needed some customisations that were not supported by FormFlow. For example, on the date question we needed the user to reply either with a valid date (e.g. 30/10/2016) or with a string (e.g. Today, Tomorrow). That proved rather tricky to do with FormFlow. Consequently, we quickly opted to revise our architecture and used the more powerful SDK’s Dialogs instead.
We started by creating a simple dialog to hold all request and response messages. This worked but, as we described, the amount of input steps required was big enough. So, we again quickly decided to create custom dialogs for each one of the described steps. Each dialog would ask the user a question, get the response, filter/validate it and either finish its operation (if the response was OK) or ask the user again (if the response was not OK). And what a better way to “chain” all these dialogs together than a dialog chain, already supported by the framework? Without further ado, here’s the Bot Framework Chain that’s powering our bot.
In the beginning we’re creating some private fields. These will be used to hold the responses given by the user. Then, the entire chain is created in the CreateChain method. There the flow of request/response to and from the user is described. At each step, we call a specific dialog, get the result given from the user, save it in one of the private fields and continue with the next dialog in the chain. You may notice that we are using a LoopWhile method that is not present in the official Bot Framework. Thing is, we needed a loop in the chain at this point (if you don’t find any available parking lots in the time frame provided, start over). At the time we wrote that piece of code the Bot Framework didn’t have one, so we wrote one ourselves. However, there is such a method now (and we of course recommend using it).
Take a look at my LoopWhileDialog class
Let’s proceed in seeing some of the code in the dialogs used by our bot.
We needed a simple dialog that would ask the user a question, get an answer, validate it and either return success or prompt the user for a correct one. With these, requirements, we build the CustomTextInputDialog class
Based on this class, we built special classes to validate specific user details, such as PhoneCustomInputValidator, EmailCustomInputValidator and a TextCustomInputValidator (which basically checks whether the input string is within a specified length). Classes have to implement the simple ICustomValidator interface.
We needed a class that would get date+time details of user’s arrival and departure from the parking lot. We developed the DateTimeInputDialog class for this purpose
This dialog allows user to either select a specific date (today/tomorrow for arrival, after 3 days/after 5 days for departure) via a HeroCard or input a specific date and time. Moreover, it performs various validation checks, e.g. making sure that dateTimeTo > dateTimeFrom. Attention is also being paid to the date/time’s input, regarding time difference between Greece (where the parking space is) and Azure’s Europe Western Europe data center, where the bot code resides. For instance, if the user wishes to arrive at the parking “today”, we need to take into account what “today” means for the Azure data center. We know that we’re deploying to Azure’s Western Europe data center, so we’re calculating the time difference between Western Europe and Greece, taking into account DaylightSavingTime. Maybe (well, almost certainly!) there’s a better way to do this, but if it ain’t broke, why fix it :) ?
FullNameInputDialog is pretty straight forward, they key here is that we’re using the Message.Recipient.Name property to get the user’s name from the conversation channel.
Showing a receipt to the user
As soon as the bot gathers all required data from the user, it asks for a final confirmation. If the user issues it, then bot calls ParkAround’s internal API to perform the booking. Afterwards, it has to deliver a receipt to the user. ReceiptCard class is an extendable class (via the Facts property) which we use to deliver a Facebook Messenger-formatted receipt to the user.
ASP.NET localization is used in the (likely) event that we’d like our bot to support more languages in the near future. In the aforementioned pieces of code, you’ll find many references to a StringMessages class. This is the class we’re using in our resource files and holds our localised string values. It’s considered a best practice to use these in every project since there’s always a chance that a new language will be required to add in the project in order to target a new market.
Bot deployment to Azure
You may ask how we deploy the bot. Well, we could use Build/Deploy from Visual Studio but we liked something better. Since ParkAround uses BitBucket as a source code repository, we chose to use App Service continuous deployment support to deploy bot’s to Azure. Upon publishing to a specific repository, App Service grabs the code and deploys it.
Nice, where can I find more bots? How can I register mine and connect it to conversation channels?
Feel free to browse the Bot Framework Bot Directory here and register a new bot you have developed here. There, you can also find documentation guidance on how to connect it to various conversation channels. Moreover, if you need natural language processing for your bot, LUIS is your friend.
Thanks for reading, hope it helps!