DEV Community

Cover image for Create a chatbot that tells you the weather forecast for any city in under 100 LoC
Jordi Cabot
Jordi Cabot

Posted on • Originally published at xatkit.com

Create a chatbot that tells you the weather forecast for any city in under 100 LoC

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());
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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 colects 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<JsonElement> 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} &deg;C with " +
                                        "{1} ![{1}]({2}) with a high of {3} &deg;C and a low of {4} &deg;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);

Enter fullscreen mode Exit fullscreen mode

The weather forecast chatbot

You can see the resulting bot in action here.

weather bot in action

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

Top comments (0)