dadacat-lambda-pipeline
Version:
JavaScript client for the dadacat 3-lambda image generation pipeline
341 lines (305 loc) • 10.1 kB
JavaScript
/**
* Image Generation Options Configuration and Validation
* Based on the Python ImageGenerationOptions class
*/
export class ImageGenerationOptions {
static OPTIONS = {
"model": {
"name": "Model",
"description": "The model to use for image generation",
"options": {
"gpt-image-1": "GPT Image 1",
"dall-e-3": "DALL-E 3",
"dall-e-2": "DALL-E 2"
},
"default": "dall-e-3"
},
"size": {
"name": "Image Size",
"description": "The size of the generated images",
"options": {
"dall-e-2": [
{"value": "256x256", "display": "Small (256x256)"},
{"value": "512x512", "display": "Medium (512x512)"},
{"value": "1024x1024", "display": "Large (1024x1024)"}
],
"dall-e-3": [
{"value": "1024x1024", "display": "Square (1024x1024)"},
{"value": "1792x1024", "display": "Landscape (1792x1024)"},
{"value": "1024x1792", "display": "Portrait (1024x1792)"}
],
"gpt-image-1": [
{"value": "1024x1024", "display": "Square (1024x1024)"},
{"value": "1536x1024", "display": "Landscape (1536x1024)"},
{"value": "1024x1536", "display": "Portrait (1024x1536)"}
]
},
"default": {
"dall-e-2": "1024x1024",
"dall-e-3": "1024x1024",
"gpt-image-1": "1024x1024"
}
},
"n": {
"name": "Number of Images",
"description": "The number of images to generate",
"options": {
"dall-e-2": Array.from({length: 10}, (_, i) => i + 1), // 1-10
"dall-e-3": [1], // DALL-E 3 only supports n=1
"gpt-image-1": Array.from({length: 10}, (_, i) => i + 1) // 1-10
},
"default": 1
},
"quality": {
"name": "Image Quality",
"description": "The quality of the image that will be generated",
"options": {
"dall-e-2": {"standard": "Standard"},
"dall-e-3": {
"standard": "Standard",
"hd": "HD"
},
"gpt-image-1": {
"auto": "Auto",
"high": "High",
"medium": "Medium",
"low": "Low"
}
},
"default": {
"dall-e-2": "standard",
"dall-e-3": "standard",
"gpt-image-1": "auto"
}
},
"style": {
"name": "Image Style",
"description": "The style of the generated images (DALL-E 3 only)",
"options": {
"dall-e-2": null,
"dall-e-3": {
"vivid": "Vivid (hyper-real and dramatic)",
"natural": "Natural (more natural looking)"
},
"gpt-image-1": null
},
"default": {
"dall-e-3": "vivid"
}
},
"background": {
"name": "Background",
"description": "Sets transparency for the background (GPT Image 1 only)",
"options": {
"dall-e-2": null,
"dall-e-3": null,
"gpt-image-1": {
"auto": "Auto (model decides)",
"transparent": "Transparent",
"opaque": "Opaque"
}
},
"default": {
"gpt-image-1": "auto"
}
},
"moderation": {
"name": "Content Moderation",
"description": "Content moderation level for images (GPT Image 1 only)",
"options": {
"dall-e-2": null,
"dall-e-3": null,
"gpt-image-1": {
"auto": "Auto (standard filtering)",
"low": "Low (less restrictive filtering)"
}
},
"default": {
"gpt-image-1": "auto"
}
},
"output_format": {
"name": "Output Format",
"description": "Format of generated images (GPT Image 1 only)",
"options": {
"dall-e-2": null,
"dall-e-3": null,
"gpt-image-1": {
"png": "PNG",
"jpeg": "JPEG",
"webp": "WebP"
}
},
"default": {
"gpt-image-1": "png"
}
},
"output_compression": {
"name": "Output Compression",
"description": "Compression level for WebP/JPEG (GPT Image 1 only)",
"options": {
"dall-e-2": null,
"dall-e-3": null,
"gpt-image-1": {
"values": Array.from({length: 100}, (_, i) => i + 1), // 1-100%
"applicable_formats": ["webp", "jpeg"]
}
},
"default": {
"gpt-image-1": 100
}
},
"response_format": {
"name": "Response Format",
"description": "Format in which images are returned (DALL-E models only)",
"options": {
"dall-e-2": {
"url": "URL",
"b64_json": "Base64 JSON"
},
"dall-e-3": {
"url": "URL",
"b64_json": "Base64 JSON"
},
"gpt-image-1": null // Always returns base64
},
"default": {
"dall-e-2": "url",
"dall-e-3": "url"
}
}
};
/**
* Validate options against the specified model
* @param {Object} options - The options to validate
* @param {string} model - The model to validate against
* @returns {Object} Validation result with validated options and errors
*/
static validateOptions(options = {}, model = 'dall-e-3') {
const validationResult = {
validatedOptions: {},
errors: [],
warnings: []
};
// Validate model first
if (!this.OPTIONS.model.options[model]) {
validationResult.errors.push(`Invalid model: ${model}. Valid models: ${Object.keys(this.OPTIONS.model.options).join(', ')}`);
return validationResult;
}
// Start with defaults for the model
validationResult.validatedOptions = this.getDefaultOptions(model);
// Validate each provided option
for (const [optionName, optionValue] of Object.entries(options)) {
const optionConfig = this.OPTIONS[optionName];
if (!optionConfig) {
validationResult.warnings.push(`Unknown option: ${optionName}`);
continue;
}
const modelOptions = optionConfig.options[model];
// Skip validation if this option doesn't apply to this model
if (modelOptions === null) {
validationResult.warnings.push(`Option '${optionName}' is not supported by model '${model}'`);
continue;
}
// Validate the option value
const validationError = this._validateOptionValue(optionName, optionValue, modelOptions, model);
if (validationError) {
validationResult.errors.push(validationError);
} else {
validationResult.validatedOptions[optionName] = optionValue;
}
}
return validationResult;
}
/**
* Get default options for a specific model
* @param {string} model - The model to get defaults for
* @returns {Object} Default options for the model
*/
static getDefaultOptions(model = 'dall-e-3') {
const defaults = {};
for (const [optionName, optionConfig] of Object.entries(this.OPTIONS)) {
if (optionName === 'model') continue; // Skip model option itself
if (optionConfig.options[model] !== null) {
if (typeof optionConfig.default === 'object' && optionConfig.default[model] !== undefined) {
defaults[optionName] = optionConfig.default[model];
} else if (typeof optionConfig.default !== 'object') {
defaults[optionName] = optionConfig.default;
}
}
}
defaults.model = model;
return defaults;
}
/**
* Get all supported options for a specific model
* @param {string} model - The model to get options for
* @returns {Object} Supported options for the model
*/
static getSupportedOptions(model = 'dall-e-3') {
const supported = {};
for (const [optionName, optionConfig] of Object.entries(this.OPTIONS)) {
if (optionConfig.options[model] !== null) {
supported[optionName] = {
name: optionConfig.name,
description: optionConfig.description,
options: optionConfig.options[model],
default: typeof optionConfig.default === 'object' ?
optionConfig.default[model] : optionConfig.default
};
}
}
return supported;
}
/**
* Validate a specific option value
* @private
*/
static _validateOptionValue(optionName, value, modelOptions, model) {
switch (optionName) {
case 'size':
const validSizes = modelOptions.map(option => option.value);
if (!validSizes.includes(value)) {
return `Invalid size '${value}' for model '${model}'. Valid sizes: ${validSizes.join(', ')}`;
}
break;
case 'n':
if (!modelOptions.includes(value)) {
return `Invalid number of images '${value}' for model '${model}'. Valid values: ${modelOptions.join(', ')}`;
}
break;
case 'quality':
case 'style':
case 'background':
case 'moderation':
case 'output_format':
case 'response_format':
if (typeof modelOptions === 'object' && !modelOptions[value]) {
return `Invalid ${optionName} '${value}' for model '${model}'. Valid values: ${Object.keys(modelOptions).join(', ')}`;
}
break;
case 'output_compression':
if (modelOptions.values && !modelOptions.values.includes(value)) {
return `Invalid output_compression '${value}' for model '${model}'. Valid range: 1-100`;
}
break;
}
return null; // No error
}
/**
* Clean options to only include those supported by the model
* @param {Object} options - Options to clean
* @param {string} model - Model to clean options for
* @returns {Object} Cleaned options
*/
static cleanOptionsForModel(options = {}, model = 'dall-e-3') {
const cleaned = {};
for (const [optionName, optionValue] of Object.entries(options)) {
const optionConfig = this.OPTIONS[optionName];
if (optionConfig && optionConfig.options[model] !== null) {
cleaned[optionName] = optionValue;
}
}
return cleaned;
}
}