openai-python icon indicating copy to clipboard operation
openai-python copied to clipboard

Structured outputs `anyOf` schema with items sharing identical first field fails with 400.

Open AndreiSiliUiPath opened this issue 9 months ago • 0 comments

Confirm this is an issue with the Python library and not an underlying OpenAI API

  • [x] This is an issue with the Python library

Describe the bug

When using an anyOf schema in structured outputs where the corresponding object schemas share the name of the first key is identical, the API responds with 400 without any explanation of the issue.

From this post it seems we should at least get back an informative error message.

P.s. I tried posting on the developer community first but for some reason it won't let me create an account.

To Reproduce

Run the code below.

Code snippets

import asyncio
import enum

import openai
from pydantic import BaseModel, Field


class OperationType(str, enum.Enum):
    A = "a"
    B = "b"


class OperationA(BaseModel):
    name: str = Field(..., description="The name of the operation")
    type: OperationType = Field(..., description="Type of operation to perform")
    field_a: str = Field(..., description="The field on which to perform the operation")
    value_a: str = Field(..., description="The value to set for the field")


class OperationB(BaseModel):
    name: str = Field(..., description="The name of the operation")
    type: OperationType = Field(..., description="Type of operation to perform")
    field_b: str = Field(..., description="The field on which to perform the operation")
    value_b: str = Field(..., description="The value to set for the field")


class ResponseSchema(BaseModel):
    operations: list[OperationA | OperationB] = Field(..., description="The operations to perform")


async def main():
    client = openai.AzureOpenAI(
        api_key="",
        azure_endpoint="",
        api_version="2025-01-01-preview",
        timeout=120,
        max_retries=0,
    )

    response = client.beta.chat.completions.parse(
        messages=[
            {"role": "system", "content": "You are a helpful assistant that can perform operations on a JSON object."},
            {"role": "user", "content": "I want to update the field 'a' to 'b' and the field 'b' to 'a'."},
        ],
        model="o3-mini-2025-01-31",
        reasoning_effort="low",
        response_format=ResponseSchema,
    )

    return response


if __name__ == "__main__":
    asyncio.run(main())

>>> openai.BadRequestError: Error code: 400 - {'error': {'message': 'Bad request: Invalid response_format provided.', 'type': 'invalid_request_error', 'param': None, 'code': None}}

OS

Linux

Python version

Python 3.10.12

Library version

openai 1.61.0

AndreiSiliUiPath avatar Mar 13 '25 10:03 AndreiSiliUiPath