In prep for fine tuned models support for function calls what would training data look like?

Here is how I think ‘function calling’ works:
* User asks a question.
* The model recognizes the need for a function call and outputs a JSON object with the function call’s name and required arguments.
* My application backend then makes the appropriate API call or database query.
* The response from this API call is sent back to the model.
* The model then crafts a human-readable response based on this data and sends it back to the user.

When function calling is available in fine-tuned models (i don’t believe it’s available yet but I understand it’s coming), In preparation for this new feature I want to build out my training data to support getting data from multiple functions and leveraging it in a formatted response.

I’m making an assumption (I know… that’s bad…) that the training data instructs the model on how to respond to user queries and, more importantly for this use case, when to invoke a function call to fetch external data. I believe that the “bridge” between the training data and the function calls is the learned behavior of the model to recognize when it should fetch external data based on user input and the context of the conversation. Given this, I’m wondering if I can structure training data to teach the model when to make a function call.

For Example:
User: “What will a 2% rise in the inflation rate in the US do to my portfolio?”
Assistant: (Recognizing the need for real-time data) “Let me get your portfolio and also check the current inflation rate for you.”
Model’s Function Call: The model then makes a function call to get_portfolio.
Function’s Response: User owns 10 shares of Apple.
Model’s Function Call: The model then makes a function call to get_current_inflation with the argument { “country”: “US” }.
Function’s Response: The function returns with a data point, for example, 5.4% and adds 2% for new inflation rate of 7.4%.
Model’s Function Call: The model then makes a function call to calculate_what_a_rise_in_inflation_will_do to each asset in the portfolio.
Function’s Response: The function returns the potential impact to Apple
Assistant’s Final Response: “The current inflation rate in the US is 5.4% and a 2% increase will make the inflation rate 7.4% and impact on Apple may be ZZZ”

My Question: In the training data, would it look something like:

{
  "model": "gpt-3.5-turbo-0613",
  "messages": [
    {"role": "user", "content": "What will a 2% rise in the inflation rate in the US do to my portfolio?"},
    {"role": "assistant", "content": null, "function_call": {"name": "get_current_inflation", "arguments": "{ \"country\": \"US\"}"}},
    {"role": "function", "name": "get_current_inflation", "content": "{\"rate\": \"5.4%\"}"},
    {"role": "assistant", "content": null, "function_call": {"name": "get_portfolio"}},
    {"role": "function", "name": "get_portfolio", "content": "{\"asset\": \"Apple\",\"shares\": \"10\"}"},
    {"role": "assistant", "content": null, "function_call": {"name": "what_a_rise_in_inflation_will_do", "arguments": "{\"inflation\": \"5.4%\", \"portfolio\":{\"asset\": \"Apple\",\"shares\": \"10\"}}"}},
    {"role": "function", "name": "what_a_rise_in_inflation_will_do", "content": "{\"impact\": \"ZZZ\"}"},
    {"role": "assistant", "content": "The current inflation rate in the US is 5.4%. With a 2% increase, this would reach 7.4%. Given your portfolio holding 10 shares of Apple, the impact would be ZZZ."}
  ]
}
1 Like

If you are asking about function calling with fine tuned models (not currently available) then the issue will be, what if you train out the function calling feature, or train it in a way that breaks function calling. How would you notice? How would you debug that? could a single training entry break function calls?

I suspect this not be a rapid feature introduction unless the way function calling works is changed to another level of the model’s inference chain, some “protected mode” level.

i’m currently building out functions calls with the base LLM and logging the models interaction with the function calls. If you have a standard set of calls used to test the model and compare the answers against a validation dataset w/visibility to the log output it (“train it in a way that breaks function calling”) should be visible to you. or am I misunderstanding your response?

but, what i’m trying to validate is if the JSON format I posted was valid for such a task (once function calling w/FT is available). We have some very complex analysis we are attempting to complete with a model and this would be a great solution. It’s going to take months to build the training set so I’d like to get after it prior to openai releasing the feature. I suspect there are a lot of people waiting for such a feature given it’s power. it really sets them apart from others.

1 Like

Ahh, I see. Well there is no official documentation on it so anything would be guesswork, your approach seems reasonable. But I do know that function calling is not all exactly as it is viewed to the developer side of the API, so there may need to be further work done to any fine tuning API to do the function definition translations from json to what is used internally.

2 Likes

This is a friendly reminder that a fine tuned model is 8 times more expensive than the standard version. Are you worried that you have too many functions to fit inside the context window? Or is it that the function calling isn’t consistent enough? :laughing:

1 Like

imagine you have a vertical (finance) application that answers complex questions. To answer a question in this vertical the user has to get information from API1 then make a decision if they go to API2 or API3 to get more data, then they have to process API1 and (2 or 3) data to come up with the final answer.

The simple example above was a user asking a finance professional a question and the finance professional going through a process to generate an answer. The use case would work really well with all of our other standard training data supporting the answer as well.

Function calling (I think–again might be bad assumption) would help us with our context window issues as currently we are putting the data in the prompt and that’s not working well (always exceeding 4096). In my testing with the base model it’s been very consistent so I don’t see that issue (yet).

I’ll give you a hint: the AI doesn’t generate a function object container anything like you receive as an API reply. Or say “function_call”.

1 Like

I see… so rather than encoding process in training data we need to put the process in the function_call. that’s unfortunate but I can make it work.

Rather, the endpoint expects to be triggered by a particular format of AI language output, let’s make up a “totally hypothetical” format like \n\nmy_function({"property1": "value"}) -> str. Then you’d have to train on having the AI reply like that.

It would be somewhat pointless to train on a function now, as the endpoint must be activated by the function specification, gpt-3.5-turbo works just fine for normal functions, and OpenAI could make a totally new fine-tune function call format upon release of the feature just to perpetuate the obfuscation.

1 Like

Here’s a few examples from the OpenAI cookbook that may help fill in some gaps:

And

2 Likes

Thank you. Those are great articles. The Chinook example is good.

1 Like

You’re welcome!

You probably need more than that though, my best advice is to think of fine tuning as the last step in your development process, I fully believe you can make all of this work without fine tuning at all.

1 Like

@n2u I was testing your approach to using the base model with function calling and have run into a snag.

I now have a lot of functions (see some below) and it’s easy to get the model to call any of them individually. My problem is if more than 1 function is required to answer the question–for example, “get me the last 3 readings for GNP and the last 3 readings for Personal Savings Rate (PSR)”. Right now it picks one and gives me back the data. I’ve tried to force the process below with no luck. I read this but it’s clear as mud. I’d like to try the approach @magalhas laid out but i really don’t understand it. has anyone written up a solution that is easier to comprehend?

$functions = [
    [
        "name" => "GetGNP",
        "description" => "Fetch the Gross National Product Data.",
        "parameters" => [...]
    ],
    [
        "name" => "GetPSR",
        "description" => "Get the Personal Savings Rate data.",
        "parameters" => [...]
    ],
    [
        "name" => "GetGDP",
        "description" => "Get Gross Domestic Product Data.",
        "parameters" => []
    ],
    [... many more ...]
};

Process I tried with no luck:
$data = callModel()

    {"role": "system", "content": "This is a finance model..."},
    {"role": "user", "content": "get me the last 3 readings for GNP and the last 3 readings for Personal Savings Rate (PSR)"}
]

$functionData = callAppropriateFunction
callModelWithFunctionData($ai_model, $input, $functions, $data, $functionData)

    {"role": "system", "content": "This is a finance model..."},
    {"role": "user", "content": "get me the last 3 readings for GNP and the last 3 readings for Personal Savings Rate (PSR)"},
    {"role": "assistant", "content": null, "function_call": {"name": "GetGNP", "arguments": {}}},
    {"role": "function", "name": "GetGNP", "content": "{...GNP Data...}"}
]

$functionData = callAppropriateFunction
callModelWithFunctionData($ai_model, $input, $functions, $data, $functionData)

    {"role": "system", "content": "This is a finance model..."},
    {"role": "user", "content": "get me the last 3 readings for GNP and the last 3 readings for Personal Savings Rate (PSR)"},
    {"role": "assistant", "content": null, "function_call": {"name": "GetGNP", "arguments": {}}},
    {"role": "function", "name": "GetGNP", "content": "{...GNP Data...}"},
    {"role": "assistant", "content": null, "function_call": {"name": "GetPSR", "arguments": {}}},
    {"role": "function", "name": "GetPSR", "content": "{...PSR Data...}"}
]

$functionData = callAppropriateFunction
callModelWithFunctionData($ai_model, $input, $functions, $data, $functionData)

    {"role": "system", "content": "This is a finance model..."},
    {"role": "user", "content": "get me the last 3 readings for GNP and the last 3 readings for Personal Savings Rate (PSR)"},
    {"role": "assistant", "content": null, "function_call": {"name": "GetGNP", "arguments": {}}},
    {"role": "function", "name": "GetGNP", "content": "{...GNP Data...}"},
    {"role": "assistant", "content": null, "function_call": {"name": "GetPSR", "arguments": {}}},
    {"role": "function", "name": "GetPSR", "content": "{...PSR Data...}"},
    {"role": "assistant", "content": "Here are the last 3 readings for GNP: ... and for PSR: ..."}
]

I’d say you have multiple options here, you can change your function to allow a list input, or you can try putting something like “you are an assistant that always replies with multiple function calls” in the system prompt. :laughing:

1 Like

Question: If the three function calls return the correct result independent of each other why not simplify by creating one function that does it all in a single function call?
Should be simple, time and cost effective.

1 Like

we use a lot of financial indicators (thousands) and a lot of other apis. Each of the questions (prompts) calls for a set of different indicators, contrasting/comparing them with each other to draw conclusions based on trends. I was over simplifying my prompt for example purposes–the typical question would be more in line with “compare the Fed funds rate with consumers’ expected one-year inflation rate and help me determine if the Fed’s rate is above expected inflation”. I am attempting the first step and that’s just to get the model to retrieve the necessary data to go to the next step of contrasting/comparing.

I’m starting to test bypassing the function calling feature all together. If I call the model like this: ‘messages’ => [
[
“role” => “system”,
“content” => “review the prompt and determine how many function calls that are contained in the xml brackets < functions > < /functions > are required to answer the users questions and return those function calls and their arguments back to the user in JSON.”
],
[
“role” => “user”,
“content” => $userInput . " " . json_encode($functions) . " "
]

Then loop thru what is returned and make the function calls myself.

Then re-ask the model the question but now provide the data from the function calls to the model.

Thank you for your reply.
In case you have not seen this topic, it may be off interest:

I believe your main challenge will be the large amount of parameters or functions that the model will have to handle reliably.

1 Like

with that example the type of question is static. my questions are dynamic (different indicators and different desired analysis of those indicators).

To clarify my idea: the goal is to reduce the number of function calls. Maybe create a master function to get_data that will take an array of indicators and the requested time periods as parameters and you unpack this in your backend before returning to the model with the results for the reasoning step.

In your current set-up, as I understand it, the model must be able to disambiguate which of the many, many functions to call in a line of requests.
Instead you could create a process where the model replies in a structured format with the required data. And this structured data is then processed via scripts. Maybe a smaller model could also suffice to extract the required data types.

This would allow you to start testing, building and training today instead of waiting for a feature with unknown specifications.

1 Like

yep, that is exactly what i need to do. I just completed the part where the model returns a JSON blob of all the function calls needed to answer the question. Now i’m building the code to run them all and put them in a format the model will understand along with the users initial question. I think by doing it this way i can bypasses the need for the function calling feature and it’s limitations. Here is the blob the model just returned:

  "message": [
    {
      "name": "GetFredData",
      "arguments": {
        "series_id": "UNRATE",
        "observation_start": "2022-01-01"
      }
    },
    {
      "name": "GetFredData",
      "arguments": {
        "series_id": "RSAFS",
        "observation_start": "2022-01-01"
      }
    }
  ]
}

Thanks for pushing me this direction.

1 Like