OpenAI 400 Error about JSON and and String

This is my code:

import csv
from datetime import datetime, timedelta
import openai
import os
import re
import json

# Set the working directory to the script's directory
os.chdir(os.path.dirname(os.path.abspath(__file__)))

# Function to book a date
def book_date(date, phone_number):
    file_path = 'bookings.csv'
    today = datetime.now()
    one_month_later = today + timedelta(days=30)

    # Regex pattern for Quebec phone numbers
    phone_pattern = re.compile(r"\(?(418|438|450|514|579|581|819|873)\)?[\s-]?[0-9]{3}[\s-]?[0-9]{4}")

    # Validating the date format
    try:
        requested_date = datetime.strptime(date, "%Y-%m-%d-%H-%M")
    except ValueError:
        return "Invalid date format. Please use YYYY-MM-DD-HH-MM."

    # Validating the phone number format
    if not phone_pattern.match(phone_number):
        return "Invalid Quebec phone number format."

    # Validating the booking date range
    if not (today <= requested_date <= one_month_later):
        return "Booking date must be today or within one month from today and not in the past."

    # Creating the file if it does not exist
    if not os.path.exists(file_path):
        with open(file_path, mode='w', newline='') as file:
            writer = csv.writer(file)
            writer.writerow(['Date', 'Booking'])

    bookings = []
    date_booked = False
    phone_booked = False

    # Reading existing bookings
    with open(file_path, mode='r', newline='') as file:
        reader = csv.reader(file)
        header = next(reader, ['Date', 'Booking'])

        for row in reader:
            if len(row) > 1:
                booked_date = datetime.strptime(row[0], "%Y-%m-%d-%H-%M")
                if row[0] == date:
                    date_booked = True
                if "Booked by " + phone_number in row[1]:
                    if today <= booked_date <= one_month_later:
                        phone_booked = True
                bookings.append(row)

    # Checking if the phone number or date is already booked
    if phone_booked:
        return "This phone number already has an active booking."
    if date_booked:
        return "Already Booked"

    # Inserting new booking in sorted order
    new_booking = [date, f"Booked by {phone_number}"]
    bookings.append(new_booking)
    bookings.sort(key=lambda x: datetime.strptime(x[0], "%Y-%m-%d-%H-%M"))

    # Writing updated bookings to the file
    with open(file_path, mode='w', newline='') as file:
        writer = csv.writer(file)
        writer.writerow(header)
        writer.writerows(bookings)

    return "Booking Successful"

# Initialize OpenAI client
client = openai.Client(api_key=os.getenv("OPENAI_API_KEY"))

# Main script to process user input and function calls
def main():
    user_input = input("Input: ")

    messageList = [
        {
            "role": "system",
            "content": f"The current date is: {datetime.now().strftime('%Y-%m-%d %A')}\nDon't make assumptions about what values to plug into functions. You must ask for clarification if a user request does not provide all needed info (Exact Hour and Minute)"
        },
        {
            "role": "user",
            "content": user_input
        }
    ]

    # First API Call
    response = client.chat.completions.create(
        model="gpt-4-1106-preview",
        tools=[
            {
                "type": "function",
                "function": {
                    "name": "book_date",
                    "description": "Book a date using a specific format",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "date": {
                                "type": "string",
                                "description": "The date to book in YYYY-MM-DD-HH-MM format. 24H Format"
                            },
                            "phone_number": {
                                "type": "string",
                                "description": "The phone number for booking in this format: (###) ###-####"
                            }
                        },
                        "required": ["date", "phone_number"]
                    }
                }
            }
        ],
        messages=messageList,
        temperature=0.7
    )

    # Check if a tool call was made
    if response.choices[0].message.tool_calls:
        chosen_function = response.choices[0].message.tool_calls[0]

        if chosen_function.function.name == "book_date":

            chosen_arguments = json.loads(chosen_function.function.arguments)
            called_function = book_date(chosen_arguments["date"], chosen_arguments["phone_number"])
            
            print(called_function)

            # Append the function call response correctly with tool_call_id
            messageList.append({
                "role": "assistant",
                "tool_calls": [{
                    "id": chosen_function.id,
                    "function": {
                        "name":  chosen_function.function,
                        "output": called_function,  # Ensure the output is an object if required by the API
                        "type": "string",
                    },
                    "type": "function"
                }],
            })

    print(response)

    newinput = input("Input: ")

    messageList.append({
        "role": "user",
        "content": newinput
    })

    # Second API Call
    newresponse = client.chat.completions.create(
        model="gpt-4-1106-preview",
        tools=[
            {
                "type": "function",
                "function": {
                    "name": "book_date",
                    "description": "Book a date using a specific format",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "date": {
                                "type": "string",
                                "description": "The date to book in YYYY-MM-DD-HH-MM format. 24H Format"
                            },
                            "phone_number": {
                                "type": "string",
                                "description": "The phone number for booking in this format: (###) ###-####"
                            }
                        },
                        "required": ["date", "phone_number"]
                    }
                }
            }
        ],
        messages=messageList,
        temperature=0.7
    )

    print(newresponse)

if __name__ == "__main__":
    main()

I am always getting this error:

Traceback (most recent call last):
  File "/Users/andrewzhuang/Programming/Python/Car_Repair/robot.py", line 193, in <module>
    main()
  File "/Users/andrewzhuang/Programming/Python/Car_Repair/robot.py", line 161, in main
    newresponse = client.chat.completions.create(
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/openai/_utils/_utils.py", line 271, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/openai/resources/chat/completions.py", line 643, in create
    return self._post(
           ^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/openai/_base_client.py", line 1091, in post
    return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/openai/_base_client.py", line 852, in request
    return self._request(
           ^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/openai/_base_client.py", line 933, in _request
    raise self._make_status_error_from_response(err.response) from None
openai.BadRequestError: Error code: 400 - {'error': {'message': '{\'arguments\': \'{"date":"2024-01-21-00-00","phone_number":"(514) 678-2189"}\', \'name\': \'book_date\'} is not of type \'string\' - \'messages.2.tool_calls.0.function.name\'', 'type': 'invalid_request_error', 'param': None, 'code': None}}

Hi @YourAverageDev

You shouldn’t pass the tools when you are replying with the response of the function call.

Also here’s the correct way to append the function call response to the end of messages to be passed to the model:

messages.push({
        tool_call_id: toolCall.id,
        role: "tool",
        name: functionName,
        content: functionResponse,
      }); // extend conversation with function response

Ty, Just found the errors in my code, fixed it. For people that need it, here’s my updated code

import csv
from datetime import datetime, timedelta
import openai
import os
import re
import json

# Set the working directory to the script's directory
os.chdir(os.path.dirname(os.path.abspath(__file__)))

# Function to book a date
def book_date(date, phone_number):
    file_path = 'bookings.csv'
    today = datetime.now()
    one_month_later = today + timedelta(days=30)

    # Regex pattern for Quebec phone numbers
    phone_pattern = re.compile(r"\(?(418|438|450|514|579|581|819|873)\)?[\s-]?[0-9]{3}[\s-]?[0-9]{4}")

    # Validating the date format
    try:
        requested_date = datetime.strptime(date, "%Y-%m-%d-%H-%M")
    except ValueError:
        return "Invalid date format. Please use YYYY-MM-DD-HH-MM."

    # Validating the phone number format
    if not phone_pattern.match(phone_number):
        return "Invalid Quebec phone number format."

    # Validating the booking date range
    if not (today <= requested_date <= one_month_later):
        return "Booking date must be today or within one month from today and not in the past."

    # Creating the file if it does not exist
    if not os.path.exists(file_path):
        with open(file_path, mode='w', newline='') as file:
            writer = csv.writer(file)
            writer.writerow(['Date', 'Booking'])

    bookings = []
    date_booked = False
    phone_booked = False

    # Reading existing bookings
    with open(file_path, mode='r', newline='') as file:
        reader = csv.reader(file)
        header = next(reader, ['Date', 'Booking'])

        for row in reader:
            if len(row) > 1:
                booked_date = datetime.strptime(row[0], "%Y-%m-%d-%H-%M")
                if row[0] == date:
                    date_booked = True
                if "Booked by " + phone_number in row[1]:
                    if today <= booked_date <= one_month_later:
                        phone_booked = True
                bookings.append(row)

    # Checking if the phone number or date is already booked
    if phone_booked:
        return "This phone number already has an active booking."
    if date_booked:
        return "Already Booked"

    # Inserting new booking in sorted order
    new_booking = [date, f"Booked by {phone_number}"]
    bookings.append(new_booking)
    bookings.sort(key=lambda x: datetime.strptime(x[0], "%Y-%m-%d-%H-%M"))

    # Writing updated bookings to the file
    with open(file_path, mode='w', newline='') as file:
        writer = csv.writer(file)
        writer.writerow(header)
        writer.writerows(bookings)

    return "Booking Successful"

# Initialize OpenAI client
client = openai.Client(api_key=os.getenv("OPENAI_API_KEY"))

# Main script to process user input and function calls




messageList = [
    {
        "role": "system",
        "content": f"The current date is: {datetime.now().strftime('%Y-%m-%d %A')}\nDon't make assumptions about what values to plug into functions. You must ask for clarification if a user request does not provide all needed info (Exact Hour and Minute). When a function is called, you also must provide a response to the user."
    }
]

while True:

    user_input = input("Input: ")

    messageList.append({
            "role": "user",
            "content": user_input
        })

    # First API Call
    response = client.chat.completions.create(
        model="gpt-3.5-turbo-1106",
        tools=[
            {
                "type": "function",
                "function": {
                    "name": "book_date",
                    "description": "Book a date using a specific format",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "date": {
                                "type": "string",
                                "description": "The date to book in YYYY-MM-DD-HH-MM format. 24H Format"
                            },
                            "phone_number": {
                                "type": "string",
                                "description": "The phone number for booking in this format: (###) ###-####"
                            }
                        },
                        "required": ["date", "phone_number"]
                    }
                }
            }
        ],
        messages=messageList,
        temperature=0.7
    )

    response_message = response.choices[0].message

    messageList.append(response_message)

    tool_calls = response_message.tool_calls


    if tool_calls:
            available_functions = {
                "book_date": book_date,
            }

            for tool_call in tool_calls:
                function_name = tool_call.function.name
                function_to_call = available_functions[function_name]
                function_args = json.loads(tool_call.function.arguments)
                print(function_args)
                function_response = function_to_call(
                    date=function_args.get("date"),
                    phone_number=function_args.get("phone_number"),
                )
                messageList.append(
                    {
                        "tool_call_id": tool_call.id,
                        "role": "tool",
                        "name": function_name,
                        "content": function_response,
                    }
                )  # extend conversation with function response
    print(response_message.content)
1 Like