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

Structured Outputs fail with gpt4o when Zod schema includes pattern

Open jbeoris opened this issue 1 year ago • 2 comments
trafficstars

Confirm this is a Node library issue and not an underlying OpenAI API issue

  • [X] This is an issue with the Node library

Describe the bug

There is currently an issue when passing a Zod schema containg z.ZodStrings with patterns the new gpt4o structure outputs API with the NodeJS library.

For instance:

const MySchema = z.object({ myString: z.string().includes('my-pattern') })

results in the following error:

BadRequestError: 400 Invalid schema for response_format 'my-schema': In context=('properties', 'myString'), 'pattern' is not permitted

I have temporarily fixed this by wrapping all schemas passed to this endpoint with the following recursive removal code below.

function removeStringIncludes(schema: z.ZodTypeAny): z.ZodTypeAny {
  if (schema instanceof z.ZodString) {
    return z.string();
  } else if (schema instanceof z.ZodObject) {
    const newShape: { [k: string]: z.ZodTypeAny } = {};
    Object.entries(schema.shape).forEach(([key, value]) => {
      newShape[key] = removeStringIncludes(value as z.ZodTypeAny);
    });
    return z.object(newShape);
  } else if (schema instanceof z.ZodArray) {
    return z.array(removeStringIncludes(schema.element));
  } else if (schema instanceof z.ZodEnum) {
    return z.enum(schema._def.values.map((v: any) => removeStringIncludes(v)));
  } else if (schema instanceof z.ZodUnion) {
    return z.union(schema.options.map(removeStringIncludes));
  } else if (schema instanceof z.ZodIntersection) {
    return z.intersection(
      removeStringIncludes(schema._def.left),
      removeStringIncludes(schema._def.right)
    );
  }
  
  return schema;
}

It would be nice for OpenAI to support all schemas, as there are lots of validations baked into Zod schemas that are really convenient and having to work around this and strip them out while passing them to the API is tedious and weakens the power of the almighty Zod.

To Reproduce

pass this schema via zodResponseFormat(mySchema, 'schema') to the new structure outputs endpoint with the sdk.

const MySchema = z.object({ myString: z.string().includes('my-pattern') })'

Code snippets

No response

OS

macOS

Node version

Node v18.18.2

Library version

openai v4.55.0

jbeoris avatar Aug 09 '24 20:08 jbeoris

what exactly is the problem with this schema? what does it mean?

BadRequestError: 400 Invalid schema for response_format 'my-schema': In context=('properties', 'myString'), 'pattern' is not permitted

does it mean the specific keyword pattern is not permitted?

sreeprasannar avatar Aug 23 '24 22:08 sreeprasannar

what exactly is the problem with this schema? what does it mean?

BadRequestError: 400 Invalid schema for response_format 'my-schema': In context=('properties', 'myString'), 'pattern' is not permitted

does it mean the specific keyword pattern is not permitted?

Yes. pattern is not supported

peterje avatar Aug 23 '24 22:08 peterje

Sadly there isn't anything we can really do about this at the SDK layer as pattern is not supported by the API.

RobertCraigie avatar Jul 10 '25 11:07 RobertCraigie