[Python] openai structured outputs schema with condition

Discussão em 'Python' iniciado por Stack, Fevereiro 11, 2025.

  1. Stack

    Stack Membro Participativo

    I’m trying to use openai structured outputs with a JSON Schema, such that: • If part1 is "yes", then part2 must be present (required). • If part1 is "no", then part2 must not be included at all.

    Below is my code, I’m attempting to enforce the conditional requirement in the allOf section. However, openai will not accept this schema because of the "allOf" part.

    How can I fix (or confirm) the JSON Schema definition to correctly handle this conditional requirement?

    import openai
    import json
    import jsonschema
    from dotenv import load_dotenv
    import os

    load_dotenv()
    api_key = os.getenv("API_KEY")
    api_version = os.getenv("API_VERSION")
    base_url = os.getenv("API_BASE_URL_4o")

    # 1. Configure OpenAI credentials
    openai.api_key = api_key
    openai.api_version = api_version
    openai.api_type = "azure"
    openai.base_url = base_url

    # 2. Define the function schema
    answer_question_function = {
    "name": "answer_question",
    "description": "Answers user question with conditional parts",
    "parameters": {
    "type": "object",
    "properties": {
    "part1": {
    "type": "string",
    "enum": ["yes", "no"],
    "description": "First part answer"
    },
    "part2": {
    "type": "string",
    "enum": ["yes", "no"],
    "description": "Second part answer; required only if part1 is yes"
    }
    },
    "required": ["part1"],
    "allOf": [
    {
    "if": {
    "properties": {
    "part1": {"const": "yes"}
    }
    },
    "then": {
    "required": ["part2"]
    }
    },
    {
    "if": {
    "properties": {
    "part1": {"const": "no"}
    }
    },
    "then": {
    "not": {"required": ["part2"]}
    }
    }
    ]
    }
    }

    # 3. Write a helper function to validate the JSON result against our schema
    def validate_function_call_arguments(args):
    schema = answer_question_function["parameters"]
    jsonschema.validate(instance=args, schema=schema)

    # 4. E2E test function
    def run_e2e_test(user_prompt):
    """
    Sends a prompt to the model, requests a function call,
    and validates the JSON arguments returned.
    """

    load_dotenv()
    api_key = os.getenv("API_KEY")
    api_version = os.getenv("API_VERSION")
    base_url = os.getenv("API_BASE_URL_4o")

    openai.api_key = api_key
    openai.api_version = api_version
    openai.api_type = "azure"
    openai.base_url = base_url

    try:
    response = openai.chat.completions.create(
    model="gpt-4o",
    messages=[
    {
    "role": "user",
    "content": user_prompt
    }
    ],
    response_format={
    "type": "json_schema",
    "json_schema": {
    "name": "answer_question",
    "schema": answer_question_function["parameters"]
    }
    },
    )

    # Check if it's a function call:
    choice = response["choices"][0]

    if choice["finish_reason"] == "function_call":
    function_call = choice["message"]["function_call"]
    function_name = function_call["name"]
    arguments_json = function_call["arguments"]

    print(f"Function called: {function_name}")
    print(f"Raw arguments: {arguments_json}")

    # Convert the JSON string into a Python dict
    arguments = json.loads(arguments_json)

    # Validate
    validate_function_call_arguments(arguments)
    print("✅ JSON arguments valid against the schema.")
    print(f"Final arguments object: {arguments}")

    else:
    # If no function call was made, print the plain text response
    print("No function call. Text response from model:")
    print(choice["message"]["content"])

    except jsonschema.ValidationError as e:
    print("❌ JSON arguments failed validation:")
    print(str(e))
    except Exception as e:
    print("❌ Something went wrong:")
    print(str(e))

    # 5. Run a few test scenarios
    if __name__ == "__main__":
    print("===== TEST: Expecting part1 = yes, then part2 is required =====")
    run_e2e_test("Should part1 be yes? If so, give me part2 too.")

    print("\n===== TEST: Expecting part1 = no, then part2 should not appear =====")
    run_e2e_test("Should part1 be no? Then we don’t want part2.")
    print()

    Continue reading...

Compartilhe esta Página