From 5c98623f2b7f6cb7b4679c45c47daa51dd7afe01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Mon, 24 Feb 2025 16:49:55 +0800 Subject: [PATCH] x --- src/onebot/network/plugin.ts | 4 +- src/plugin/index.ts | 135 +++++++++++++++++++++-------------- 2 files changed, 83 insertions(+), 56 deletions(-) diff --git a/src/onebot/network/plugin.ts b/src/onebot/network/plugin.ts index 8376fb9e..b4a4fb03 100644 --- a/src/onebot/network/plugin.ts +++ b/src/onebot/network/plugin.ts @@ -1,5 +1,5 @@ import { OB11EmitEventContent, OB11NetworkReloadType } from './index'; -import { NapCatOneBot11Adapter, OB11ArrayMessage, OB11Message } from '@/onebot'; +import { NapCatOneBot11Adapter, OB11ArrayMessage } from '@/onebot'; import { NapCatCore } from '@/core'; import { PluginConfig } from '../config/config'; import { plugin_onmessage } from '@/plugin'; @@ -15,7 +15,7 @@ export class OB11PluginAdapter extends IOB11NetworkAdapter { messagePostFormat: 'array', reportSelfMessage: false, enable: true, - debug: false, + debug: true, }; super(name, config, core, obContext, actions); } diff --git a/src/plugin/index.ts b/src/plugin/index.ts index 74043159..ebbebd3e 100644 --- a/src/plugin/index.ts +++ b/src/plugin/index.ts @@ -1,5 +1,5 @@ import { NapCatOneBot11Adapter, OB11ArrayMessage, OB11MessageDataType } from '@/onebot'; -import { ChatType, NapCatCore, Peer, RawMessage } from '@/core'; +import { NapCatCore, RawMessage } from '@/core'; import { ActionMap } from '@/onebot/action'; import { OB11PluginAdapter } from '@/onebot/network/plugin'; import { OpenAI } from 'openai'; @@ -8,7 +8,10 @@ const API_KEY = 'sk-vDXUiGa1fx8ygDJDjAlr2rUyoz3uPhMxr8zId8n3ycMkV23i'; const BASE_URL = 'https://api.bili2233.work/v1'; const MODEL = 'gemini-2.0-flash-thinking-exp'; const SHORT_TERM_MEMORY_LIMIT = 100; - +const BOT_NAME = '千千'; +const PROMPT = + `你的名字叫千千,你现在处于一个QQ群聊之中,作为博学多识的可爱群员,热心解答各种问题和高强度水群 +记住你说的话要尽量的简洁但具有情感,不要长篇大论,一句话不宜超过五十个字。`; const client = new OpenAI({ apiKey: API_KEY, baseURL: BASE_URL @@ -16,6 +19,7 @@ const client = new OpenAI({ const longTermMemory: Map = new Map(); const shortTermMemory: Map = new Map(); +const memoryTransferCount: Map = new Map(); async function createChatCompletionWithRetry(params: any, retries: number = 3): Promise { for (let attempt = 0; attempt < retries; attempt++) { @@ -28,25 +32,6 @@ async function createChatCompletionWithRetry(params: any, retries: number = 3): } } -async function handleMessageArray2String(messages: RawMessage[]): Promise { - const result: string[] = []; - let data = ''; - for (let i = 0; i < messages.length; i++) { - try { - if (messages[i]) { - data += await handleMessage2String(messages[i]!) + '\n'; - } - } catch { - continue; - } - if ((i + 1) % 1000 === 0 || i === messages.length - 1) { - result.push(data); - data = ''; - } - } - return result; -} - async function handleMessage2String(message: RawMessage): Promise { let data = ''; for (let element of message.elements) { @@ -56,7 +41,7 @@ async function handleMessage2String(message: RawMessage): Promise { if (element.replyElement) { const records = message.records.find(msgRecord => msgRecord.msgId === element.replyElement?.sourceMsgIdInRecords); if (records) { - data += '[Reply] 回应别人的消息 ->' + await handleMessage2String(records) + '<-'; + data += '[Reply] 回应内容 源消息[' + await handleMessage2String(records) + ']'; } } } @@ -65,10 +50,7 @@ async function handleMessage2String(message: RawMessage): Promise { } function updateMemoryLayer(memoryLayer: Map, group_id: string, newMessages: string[]) { - if (!memoryLayer.has(group_id)) { - memoryLayer.set(group_id, []); - } - const currentMemory = memoryLayer.get(group_id)!; + const currentMemory = memoryLayer.get(group_id) || []; currentMemory.push(...newMessages); if (currentMemory.length > SHORT_TERM_MEMORY_LIMIT) { memoryLayer.set(group_id, currentMemory.slice(-SHORT_TERM_MEMORY_LIMIT)); @@ -85,6 +67,7 @@ async function mergeAndUpdateMemory(existing_memories: string, new_memory: strin - 如果一个记忆直接与新信息矛盾,请批判性地评估两条信息: - 如果新记忆提供了更近期或更准确的更新,用新记忆替换旧记忆。 - 如果新记忆看起来不准确或细节较少,保留旧记忆并丢弃新记忆。 + - 注意区分对应人物的记忆和印象, 不要产生混淆人物的印象和记忆。 - 在所有记忆中保持一致且清晰的风格,确保每个条目简洁而信息丰富。 - 如果新记忆是现有记忆的变体或扩展,更新现有记忆以反映新信息。 以下是任务的详细信息: @@ -102,24 +85,61 @@ ${new_memory}`; } async function generateChatCompletion(content_data: string): Promise { + console.log(content_data); const chatCompletion = await createChatCompletionWithRetry({ messages: [{ role: 'user', content: content_data }], model: MODEL }); - console.log(chatCompletion); return chatCompletion.choices[0]?.message.content || ''; } -async function updateMemory(group_id: string, newMessages: string[]) { - updateMemoryLayer(shortTermMemory, group_id, newMessages); +async function updateMemory(group_id: string, newMessages: string) { + updateMemoryLayer(shortTermMemory, group_id, [newMessages]); const currentMemory = longTermMemory.get(group_id) || ''; + const transferCount = memoryTransferCount.get(group_id) || 0; + if (shortTermMemory.get(group_id)!.length >= SHORT_TERM_MEMORY_LIMIT) { - const mergedMemory = await mergeAndUpdateMemory(currentMemory, shortTermMemory.get(group_id)!.join('\n')); - longTermMemory.set(group_id, mergedMemory); - shortTermMemory.set(group_id, []); + memoryTransferCount.set(group_id, transferCount + 1); + if (memoryTransferCount.get(group_id)! >= 1) { + const mergedMemory = await mergeAndUpdateMemory(currentMemory, shortTermMemory.get(group_id)!.join('\n')); + longTermMemory.set(group_id, mergedMemory); + shortTermMemory.set(group_id, []); + memoryTransferCount.set(group_id, 0); + } } } +async function clearShortTermMemory(group_id: string) { + shortTermMemory.set(group_id, []); + memoryTransferCount.set(group_id, 0); +} + +async function clearLongTermMemory(group_id: string) { + longTermMemory.set(group_id, ''); +} + +async function handleClearMemoryCommand(group_id: string, type: 'short' | 'long', action: ActionMap, adapter: string, instance: OB11PluginAdapter) { + if (type === 'short') { + await clearShortTermMemory(group_id); + await sendGroupMessage(group_id, '短期上下文已清理', action, adapter, instance); + } else { + await clearLongTermMemory(group_id); + await sendGroupMessage(group_id, '长期上下文已清理', action, adapter, instance); + } +} + +async function sendGroupMessage(group_id: string, text: string, action: ActionMap, adapter: string, instance: OB11PluginAdapter) { + await action.get('send_group_msg')?.handle({ + group_id: String(group_id), + message: [ + { + type: OB11MessageDataType.text, + data: { text } + } + ] + }, adapter, instance.config); +} + export const plugin_onmessage = async ( adapter: string, core: NapCatCore, @@ -133,35 +153,42 @@ export const plugin_onmessage = async ( if (!user_uid) { return; } - const peer: Peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: message.group_id?.toString() ?? '' }; - const msg = await core.apis.MsgApi.queryFirstMsgBySender(peer, [user_uid]); - if (msg.msgList.length < 1) { + let msg_string = ''; + try { + msg_string = await handleMessage2String(message.raw!); + } catch (error) { + if (msg_string == '') { + return; + } + } + + const user_info = await action.get('get_group_member_info')?.handle({ group_id: message.group_id?.toString()!, user_id: user_id }, adapter, instance.config); + //const text = `${message.sender.nickname}(${message.sender.user_id})发送了消息 : ${msg_string}`; + if (message.raw_message === '/清除短期上下文') { + await handleClearMemoryCommand(message.group_id?.toString()!, 'short', action, adapter, instance); return; } - const msg_string_all = await handleMessageArray2String(msg.msgList); - const user_info = await action.get('get_group_member_info')?.handle({ group_id: message.group_id?.toString()!, user_id: user_id }, adapter, instance.config); - - const msg_string = msg_string_all.join('\n'); - - await updateMemory(message.group_id?.toString()!, msg_string_all); + if (message.raw_message === '/清除长期上下文') { + await handleClearMemoryCommand(message.group_id?.toString()!, 'long', action, adapter, instance); + return; + } + const orimsgid = message.message.find(e => e.type == 'reply')?.data.id; + const orimsg = orimsgid ? await action.get('get_msg')?._handle({ message_id: orimsgid }, adapter, instance.config) : undefined; + if ( + !message.raw_message.startsWith(BOT_NAME) && + !message.message.find(e => e.type == 'at' && e.data.qq == core.selfInfo.uin) && + orimsg?.sender.user_id.toString() !== core.selfInfo.uin + ) { + return; + } + await updateMemory(message.group_id?.toString()!, msg_string); const longTermMemoryString = longTermMemory.get(message.group_id?.toString()!) || ''; const shortTermMemoryString = shortTermMemory.get(message.group_id?.toString()!)?.join('\n') || ''; const content_data = - `请根据下面聊天内容,继续与 ${user_info?.data?.card || user_info?.data?.nickname} 进行对话。注意回复内容只用输出内容,不要提及此段话,注意一定不要使用markdown,请采用纯文本回复。长时间记忆:\n${longTermMemoryString}\n短时间记忆:\n${shortTermMemoryString}\n当前对话:\n${msg_string}\n}`; - console.log(`Final content data: ${content_data}`); + `请根据下面聊天内容,继续与 ${user_info?.data?.card || user_info?.data?.nickname} 进行对话。注意回复内容只用输出内容,不要提及此段话,注意一定不要使用markdown,请采用纯文本回复。你的人设:${PROMPT}长时间记忆:\n${longTermMemoryString}\n短时间记忆:\n${shortTermMemoryString}\n当前对话:\n${msg_string}\n}`; const msg_ret = await generateChatCompletion(content_data); - console.log(`Final content ret: ${msg_ret}`); - - await action.get('send_group_msg')?.handle({ - group_id: String(message.group_id), - message: [ - { - type: OB11MessageDataType.text, - data: { text: msg_ret } - } - ] - }, adapter, instance.config); + await sendGroupMessage(message.group_id?.toString()!, msg_ret, action, adapter, instance); }; \ No newline at end of file