From 20eaf117f1cb19b13ee4a087586d826885c563fc Mon Sep 17 00:00:00 2001 From: Jerrypluay Date: Sun, 7 Dec 2025 00:39:52 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(imageProcessor):=20add=20image?= =?UTF-8?q?=20editing=20functionality=20and=20improve=20response=20structu?= =?UTF-8?q?re=20for=20better=20processing.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/ai/imageProcessor.js | 125 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 118 insertions(+), 7 deletions(-) diff --git a/lib/ai/imageProcessor.js b/lib/ai/imageProcessor.js index 077fb4c..b746a97 100644 --- a/lib/ai/imageProcessor.js +++ b/lib/ai/imageProcessor.js @@ -89,7 +89,6 @@ class ImageProcessor { quality: config.quality || 'standard', style: config.style || 'vivid', response_format: config.responseFormat || 'url', - user: config.user || undefined }; const response = await axios.post( @@ -145,21 +144,22 @@ class ImageProcessor { const messages = [ { role: 'system', - content: '请你根据用户的描述生成高质量且准确的图像,条件允许的情况下,请先思考用户的意图再生成图像,请直接返回图像url,不要任何其他内容' + content: [ + {type: 'text', text: '请你根据用户的描述生成高质量且准确的图像,条件允许的情况下,请先思考用户的意图再生成图像,请直接返回图像url,不要任何其他内容'} + ] }, { role: 'user', - content: prompt + content: [ + {type: 'text', text: prompt} + ] } ]; const requestBody = { model: config.model || 'google/gemini-3-pro-image-preview', messages: messages, - max_tokens: config.maxTokens || 4000, temperature: config.temperature || 0.7, modalities: config.modalities || ['text', 'image'], - size: config.size || '1024x1024', - response_format: config.responseFormat || 'url' }; const response = await axios.post( @@ -229,6 +229,117 @@ class ImageProcessor { } } + async editImage(prompt, sourceImageArr, config){ + if(config.imageMode==='openai'){ + return await this.editImageByOpenAI(prompt, sourceImageArr, config); + } else if(config.imageMode==='chat'){ + return await this.editImageByChat(prompt, sourceImageArr, config); + } else { + return await this.editImageByChat(prompt, sourceImageArr, config); + } + } + + /** + * 使用对话式接口编辑图像(如gemini-3-pro-image-preview) + * @param {string} prompt - 编辑描述 + * @param {string} sourceImageArr - 源图像URL数组 + * @param {Object} config - 配置对象 + * @returns {Promise} 编辑结果 + */ + async editImageByChat(prompt, sourceImageArr, config) { + try{ + logger.info(`[crystelf-ai] 开始编辑图像: ${prompt}, 源图像数量: ${sourceImageArr.length}`); + if(!sourceImageArr||sourceImageArr.length===0){ + return { + success: false, + error: '编辑图像需要提供源图像' + }; + } + let messages = []; + messages.push({ + role: 'system', + content: [ + {type: 'text', text: '请你根据用户的描述编辑图像,条件允许的情况下,请先思考用户的意图再编辑图像,请直接返回图像url,不要任何其他内容'} + ] + }); + let userContent = []; + userContent.push({type: 'text', text: prompt}); + sourceImageArr.forEach((img) => { + userContent.push({type: 'image_url', image_url: {url: img}}); + }); + messages.push({ + role: 'user', + content: userContent + }); + + const requestBody = { + model: config.model || 'google/gemini-3-pro-image-preview', + messages: messages, + temperature: config.temperature || 0.7, + modalities: config.modalities || ['text', 'image'], + }; + + const response = await axios.post( + `${config.baseApi}/v1/chat/completions`, + requestBody, + { + headers: { + 'Authorization': `Bearer ${config.apiKey}`, + 'Content-Type': 'application/json' + }, + timeout: config.timeout || 60000 + } + ); + + if (response.data && response.data.choices && response.data.choices.length > 0) { + const choice = response.data.choices[0]; + if (choice.message && choice.message.images && choice.message.images.length > 0) { + const imageData = choice.message.images[0]; + const imageUrl = imageData.image_url ? imageData.image_url.url : null; + + if (imageUrl) { + logger.info(`[crystelf-ai] 对话接口图像生成成功: ${imageUrl.substring(0, 50)}...`); + return { + success: true, + imageUrl: imageUrl, + description: prompt, + model: config.model || 'google/gemini-3-pro-image-preview', + rawResponse: response.data + }; + } + } + if (choice.message && choice.message.content) { + const imageUrl = this.extractImageUrl(choice.message.content); + if (imageUrl) { + logger.info(`[crystelf-ai] 从响应内容中提取到图像URL: ${imageUrl}`); + return { + success: true, + imageUrl: imageUrl, + description: prompt, + model: config.model || 'google/gemini-3-pro-image-preview', + rawResponse: response.data + }; + } else { + logger.info(`[crystelf-ai] 收到文本响应: ${choice.message.content}`); + return { + success: true, + response: choice.message.content, + description: prompt, + model: config.model || 'google/gemini-3-pro-image-preview', + rawResponse: response.data + }; + } + } + } + } catch (err){ + logger.error(`[crystelf-ai] 图像编辑失败: ${error.message}`); + return { + success: false, + error: `图像编辑失败: ${error.message}` + }; + } + } + /** * 编辑图像 - 使用OpenAI标准接口 * @param {string} prompt - 编辑描述 @@ -236,7 +347,7 @@ class ImageProcessor { * @param {Object} config - 配置对象 * @returns {Promise} 编辑结果 */ - async editImage(prompt, sourceImageArr, config) { + async editImageByOpenAI(prompt, sourceImageArr, config) { try { logger.info(`[crystelf-ai] 开始编辑图像: ${prompt}, 源图像数量: ${sourceImageArr.length}`);