From 8973077abd5adb8d8c1a2d4fe0cbdc7dc7a403b6 Mon Sep 17 00:00:00 2001 From: thzxx Date: Sun, 19 Apr 2026 19:36:41 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=87=AA=E5=8A=A8=E8=AE=B0=E5=BF=86?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20=E2=80=94=20=E7=A6=81=E6=AD=A2=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=8F=90=E5=8F=96=E8=A7=84=E5=88=99=E3=80=81=E6=8F=90?= =?UTF-8?q?=E9=AB=98=E6=8F=90=E5=8F=96=E9=97=A8=E6=A7=9B=E4=B8=8E=E8=B4=A8?= =?UTF-8?q?=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/components/input-area.ts | 2 +- src/renderer/services/agent-engine.ts | 2 +- src/renderer/services/memory-manager.ts | 51 ++++++++++++++++++------- 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/renderer/components/input-area.ts b/src/renderer/components/input-area.ts index 5b8ee8b..5ea3ad8 100644 --- a/src/renderer/components/input-area.ts +++ b/src/renderer/components/input-area.ts @@ -706,7 +706,7 @@ export async function sendMessage(): Promise { updateTotalTokens(); // ── 自动提取记忆(非阻塞)── - if (isMemoryEnabled() && freshSession.messages.length >= 6) { + if (isMemoryEnabled() && freshSession.messages.length >= 10) { const currentSession2 = state.get(KEYS.CURRENT_SESSION); if (currentSession2) { extractMemoriesFromConversation( diff --git a/src/renderer/services/agent-engine.ts b/src/renderer/services/agent-engine.ts index b75807d..fbdfefc 100644 --- a/src/renderer/services/agent-engine.ts +++ b/src/renderer/services/agent-engine.ts @@ -660,7 +660,7 @@ export async function runAgentLoop( logInfo('无工具调用,ReAct Agent Loop 结束'); // 自动提取记忆(仅在对话结束后) - if (isMemoryEnabled() && messages.length >= 4) { + if (isMemoryEnabled() && messages.length >= 10) { try { const { extractMemoriesFromConversation } = await import('./memory-manager.js'); await extractMemoriesFromConversation( diff --git a/src/renderer/services/memory-manager.ts b/src/renderer/services/memory-manager.ts index 633ec28..ad0d29b 100644 --- a/src/renderer/services/memory-manager.ts +++ b/src/renderer/services/memory-manager.ts @@ -248,6 +248,12 @@ export async function addMemory(data: { }): Promise { const db = state.get(KEYS.DB); + // 自动提取来源禁止添加 rule 类型 + if (data.type === 'rule' && data.source === '自动提取') { + logWarn('记忆提取拦截', '自动提取不允许创建规则类型,规则只能由用户手动添加'); + throw new Error('规则类型记忆只能由用户手动添加'); + } + // 安全扫描:检测 prompt injection 和敏感信息 const securityCheck = scanMemorySecurity(data.content); if (!securityCheck.safe) { @@ -651,18 +657,30 @@ ${conversationText.slice(0, 4000)} } \`\`\` -记忆类型说明: -- fact: 关于用户的事实(项目、身份、背景、习惯) -- preference: 用户偏好(语言风格、输出格式、技术栈偏好) -- rule: 用户要求遵守的规则(编码规范、输出要求) +记忆类型说明(自动提取仅支持以下两种): +- fact: 关于用户的具体事实(项目信息、技术栈、工作内容、个人背景) +- preference: 用户明确表达的偏好(喜欢某种输出格式、编码风格等) -提取规则: -1. 只提取真正有价值、值得跨会话记住的信息 -2. 每条记忆精炼简洁,不超过 50 字 -3. importance 1-10,5 为普通,8+ 为必须记住 -4. tags 2-5 个关键词,用于检索匹配 -5. 最多提取 5 条,宁缺毋滥 -6. 如果对话中没有值得记住的信息,返回 {"entries": []}`; +⚠️ 严禁自动提取的类型: +- rule(规则): 规则只能由用户手动添加,绝对不要自动提取规则 + +提取标准(极其严格): +1. 只提取用户**明确陈述**的、有长期价值的信息,不要猜测或推断 +2. 必须是**跨会话有用**的信息——如果只是本次对话的临时内容,不要提取 +3. 每条记忆精炼简洁,不超过 50 字 +4. importance 1-10,只有真正重要的才给 7+ +5. tags 2-5 个关键词,用于检索匹配 +6. 最多提取 3 条,宁缺毋滥 + +以下内容**不要提取**(常见错误): +- 对话中的临时任务描述(如"帮我写个函数") +- AI 的回复或建议内容 +- 泛泛的表述(如"用户喜欢编程"、"用户是开发者") +- 一次性的查询或请求 +- 用户没有明确表达的隐含偏好 +- 任何可以简单从对话上下文推断的信息 + +如果对话中没有真正值得跨会话记住的信息,返回 {"entries": []}`; try { const response = await api.chat({ @@ -685,13 +703,18 @@ ${conversationText.slice(0, 4000)} const currentSession = state.get(KEYS.CURRENT_SESSION); for (const entry of parsed.entries) { if (!entry.content || entry.content.length < 5) continue; - const validType = (['fact', 'preference', 'rule'] as const).includes(entry.type as any) ? entry.type : 'fact'; + const validType = entry.type === 'fact' || entry.type === 'preference' ? entry.type : 'fact'; + // 自动提取仅允许 fact 和 preference + if (entry.type === 'rule') { + logDebug('跳过自动提取的规则类型', entry.content.slice(0, 40)); + continue; + } await addMemory({ - type: validType as any, + type: validType, content: entry.content, importance: Math.min(10, Math.max(1, entry.importance || 5)), tags: entry.tags || [], - source: sessionTitle || '自动提取', + source: '自动提取', sessionId: currentSession?.id }); count++;