openai-zod-validator
v1.0.0
Published
Structured output validation and transformation tool for OpenAI SDK 6 with Zod 4 schema validation
Maintainers
Readme
OpenAI Zod Validator
A powerful TypeScript library for validating OpenAI SDK 6 structured outputs and function calls using Zod 4 schemas. Ensures type-safe AI responses with full TypeScript inference.
Features
- ✅ Full TypeScript support with type inference
- ✅ Compatible with OpenAI SDK 6.x
- ✅ Built for Zod 4.x schemas
- ✅ Validates structured outputs, function calls, and tool calls
- ✅ Convert Zod schemas to OpenAI function parameters
- ✅ Comprehensive error handling
- ✅ Zero configuration required
Installation
npm install openai-zod-validator openai zodQuick Start
import OpenAI from 'openai';
import { z } from 'zod';
import { createOpenAIValidator } from 'openai-zod-validator';
// Define your Zod schema
const ResponseSchema = z.object({
name: z.string(),
age: z.number(),
email: z.string().email(),
});
// Create a validator
const validator = createOpenAIValidator(ResponseSchema);
// Use with OpenAI
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const completion = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Generate user data' }],
response_format: { type: 'json_object' },
});
// Validate the response
const result = validator.validateCompletion(completion);
console.log(result.data); // Fully typed as { name: string; age: number; email: string }Usage with OpenAI SDK 6
1. Structured Outputs (JSON Mode)
import OpenAI from 'openai';
import { z } from 'zod';
import { createOpenAIValidator } from 'openai-zod-validator';
const openai = new OpenAI();
// Define schema
const RecipeSchema = z.object({
name: z.string(),
ingredients: z.array(z.string()),
steps: z.array(z.string()),
cookingTime: z.number(),
});
const validator = createOpenAIValidator(RecipeSchema);
async function generateRecipe() {
const completion = await openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'user',
content: 'Generate a recipe for chocolate chip cookies',
},
],
response_format: { type: 'json_object' },
});
const result = validator.validateCompletion(completion);
if (result.success) {
console.log('Recipe:', result.data); // Fully typed!
} else {
console.error('Validation errors:', result.errors);
}
}2. Function Calling
import OpenAI from 'openai';
import { z } from 'zod';
import { createOpenAIValidator, zodToOpenAIParameters } from 'openai-zod-validator';
const openai = new OpenAI();
// Define function parameter schema
const GetWeatherSchema = z.object({
location: z.string(),
unit: z.enum(['celsius', 'fahrenheit']),
});
const validator = createOpenAIValidator(GetWeatherSchema);
async function callWithFunctions() {
const completion = await openai.chat.completions.create({
model: 'gpt-4',
messages: [
{
role: 'user',
content: 'What is the weather in San Francisco?',
},
],
functions: [
{
name: 'get_weather',
description: 'Get the current weather in a location',
parameters: zodToOpenAIParameters(GetWeatherSchema),
},
],
function_call: 'auto',
});
const message = completion.choices[0]?.message;
if (message?.function_call) {
const result = validator.validateFunctionCall(message.function_call);
if (result.success) {
console.log('Function arguments:', result.data);
// result.data is typed as { location: string; unit: 'celsius' | 'fahrenheit' }
}
}
}3. Tool Calls (OpenAI SDK 6 Tools API)
import OpenAI from 'openai';
import { z } from 'zod';
import { createOpenAIValidator, zodToOpenAIParameters } from 'openai-zod-validator';
const openai = new OpenAI();
const SearchSchema = z.object({
query: z.string(),
limit: z.number().optional(),
});
const validator = createOpenAIValidator(SearchSchema);
async function callWithTools() {
const completion = await openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'user',
content: 'Search for TypeScript tutorials',
},
],
tools: [
{
type: 'function',
function: {
name: 'search',
description: 'Search for content',
parameters: zodToOpenAIParameters(SearchSchema),
},
},
],
});
const message = completion.choices[0]?.message;
if (message?.tool_calls) {
for (const toolCall of message.tool_calls) {
const result = validator.validateToolCall(toolCall);
if (result.success) {
console.log('Tool arguments:', result.data);
}
}
}
}4. Direct Data Validation
import { z } from 'zod';
import { createOpenAIValidator } from 'openai-zod-validator';
const UserSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
age: z.number().min(0),
});
const validator = createOpenAIValidator(UserSchema);
// Validate any data
const data = {
id: '123',
name: 'John Doe',
email: '[email protected]',
age: 30,
};
const result = validator.validate(data);
if (result.success) {
console.log('Valid user:', result.data);
} else {
console.error('Validation errors:', result.errors);
}API Reference
createOpenAIValidator(schema, options?)
Creates a validator instance for a Zod schema.
Parameters:
schema: A Zod schemaoptions?: Optional configurationthrowOnError?: boolean- Whether to throw on validation errors (default:true)stripUnknown?: boolean- Whether to strip unknown keys (default:false)
Returns: Validator instance with methods:
validate(data)- Validate any datavalidateCompletion(completion)- Validate OpenAI chat completionvalidateFunctionCall(functionCall)- Validate function call argumentsvalidateToolCall(toolCall)- Validate tool call argumentsgetSchema()- Get the underlying Zod schema
zodToOpenAIParameters(schema)
Converts a Zod schema to OpenAI function parameters format.
Parameters:
schema: A Zod schema
Returns: OpenAI-compatible parameter object
Advanced Examples
Custom Error Handling
const validator = createOpenAIValidator(MySchema, {
throwOnError: false
});
const result = validator.validate(data);
if (!result.success) {
result.errors?.errors.forEach(error => {
console.log(`Error at ${error.path.join('.')}: ${error.message}`);
});
}Complex Nested Schemas
const AddressSchema = z.object({
street: z.string(),
city: z.string(),
zipCode: z.string(),
});
const PersonSchema = z.object({
name: z.string(),
age: z.number(),
addresses: z.array(AddressSchema),
metadata: z.record(z.string()),
});
const validator = createOpenAIValidator(PersonSchema);
// Full type inference works with nested objects
const result = validator.validate(data);
// result.data is fully typed with all nested propertiesUsing with Streaming
const validator = createOpenAIValidator(ResponseSchema);
const stream = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Generate data' }],
stream: true,
response_format: { type: 'json_object' },
});
let accumulatedContent = '';
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
accumulatedContent += content;
}
// Validate accumulated content
const result = validator.validate(JSON.parse(accumulatedContent));TypeScript Support
This library is built with TypeScript and provides full type inference:
const Schema = z.object({
name: z.string(),
count: z.number(),
});
const validator = createOpenAIValidator(Schema);
const result = validator.validate(data);
if (result.success) {
// result.data is automatically typed as:
// { name: string; count: number }
console.log(result.data.name.toUpperCase());
console.log(result.data.count * 2);
}Error Handling
The library provides detailed error information:
const validator = createOpenAIValidator(Schema, { throwOnError: false });
const result = validator.validate(invalidData);
if (!result.success) {
result.errors?.errors.forEach(error => {
console.log('Path:', error.path);
console.log('Message:', error.message);
console.log('Code:', error.code);
});
}Requirements
- Node.js >= 18.0.0
- OpenAI SDK >= 6.0.0
- Zod >= 4.0.0
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues and questions, please open an issue on GitHub.
