Combining chatbot platforms with open data sources is one of the most powerful ways to easily create chat interfaces that provide useful information to its users. This is what we call Open Data chatbots.
In particular, today, we show how you can create a chatbot with Xatkit that queries OpenWeather to give you the weather forecast in any city in the world. All this in less than 100 lines of code. You have the full code of the bot in our examples repository but we’ll see in this post all its key components.
Declaring the weather forecast intent
The first step is defining the asking for weather forecast intent. This is how you do it in Xatkit
val howIsTheWeather = intent("HowIsTheWeather") .trainingSentence("How is the weather today in CITY?") .trainingSentence("What is the forecast for today in CITY?") .parameter("cityName").fromFragment("CITY").entity(city());
Note how as part of the intent we collect the name of the desired city. Also to help the NLP Engine, we declare that the City name should be part of the predefined city entity, comprising the list of all (major) cities in the world. Xatkit maps this to the corresponding city entity available in all the popular Intent Recognition Providers. So, make sure you configure the bot to be used with DialogFlow or Nlp.js (and remember that your choice of NLP Engine does not affect the bot code, just its property file).
Reacting to the weather forecast request
Once the intent has been matched, the bot must call the REST API of OpenWeather passing the requested city as parameter.
We first wait for the intent to match in an initial state for the bot
awaitingInput .next() .when(intentIs(howIsTheWeather)).moveTo(printWeather);
And once the match takes place the transition to the printWeather
state to actually process the request. See the full code of this state below.
Remember that Xatkit comes with a REST platform abstraction that you can use to simplify the query and response processing of any external REST API. Thus, getJsonRequest
helps you build the exact URL request to send to the API and collects the answer in the response
object you can then use to check for the success status of the query and the easy access to the returned information.
If successful, from this response object, we build the reply to print back to the user. And go back to the initial state in case the user wants to ask for another city.
printWeather .body(context -> { String cityName = (String) context.getIntent().getValue("cityName"); Map<String, Object> queryParameters = new HashMap<>(); queryParameters.put("q", cityName); ApiResponse response = restPlatform.getJsonRequest(context, "http://api" + ".openweathermap.org/data/2.5/weather", queryParameters, Collections.emptyMap(), Collections.emptyMap()); if (response.getStatus() == 200) { long temp = Math.round(response.getBody().getAsJsonObject().get("main").getAsJsonObject().get( "temp").getAsDouble()); long tempMin = Math.round(response.getBody().getAsJsonObject().get("main").getAsJsonObject().get( "temp_min").getAsDouble()); long tempMax = Math.round(response.getBody().getAsJsonObject().get("main").getAsJsonObject().get( "temp_max").getAsDouble()); String weather = response.getBody().getAsJsonObject().get("weather").getAsJsonArray().get(0).getAsJsonObject().get("description").getAsString(); String weatherIcon = "http://openweathermap.org/img/wn/" + response.getBody().getAsJsonObject().get( "weather").getAsJsonArray().get(0).getAsJsonObject().get("icon").getAsString() + ".png"; reactPlatform.reply(context, MessageFormat.format("The current weather is {0} °C with " + "{1} ![{1}]({2}) with a high of {3} °C and a low of {4} °C", temp, weather, weatherIcon, tempMax, tempMin)); } else if (response.getStatus() == 400) { reactPlatform.reply(context, "Oops, I couldn't find this city"); } else { reactPlatform.reply(context, "Sorry, an error " + response.getStatus() + " " + response.getStatusText() + " occurred when accessing the openweathermap service"); } }) .next() .moveTo(awaitingInput);
The weather forecast chatbot
You can see the resulting bot in action here.
Note that the bot is able to understand the user questions even if they are not an exact match of the training sentences as we using our DialogFlow connector as NLP provider in this case. Note that the bot is also giving you a nice reason to come live in Barcelona :-).
Obviously, this is a minimal example you could build on to expand the conversation or provide additional information. You have the full power of our Fluent API and state machine semantics backing you up!.
Photo by Wim van ‘t Einde on Unsplash
If you’d prefer to use an API that does not require an API Key, this twitter thread may be useful: https://mobile.twitter.com/mor10/status/1544889264034328577