feat(providers): Add research API and image generation/editing support; extend providers and tests
This commit is contained in:
@@ -9,7 +9,13 @@ export type TChatCompletionRequestMessage = {
|
||||
};
|
||||
|
||||
import { MultiModalModel } from './abstract.classes.multimodal.js';
|
||||
import type { ResearchOptions, ResearchResponse } from './abstract.classes.multimodal.js';
|
||||
import type {
|
||||
ResearchOptions,
|
||||
ResearchResponse,
|
||||
ImageGenerateOptions,
|
||||
ImageEditOptions,
|
||||
ImageResponse
|
||||
} from './abstract.classes.multimodal.js';
|
||||
|
||||
export interface IOpenaiProviderOptions {
|
||||
openaiToken: string;
|
||||
@@ -17,6 +23,7 @@ export interface IOpenaiProviderOptions {
|
||||
audioModel?: string;
|
||||
visionModel?: string;
|
||||
researchModel?: string;
|
||||
imageModel?: string;
|
||||
enableWebSearch?: boolean;
|
||||
}
|
||||
|
||||
@@ -328,4 +335,121 @@ export class OpenAiProvider extends MultiModalModel {
|
||||
throw new Error(`Failed to perform research: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Image generation using OpenAI's gpt-image-1 or DALL-E models
|
||||
*/
|
||||
public async imageGenerate(optionsArg: ImageGenerateOptions): Promise<ImageResponse> {
|
||||
const model = optionsArg.model || this.options.imageModel || 'gpt-image-1';
|
||||
|
||||
try {
|
||||
const requestParams: any = {
|
||||
model,
|
||||
prompt: optionsArg.prompt,
|
||||
n: optionsArg.n || 1,
|
||||
};
|
||||
|
||||
// Add gpt-image-1 specific parameters
|
||||
if (model === 'gpt-image-1') {
|
||||
if (optionsArg.quality) requestParams.quality = optionsArg.quality;
|
||||
if (optionsArg.size) requestParams.size = optionsArg.size;
|
||||
if (optionsArg.background) requestParams.background = optionsArg.background;
|
||||
if (optionsArg.outputFormat) requestParams.output_format = optionsArg.outputFormat;
|
||||
if (optionsArg.outputCompression !== undefined) requestParams.output_compression = optionsArg.outputCompression;
|
||||
if (optionsArg.moderation) requestParams.moderation = optionsArg.moderation;
|
||||
if (optionsArg.stream !== undefined) requestParams.stream = optionsArg.stream;
|
||||
if (optionsArg.partialImages !== undefined) requestParams.partial_images = optionsArg.partialImages;
|
||||
} else if (model === 'dall-e-3') {
|
||||
// DALL-E 3 specific parameters
|
||||
if (optionsArg.quality) requestParams.quality = optionsArg.quality;
|
||||
if (optionsArg.size) requestParams.size = optionsArg.size;
|
||||
if (optionsArg.style) requestParams.style = optionsArg.style;
|
||||
requestParams.response_format = 'b64_json'; // Always use base64 for consistency
|
||||
} else if (model === 'dall-e-2') {
|
||||
// DALL-E 2 specific parameters
|
||||
if (optionsArg.size) requestParams.size = optionsArg.size;
|
||||
requestParams.response_format = 'b64_json';
|
||||
}
|
||||
|
||||
const result = await this.openAiApiClient.images.generate(requestParams);
|
||||
|
||||
const images = (result.data || []).map(img => ({
|
||||
b64_json: img.b64_json,
|
||||
url: img.url,
|
||||
revisedPrompt: img.revised_prompt
|
||||
}));
|
||||
|
||||
return {
|
||||
images,
|
||||
metadata: {
|
||||
model,
|
||||
quality: result.quality,
|
||||
size: result.size,
|
||||
outputFormat: result.output_format,
|
||||
tokensUsed: result.usage?.total_tokens
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Image generation error:', error);
|
||||
throw new Error(`Failed to generate image: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Image editing using OpenAI's gpt-image-1 or DALL-E 2 models
|
||||
*/
|
||||
public async imageEdit(optionsArg: ImageEditOptions): Promise<ImageResponse> {
|
||||
const model = optionsArg.model || this.options.imageModel || 'gpt-image-1';
|
||||
|
||||
try {
|
||||
const requestParams: any = {
|
||||
model,
|
||||
image: optionsArg.image,
|
||||
prompt: optionsArg.prompt,
|
||||
n: optionsArg.n || 1,
|
||||
};
|
||||
|
||||
// Add mask if provided
|
||||
if (optionsArg.mask) {
|
||||
requestParams.mask = optionsArg.mask;
|
||||
}
|
||||
|
||||
// Add gpt-image-1 specific parameters
|
||||
if (model === 'gpt-image-1') {
|
||||
if (optionsArg.quality) requestParams.quality = optionsArg.quality;
|
||||
if (optionsArg.size) requestParams.size = optionsArg.size;
|
||||
if (optionsArg.background) requestParams.background = optionsArg.background;
|
||||
if (optionsArg.outputFormat) requestParams.output_format = optionsArg.outputFormat;
|
||||
if (optionsArg.outputCompression !== undefined) requestParams.output_compression = optionsArg.outputCompression;
|
||||
if (optionsArg.stream !== undefined) requestParams.stream = optionsArg.stream;
|
||||
if (optionsArg.partialImages !== undefined) requestParams.partial_images = optionsArg.partialImages;
|
||||
} else if (model === 'dall-e-2') {
|
||||
// DALL-E 2 specific parameters
|
||||
if (optionsArg.size) requestParams.size = optionsArg.size;
|
||||
requestParams.response_format = 'b64_json';
|
||||
}
|
||||
|
||||
const result = await this.openAiApiClient.images.edit(requestParams);
|
||||
|
||||
const images = (result.data || []).map(img => ({
|
||||
b64_json: img.b64_json,
|
||||
url: img.url,
|
||||
revisedPrompt: img.revised_prompt
|
||||
}));
|
||||
|
||||
return {
|
||||
images,
|
||||
metadata: {
|
||||
model,
|
||||
quality: result.quality,
|
||||
size: result.size,
|
||||
outputFormat: result.output_format,
|
||||
tokensUsed: result.usage?.total_tokens
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Image edit error:', error);
|
||||
throw new Error(`Failed to edit image: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user