Skip to content

August 17th, 2023

OpenAI Function Calling in Rasa

  • portrait of Sonam Pankaj

    Sonam Pankaj

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:

DataFlow

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):
    d = json.loads(d)
    for i in d.keys():
        d[i]= float(d[i])
    t = min(d, key =d.get)
    return t

Let’s discuss the JSON output of ChatCompletion. It doesn’t directly give you the answer, but it provides you with the JSON output with arguments. And the arguments have the same data structure as you gave in the parameters' description.

And thus, the final result looks like this for action_distance. I love to use it whenever there is a complex query with more than one numerical question, which comes from the function we described by extracting arguments from ChatCompletion. It’s a powerful tool for any agent.

Output from ChatCompletion

If you have topics that you would like us to cover next, please let us know by posting on our community forum: https://forum.rasa.com/ . Also, don’t forget to subscribe to the Rasa youtube channel for more content on Generative AI!