From 9e4f59f435119555ccd9dfdbcd743609a21453c0 Mon Sep 17 00:00:00 2001 From: error2913 <2913949387@qq.com> Date: Thu, 3 Jul 2025 00:02:08 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E7=9F=AD?= =?UTF-8?q?=E6=9C=9F=E8=AE=B0=E5=BF=86=E5=8D=95=E7=8B=AC=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E5=BC=80=E5=90=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/AI/AI.ts | 4 ++-- src/AI/memory.ts | 20 +++++++++++++------- src/index.ts | 19 ++++++++++++++++--- src/update.ts | 3 ++- src/utils/utils_message.ts | 6 +++--- 5 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/AI/AI.ts b/src/AI/AI.ts index 3b73e46..2fb8331 100644 --- a/src/AI/AI.ts +++ b/src/AI/AI.ts @@ -28,13 +28,13 @@ export class AI { privilege: Privilege; // 下面是临时变量,用于处理消息 - stream: { + stream: { // 用于流式输出相关 id: string, reply: string, toolCallStatus: boolean } - bucket: { + bucket: { // 触发次数令牌桶 count: number, lastTime: number } diff --git a/src/AI/memory.ts b/src/AI/memory.ts index 369b986..7ea8bff 100644 --- a/src/AI/memory.ts +++ b/src/AI/memory.ts @@ -30,17 +30,19 @@ export interface MemoryInfo { export class Memory { persona: string; memoryMap: { [key: string]: MemoryInfo }; - shortMemory: string[]; + useShortMemory: boolean; + shortMemoryList: string[]; constructor() { this.persona = '无'; this.memoryMap = {}; - this.shortMemory = []; + this.useShortMemory = false; + this.shortMemoryList = []; } static reviver(value: any): Memory { const memory = new Memory(); - const validKeys = ['persona', 'memoryMap', 'shortMemory']; + const validKeys = ['persona', 'memoryMap', 'useShortMemory', 'shortMemory']; for (const k in value) { if (validKeys.includes(k)) { @@ -108,7 +110,7 @@ export class Memory { } clearShortMemory() { - this.shortMemory = []; + this.shortMemoryList = []; } limitMemory() { @@ -139,12 +141,16 @@ export class Memory { limitShortMemory() { const { shortMemoryLimit } = ConfigManager.memory; - if (this.shortMemory.length > shortMemoryLimit) { - this.shortMemory.splice(0, this.shortMemory.length - shortMemoryLimit); + if (this.shortMemoryList.length > shortMemoryLimit) { + this.shortMemoryList.splice(0, this.shortMemoryList.length - shortMemoryLimit); } } async updateShortMemory(ctx: seal.MsgContext, msg: seal.Message, ai: AI, sumMessages: Message[]) { + if (!this.useShortMemory) { + return; + } + const { url, apiKey } = ConfigManager.request; const { roleSettingTemplate, isPrefix, showNumber, showMsgId } = ConfigManager.message; const { memoryBodyTemplate, memoryPromptTemplate } = ConfigManager.memory; @@ -217,7 +223,7 @@ export class Memory { }; - this.shortMemory.push(memoryData.content); + this.shortMemoryList.push(memoryData.content); this.limitShortMemory(); memoryData.memories.forEach(m => { diff --git a/src/index.ts b/src/index.ts index 3b5c6ad..9f8adb6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -500,14 +500,26 @@ function main() { case 'short': { const val3 = cmdArgs.getArgN(3); switch (val3) { + case 'on': { + ai.memory.useShortMemory = true; + seal.replyToSender(ctx, msg, '短期记忆已开启'); + AIManager.saveAI(id); + return ret; + } + case 'off': { + ai.memory.useShortMemory = false; + seal.replyToSender(ctx, msg, '短期记忆已关闭'); + AIManager.saveAI(id); + return ret; + } case 'show': { - const s = ai.memory.shortMemory.map((item, index) => `${index + 1}. ${item}`).join('\n'); + const s = ai.memory.shortMemoryList.map((item, index) => `${index + 1}. ${item}`).join('\n'); seal.replyToSender(ctx, msg, s || '无'); return ret; } case 'clr': { ai.memory.clearShortMemory(); - seal.replyToSender(ctx, msg, '群聊记忆已清除'); + seal.replyToSender(ctx, msg, '短期记忆已清除'); AIManager.saveAI(id); return ret; } @@ -522,7 +534,7 @@ function main() { ai.context.summaryCounter = 0; ai.memory.updateShortMemory(ctx, msg, ai, ai.context.messages.slice(0, shortMemorySummaryRound)) .then(() => { - const s = ai.memory.shortMemory.map((item, index) => `${index + 1}. ${item}`).join('\n'); + const s = ai.memory.shortMemoryList.map((item, index) => `${index + 1}. ${item}`).join('\n'); seal.replyToSender(ctx, msg, s || '无'); }); return ret; @@ -534,6 +546,7 @@ function main() { 【.ai memo [p/g] show】展示个人/群聊记忆 【.ai memo [p/g] del --关键词1 --关键词2】删除个人/群聊记忆 【.ai memo [p/g] clr】清除个人/群聊记忆 +【.ai memo s [on/off]】开启/关闭短期记忆 【.ai memo s show】展示短期记忆 【.ai memo s clr】清除短期记忆 【.ai memo sum】总结短期记忆`); diff --git a/src/update.ts b/src/update.ts index 0298df5..e06199f 100644 --- a/src/update.ts +++ b/src/update.ts @@ -2,7 +2,8 @@ export const updateInfo = { "4.10.1": `- 修复了构建ctx时,isPrivate始终为0的问题 - 新增保存图片功能 -- 重构了定时任务的执行`, +- 重构了定时任务的执行 +- 新增短期记忆单独控制开启`, "4.10.0": `- 新增了全局待机模式配置项 - 修改了部分正则和部分默认配置项 - 修复了无法调用内置指令 diff --git a/src/utils/utils_message.ts b/src/utils/utils_message.ts index 47e5593..5ac1378 100644 --- a/src/utils/utils_message.ts +++ b/src/utils/utils_message.ts @@ -45,8 +45,8 @@ export function buildSystemMessage(ctx: seal.MsgContext, ai: AI): Message { // 短期记忆 let shortMemoryPrompt = ''; - if (isShortMemory) { - shortMemoryPrompt = ai.memory.shortMemory.map((item, index) => `${index + 1}. ${item}`).join('\n'); + if (isShortMemory && ai.memory.useShortMemory) { + shortMemoryPrompt = ai.memory.shortMemoryList.map((item, index) => `${index + 1}. ${item}`).join('\n'); } // 调用函数 @@ -72,7 +72,7 @@ export function buildSystemMessage(ctx: seal.MsgContext, ai: AI): Message { "可发送图片列表": sandableImagesPrompt, "开启长期记忆": isMemory && memoryPrompt, "记忆信息": memoryPrompt, - "开启短期记忆": isShortMemory && shortMemoryPrompt, + "开启短期记忆": isShortMemory && ai.memory.useShortMemory && shortMemoryPrompt, "短期记忆信息": shortMemoryPrompt, "开启工具函数提示词": isTool && usePromptEngineering, "函数列表": toolsPrompt From 49350b046ec46807e66ac30c709373e3507b40d8 Mon Sep 17 00:00:00 2001 From: error2913 <2913949387@qq.com> Date: Mon, 25 Aug 2025 21:24:12 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Estatus=E5=91=BD?= =?UTF-8?q?=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.ts | 52 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/index.ts b/src/index.ts index 9f8adb6..aa58d79 100644 --- a/src/index.ts +++ b/src/index.ts @@ -369,6 +369,27 @@ function main() { const ai2 = AIManager.getAI(muid); const val2 = cmdArgs.getArgN(2); switch (val2) { + case 'status': { + let ai3 = ai; + if (cmdArgs.at.length > 0 && (cmdArgs.at.length !== 1 || cmdArgs.at[0].userId !== ctx.endPoint.userId)) { + ai3 = ai2; + } + + const { isMemory, isShortMemory } = ConfigManager.memory; + + const keywords = new Set(); + for (const key in ai3.memory.memoryMap) { + ai3.memory.memoryMap[key].keywords.forEach(kw => keywords.add(kw)); + } + + seal.replyToSender(ctx, msg, `${ai3.id} +长期记忆开启状态: ${isMemory ? '是' : '否'} +长期记忆条数: ${Object.keys(ai3.memory.memoryMap).length} +关键词库: ${Array.from(keywords).join('、')} +短期记忆开启状态: ${(isShortMemory && ai3.memory.useShortMemory) ? '是' : '否'} +短期记忆条数: ${ai3.memory.shortMemoryList.length}`); + return ret; + } case 'p': case 'private': { const val3 = cmdArgs.getArgN(3); @@ -398,11 +419,6 @@ function main() { } } } - case 'show': { - const s = ai2.memory.buildMemory(true, mctx.player.name, mctx.player.userId, '', ''); - seal.replyToSender(ctx, msg, s || '无'); - return ret; - } case 'del': { const idList = cmdArgs.args.slice(3); const kw = cmdArgs.kwargs.map(item => item.name); @@ -416,6 +432,11 @@ function main() { AIManager.saveAI(muid); return ret; } + case 'show': { + const s = ai2.memory.buildMemory(true, mctx.player.name, mctx.player.userId, '', ''); + seal.replyToSender(ctx, msg, s || '无'); + return ret; + } case 'clr': { ai2.memory.clearMemory(); seal.replyToSender(ctx, msg, '个人记忆已清除'); @@ -466,11 +487,6 @@ function main() { } } } - case 'show': { - const s = ai.memory.buildMemory(false, '', '', ctx.group.groupName, ctx.group.groupId); - seal.replyToSender(ctx, msg, s || '无'); - return ret; - } case 'del': { const idList = cmdArgs.args.slice(3); const kw = cmdArgs.kwargs.map(item => item.name); @@ -484,6 +500,11 @@ function main() { AIManager.saveAI(id); return ret; } + case 'show': { + const s = ai.memory.buildMemory(false, '', '', ctx.group.groupName, ctx.group.groupId); + seal.replyToSender(ctx, msg, s || '无'); + return ret; + } case 'clr': { ai.memory.clearMemory(); seal.replyToSender(ctx, msg, '群聊记忆已清除'); @@ -541,15 +562,14 @@ function main() { } default: { seal.replyToSender(ctx, msg, `帮助: +【.ai memo status (@xxx)】查看记忆状态,@为查看个人记忆状态 【.ai memo [p/g] st <内容>】设置个人/群聊设定 【.ai memo [p/g] st clr】清除个人/群聊设定 -【.ai memo [p/g] show】展示个人/群聊记忆 【.ai memo [p/g] del --关键词1 --关键词2】删除个人/群聊记忆 -【.ai memo [p/g] clr】清除个人/群聊记忆 +【.ai memo [p/g/s] show】展示个人/群聊/短期记忆 +【.ai memo [p/g/s] clr】清除个人/群聊/短期记忆 【.ai memo s [on/off]】开启/关闭短期记忆 -【.ai memo s show】展示短期记忆 -【.ai memo s clr】清除短期记忆 -【.ai memo sum】总结短期记忆`); +【.ai memo sum】立即总结一次短期记忆`); return ret; } } @@ -1154,7 +1174,7 @@ ${Object.keys(tool.info.function.parameters.properties).map(key => { cmdImage.name = 'img'; // 指令名字,可用中文 cmdImage.help = `盗图指南: 【.img draw [stl/lcl/save/all]】随机抽取偷的图片/本地图片/保存的图片/全部 -【.img stl (on/off)】偷图 开启/关闭 +【.img stl [on/off]】偷图 开启/关闭 【.img f [stl/save/all]】遗忘偷的图片/保存的图片/全部 【.img itt [图片/ran] (附加提示词)】图片转文字 【.img list [show/send]】展示保存的图片列表/展示并发送所有保存的图片 From 9090749ee14cac80adafcb29b312384ac05fb488 Mon Sep 17 00:00:00 2001 From: error2913 <2913949387@qq.com> Date: Mon, 25 Aug 2025 21:33:42 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=E8=AE=B0=E5=BF=86=E6=80=BB?= =?UTF-8?q?=E7=BB=93=E4=B8=93=E7=94=A8URL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/AI/memory.ts | 11 +++++++++-- src/config/config_memory.ts | 4 ++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/AI/memory.ts b/src/AI/memory.ts index 7ea8bff..fa9fb22 100644 --- a/src/AI/memory.ts +++ b/src/AI/memory.ts @@ -151,9 +151,16 @@ export class Memory { return; } - const { url, apiKey } = ConfigManager.request; + const { url: chatUrl, apiKey: chatApiKey } = ConfigManager.request; const { roleSettingTemplate, isPrefix, showNumber, showMsgId } = ConfigManager.message; - const { memoryBodyTemplate, memoryPromptTemplate } = ConfigManager.memory; + const { memoryUrl, memoryApiKey, memoryBodyTemplate, memoryPromptTemplate } = ConfigManager.memory; + + let url = chatUrl; + let apiKey = chatApiKey; + if (memoryUrl.trim()) { + url = memoryUrl; + apiKey = memoryApiKey; + } try { let [roleSettingIndex, _] = seal.vars.intGet(ctx, "$gSYSPROMPT"); diff --git a/src/config/config_memory.ts b/src/config/config_memory.ts index 211bc0e..944a359 100644 --- a/src/config/config_memory.ts +++ b/src/config/config_memory.ts @@ -31,6 +31,8 @@ export class MemoryConfig { seal.ext.registerBoolConfig(MemoryConfig.ext, "是否启用短期记忆", true, ""); seal.ext.registerIntConfig(MemoryConfig.ext, "短期记忆上限", 10, ""); seal.ext.registerIntConfig(MemoryConfig.ext, "短期记忆总结轮数", 10, ""); + seal.ext.registerStringConfig(MemoryConfig.ext, "记忆总结 url地址", "", '为空时,默认使用对话接口'); + seal.ext.registerStringConfig(MemoryConfig.ext, "记忆总结 API Key", "你的API Key", '若使用对话接口无需填写'); seal.ext.registerTemplateConfig(MemoryConfig.ext, "记忆总结 body", [ `"model":"deepseek-chat"`, `"max_tokens":1024`, @@ -114,6 +116,8 @@ export class MemoryConfig { isShortMemory: seal.ext.getBoolConfig(MemoryConfig.ext, "是否启用短期记忆"), shortMemoryLimit: seal.ext.getIntConfig(MemoryConfig.ext, "短期记忆上限"), shortMemorySummaryRound: seal.ext.getIntConfig(MemoryConfig.ext, "短期记忆总结轮数"), + memoryUrl: seal.ext.getStringConfig(MemoryConfig.ext, "记忆总结 url地址"), + memoryApiKey: seal.ext.getStringConfig(MemoryConfig.ext, "记忆总结 API Key"), memoryBodyTemplate: seal.ext.getTemplateConfig(MemoryConfig.ext, "记忆总结 body"), memoryPromptTemplate: seal.ext.getTemplateConfig(MemoryConfig.ext, "记忆总结prompt模板") } From 0815f520d1c28318faf6b3b24235b58ae4feb493 Mon Sep 17 00:00:00 2001 From: error2913 <2913949387@qq.com> Date: Mon, 25 Aug 2025 22:08:04 +0800 Subject: [PATCH 4/4] =?UTF-8?q?chore:=20=E4=BF=AE=E6=94=B9=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/config_backend.ts | 6 +++--- src/update.ts | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/config/config_backend.ts b/src/config/config_backend.ts index f48d1b6..53b5eee 100644 --- a/src/config/config_backend.ts +++ b/src/config/config_backend.ts @@ -8,9 +8,9 @@ export class BackendConfig { seal.ext.registerStringConfig(BackendConfig.ext, "流式输出", "http://localhost:3010", '自行搭建或使用他人提供的后端'); seal.ext.registerStringConfig(BackendConfig.ext, "图片转base64", "https://urltobase64.白鱼.chat", '可自行搭建'); - seal.ext.registerStringConfig(BackendConfig.ext, "联网搜索", "https://searxng.白鱼.chat", '可自行搭建'); - seal.ext.registerStringConfig(BackendConfig.ext, "网页读取", "https://webread.白鱼.chat", '可自行搭建'); - seal.ext.registerStringConfig(BackendConfig.ext, "用量图表", "http://error.白鱼.chat:3009", '可自行搭建'); + seal.ext.registerStringConfig(BackendConfig.ext, "联网搜索", "https://searxng.fishwhite.top", '可自行搭建'); + seal.ext.registerStringConfig(BackendConfig.ext, "网页读取", "https://webread.fishwhite.top", '可自行搭建'); + seal.ext.registerStringConfig(BackendConfig.ext, "用量图表", "http://localhost:3009", '可自行搭建'); } static get() { diff --git a/src/update.ts b/src/update.ts index e06199f..2165dbd 100644 --- a/src/update.ts +++ b/src/update.ts @@ -1,9 +1,12 @@ // 版本更新日志,格式为 "版本号": "更新内容",版本号格式为 "x.y.z",按照时间顺序从新到旧排列。 export const updateInfo = { - "4.10.1": `- 修复了构建ctx时,isPrivate始终为0的问题 + "4.10.1": ` +- 可能修复了非指令无法响应的问题 +- 修复了构建ctx时,isPrivate始终为0的问题 - 新增保存图片功能 - 重构了定时任务的执行 -- 新增短期记忆单独控制开启`, +- 新增短期记忆单独控制开启 +- 新增memo status命令`, "4.10.0": `- 新增了全局待机模式配置项 - 修改了部分正则和部分默认配置项 - 修复了无法调用内置指令