We recently posted a step-by-step video demo of OpenAI function calling with Rasa on our youtube channel. It's an extension of the previous video and blog we did about answering questions on structured data with ChatGPT and Rasa.

If you haven’t checked out our previous tutorial on answering questions with ChatGPT in Rasa, I would suggest you check that out first.

For this demo, we used the same restaurants.csv file but added one more field called distance and gave each restaurant a distance measurement in kilometers.

Restaurants,Rating,Has WiFi,cuisine,distance
Mama's Pizza,4.5,False,italian,10
60 seconds to Nepoli,4.6,True,mexican,05
China Palace,3.2,False,chinese,20
The Cheesecake Factory,4.2,True,american,15
Pizza Hut,3.8,True,italian,10

With function calling, developers can now describe functions to `gpt-4-0613` and `gpt-3.5-turbo-0613`, and have the model intelligently choose to output a JSON object containing arguments to call those functions. It allows developers to get structured data back from the model more reliably. In other words, it generates the JSON output in the data structure you gave in the description for the function.

Why might we need OpenAI function calling in ChatCompletion? It should be kept in mind that for complex mathematical queries it's important to run it in ChatCompletion as function calling and not simple ChatCompletion. According to research, ChatGPT can sometimes lead to wrong numerical answers. You can read about the mathematical capability of ChatGPT here.

Let's understand the dataflow given in the diagram. From restaurant.csv, if the intent is a restaurant, it shows the top 5 restaurants from the CSV; now, it can go two ways, either details or distance. If you include distance in the query, it will follow the intent distance, the flow-diagram is as follows:

If it goes to the action_distance, it will output a dictionary list with restaurant_name and distance. We can then feed to a function that calculates the shortest distance and gives us the key.

The ChatCompletion has four main parts:

1. Content
2. Model
3. Function (which consists of three parts):
a. Name of the function
b. Description of the function
c. Parameters, which have properties and descriptions.
The description of the parameters is the most important and is where the "magic" of the OpenaAI function lies. This tells you what should be the data structure output of the arguments
4. Function call: when to call the function.
``````ef ask_distance(restaurant_list):
content = "measure the least distance with each given restaurant" +'/n/n' + restaurant_list
completion = openai.ChatCompletion.create(
model="gpt-4-0613",
messages=[{"role": "user", "content": content}],
functions=[
{
"name": "get_measure",
"description": "Get the least distance",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "list of all the restaurants and distances as a dictionary(restuarant_name:distance)",
},
},
"required": ["distance"],
},
}
],
function_call={"name":"get_measure"}
)
return completion.choices[0].message
``````

Here is the function that takes the arguments generated by ChatCompletion and outputs the action_distance. Again, you should ensure that the data structure output from the function call suits the function. In the example below we received the list of dictionaries and asked to calculate the key for the minimum value.

``````def get_distance(d):