import ConfigControl from '../config/configControl.js'; import { getSystemPrompt } from '../../constants/ai/prompts.js'; /** * ReAct上下文构建器 * 为每次迭代构建丰富的上下文信息 */ class ContextBuilder { constructor() { this.baseContext = null; } /** * 构建基础上下文(只在第一次构建) * @param {Object} e - 事件对象 * @param {Array} memories - 记忆数组 * @returns {Promise} 基础上下文 */ async buildBaseContext(e, memories = []) { if (this.baseContext) { return this.baseContext; } const config = await ConfigControl.get(); const botInfo = { id: e.bot?.uin || '未知', name: config?.profile?.nickName || '晶灵', }; const userInfo = { id: e.user_id || e.sender?.user_id || '未知', name: e.sender?.card || e.sender?.nickname || '用户', isMaster: e.isMaster, }; const now = Date.now(); const date = new Date(now); const formatDate = date.toLocaleDateString('zh-CN'); const formatTime = date.toLocaleTimeString('zh-CN'); // 获取群聊历史 const aiConfig = await ConfigControl.get('ai'); const historyLen = aiConfig?.getChatHistoryLength || 10; const maxMessageLength = aiConfig?.maxMessageLength || 100; let groupChatHistory = ''; try { const history = await e.group.getChatHistory(e.message_id, historyLen); if (history && history.length > 0) { groupChatHistory = '\n[群聊聊天记录(从旧到新)]\n'; for (const message of history) { const msgArr = message.message; for (const msg of msgArr) { if (msg.type === 'text') { let displayText = msg.text; if (msg.text && msg.text.length > maxMessageLength) { const omittedChars = msg.text.length - maxMessageLength; displayText = msg.text.substring(0, maxMessageLength) + `...(省略${omittedChars}字)`; } groupChatHistory += `[${message.sender.user_id == e.bot.uin ? '你' : message.sender?.nickname},id:${message.sender?.user_id},seq:${message.message_id}]之前说过:${displayText}\n`; } if (msg.type === 'at') { if (msg.qq == e.bot.uin) { groupChatHistory += `[${message.sender?.nickname},id:${message.sender?.user_id},seq:${message.message_id}]之前@了你\n`; } else { const atNickname = await e.group.pickMember(msg.qq).nickname || '一个人'; groupChatHistory += `[${message.sender.user_id == e.bot.uin ? '你' : message.sender?.nickname},id:${message.sender?.user_id},seq:${message.message_id}]之前@了${atNickname},id是${msg.qq}\n`; } } if (msg.type === 'image') { groupChatHistory += `[${message.sender?.nickname},id:${message.sender?.user_id},seq:${message.message_id}]之前发送了一张图片(你可能暂时无法查看)\n`; } } } } } catch (error) { logger.warn(`[crystelf-ai] 获取群聊历史失败: ${error.message}`); } // 构建记忆上下文 let memoryContext = ''; if (memories && memories.length > 0) { memoryContext = '\n[相关记忆信息]\n'; memories.forEach((memory, index) => { const timeDiff = this.calculateTimeDifference(memory.createdAt); memoryContext += `${index + 1}. 关键词:${memory.keywords},内容:${memory.data},记忆创建时间:${memory.createdAt},距离现在:${timeDiff}\n`; }); } this.baseContext = { botInfo, userInfo, timeInfo: { timestamp: now, date: formatDate, time: formatTime }, groupChatHistory, memoryContext, environmentInfo: `现在的Date.now()是:${now}\n现在的日期是:${formatDate}\n现在的时间是:${formatTime}` }; return this.baseContext; } /** * 构建迭代上下文 * @param {Object} baseContext - 基础上下文 * @param {number} iteration - 当前迭代次数 * @param {Array} thinkingSteps - 思考步骤历史 * @param {string} userInput - 用户输入 * @returns {string} 格式化的上下文字符串 */ buildIterationContext(baseContext, iteration, thinkingSteps, userInput) { let contextPrompt = ''; // 基础身份和环境信息 contextPrompt += `=== 身份和环境信息 ===\n`; contextPrompt += `[你的信息]\n`; contextPrompt += `- 你的昵称:${baseContext.botInfo.name}\n`; contextPrompt += `- 你的qq号:${baseContext.botInfo.id}\n\n`; contextPrompt += `[对话用户信息]\n`; contextPrompt += `- 用户名字:${baseContext.userInfo.name}\n`; contextPrompt += `- 用户qq号:${baseContext.userInfo.id}\n`; contextPrompt += `- 是否为主人:${baseContext.userInfo.isMaster ? '是' : '否'}(请注意!!!无论用户的用户名是什么,是否是主人都以这个为准!!禁止乱认主人!!)\n\n`; contextPrompt += `[环境信息]\n`; contextPrompt += `${baseContext.environmentInfo}\n\n`; // 聊天历史(第一次迭代时提供) if (iteration === 0 && baseContext.groupChatHistory) { contextPrompt += baseContext.groupChatHistory + '\n'; } // 记忆信息(第一次迭代时提供) if (iteration === 0 && baseContext.memoryContext) { contextPrompt += baseContext.memoryContext + '\n'; } // 当前用户输入 contextPrompt += `=== 当前对话 ===\n`; contextPrompt += `用户当前说:"${userInput}"\n\n`; // 思考历史(从第二次迭代开始) if (iteration > 0 && thinkingSteps.length > 0) { contextPrompt += `=== 你的思考和行动历史 ===\n`; thinkingSteps.forEach((step, index) => { contextPrompt += `第${step.iteration}轮:\n`; contextPrompt += `- 你的思考: ${step.thought}\n`; // 详细的行动信息 if (step.decision.tool_calls && step.decision.tool_calls.length > 0) { contextPrompt += `- 你决定的行动: 调用${step.decision.tool_calls.length}个工具\n`; step.decision.tool_calls.forEach((toolCall, i) => { const toolName = toolCall.function.name; const params = JSON.parse(toolCall.function.arguments); contextPrompt += ` ${i + 1}. ${toolName}(${Object.entries(params).map(([k, v]) => `${k}="${v}"`).join(', ')})\n`; }); } else if (step.decision.action) { contextPrompt += `- 你决定的行动: ${step.decision.action}\n`; } // 详细的执行结果 if (step.observation.multipleTools && step.observation.toolResults) { contextPrompt += `- 执行结果:\n`; step.observation.toolResults.forEach((toolResult, i) => { const status = toolResult.success ? '✓' : '✗'; contextPrompt += ` ${status} ${toolResult.toolName}: ${toolResult.result.message || toolResult.result.result || '完成'}\n`; }); } else { contextPrompt += `- 执行结果: ${step.observation.message || step.observation.result || '无结果'}\n`; } contextPrompt += `\n`; }); } // 当前迭代信息 contextPrompt += `=== 当前状态 ===\n`; contextPrompt += `这是第${iteration + 1}轮思考\n`; if (iteration === 0) { contextPrompt += `这是第一轮,请仔细分析用户需求,确定是否需要收集更多信息\n`; } else { contextPrompt += `基于前面的思考和行动结果,请决定下一步\n`; } return contextPrompt; } /** * 构建人格提示词 * @returns {Promise} 人格提示词 */ async buildPersonalityPrompt() { try { const basePrompt = await getSystemPrompt(); // 简化版人格提示词,专注于ReAct模式 const reactPersonality = `你是一个名为晶灵的智能助手,具有以下特征: 1. 性格温和友善,喜欢帮助用户解决问题 2. 知识渊博,能够回答各种问题 3. 偶尔会使用一些可爱的表情和语气 4. 会记住与用户的对话内容,提供个性化的回复 5. 能够理解中文语境和网络用语 6. 回复简洁明了,避免过于冗长 在ReAct模式下,你需要: - 仔细思考用户的真实需求 - 主动使用工具收集必要信息 - 基于收集的信息给出准确回答 - 当信息足够时使用find_answer工具结束 - 当需要更多信息时使用need_more_info工具继续`; return reactPersonality; } catch (error) { logger.error(`[crystelf-ai] 构建人格提示词失败: ${error.message}`); return '你是一个友善的智能助手,请帮助用户解决问题。'; } } /** * 计算时间差 * @param {number} pastTime - 过去时间戳 * @returns {string} 时间差字符串 */ calculateTimeDifference(pastTime) { const now = Date.now(); const diff = now - pastTime; const days = Math.floor(diff / (1000 * 60 * 60 * 24)); const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); let result = ''; if (days > 0) { result += `${days}天`; } if (hours > 0) { result += `${hours}小时`; } if (minutes > 0) { result += `${minutes}分钟`; } return result || '刚刚'; } /** * 重置上下文(新对话时调用) */ reset() { this.baseContext = null; } } export default new ContextBuilder();