Function calling calls the function without parameters

This is my code:

# import logging
# import time
import openai
from dotenv import find_dotenv, load_dotenv
import requests
import os
import json
# import streamlit as st

load_dotenv()

client = openai.OpenAI()
model = os.getenv("MODEL")
temperature = float(os.getenv("TEMPERATURE"))
bearer_token = os.getenv("BEARER_TOKEN")

#ibyW5IZ6nmvaw7nIMMTMz

conversation_history = []

functions = [
    {
        "name": "get_customer",
        "type": "function",
        "function": {
            "name": "get_customer",
            "description": "Get a customer's details based on their customer ID",
            "parameters": {
                "type": "object",
                "properties": {
                    "customerID": {
                        "type": "string",
                        "description": "ID of the customer"
                    }
                },
                "required": ["customerID"]
            }
        }
    }    
]

def get_customer(customerID):
    url = (
        f"https://localhost/usage-engine/customer/{customerID}"
    )

    try:
        response = requests.get(url, headers={"Authorization": "Bearer " + bearer_token})
        if response.status_code == 200:
            offers = json.dumps(response.json(), indent=4)
            customer_json = json.loads(offers)
            data = customer_json
            print(data)
            customerId = data['customerInfo']['customerId']
            createdAt = data['customerInfo']['createdAt']

            customer_details = f"""
            Customer ID: {customerId},
            Created At: {createdAt},
            """

            return customer_details
        else:
            return []
        
    except requests.exceptions.RequestException as e:
        print("Error occured during API request", e)

while True:
    user_input = input("Enter your message: ")
    if user_input!=None:
        conversation_history.append({"role": "user", "content": user_input})

    conversation_history.append({"role": "system", "content": "Don't call 'get_customer' unnessarily. Only call function 'get_customer' if all arguments are given. ask the user for the parameters if it is not present, before calling. never ever ever call the function without mandatory arguments and parameters"})

    response = client.chat.completions.create(
        model=model,
        messages=conversation_history,
        temperature=temperature,
        functions=functions,
        function_call="auto"
    )
    if response.choices[0].message.content!=None:
        conversation_history.append({"role": "assistant", "content": response.choices[0].message.content})

    # #print("Bot:",response.choices[0].message.content)
    response_message = response.choices[0].message
    print("Bot:",response_message)
    
    if dict(response_message).get('function_call'):
        
        # Which function call was invoked
        function_called = response_message.function_call.name
        
        # Extracting the arguments
        function_args  = json.loads(response_message.function_call.arguments)
        
        # Function names
        available_functions = {
            "get_customer": get_customer
        }
        
        fuction_to_call = available_functions[function_called]
        response_message = fuction_to_call(*list(function_args .values()))
        
    else:
        response_message = response_message.content

The output is:

Enter your message: i need details of a customer whose ID is ibyW5IZ6nmvaw7nIMMTMz
Bot: ChatCompletionMessage(content=None, role='assistant', function_call=FunctionCall(arguments='{}', name='get_customer'), tool_calls=None)
Traceback (most recent call last):
  File "/Users/suganth/Documents/LLM/OpenAI/main.py", line 104, in <module>
    response_message = fuction_to_call(*list(function_args .values()))
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: get_customer() missing 1 required positional argument: 'customerID'

Hey,

Is there a reason the system message is not first? Tried it out and putting it first seems to work well.

1 Like

I changed it and I got this response. The ID is not being set, even though if I provide it explicitly:

Enter your message: hi
Bot: ChatCompletionMessage(content='Hello! How can I assist you today?', role='assistant', function_call=None, tool_calls=None)
Enter your message: can i get the details of the customer ibyW5IZ6nmvaw7nIMMTMz
Bot: ChatCompletionMessage(content='Sure! To get the details of the customer with the ID "ibyW5IZ6nmvaw7nIMMTMz", I need to call the `get_customer` function. However, I need some additional information to proceed. Could you please provide the necessary parameters for the function call?', role='assistant', function_call=None, tool_calls=None)
Enter your message: the ID is ibyW5IZ6nmvaw7nIMMTMz
Bot: ChatCompletionMessage(content=None, role='assistant', function_call=FunctionCall(arguments='{}', name='get_customer'), tool_calls=None)
Traceback (most recent call last):
  File "/Users/suganth/Documents/LLM/OpenAI/main.py", line 103, in <module>
    response_message = fuction_to_call(*list(function_args .values()))
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: get_customer() missing 1 required positional argument: 'customerID'

Where is the system message here?

Without looking to much at the code itself (sorry if I’m missing something), I think it would be better if the system message is added first, and outside of the loop.

I did an attempt of a single call with your provided input and I got the expected result, see the following playground screenshot (you can also see the model configuration I’ve been using):

1 Like

Apologies for not providing the changed code earlier. This is the changed code that I was talking about:

# import logging
# import time
import openai
from dotenv import find_dotenv, load_dotenv
import requests
import os
import json
# import streamlit as st

load_dotenv()

client = openai.OpenAI()
model = os.getenv("MODEL")
temperature = float(os.getenv("TEMPERATURE"))
bearer_token = os.getenv("BEARER_TOKEN")

#ibyW5IZ6nmvaw7nIMMTMz

conversation_history = []
conversation_history.append({"role": "system", "content": "Don't call 'get_customer' unnessarily. Only call function 'get_customer' if all arguments are given. ask the user for the parameters if it is not present, before calling. never ever ever call the function without mandatory arguments and parameters"})

functions = [
    {
        "name": "get_customer",
        "type": "function",
        "function": {
            "name": "get_customer",
            "description": "Get a customer's details based on their customer ID",
            "parameters": {
                "type": "object",
                "properties": {
                    "customerID": {
                        "type": "string",
                        "description": "ID of the customer"
                    }
                },
                "required": ["customerID"]
            }
        }
    }    
]

def get_customer(customerID):
    url = (
        f"https://api.test.blu-ocean.net/usage-engine/customer/{customerID}"
    )

    try:
        response = requests.get(url, headers={"Authorization": "Bearer " + bearer_token})
        if response.status_code == 200:
            offers = json.dumps(response.json(), indent=4)
            customer_json = json.loads(offers)
            data = customer_json
            print(data)
            customerId = data['customerInfo']['customerId']
            createdAt = data['customerInfo']['createdAt']

            customer_details = f"""
            Customer ID: {customerId},
            Created At: {createdAt},
            """

            return customer_details
        else:
            return []
        
    except requests.exceptions.RequestException as e:
        print("Error occured during API request", e)

while True:
    user_input = input("Enter your message: ")
    if user_input!=None:
        conversation_history.append({"role": "user", "content": user_input})

    response = client.chat.completions.create(
        model=model,
        messages=conversation_history,
        temperature=temperature,
        functions=functions,
        function_call="auto"
    )
    if response.choices[0].message.content!=None:
        conversation_history.append({"role": "assistant", "content": response.choices[0].message.content})

    # #print("Bot:",response.choices[0].message.content)
    response_message = response.choices[0].message
    print("Bot:",response_message)
    
    if dict(response_message).get('function_call'):
        
        # Which function call was invoked
        function_called = response_message.function_call.name
        
        # Extracting the arguments
        function_args  = json.loads(response_message.function_call.arguments)
        
        # Function names
        available_functions = {
            "get_customer": get_customer
        }
        
        fuction_to_call = available_functions[function_called]
        response_message = fuction_to_call(*list(function_args .values()))
        
    else:
        response_message = response_message.content

Response:

Enter your message: hi
Bot: ChatCompletionMessage(content='Hello! How can I assist you today?', role='assistant', function_call=None, tool_calls=None)
Enter your message: can i get the details of the customer ibyW5IZ6nmvaw7nIMMTMz
Bot: ChatCompletionMessage(content='Sure! To get the details of the customer with the ID "ibyW5IZ6nmvaw7nIMMTMz", I need to call the `get_customer` function. However, I need some additional information to proceed. Could you please provide the necessary parameters for the function call?', role='assistant', function_call=None, tool_calls=None)
Enter your message: the ID is ibyW5IZ6nmvaw7nIMMTMz
Bot: ChatCompletionMessage(content=None, role='assistant', function_call=FunctionCall(arguments='{}', name='get_customer'), tool_calls=None)
Traceback (most recent call last):
  File "/Users/suganth/Documents/LLM/OpenAI/main.py", line 103, in <module>
    response_message = fuction_to_call(*list(function_args .values()))
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: get_customer() missing 1 required positional argument: 'customerID'

Thanks.
What model and temperature are being used?

1 Like

Model is gpt-3.5-turbo-16k
Temperature is 0.5

Thanks.

I was trying again with the whole chat history and the same parameters and things seem to work well (the function isa called without clarification), however I was using a playground and not running your exact code.
Maybe there’s some small issue with the code itself? For debugging I’d try printing conversation_history before the call to make sure it’s exactly what you expect it to be.

1 Like

Thanks for the response. I tried printing conversation_history before I call the API, and I got this:

Enter your message: hi
[{'role': 'system', 'content': "Don't call 'get_customer' unnessarily. Only call function 'get_customer' if all arguments are given. ask the user for the parameters if it is not present, before calling. never ever ever call the function without mandatory arguments and parameters. Take ID as parameter"}, {'role': 'user', 'content': 'hi'}]
Bot: ChatCompletionMessage(content='Hello! How can I assist you today?', role='assistant', function_call=None, tool_calls=None)
Enter your message: i want to get the details of the customer with id ibyW5IZ6nmvaw7nIMMTMz
[{'role': 'system', 'content': "Don't call 'get_customer' unnessarily. Only call function 'get_customer' if all arguments are given. ask the user for the parameters if it is not present, before calling. never ever ever call the function without mandatory arguments and parameters. Take ID as parameter"}, {'role': 'user', 'content': 'hi'}, {'role': 'assistant', 'content': 'Hello! How can I assist you today?'}, {'role': 'user', 'content': 'i want to get the details of the customer with id ibyW5IZ6nmvaw7nIMMTMz'}]
Bot: ChatCompletionMessage(content=None, role='assistant', function_call=FunctionCall(arguments='{}', name='get_customer'), tool_calls=None)
Traceback (most recent call last):
  File "/Users/suganth/Documents/LLM/OpenAI/main.py", line 102, in <module>
    response_message = fuction_to_call(*list(function_args .values()))
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: get_customer() missing 1 required positional argument: 'customerID'

The inputs are as intended, but still the issue is occuring

Yes, this is rather goofy.

There should be a persistent system message first that gives the AI its identity and purpose.

system = “You are IDBot, a conversational AI assistant with database lookup skills.”

The function specifications are added to, and the AI is trained on, functions in that first system message.

messages = system + conversation_history + user

where conversation_history is a full record of every AI assistant output and every response that happened previously. That includes every AI function call (in a special format) and every return value, placed after the user input.

The function specification is where the purpose of the function, and restrictions on use are. “this function cannot be called unless an alphanumeric customer ID has been provided by the user directly in the chat”.

then returning the value to the AI so it can answer, the new messages look like

messages = system + conversation_history + user + assistant_function + function_return

using the function role.

My documentation:

1 Like

Thanks.
I’m not sure why yours doesn’t work as expected, but at lease I can see now the difference between my call and yours (sorry for missing that before!): I’m using the tools (and tool_choice) parameters for the function, and not the functions (and `function_call) one that you use (which is now deprecated btw), maybe you should try it out?

https://platform.openai.com/docs/api-reference/chat/create#chat-create-tools

1 Like

Thanks for the responses @_j and @ramn7! I incorporated changes mentioned by both of you and now the ID is being set properly. But the function is not being called. I tried adding a log at the first line of the function, it is not getting printed. Any reasons?

Code:

import openai
from dotenv import load_dotenv
import requests
import os
import json

load_dotenv()

client = openai.OpenAI()
model = os.getenv("MODEL")
temperature = float(os.getenv("TEMPERATURE"))
bearer_token = os.getenv("BEARER_TOKEN")

#ibyW5IZ6nmvaw7nIMMTMz

conversation_history = []
conversation_history.append({"role": "system", "content": "You are a DataBot. You can lookup databases and provide information. You can create data in database if requested by the user."})

tools = [
    {
        "name": "get_customer",
        "type": "function",
        "function": {
            "name": "get_customer",
            "description": "Get a customer's details based on their customer ID. This function cannot be called unless an alphanumeric customer ID has been provided by the user directly in the chat",
            "parameters": {
                "type": "object",
                "properties": {
                    "customerID": {
                        "type": "string",
                        "description": "ID of the customer"
                    }
                },
                "required": ["customerID"]
            }
        }
    }    
]

def get_customer(customerID):
    print("Entered")
    url = (
        f"https://api.test.blu-ocean.net/usage-engine/customer/{customerID}"
    )

    try:
        response = requests.get(url, headers={"Authorization": "Bearer " + bearer_token})
        if response.status_code == 200:
            offers = json.dumps(response.json(), indent=4)
            customer_json = json.loads(offers)
            data = customer_json
            print(data)
            customerId = data['customerInfo']['customerId']
            createdAt = data['customerInfo']['createdAt']

            customer_details = f"""
            Customer ID: {customerId},
            Created At: {createdAt},
            """

            return customer_details
        else:
            return []
        
    except requests.exceptions.RequestException as e:
        print("Error occured during API request", e)

while True:
    user_input = input("Enter your message: ")
    if user_input!=None:
        conversation_history.append({"role": "user", "content": user_input})
    
    response = client.chat.completions.create(
        model=model,
        messages=conversation_history,
        temperature=temperature,
        tools=tools,
        tool_choice="auto"
    )
    if response.choices[0].message.content!=None:
        conversation_history.append({"role": "assistant", "content": response.choices[0].message.content})

    # #print("Bot:",response.choices[0].message.content)
    response_message = response.choices[0].message
    print("Bot:",response_message)
    
    if dict(response_message).get('function_call'):
        
        # Which function call was invoked
        function_called = response_message.function_call.name
        
        # Extracting the arguments
        function_args  = json.loads(response_message.function_call.arguments)
        
        # Function names
        available_functions = {
            "get_customer": get_customer
        }
        
        fuction_to_call = available_functions[function_called]
        response_message = fuction_to_call(*list(function_args .values()))
        
    else:
        response_message = response_message.content

Output:

Enter your message: hi
Bot: ChatCompletionMessage(content='Hello! How can I assist you today?', role='assistant', function_call=None, tool_calls=None)
Enter your message: show me the details of the customer ibyW5IZ6nmvaw7nIMMTMz
Bot: ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_TdDR0U0yoNt7na3qblUYevuY', function=Function(arguments='{\n  "customerID": "ibyW5IZ6nmvaw7nIMMTMz"\n}', name='get_customer'), type='function')])

The call response is now in an array under tool_calls, and not function_call.

1 Like

Yes. but in the tool_calls I’m not getting the response from the function as I have provided the output. I added a print statement called “entered” at the first line of the function as you can verify. It is not being printed in the terminal, which means it is not called at all

Not sure I follow…

Your code checks for function_call field before calling the function (this is from your most recent message), am I missing something?

1 Like

Ah! My bad. Missed that part, sorry. Will make the change and let you know

There are two return types in a response, either functions, or tool_calls. The output is based on how you sent the API Request. The specification also has a different form if using tools.

It is certainly possible to write parsing code that is compatible with either return so you can switch API send methods, extracting either and then act on them.

tools requires the ID be recorded, and then both assistant and tool return you append to the conversation so far, after the most recent input, must be sent back with the ID.

2 Likes

Thanks @_j !

I was trying to help OP understand why their code wasn’t calling the function. In this case they changed the request from functions to tools but kept the code calling it looking for the function output.

1 Like

Thanks @ramn7 and @_j for your responses. I’m able to get the response now. Thank you :smiley:

1 Like