From 1283db5d1edec6518d9a6b30381651cab874a8b0 Mon Sep 17 00:00:00 2001 From: Jerryplusy Date: Fri, 5 Dec 2025 23:48:47 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(ai):=20Enhance=20multimodal=20?= =?UTF-8?q?support=20by=20allowing=20smart=20selection=20of=20model=20base?= =?UTF-8?q?d=20on=20message=20type.=20=F0=9F=93=84=20config:=20Add=20smart?= =?UTF-8?q?=20multimodal=20option=20for=20flexible=20AI=20model=20usage.?= =?UTF-8?q?=20=F0=9F=9B=A0=EF=B8=8F=20fix(aiCaller):=20Update=20AI=20calle?= =?UTF-8?q?r=20logic=20to=20utilize=20smart=20multimodal=20settings=20effe?= =?UTF-8?q?ctively.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ai.js | 17 +++++++++++++++-- config/ai.json | 2 ++ lib/ai/aiCaller.js | 19 +++++++++++++++++-- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/apps/ai.js b/apps/ai.js index 3ffbc08..d1467aa 100644 --- a/apps/ai.js +++ b/apps/ai.js @@ -352,10 +352,23 @@ async function callAiForResponse(messageData, e, aiConfig) { e.user_id ); //更新session + let userMessageContent, assistantMessageContent; + const usedMultimodal = aiConfig.multimodalEnabled && + (!aiConfig.smartMultimodal || messageData.originalMessages?.some(msg => msg.type === 'image_url')); + + if (usedMultimodal && messageData.originalMessages) { + userMessageContent = messageData.originalMessages.map(msg => { + if (msg.type === 'text') return msg.content; + if (msg.type === 'image_url') return `[图片消息]`; + }).filter(Boolean).join(''); + } else { + userMessageContent = messageData.text; + } + assistantMessageContent = aiResult.response; const newChatHistory = [ ...chatHistory, - { role: 'user', content: messageData.text }, - { role: 'assistant', content: aiResult.response }, + { role: 'user', content: userMessageContent }, + { role: 'assistant', content: assistantMessageContent }, ]; SessionManager.updateChatHistory(e.group_id, newChatHistory); SessionManager.deactivateSession(e.group_id, e.user_id); diff --git a/config/ai.json b/config/ai.json index 8979809..59078b8 100644 --- a/config/ai.json +++ b/config/ai.json @@ -10,6 +10,8 @@ "modelType": "deepseek-ai/DeepSeek-V3.2-Exp", "?multimodalEnabled": "是否启用多模态模型模式,启用后将忽略文本模型", "multimodalEnabled": false, + "?smartMultimodal": "智能多模态模式,开启时只有文字用文本模型,有图片才用多模态模型", + "smartMultimodal": false, "?multimodalModel": "多模态模型名称", "multimodalModel": "Qwen/Qwen2.5-VL-72B-Instruct", "?temperature": "聊天温度,可选0-2.0,温度越高创造性越高", diff --git a/lib/ai/aiCaller.js b/lib/ai/aiCaller.js index add22fa..3c1e019 100644 --- a/lib/ai/aiCaller.js +++ b/lib/ai/aiCaller.js @@ -45,7 +45,16 @@ class AiCaller { return { success: false, error: 'AI调用器未初始化' }; } try { - if (this.config.multimodalEnabled) { + if (this.config.smartMultimodal && this.config.multimodalEnabled) { + const hasImage = originalMessages.some(msg => msg.type === 'image_url'); + if (hasImage) { + logger.info('[crystelf-ai] 检测到图片,使用多模态模型'); + return await this.callMultimodalAi(originalMessages, chatHistory, memories, e); + } else { + logger.info('[crystelf-ai] 纯文本消息,使用文本模型'); + return await this.callTextAi(prompt, chatHistory, memories, e); + } + } else if (this.config.multimodalEnabled) { return await this.callMultimodalAi(originalMessages, chatHistory, memories, e); } else { return await this.callTextAi(prompt, chatHistory, memories, e); @@ -72,9 +81,15 @@ class AiCaller { try { const fullPrompt = this.buildPrompt(prompt); const apiCaller = this.openaiChat; + + const formattedChatHistory = chatHistory.map(msg => ({ + role: msg.role, + content: msg.content + })); + const result = await apiCaller.callAi({ prompt: fullPrompt, - chatHistory: chatHistory, + chatHistory: formattedChatHistory, model: this.config.modelType, temperature: this.config.temperature, customPrompt: await this.getSystemPrompt(e, memories),