Multiple Function calling - call second function based on the response from the first function response

I have two functions : createMashup() and addMashupToTab(). Consider the scenario where the user asks to create a mashup. Here the createMashup() gets called correctly. Now if the user asks something like “add the created mashup in a tab”, I want to call the function addMashupToTab() by passing the id of the mashup created earlier. Basically, I want to know how I can get the response from a function call, take a property and when the second function call happens, pass this property as parameter. How can I do this?

You can attach metadata to the thread to track the current ID of your object.

If you want to perform these two functions at the same time then you need to ensure that in the back-end you have a priority map and sequential operations.

1 Like

Iterative function-calling is built into the model. You just have to make sure that you return to looking for more function calls after returning the first value as a function response.

Then the description of each function should be clear, stating what is required as an input before calling it, and what the expected result would be:

“name”: “addMashupToTab”,
“description”: “Cannot be called without first using createMashup to generate id. Renders a previously-created mashup ID to a graphic user interface”,

2 Likes

Tony when you are using function calls you format the calls to the local functions yourself, so if you store the mashup id after you call your createMashup() routine then when someone asks for addMashuptoTab you can format the function call to your addMashupToTab with the Mashup id you saved plus any additional parameters that you receive from the user.

1 Like

Can you help me with a small example?

What are you thinking of?

Typical exchange:

  1. system
  2. user → send
  3. assistant: tools?
  4. code: tools! → send
  5. assistant: tools?
  6. code: tools! → send
  7. assistant: answer

Simply keep getting the response. Metacode:

messages += user_message

while tool_calls != [] or function_call !=[]) \
        and not (input := user_message or tool_return or None)
    
    content, function_call, tool_calls = api_call_parse(messages + input)
    messages += input
    user_message=None
    # keep fulfilling tools with return values
    messages += function_call or tool_calls or content
    tool_return = run_functions(function_call, tool_calls)    

(PS don’t ask GPT-4o to analyze the steps are performed properly, as it just immediately damages the logic and produces multiple turns of garbage. gpt-4-0314 gives a correct analysis of step-by-step operation…)

Thanks for this! Can you also please help with how the system message should look like?

The system message should act as an instruction talking to the AI, giving it name, purpose, description of its job to perform or specialization to pay attention to.

If more complex, document structure is helpful

A basic form is “You are xxx, an AI assistant that performs xxx on the xxx website, as a backend helper without direct user interation. Process the input for xxx…”

Untitled

Why are you looking to make two separate function calls? You can achieve this with a single function call by adding an extra parameter, such as addToTab. Based on the user query, you can assign the appropriate value to this parameter(use the proper instruction) and merge the functionality of both createMashup() and addMashupToTab() into one function. Based on addToTab value you can call the second function or can ignore it.

Edit: Here is the code with single function calling

def create_mashup():
    return 'Mashup created.'
def add_mashup_to_tab():
    return 'Mashup added to tab.'

def mashup(mashup_to_tab):
    output = create_mashup()
    if mashup_to_tab:
        output = add_mashup_to_tab()
    return output

tools_list = [
    {
        "type": "function",
        "function": {
            "name": "mashup",
            "description": "",
            "parameters": {
                "type": "object",
                "properties": {
                    "mashup_to_tab": {
                        "type": "boolean",
                        "description": "this parameter is True if user wants to add mashup to tab else False"
                    },
                     
                },
                "required": ["mashup_to_tab"]
            }
        }
    }
]

# Create an Assistant using the tools list 

assistant = client.beta.assistants.create(
    name="Mashup Assistant",
    instructions="""You are an expert in mashup, if user doesn't want add mashup to tab then mashup_to_tab should be False else True. You should return the output of the function call""",
    tools= tools_list,
    model="gpt-4o",
)

I agree with @darkknight, but if you do want to make two or more function calls, all you have to know is if you have a function that requires a value from a previous function call you can append the value to your list of arguments before making the local function call. In the example below I have a function called greet that requires three parameters, when I create the tools list for the assistant, I only make it aware of two of the three parameters. Before making the function call I add the third parameter after the two that have been pulled from the prompt.

Create a local function called greet that requires three parameters

def greet(name, greeting, punctuation):
    greeting_id = str('\n'+name+' '+greeting+' '+punctuation)
    return greeting_id 

Create the tool list for an assistant where the third parameter, punctation is omitted.


tools_list = [
    {
        "type": "function",
        "function": {
            "name": "greet",
            "description": "",
            "parameters": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "name of person to be greeted"
                    },
                     "greeting": {
                        "type": "string",
                        "description": "greeting text"
                    },
                     
                },
                "required": ["name", "greeting:"]
            }
        }
    }
]

# Create an Assistant using the tools list 

assistant = client.beta.assistants.create(
    name="greeting Assistant",
    instructions="""You are an expert in create a polite greeting""",
    tools= tools_list,
    model="gpt-4o",
)

When it comes time to call the function take the parameters name and greeting from the user prompt but before calling the function add the third parameter, punctuation to the tuple of arguments.

while run.status == 'requires_action':
    
    function_names = []
    outputs = []
    call_ids = []
    tool_outputs=[]

    # get the tool calls to be made from the run object 
    tool_calls = run.required_action.submit_tool_outputs.tool_calls
    
    # This for loop is for when there are multiple tool calls in a required action step   
    
    for tc in tool_calls:
        
        # save the call_id to pass back to run object later along with the result of the function call  
        call_ids.append(tc.id)
        
        # Get the function name to be called 
        function_names.append(tc.function.name)
    

        # Arguments are in JSON format, parse them into a Python dictionary

        arguments = json.loads(tc.function.arguments)
        
        arg_tuple = ()
        
        punctuation = '!!!'
        
        for key,value in arguments.items():
            arg_tuple += (value,)

        # add the third argument to the tuple before calling greet
        arg_tuple += (punctuation,)  

    # make all the function calls required 
    
    for fn in function_names: 
        # call the local function using the function name and the tuple of arguments 
        result = globals()[fn](*arg_tuple)
        print ('\n function name called:',fn,'\n argument:',arg_tuple,'result: ',result)
        # save the results 
        outputs.append(result)

.

I agree. I have added the code with single function calling in my previous response.