Emulated multi-function calls within one request

@magalhas I tried your method, but I had trouble getting a consistent format. The JSON keys change, how did you fix that?

Do you mean the format it uses? Sometimes it might be functions.functionName others straight functionName? If that’s the case you can also ask in the prompt to use a specific format that fits your code.

1 Like

Isn’t that the classical (old) way of calling functions with all the problems we had to deal with in the many months before OpenAI published the function calling API? The three most severe ones always being:

  • Despite an emphasising system message, not picking a presented function and instead answering that it cannot do what you asked it to do
  • NL intro and extros you need to detect and cut out
  • Sloppy json (I used yaml; less mistakes the LLM could do with formatting and quotes)

It’s such a relief that this is now over and we have a proper API and model trained to actually invoke the presented functions. I am very happy that the system message approach is finally no longer necessary, aren’t you? Was your experience negative with that feature?

1 Like

You still provide functions through the proper API and from my experience it replies always in the intended format. Problem with current functions implementation is if you want more than one function to be called.

When I read this thread I was hopeful that this will provide the solution but in my case, gpt just returns the text as the value for the property.

{
  extractMeetingLog: {
    text: "Met with John Smith. His wife is Mary, daughter is Sarah, and son Henderson. He's 45 now and wanting to retire by 60. Has 100k in retirement savings. He just changed jobs to work as a Project Manager with IBM. Mary's email address for future reference is mary@gmail.com. As next steps, need to set up John's sample portfolio, and send him a follow-up with a reminder with the onboarding materials by Friday. Separately Mary was interested in learning more about the Soundwaters charity, send her a link to the site tomorrow."
  },
  extractActionItems: {
    text: "As next steps, need to set up John's sample portfolio, and send him a follow-up with a reminder with the onboarding materials by Friday. Separately Mary was interested in learning more about the Soundwaters charity, send her a link to the site tomorrow."
  }
}

and this is my schema

{
    name: "multiFunctionCalls",
    description: "Call two functions in one call",
    parameters: {
      type: "object",
      properties: {
        extractMeetingLog: {
          name: "extractMeetingLog",
          description:
            "Extract date, names of attendees and summary of the meeting.",
          parameters: {
            type: "object", // specify that the parameter is an object
            properties: {
              date: {
                type: "string", // specify the parameter type as a string
                description: "The date of the meeting, e.g 26 July 2023",
              },
              attendees: {
                type: "string", // specify the parameter type as a string
                description:
                  "Names of attendees in the meeting, ['John', 'Sanjay', 'Mary']",
              },
              summary: {
                type: "string", // specify the parameter type as a string
                description: "Summary of the meeting.",
              },
            },
            required: ["date", "attendees", "summary"],
          },
        },
        extractActionItems: {
          name: "extractActionItems",
          description:
            "Extract a list of action item objects from the meeting notes.",
          parameters: {
            type: "object",
            properties: {
              actionItems: {
                type: "array",
                items: {
                  type: "object",
                  properties: {
                    relatedTo: {
                      type: "string",
                      description:
                        "The name of the person or item the task is related to, e.g John Smith",
                    },
                    assignedTo: {
                      type: "string",
                      description:
                        "The person the task is assigned to, e.g Me, Mary Smith",
                    },
                    dueDate: {
                      type: "string",
                      description:
                        "The date when the task is due, e.g 28 July 2023",
                    },
                    action: {
                      type: "string",
                      description:
                        "The task which needs to be done, e.g Setup onboarding materials",
                    },
                  },
                },
              },
            },
            required: ["actionItems"],
          },
        },
      },
    },
  },

Any help would be greatly appreciated. I’ve been stuck on this for some time now.

Hello @amartyasingh84 and welcome to the forum.

Sorry, for my late reply.

In the recommend solution, I put an extra required field for the function calls in the schema.
I don’t know, if this helps.
It seems also depending on the model be used.

I do not follow the development more closely like weeks before, because my priorities changed.

I hope my suggestion helps.

1 Like

+1 for adding multi-function calls as a feature to API

1 Like

You can actually do better than this. You can force the API to use a specific function called “response_with_multi_func_calls”. You can include a parameter called “reply” to capture a natural language response at the same time you also call multiple functions. To handle multiple function calls, add a parameter to “response_with_multi_func_calls” called “func_calls”. Make the parameter an array of objects. Give the objects a definition like:

properties: {
    name:{type:'string',description:'The unqualified name of the function to call from your set of known functions.'},
    args:{type:'object',description:'Set the function call arguments on this object using the definition of the function being called.',
    properties:{
        delete_me:{type:'string',description:'You MUST remove this placeholder property (name and value) and add the actual arguments from the function definition being invoked.'}
                                }
                            }
                        },
                        required:['name','arguments']

Then in the system prompt put something like “You must use the “response_with_multi_func_calls” function’s “func_calls” parameter in order to invoke secondary functions in the same way that you invoke “response_with_multi_func_calls”. You must set the function name and an argument object representing its arguments.” It’s a hack for sure, but this has worked for me without any real issue since functions were released other than it sometimes prepends “functions.” to the function names being called which I just look for and ignore.

1 Like

I’ve been stuck for awhile as well in implementing emulated function calls as I’m planning to create an AI tutor that assists me in the English language. There are instances that it works well but there are also times that it outputs this error “InvalidRequestError: Invalid value for ‘content’: expected a string, got null.” Let me know if there are incorrect approaches done in my function call and I am open to suggestions to improve the performance of my personal project.

{
    "name": "error_checker_function",
    "description":"Call three functions in one call",
    "parameters":{
        "type":"object",
        "properties":{
            "check_grammatical_error":{
                "name":"check_grammatical_error",
                "description": "Check for grammatical errors from the input",
                "parameters":{
                    "type":"object",
                    "properties":{
                        "grammar_error":{
                            "type":"string",
                            "description":"Parts of a text that do not follow standard English grammar rules, e.g I is happy"
                        },
                        "grammar_correction":{
                            "type":"string",
                            "description":"Correct the grammatical error that violates English grammar rules from the input, e.g. Instead of saying 'I is happy' it should be 'I'm happy' or 'I am happy'"
                        }
                    },
                    "required": ["grammar_error", "grammar_correction"],
                }
            },
            "check_spelling_error":{
                "name":"check_spelling_error",
                "description": "Check for spelling errors from the input",
                "parameters":{
                    "type":"object",
                    "properties":{
                        "spelling_error":{
                            "type":"string",
                            "description":"Mistakes made in writing when the proper letter arrangement in a word is not followed in the English language, e.g 'Riecive'; 'Acomodate'"
                        },
                        "spelling_correction":{
                            "type":"string",
                            "description":"Correct the improper letter arrangement done from the input, e.g. 'Receive' is the proper spelling and not 'Riecive'; 'Accomodate' is the correct spelling, not 'Acomodate'"
                        }
                    },
                    "required": ["spelling_error", "spelling_correction"],
                }
            },
            "check_improper_punctuations":{
                "name":"check_improper_punctuations",
                "description": "Check for imporer punctuations usage from the input",
                "parameters":{
                    "type":"object",
                    "properties":{
                        "punctuation_error":{
                            "type":"string",
                            "description":"Incorrect punctuation usage that does not follow proper English punctuation rules, e.g The cat's are playful"
                        },
                        "punctuation_correction":{
                            "type":"string",
                            "description":"Correct the improper usage of punctuations from the input, e.g. Instead of saying 'The cat's are playful' it should be 'The cats are playful'"
                        }
                    },
                    "required": ["punctuation_error", "punctuation_correction"],
                }
            }
        }, "required":["check_grammatical_error","check_spelling_error","check_improper_punctuations"]
    }
}

I am wondering if it’s possible to add more functions to your current schema and ultimately allow GPT to output scripts like what Microsoft did in their GPT robotic paper. [ChatGPT for Robotics]

When one actually examines the language that the AI receives from trying to make these combined multi-purpose functions, one does not see the benefit beyond increased confusion.

In fact, the reason why trying to follow examples seen in this topic won’t work well is that second-level nested objects are not provided any description to the AI, so it has nothing to go on except the property name.

1 Like

Sure, of course. You can put more properties as multiple functions. I do not now the fuzzy limit, when the AI stops to call the function correctly under a specified threshold.
It is important to give reasonable descriptions to the fields added.

That makes a lot of sense. But is it documented anywhere? Or is there a way to find out what is being sent to the model?

They are not documented, but they are discovered.

and an example of my extraction of someone’s very bad function:

1 Like

@PriNova

Thanks for sharing this, works like a charm. Also I didn’t know that you can embed properties inside properties, neat stuff.

1 Like

My advice is don’t do it because it’s not scalable and you will get inconsistent results making it much harder to debug.

Adding multiple calls to a single prompt will only cause the model to lose focus and increase the chance of hallucinating function input values.

This means that to get a more accurate response you need to use a more powerful model like GPT4 instead of 3.5 and potentially use one with a larger context window (if you have lot of calls to make).
This results in increased cost and slower response times.

Imagine if you have to execute 10 function calls to get the answer you want and they are all crammed into the same prompt and then the model chokes on the 10th function call and produces malformed JSON or it simply runs out of context leaving you with a half written response. In that scenario you have to send all 10 function calls back to the model to be reprocessed.

A better approach if you want a faster response for multiple calls is to put each call in its own prompt/completion and execute the http requests in parallel.

That way each function call is given the models full attention and you can use a model with a smaller context window and fewer parameters. It also means that you only have to send 1 function call back to the model if the response is malformed.
So it should work out cheaper, with more consistent results and be faster while also being easier to debug.

Then I would say the principle of separating concerns/responsibilities is not fulfilled. I assume, this is why in the ChatGPT web app you can only choose 3 plugins simultaneously.

I solved it by providing examples. However, I’m still wondering how the example I pass can have an effect on the content generated. Since I’m pretty sure that it’s not only influencing the format.

Since the API change to call multiple function calls https://platform.openai.com/docs/guides/function-calling, this thread is marked as solved.