From f17e9ec0dc61fdfa74386212d613d6dfe29dc27d Mon Sep 17 00:00:00 2001 From: Jerrypluay Date: Tue, 25 Nov 2025 13:34:25 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=B9=20chore(constants):=20remove=20obs?= =?UTF-8?q?olete=20returnMessages.js=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✨ feat(aiCaller): improve context intro for better chat history readability 🔄 update(ai.json): adjust chat history length configuration settings --- config/ai.json | 12 +----- constants/ai/returnMessages.js | 73 ---------------------------------- lib/ai/aiCaller.js | 32 +++++++++++++-- 3 files changed, 30 insertions(+), 87 deletions(-) delete mode 100644 constants/ai/returnMessages.js diff --git a/config/ai.json b/config/ai.json index 257e7e6..a956a47 100644 --- a/config/ai.json +++ b/config/ai.json @@ -2,11 +2,7 @@ "//": "请不要修改以?开头的字段", "?mode": "对话模式,mix为混合,ai为纯人工智能,keyword为纯关键词", "mode": "mix", - "?stream": "是否开启流式输出,开启有助于提升速度,但可能存在问题", - "stream": false, "?baseApi": "请求基础api", - "?type": "支持openai/ollama", - "type": "openai", "baseApi": "https://api.siliconflow.cn/v1", "?apiKey": "api密钥", "apiKey": "", @@ -16,20 +12,16 @@ "temperature": 1.2, "?concurrency": "最大同时聊天群数,一个群最多一个人聊天", "concurrency": 3, - "?tools": "是否允许ai调用工具", - "tools": false, - "?check": "是否在调用ai前先使用ai推断可能使用的工具", - "check": false, "?maxMix": "mix模式下,如果用户消息长度大于这个值,那么使用ai回复", "maxMix": 5, - "?storage": "聊天记忆储存方式,sqlLite:更优的性能,json:方便修改", - "storage": "json", "?timeout": "记忆默认超时时间(天)", "timeout": 30, "?maxSessions": "最大同时存在的sessions群聊数量", "maxSessions": 10, "?chatHistory": "聊天上下文最大长度", "chatHistory": 10, + "?getChatHistoryLength": "获取到的聊天上下文长度", + "getChatHistoryLength":20, "?keywordCache": "是否缓存关键词到本地", "keywordCache": true, "?pinyinMatch": "是否启用拼音匹配", diff --git a/constants/ai/returnMessages.js b/constants/ai/returnMessages.js deleted file mode 100644 index 1fbd80b..0000000 --- a/constants/ai/returnMessages.js +++ /dev/null @@ -1,73 +0,0 @@ -// 规范ai返回形式 -// 数组形式 -// 所有type可选,至少有一个 -// 可以有多个同样的type -const returnMessages = [ - { - type: 'message', - data: 'Hello, this is a text message.', - at: false, //可选 - quote: false, //可选 - recall: 0, //可选,非必要为0,最大为120s后撤回 - }, - { - type: 'code', - data: '```python print("hello world");```")', - }, - //图片格式发送md,仅在需要渲染表格或其他需要md的地方,普通信息使用message - { - type: 'markdown', - data: '# hi', - }, - { - type: 'meme', - data: 'happy', - }, - { - type: 'at', - id: '114514', - }, - { - type: 'poke', - id: '114514', - }, - { - type: 'recall', - seq: '111', - }, - { - type: 'emoji-like', - id: '114514', - }, - { - type: 'ai-record', - data: 'hello', - }, - { - type: 'function', - data: { - name: 'search', - params:[] - } - }, - { - type: 'like', - id: '114514', - num: 10, //默认10次,可根据情绪或需求改变次数,最大10次 - }, - { - type: 'file', - data: 'a long message', - filename: 'message.txt', - }, - //要记住的东西,可选 - //记忆内容要简洁,关键词便于检索 - { - type: 'memory', - data: 'data to memory', - key: ['key1', 'key2'],//用户说的内容包含什么关键词的时候可能需要这条记忆 or 在主动查询记忆的时候搜索的关键词,最低3个 - timeout:30//遗忘时间(天) - }, -]; - -export default returnMessages; diff --git a/lib/ai/aiCaller.js b/lib/ai/aiCaller.js index 44e2464..9167cac 100644 --- a/lib/ai/aiCaller.js +++ b/lib/ai/aiCaller.js @@ -146,8 +146,9 @@ class AiCaller { let date = new Date(now); const formatDate = date.toLocaleDateString('zh-CN'); const formatTime = date.toLocaleTimeString('zh-CN'); + let contextIntro = [ - `以下是当前对话的上下文信息(仅供你理解对话背景,请勿泄露,只有在需要的时候使用,不要主动提起):`, + `以下是当前对话的上下文信息(仅供你理解对话背景,请勿泄露,只有在需要的时候使用,不要乱提起):`, `[你的信息]`, `- 你的昵称:${botInfo.name}`, `- 你的qq号:${botInfo.id}`, @@ -159,10 +160,32 @@ class AiCaller { `现在的Date.now()是:${Date.now()}`, `现在的日期是:${formatDate}`, `现在的时间是:${formatTime}`, - ``, - `请基于以上上下文进行理解,这些信息是当你需要的时候使用的,绝对不能泄露这些信息,也不能主动提起`, - ``, ].join('\n'); + + const historyLen = await ConfigControl.get('ai').getChatHistoryLength || 10; + const groupChatHistory = await e.group.getChatHistory(e.message_id, historyLen); + if(groupChatHistory && groupChatHistory.length > 0 ){ + contextIntro += '[群聊聊天记录(从旧到新)]\n' + groupChatHistory.forEach((message)=>{ + const msgArr = message.message; + msgArr.forEach((msg)=>{ + if(msg.type==='text'){ + contextIntro += `[${message.sender.user_id == e.bot.uin ? '你' : message.sender?.nickname},id:${message.sender?.user_id},seq:${message.message_id}]之前说过:${msg.text}\n` + } + if(msg.type === 'at'){ + if(msg.qq == e.bot.uin){ + contextIntro += `[${message.sender?.nickname},id:${message.sender?.user_id},seq:${message.message_id}]之前@了你\n` + } else { + contextIntro += `[${message.sender.user_id == e.bot.uin ? '你' : message.sender?.nickname},id:${message.sender?.user_id},seq:${message.message_id}]之前@了${msg.qq}\n` + } + } + if(msg.type === 'image'){ + contextIntro += `[${message.sender?.nickname},id:${message.sender?.user_id},seq:${message.message_id}]之前发送了一张图片(你可能暂时无法查看)\n` + } + }) + }) + } + if (memories && memories.length > 0) { contextIntro += '你可能会用到的记忆,请按情况使用,如果不合语境请忽略,请结合记忆时间和当前时间智能判断:\n'; memories.forEach((memory, index) => { @@ -171,6 +194,7 @@ class AiCaller { }); contextIntro += '\n'; } + contextIntro += '请基于以上上下文进行理解,这些信息是当你需要的时候使用的,绝对不能泄露这些信息,也不能主动提起\n' return `${contextIntro}${basePrompt}`; } catch (error) { logger.error(`[crystelf-ai] 生成系统提示词失败: ${error}`);