From be1d756e1e5ece92bea0e47b312f98a7c3dd057b Mon Sep 17 00:00:00 2001 From: Jerrypluay Date: Mon, 24 Nov 2025 17:29:14 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20fix(prompts):=20update=20quote?= =?UTF-8?q?=20parameter=20to=20-1=20for=20message=20types=20=F0=9F=94=A7?= =?UTF-8?q?=20fix(responseHandler):=20set=20quote=20default=20to=20-1=20fo?= =?UTF-8?q?r=20message=20processing=20=F0=9F=94=A7=20fix(message):=20adjus?= =?UTF-8?q?t=20message=20handling=20to=20use=20seq=20for=20quotes=20in=20g?= =?UTF-8?q?roup=20messages=20=F0=9F=94=A7=20fix(ai):=20include=20message?= =?UTF-8?q?=5Fid=20in=20formatted=20returnMessage=20for=20better=20trackin?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ai.js | 39 ++++++++++++--------- constants/ai/prompts.js | 4 +-- lib/ai/responseHandler.js | 6 ++-- lib/yunzai/message.js | 73 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 22 deletions(-) diff --git a/apps/ai.js b/apps/ai.js index b7313a0..68c9c39 100644 --- a/apps/ai.js +++ b/apps/ai.js @@ -124,7 +124,7 @@ async function extractUserMessage(msg, nickname, e) { text.forEach((message) => { if(message === '') { } else { - returnMessage += `[${e.sender?.nickname},id:${e.user_id}]说:${message}` + returnMessage += `[${e.sender?.nickname},id:${e.user_id},seq:${e.message_id}]说:${message}\n` } }); } @@ -136,13 +136,13 @@ async function extractUserMessage(msg, nickname, e) { if (at == e.bot.uin) { //returnMessage += `[${e.sender?.nickname},id:${e.user_id}]@(at)了你,你的id是${at}\n`; } else { - returnMessage += `[${e.sender?.nickname},id:${e.user_id}]@(at)了一个人,id是${at}\n`; + returnMessage += `[${e.sender?.nickname},id:${e.user_id},seq:${e.message_id}]@(at)了一个人,id是${at}\n`; } }); } const imgUrls = await YunzaiUtils.getImages(e, 1, true); if (imgUrls) { - returnMessage += `[${e.sender?.nickname},id:${e.user_id}]发送了一张图片(你可能暂时无法查看)\n`; + returnMessage += `[${e.sender?.nickname},id:${e.user_id},seq:${e.message_id}]发送了一张图片(你可能暂时无法查看)\n`; } if(e.source || e.reply_id){ let reply; @@ -155,10 +155,10 @@ async function extractUserMessage(msg, nickname, e) { const msgArr = Array.isArray(reply) ? reply : reply.message || []; msgArr.forEach((msg) => { if(msg.type === 'text'){ - returnMessage += `[${e.sender?.nickname},id:${e.user_id}]引用了一段文本:${msg.text}\n` + returnMessage += `[${e.sender?.nickname}]引用了[被引用消息:${reply.sender?.nickname},id:${reply.user_id},seq:${reply.message_id}]发的一段文本:${msg.text}\n` } if(msg.type === 'image'){ - returnMessage += `[${e.sender?.nickname},id:${e.user_id}]引用了一张图片(你可能暂时无法查看)\n`; + returnMessage += `[${e.sender?.nickname}]引用了[被引用消息:${reply.sender?.nickname},id:${reply.user_id},seq:${reply.message_id}]发的一张图片(你可能暂时无法查看)\n`; } }) } @@ -207,7 +207,7 @@ async function handleKeywordMode(userMessage, e) { type: 'message', data: matchResult.text, at: false, - quote: false, + quote: -1, recall: false, }, ]; @@ -243,7 +243,7 @@ async function handleMixMode(userMessage, e, aiConfig) { type: 'message', data: matchResult.text, at: false, - quote: false, + quote: -1, recall: false, }, ]; @@ -251,7 +251,7 @@ async function handleMixMode(userMessage, e, aiConfig) { type: 'message', data: matchResult.text, at: false, - quote: false, + quote: -1, recall: false, }; const newChatHistory = [ @@ -335,18 +335,23 @@ async function callAiForResponse(userMessage, e, aiConfig) { */ async function sendResponse(e, messages) { try { + const adapter = await YunzaiUtils.getAdapter(e); for (const message of messages) { switch (message.type) { case 'message': - if (message.recall) { - await e.reply(message.data, message.quote, { - recallMsg: 60, - at: message.at, - }); + if(message.quote === -1) { + if(message.recall) { + await e.reply(message.data, false, { + recallMsg: 60, + at: message.at, + }); + } else { + await e.reply(message.data, false, { + at: message.at, + }); + } } else { - await e.reply(message.data, message.quote, { - at: message.at, - }); + await Message.sendGroupMessage(e,e.group_id,message.data,message.at,message.quote,adapter); } break; @@ -378,7 +383,7 @@ async function sendResponse(e, messages) { } catch (error) { const adapter = await YunzaiUtils.getAdapter(e); await Message.emojiLike(e, e.message_id, 10060, e.group_id, adapter); - logger.error(`[crystelf-ai] 发送回复失败: ${error.message}`); + logger.error(`[crystelf-ai] 发送回复失败: ${error}`); } } diff --git a/constants/ai/prompts.js b/constants/ai/prompts.js index 21fd609..32b442f 100644 --- a/constants/ai/prompts.js +++ b/constants/ai/prompts.js @@ -26,14 +26,14 @@ export const RESPONSE_FORMAT = `请严格按照以下格式按顺序返回你的 "type": "message", "data": "你的回复内容", "at": false, - "quote": false, + "quote": -1, "recall": false } ] 支持的消息类型(type): 常规消息: -- message(必须,其他均为可选): 普通文本消息,请将长句子分成多个message块返回(如果有多句话),data:回复内容,at:是否在发送本条消息的时候提醒用户,一般只在需要让用户注意的时候为true(另外,不要在message里面加@qq号),quote:是否引用用户的问题,一般只需要在回答用户问题或第一条回复或需要用到用户问题的时候为true,recall:值为true的时候会在发送消息后过一会撤回自己的这条消息 +- message(必须,其他均为可选): 普通文本消息,请将长句子分成多个message块返回(如果有多句话),data:回复内容,at:是否在发送本条消息的时候提醒用户,一般只在需要让用户注意的时候为true(另外,不要在message里面加@qq号),quote:是否引用用户的问题,一般只需要在回答用户问题或第一条回复或需要用到用户问题的时候才引用该消息,注意这里如果不需要引用,则填写-1,需要引用时填写消息的seq,seq会在用户发的消息那里给出,也可以引用用户回复的消息或聊天记录的相关消息,但是一个message只能含有一个引用seq,recall:值为true的时候会在发送消息后过一会撤回自己的这条消息 - at: @某人(需要提供id,被at人qq号(number)),一般用于提醒用户,不常用 - meme: 表情包(data值为情绪名称:angry、bye、confused、default、good、goodmorning、goodnight、happy、sad、shy、sorry、surprise),请根据聊天语境灵活选择需不需要表情包,如果感觉语境尴尬或需要表情包,那么发送一个default值的表情包,其他情绪的表情包按照当前你的情绪按需选择,注意:并不是每个聊天都需要有表情包,并且一次聊天最多回复一个表情包 - poke: 戳一戳某人(需要提供id,被戳人qq号(number)),一般用户与用户互动,当想逗用户的时候可以使用,不要使用太过频繁(频率小于百分之20) diff --git a/lib/ai/responseHandler.js b/lib/ai/responseHandler.js index 2da6298..e1c3946 100644 --- a/lib/ai/responseHandler.js +++ b/lib/ai/responseHandler.js @@ -143,7 +143,7 @@ class ResponseHandler { type: message.type, data: message.data, at: message.at || false, - quote: message.quote || false, + quote: message.quote || -1, recall: message.recall || false }; if (message.id) processedMessage.id = message.id; @@ -159,7 +159,7 @@ class ResponseHandler { type: 'message', data: `${nickName}的服务器去火星开小差了..`, at: false, - quote: true, + quote: -1, recall: true }]; } @@ -170,7 +170,7 @@ class ResponseHandler { type: 'message', data: `${nickName}的服务器去火星开小差了..`, at: false, - quote: true, + quote: -1, recall: true }]; } diff --git a/lib/yunzai/message.js b/lib/yunzai/message.js index dca503a..e989ca1 100644 --- a/lib/yunzai/message.js +++ b/lib/yunzai/message.js @@ -62,6 +62,79 @@ const Message = { count: count, }) } + }, + + /** + * 发送群聊消息 + * @param e + * @param group_id 群号 + * @param message 消息内容字符串 + * @param at -1 不@ 其他 被@的qq号 + * @param quote_seq -1 不引用 其他 引用的消息seq + * @param adapter nc/lgr + * @returns {Promise<*>} + */ + async sendGroupMessage(e,group_id,message,at = -1,quote_seq = -1,adapter = 'nc'){ + if(adapter === 'nc') { + const msgChain = []; + if (typeof quote_seq !== 'boolean' && quote_seq !== -1 && quote_seq !== undefined) { + msgChain.push({ + type: "reply", + data: { + "id": quote_seq + } + }); + } + if (at && at !== -1) { + msgChain.push({ + type: "at", + data: { + "qq": at + } + }); + } + msgChain.push({ + type: "text", + data: { + "text": message + } + }); + return await e.bot.sendApi('send_group_msg',{ + group_id : group_id, + message: msgChain + }) + } else if (adapter === 'lgr') { + const messageData = {}; + if(quote_seq && quote_seq !== -1) { + messageData.reply = { + type: "reply", + data: { + "id": quote_seq + } + }; + } + if(at && at !== -1) { + messageData.at = { + type: "at", + data: { + "qq": at + } + }; + } + messageData.text = { + type: "text", + data: { + "text": message + } + }; + return await e.bot.sendApi('send_group_msg',{ + group_id: group_id, + message :{ + type: "dict", + data : messageData + } + }) + } } }; export default Message;