mirza.town
about archive rss

19/07/2024

What is Function Calling?

In short, function calling lets the developer to fill in the parameters of an imaginary function from user input using LLMs and retrieve the input parameters of that function. The neat part is that the LLMs can trigger that function call when the user asks for it.

So, let’s say you have a function that can somehow retrieve the average weight of a specific dog breed for a specific year. So the inputs are dog_breed and dog_age and the output is dog_weight. The function call would look like this;


def get_dog_weight(dog_breed: str, dog_age: int) -> float:
    # some code of a big dictionary or even better, a neural network
    return dog_weight

As you can see, there’s no implementation of the function, just the signature. The return statement appears out of thin air when and is not outputted by the LLM.

Whenever the user asks for the average weight of their dog, the LLM can fill in the parameters and trigger the function call. The function call won’t trigger if the conversation isn’t about dog breeds and their average weight by age.

In summary, the LLM can know the signature of the function and can trigger the function call whenever it sees fit. You see, the “calling” is not in the sense of “running” the function but more in the sense of “summoning” the function.

An actual example.

Suppose you are a tech-bro and you want to invent new dishes combining two different cuisines and/or ingredients. So you’d have to parse the ingredients and the cuisines from the user input somehow, which is almost an impossible task for the conditional statements. So our function that we want to call would look like this;


def create_fusion_recipe(
    cuisines: List[str],
    ingredients: List[str] = [],
    spiciness: int = 0,
) -> dict:
    """
    Generates a fusion recipe combining two cuisines and/or ingredients.
    
    Args:
    cuisines (List[str]): List of cuisines to combine
    ingredients (List[str]): List of ingredients to include in the recipe
    spiciness (int): Level of spiciness of the recipe

    Returns:
    dict: Recipe details including estimated taste confusion and
          Instagram-worthiness
    """
    # Implementation details omitted to protect secret fusion formulas
    pass

Remember: we expect the LLM to figure out the needed parameters from the user even if it’s hot garbage.

So our actual code for ChatGPT would look like this as of 19/7/2024;


completion = openai.ChatCompletion.create(
    model="gpt-4-0613",
    messages=[
        {
            "role": "user",
            "content": "Yo, just closed a Series C and I'm ready to disrupt my palate! Need some blockchain-level fusion that combines that bougie Italian place where we pitched VCs with that AI-powered Japanese spot. Gotta have some Wagyu beef to fuel these gains, and throw in some truffles 'cause I'm worth it. Make it so cutting-edge it'll make Elon's Neuralink jealous. Oh, and keep it keto-friendly - biohacking never sleeps, bro!",
        }
    ],
    functions=[
        {
            "name": "create_fusion_recipe",
            "description": "Generates a fusion recipe combining two cuisines and/or ingredients.",
            "parameters": {
                "type": "object",
                "properties": {
                    "cuisines": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "description": "A string representing a single cuisine",
                        },
                    },
                    "ingredients": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "description": "A string representing a single ingredient",
                        },
                    },
                    "spiciness": {"type": "integer"},
                },
                "required": ["cuisines"],
            },
        }
    ],
    function_call="auto",
)

And the response from ChatGPT is as follows;


<OpenAIObject at 0x7fc3cc0e3ec0> JSON: {
  "index": 0,
  "message": {
    "role": "assistant",
    "content": null,
    "function_call": {
      "name": "create_fusion_recipe",
      "arguments": "{
            "cuisines": ["Italian", "Japanese"],
            "ingredients": ["Wagyu beef", "truffles"],
            "spiciness": 3
        }"
    }
  },
  "logprobs": null,
  "finish_reason": "function_call"
}

We could even add a “diet type” parameter for the “ketofriendliness” and whatnot.

The syntax for the function calling differs from LLM to LLM, but the concept remains the same. I think it’s far better than the Microsoft’s Guidance for filling in the values for a JSON object, for example. It’s cheaper, faster, and doesn’t have to be triggered for every user input.