Executing Functions Sequentially Using Function Calling

Overview:

I am exploring ways to execute functions sequentially using function calling (tool call) in the OpenAI API. From the documentation and observed behavior, it seems that the results of function calling are expected to be executed in parallel by default.

Goal:

Input: I want to create a flow where functionA is executed first, followed by functionB.
Desired Output: A flow where the array elements are executed in order, e.g.,

{
  "tool_calls": [
    {"type": "function", "function": {"name": "functionA", "arguments": {"a": "aaa"}}}, 
    {"type": "function", "function": {"name": "functionB", "arguments": {"b": "bbb"}}}
  ]
}

The exact format of this output is flexible as long as it achieves the goal of sequential execution.

What I’ve Tried:

  • Setting function.parameters.type to array:
    I attempted to define the parameters type as an array, but encountered a syntax error.
  • Using oneOf for Different Function Arguments:
    Since each function has different possible arguments, I tried using oneOf to specify the possible argument structures. However, this led to hallucinations where the function returned arguments not included in the oneOf list.Here’s a snippet of the JSON schema I used:
{
  "parameters": {
    "type": "object",
    "properties": {
      "tool_calls": {
        "type": "array",
        "items": {
          "oneOf": [
            {
              "type": "object",
              "properties": {
                "name": {"const": "functionA"},
                "arguments": {
                  "type": "object",
                  "properties": {"a": {"type": "string"}}
                }
              }
            },
            // Additional function definitions...
          ]
        }
      }
    }
  }
}

Questions:

  • How can I structure the function calling to ensure that functions are executed in sequence rather than in parallel?
  • Are there specific JSON schema configurations or API settings that support this kind of sequential execution?

Any insights or suggestions on how to achieve this would be greatly appreciated!

Thank you!

Hey @aiueokaki - Welcome to the community!

An easy workaround for it is mentioning your steps in the tool descriptions. This was best working for me. you could also try to pass in additional context before submitting tool outputs from funcA. So, the LLM knows exactly what to do next.

functionA: STEP1 of ___ task. (followed by func description)
functionB: STEP2 of ___ task. (followed by func description)

Cheers!

I am trying to generate a flowchart that determines the sequence in which custom library functions should be called based on their descriptions, arguments, and return values.
In this use case, the order in which the functions are called can vary and is not fixed. The challenge lies in orchestrating these function calls to ensure they execute in a desired sequence.
Is this type of sequential execution difficult to achieve with the current function calling approach?

do you know the functions to be executed from the moment the first function is triggered? for example, user sends an inquiry and based on that you already know funcABC->funcXYZ->funcDEF->funcRST should be sequentially executed?

No. Functions are not defined in what order they are called. I am wondering if it is possible to have gpt output their order and respective arguments to meet the input requirements.

ex)
input: I want to do AB and do Z.
output: funcA(args:a, aa) → funcB(args:b, bb, bbb) → funcZ(args:z)

that is possible. given a task, break it down to subtasks. your main function when invoked will contain the subtasks needed to be executed. you then execute those subtasks outside the main API call and only send back the final output.

Am I correct in assuming that the first request breaks the natural language into subtasks, and then each subtask is broken down into functions and arguments to be used in function calling?

Here’s the basic skeleton:

Can you give the sequence of function calls in the following statement as a json array. Don’t need any words. Just the array. If you encounter with parameters, do wrap the parameters within the function. If not, do indicate as such.

Call funcA with parameter a = “aaa” & ab=“abba”, then call funcZ with parameter d=123, then call funcB

[
“funcA(a=‘aaa’, ab=‘abba’)”,
“funcZ(d=123)”,
“funcB()”
]

You control the execution flow therefore if we take javascript as example. Execute the first tool and wrap it inside a promise then resolve it when done. Then do the same for each function. Its going to be sequential instead. Do you understand?