How I created a Food Recommendation Bot
The last encounter I had with a chatbot, I was in a Warcraft 3 Battle.net channel answering movie trivia questions. For a while, chatbots languished in obscurity as most could only hold simple conversations. Now, chatbots are back with a vengeance — you can order pizza through them or even talk to the dead.
Food has always been my passion and an obsession. A perennial problem I face is deciding what to eat for lunch. So one day after having a rather one-sided conversation with @atwherebot, which did look rather promising, I decided to try my hand at making my own food recommendation bot. The dream was to aggregate data on good eats from the credible local food review sites/blogs — sorry Google Places, you’re not one of them. Hence, @e8tbot (formerly Coconut, still pending that Facebook name change…) was born!
Without much prior programming experience, my stack consisted of tools that were simple enough for me to pick up. I ended up with Node.js for my app server, MongoDB for my database, LUIS for Natural Language Processing and the Microsoft Bot Framework SDK to glue them all together. Although Bot Framework allows easy integration with various messaging apps, I only published on Facebook Messenger because I liked the look and feel best. For app hosting, I used Heroku.
In this article, I won’t go through the steps of building a bot, there’s a ton of useful articles out there that go into the details. I assume you have some experience with Bot Framework so I’ll just go through the key concepts.
Local Development
After you have registered your bot on the Bot Framework, Facebook Pages/Developer, you can set up a secure tunnel to your local server with ngrok. This way, you can immediately test changes to your app via the Facebook Messenger Client without having to deploy to Heroku.
Install ngrok then run this in your command prompt: ngrok http 3978
. Copy the ngrok url and access your bot’s page to fill in the messaging endpoint with:
https://<your-ngrok-url>/api/messages
Next, hit the blue Test button! If all goes well, you should see this:
ngrok also provides a cool web interface, accessible via localhost:4040, which allows you to inspect the requests/responses going through the tunnel.
Even better still is to pair this with nodemon, which is a nifty tool that watches for changes in your code and automatically restarts the server. To make development a breeze, I have also set up a gulp pipeline that transpiles ES6, triggers a nodemon reset and then supplies development environmental variables to my app.
Obtaining User’s Location
One of the key features of my bot is that it can make food recommendations based on the user’s location. The challenge is that you can’t retrieve a user’s location directly. Instead, the user has to send you his/her location before you can extract it from the message body. What you can do is to set up Quick Replies:
Carousel to Display Recommendations
After parsing the location, I do MongoDB’s nearSphere geospatial query and order the results based on proximity (there’s no fancy shenanigans like collaborative filtering going on, yet).
Because Facebook has a limit on the number of items that can be displayed in a carousel, I perform two MongoDB queries. The first is a count
query to get the total number of records and we store that in the session.userData
object. The latter is a find
query which does the actual document retrieving, but I limit the retrieval to a maximum of 5 elements. You can maintain a cursor which keeps track of how many elements the user has seen so far. This was when I realized how useful promises (I used bluebird) were in ensuring that the queries were fired in the right order.
To create the carousel, you’ll need to instantiate multiple HeroCard objects and then chuck them into an array.
Next Steps
I’m still figuring out the NLP bit, especially how to train the AI more efficiently. It’s feeling a bit manual for me now. Most utterances I suspect are going to be single/double words such as laksa
chicken rice
korean food
. They probably wouldn’t type long sentences which the AI needs to recognize the entities/sub-entities. I’m also thinking of shifting to something like Wit.ai because it seems more user friendly (the Azure Portal is pretty hellish to navigate).
I’ll leave you here for now, if you have any suggestions/tips, feel free to leave a comment below (: