UNPKG

dadacat-lambda-pipeline

Version:
341 lines (305 loc) 10.1 kB
/** * 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; } }