Search code examples
pythonnlpazure-openaigpt-4

How can I use structured_output with Azure OpenAI with the openai Python library?


I want to use structured output with Azure OpenAI.

I tried the following code, based on the code given in https://openai.com/index/introducing-structured-outputs-in-the-api/:

from pydantic import BaseModel
from openai import AzureOpenAI

class Step(BaseModel):
    explanation: str
    output: str


class MathResponse(BaseModel):
    steps: list[Step]
    final_answer: str


client = AzureOpenAI(api_key='[redacted]',
                     api_version='2024-05-01-preview',
                     azure_endpoint='[redacted]')

completion = client.beta.chat.completions.parse(
    model="gpt-4omini-2024-07-18-name",
    messages=[
        {"role": "system", "content": "You are a helpful math tutor."},
        {"role": "user", "content": "solve 8x + 31 = 2"},
    ],
    response_format=MathResponse,
)

message = completion.choices[0].message
if message.parsed:
    print(message.parsed.steps)
    print(message.parsed.final_answer)
else:
    print(message.refusal)

I get the error:

openai.BadRequestError: Error code: 400:
{
    "error": {
        "message": "Invalid parameter: response_format must be one of json_object, text.",
        "type": "invalid_request_error",
        "param": "response_format",
        "code": "None"
    }
}

How to fix it?

I ran pip install -U openai: I use openai==1.40.1 and Python 3.11.


I also tried https://cookbook.openai.com/examples/structured_outputs_intro using using Azure+ GPT-4o mini (2024-07-18), it didn't work either, same error message:

from openai import AzureOpenAI

# Replace these variables with your Azure OpenAI endpoint and API key
endpoint = "https://<your-resource-name>.openai.azure.com"
api_key = "<your-api-key>"
deployment_name = "<your-deployment-name>" # Replace with your deployment name
MODEL = deployment_name

# API endpoint for the completion request
api_url = f"{endpoint}/openai/deployments/{deployment_name}/chat/completions?api-version=2024-06-01"


client = AzureOpenAI(api_key='[redacted]',
                     api_version='2024-07-01-preview',
                     azure_endpoint='https://[redacted].openai.azure.com/')

math_tutor_prompt = '''
    You are a helpful math tutor. You will be provided with a math problem,
    and your goal will be to output a step by step solution, along with a final answer.
    For each step, just provide the output as an equation use the explanation field to detail the reasoning.
'''

def get_math_solution(question):
    response = client.chat.completions.create(
    model=MODEL,
    messages=[
        {
            "role": "system",
            "content": math_tutor_prompt
        },
        {
            "role": "user",
            "content": question
        }
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "math_reasoning",
            "schema": {
                "type": "object",
                "properties": {
                    "steps": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "explanation": {"type": "string"},
                                "output": {"type": "string"}
                            },
                            "required": ["explanation", "output"],
                            "additionalProperties": False
                        }
                    },
                    "final_answer": {"type": "string"}
                },
                "required": ["steps", "final_answer"],
                "additionalProperties": False
            },
            "strict": True
        }
    }
    )

    return response.choices[0].message


# Testing with an example question
question = "how can I solve 8x + 7 = -23"

result = get_math_solution(question)

print(result.content)

Solution

  • Using gpt-4o-2024-08-06, which finally got deployed today (2024-09-03) on Azure, made it work. Code example from learn.microsoft.com:

    from pydantic import BaseModel
    from openai import AzureOpenAI
    
    endpoint = "https://your-azure-openai-endpoint.com"
    api_key = "your-azure-openai-key"
    deployment_name = 'deployment name' # Replace with your gpt-4o 2024-08-06 deployment name
    
    client = AzureOpenAI(api_key=api_key,
                         api_version='2024-08-01-preview',
                         azure_endpoint=endpoint)
    
    class CalendarEvent(BaseModel):
        name: str
        date: str
        participants: list[str]
    
    completion = client.beta.chat.completions.parse(
        model=deployment_name, # replace with the model deployment name of your gpt-4o 2024-08-06 deployment
        messages=[
            {"role": "system", "content": "Extract the event information."},
            {"role": "user", "content": "Alice and Bob are going to a science fair on Friday."},
        ],
        response_format=CalendarEvent,
    )
    
    event = completion.choices[0].message.parsed
    
    print(event)
    print(completion.model_dump_json(indent=2))
    

    output:

    name='Science Fair' date='Friday' participants=['Alice', 'Bob']
    {
      "id": "chatcmpl-A3XDRVolXpjeAAQIGddswI990weid",
      "choices": [
        {
          "finish_reason": "stop",
          "index": 0,
          "logprobs": null,
          "message": {
            "content": "{\"name\":\"Science Fair\",\"date\":\"Friday\",\"participants\":[\"Alice\",\"Bob\"]}",
            "refusal": null,
            "role": "assistant",
            "function_call": null,
            "tool_calls": [],
            "parsed": {
              "name": "Science Fair",
              "date": "Friday",
              "participants": [
                "Alice",
                "Bob"
              ]
            }
          },
          "content_filter_results": {
            "hate": {
              "filtered": false,
              "severity": "safe"
            },
            "self_harm": {
              "filtered": false,
              "severity": "safe"
            },
            "sexual": {
              "filtered": false,
              "severity": "safe"
            },
            "violence": {
              "filtered": false,
              "severity": "safe"
            }
          }
        }
      ],
      "created": 1725406029,
      "model": "gpt-4o-2024-08-06",
      "object": "chat.completion",
      "service_tier": null,
      "system_fingerprint": "fp_b2ffeb31ff",
      "usage": {
        "completion_tokens": 17,
        "prompt_tokens": 32,
        "total_tokens": 49
      },
      "prompt_filter_results": [
        {
          "prompt_index": 0,
          "content_filter_results": {
            "hate": {
              "filtered": false,
              "severity": "safe"
            },
            "self_harm": {
              "filtered": false,
              "severity": "safe"
            },
            "sexual": {
              "filtered": false,
              "severity": "safe"
            },
            "violence": {
              "filtered": false,
              "severity": "safe"
            }
          }
        }
      ]
    }
    

    Tested with Python 3.11.7 and openai==1.43.0.