Weather bot with semantic kernel

Weather bot with semantic kernel

Introduction

In the fast-evolving world of AI-driven chatbots, innovations like ChatGPT have revolutionized the way we interact with technology. These language models have proven to be incredibly powerful, capable of understanding and generating human-like text. However, despite their impressive capabilities, one significant limitation has been their lack of access to real-time data and databases. This restriction has hindered their ability to provide dynamic, up-to-date information to users.

Enter AI plugins, a groundbreaking solution that complements chatbots' existing capabilities and bridges the gap between their prowess and real-time data access. By integrating AI plugins, chatbots can now access external data sources, enabling them to serve as dynamic, information-rich assistants.

In this article, we will explore the potential of AI plugins, focusing on the development of a cutting-edge weather reporter plugin using Microsoft's Semantic Kernel framework. This plugin will empower our AI-driven chatbot to deliver personalized weather updates to users in real-time, enhancing their overall experience.

Open Weather API

We re going to be using the open weather API to get real-time information about weather, and forecasts of any location in the entire world. We will use its python wrapper PyOWM.

Lets see how to get the weather information of any location.

mgr = OWM("<API_TOKEN>").weather_manager()
 
def weather_at_place(location: str):
  observation = mgr.weather_at_place(location)
  w = observation.weather
  ret = {
	  'current_time' : datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
      'detailed_status' : w.detailed_status,
      'wind' : w.wind(),
      'humidity' : w.humidity,
      'temperature' : w.temperature('celsius'),
      'rain' : w.rain,
      'heat_index' : w.heat_index,
      'clouds' : w.clouds
  }
  return ret

The open weather API also provides forecast information.

def get_weather_forecast(location : str):
        forecast = mgr.forecast_at_place(location, '3h')
        target_time = datetime.now() + timedelta(hours=6)
        weather_at_target_time = forecast.get_weather_at(target_time)
        temperature = weather_at_target_time.temperature('celsius'),
        status = weather_at_target_time.detailed_status
        rain = weather_at_target_time.rain
        humidity = weather_at_target_time.humidity
        ret = {
            'current_time' : datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'forecast_time': target_time.strftime('%Y-%m-%d %H:%M:%S'),
            'temperature': temperature,
            'status': status,
            'rain': rain,
            'humidity': humidity
        }
        return ret

Now that we have figured out the API, and gotten the information we need from it, lets design the plugin wrapper around it for our chatbot.

Native functions in Semantic Kernel

We can make a plugin using native functions in semantic kernel. Native functions are used to implement your actual business logic, so that the chatbot will simply call these functions, and get the output in a deterministic manner, instead of attempting to generate an incorrect answer. Lets implement our weather functions from earlier as native functions.

from semantic_kernel.skill_definition import sk_function
class WeatherPlugin:
    def __init__(self) -> None:
        self.mgr = OWM('<API_TOKEN>').weather_manager()
 
    @sk_function(
        description="Predict weather forecast only information from a given location",
        name="ForecastAtPlace"
    )
    def get_weather_forecast(self, location : str) -> str:
				# ... same as above 
        return str(ret)
 
    @sk_function(
        description="Generate current weather information only from a given location. The returned information includes a detailed status, wind, humidity, temperature in celcius, rain, and clouds",
        name="WeatherAtPlace"
    )
    def weather_at_place(self, location: str) -> str:
	      # ... same as above
        return str(ret)

Lets analyze what we have done here.

  1. The Plugin needs to be a class, and we can declare any data belonging to the plugin as its attributes.
  2. Both of the functions defined earlier are methods of this class.
  3. Each method needs to have the @sk_function decorator to be usable, which takes a description, and a name. It is crucial that the description be as descriptive, and correct as possible as it will be used later on by GPT for decision making.

Semantic functions

In Semantic Kernel, prompt engineering is done in isolated reusable pieces or templates known as semantic functions. Each semantic function can take in different inputs which are inferred from the input. Following is an example of what a semantic function can look like.

Translate the input below into {{$language}}

MAKE SURE YOU ONLY USE {{$language}}.

{{$input}}

Translation:

As you can see, it takes in the languagevariable, and the predefined input variable. Apart from that a semantic function can also take in GPT parameters like temperature, and max_tokens etc.

Lets make a semantic function for each native function we defined earlier. We will also have to initialize our Kernel. Moreover, we will be using the Text-Davinci model from AzureOpenAI for our text completion.

import semantic_kernel as sk
from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion
 
kernel = sk.Kernel()
planner = BasicPlanner()
 
deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()
kernel.add_text_completion_service("dv", AzureTextCompletion("Text-Davinci", endpoint, api_key))
 
WeatherReporter = kernel.create_semantic_function(
    """You are a weather reporter. you will receive the weather data as json, and you 
				will tell it to your viewers in a concise, catchy and jolly manner. mention 
				times if present in data.
			----------------------
			{{$input}}
			""", 
    description="Receives weather data as json, and converts it to human readable form.",
    skill_name="WeatherReporter",
    max_tokens=1000,
    temperature=0.3,
    top_p=0.5)
 
WeatherForecaster = kernel.create_semantic_function(
    """You are a weather reporter who reports forecasts. you will receive the weather 
			 forecasts as json, and you will tell it to your viewers in a concise, catchy 
			 and jolly manner. make sure to mention that it is a forecast, and mention times 
			 if present in data.
			----------------------
			{{$input}}
			""", 
    description="Receives weather forecast information as json, and converts it to human readable form.",
    skill_name="WeatherForecaster",
    max_tokens=1000,
    temperature=0.3,
    top_p=0.5)

As it was stated earlier, the description here is of utmost importance as it will be used by the LLM to make decisions about which function to call given the user input.

Orchestration using Planner

We have defined all of the different semantic and native functions. We only need to use them now, and this is where the Planner comes in. But what is this Planner? As the official documentation says:

Planner is a function that takes a user's ask and returns back a plan on how to accomplish the request. It does so by using AI to mix-and-match the plugins registered in the kernel so that it can recombine them into a series of steps that complete a goal.

A diagram of the semantic kernel planner

Lets import our native functions into our kernel, so we can give them all to the planner.

from semantic_kernel.planning.basic_planner import BasicPlanner
 
kernel.import_skill(WeatherPlugin(), skill_name="WeatherPlugin")
planner = BasicPlanner()

Now that we have got our planner, we are ready to make a plan. But first we must give it an input, or an ask. What do we want our planner to plan? Lets assume that we want to know what the weather is like in New York?

import asyncio
 
ask = "What is it like in New York?"
plan = asyncio.run(planner.create_plan_async(ask, kernel))
print(plan.generated_plan)
"""
[Output]
{
        "input": "New York",
        "subtasks": [
            {"function": "WeatherPlugin.WeatherAtPlace"},
            {"function": "WeatherReporter.f_39862838_17a3_4893_a0a6_eb5733cc95d7"}
        ]
}
"""

As we can see the planner has generated a plan for us in which it decided to first call our native function WeatherAtPlace with the input New York, and then it wants to call our semantic function WeatherReporter. Its admirable how it was able to extract the location from the input without any explicit NLP techniques, and it was able to plan the correct functions in the right order.

Now we can go ahead and execute this plan.

out = asyncio.run(planner.execute_plan_async(plan, kernel))
print(out)
"""
[Output]
Good evening everyone! It's currently 9:41 PM and the weather is looking overcast with 
100% cloud coverage. The temperature is a pleasant 24.09 degrees Celsius, with a maximum 
of 25.72 and a minimum of 22.75. The wind is blowing at 6.69 m/s with a gust of 8.75 m/s.
The humidity is 70%. Enjoy the rest of your evening!
"""

The code for this is available as a Colab notebook here.

Get Creative

Now that you've successfully set up your weather reporter chatbot using Semantic Kernel and integrated AI plugins, it's time to take your experimentation to the next level. The beauty of AI-driven chatbots lies in their adaptability and potential for customization. Here are some exciting ways you can enhance your chatbot and provide a more engaging user experience:

  1. Experiment with Complex Prompts: Challenge yourself to create more intricate and diverse prompts for your chatbot. By experimenting with different input styles and questions, you can explore the full potential of your AI language model and witness its adaptability in delivering contextually accurate responses.
  2. Extend to a Travel Bot: Why stop at weather reporting when you can transform your chatbot into a versatile travel companion? Consider adding travel-related features to your chatbot, such as providing recommendations for attractions, local cuisine, and activities at various travel destinations.
  3. Leverage the Google Places API: To make your travel bot truly dynamic, integrate the powerful Places API by Google. This will enable your chatbot to fetch real-time information about popular tourist spots, nearby restaurants, and other exciting places of interest at any location around the world.
  4. Personalized Travel Itineraries: Take it a step further and empower your chatbot to create personalized travel itineraries based on users' preferences and interests. By analyzing user input and combining it with Places API data, your chatbot can craft tailor-made travel plans for each user.
  5. Language Translation: To cater to a global audience, consider integrating language translation capabilities into your chatbot. This feature will allow users to interact with your chatbot in their preferred language, breaking down language barriers and widening your bot's reach.

Remember, the key to building an exceptional chatbot lies in continuous experimentation and innovation. Embrace the flexibility of AI and push the boundaries of your creation. By adding travel bot features and exploring different integrations, you can craft a unique and invaluable assistant that users will love engaging with. So, unleash your creativity and embark on a journey of limitless possibilities with your AI-powered chatbot!

Conclusion

In this article, we explored the world of AI-driven chatbots and their limitations in accessing real-time data. To overcome this hurdle, we introduced AI plugins as a groundbreaking solution to integrate external data sources seamlessly. Leveraging the power of Microsoft's Semantic Kernel framework, we developed a cutting-edge weather reporter plugin for our chatbot.

With the integration of the Open Weather API and Python wrapper PyOWM, we learned how to retrieve real-time weather information and forecasts for any location worldwide. We then designed the plugin wrapper around these functions, making them accessible to our chatbot.

Through the implementation of native functions and semantic functions in Semantic Kernel, we created a dynamic weather reporter chatbot. The planner, with its AI-driven decision-making capability, intelligently orchestrated the sequence of tasks required to answer user queries effectively.