From 1a4a8dce980e2f22ad62e2c8487ff1446f404a03 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 30 Apr 2026 16:44:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=A7=BB=E6=A4=8D6=E4=B8=AA=E7=BC=BA?= =?UTF-8?q?=E5=A4=B1=E5=B7=A5=E5=85=B7=E5=AE=9A=E4=B9=89=E5=92=8Chandler?= =?UTF-8?q?=E5=88=B0AIAgentService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - memory_introspect — 查看记忆状态统计 - memory_archive — 归档旧记忆 - memory_cleanup — 清理已删除数据 - memory_query_archived — 查询已归档记忆 - context_rewrite — 压缩工具调用上下文 - persona_remove — 删除单条人设属性 同时在GraphMemoryService添加: - queryArchived() 方法 - personaRemove() 方法 更新系统提示词,加入工具调用规则和context_rewrite使用说明 --- .../src/main/ets/services/AIAgentService.ets | 108 ++++++++++++++++++ .../main/ets/services/GraphMemoryService.ets | 35 ++++++ 2 files changed, 143 insertions(+) diff --git a/entry/src/main/ets/services/AIAgentService.ets b/entry/src/main/ets/services/AIAgentService.ets index d66cd38..3472600 100644 --- a/entry/src/main/ets/services/AIAgentService.ets +++ b/entry/src/main/ets/services/AIAgentService.ets @@ -232,7 +232,13 @@ ${personaContext || '你是一个帮助用户记录和回忆信息的助手。 - memory_recall(queryIntent, seedEntities?, depth?, timeRange?, sessionFilter?): 检索记忆 - memory_commit(triplets, entityTypes?, sessionId?, turnId?): 写入记忆 - memory_purge(criteria, mode, newRelation?): 删除/修正记忆 +- memory_introspect(sessionId?): 查看记忆状态统计 +- memory_archive(days?): 归档旧记忆 +- memory_cleanup(dryRun?): 清理已删除数据 +- memory_query_archived(days?, keyword?): 查询已归档记忆 +- context_rewrite(summary): 压缩工具调用上下文 - persona_update(tone?, style?, personality?, catchphrase?, background?): 更新人设 +- persona_remove(attribute): 删除单条人设属性 - persona_clear(): 清除人设 - task_create(taskId, description, infoNodes?): 创建任务 - task_set_state(taskId, state): 设置任务状态 @@ -241,6 +247,11 @@ ${personaContext || '你是一个帮助用户记录和回忆信息的助手。 - task_archive(taskId, summary?): 归档任务 - task_query(limit?, stateFilter?): 查询任务列表 +## 工具调用规则 +1. 每轮对话必须按顺序执行:步骤1查询人设 → 步骤2查询工作记忆链 → 步骤3处理请求 +2. context_rewrite 必须单独调用,不能和其他工具在同一轮一起调! +3. 工具调用 ≥5 次后应使用 context_rewrite 压缩上下文 + ## 写入规则 用户明确表达以下信息时必须写入记忆: - 偏好、兴趣 @@ -324,12 +335,37 @@ const queryProps: ToolPropertiesDefinition = { limit: makeIntegerProp('返回数量,默认10'), stateFilter: makeStringProp('状态过滤: 进行中/已完成/已暂停/已取消/archived') }; +const introspectProps: ToolPropertiesDefinition = { + sessionId: makeStringProp('会话ID(可选)') +}; +const archiveProps2: ToolPropertiesDefinition = { + days: makeIntegerProp('归档天数,默认30') +}; +const cleanupProps: ToolPropertiesDefinition = { + dryRun: makeBoolProp('仅预览不删除') +}; +const queryArchivedProps: ToolPropertiesDefinition = { + days: makeIntegerProp('最近N天内的归档记录'), + keyword: makeStringProp('关键词过滤') +}; +const contextRewriteProps: ToolPropertiesDefinition = { + summary: makeStringProp('压缩后的摘要文本,必须包含工具调用元信息') +}; +const personaRemoveProps: ToolPropertiesDefinition = { + attribute: makeStringProp('要删除的属性名(如:扮演角色、说话风格)') +}; const TOOLS_DEFINITION: ToolFunctionDef[] = [ makeToolDef('memory_recall', '检索记忆。支持关键词、种子实体、深度扩展。返回相关实体和关系。', recallProps, ['queryIntent']), makeToolDef('memory_commit', '写入记忆。将三元组写入图数据库。', commitProps, ['triplets']), makeToolDef('memory_purge', '删除或修正记忆。支持条件删除和纠错替代。', purgeProps, ['criteria', 'mode']), + makeToolDef('memory_introspect', '查看记忆状态。返回实体数量、关系数量、热点实体。', introspectProps), + makeToolDef('memory_archive', '归档旧记忆。将N天前的非活跃关系标记为归档状态。', archiveProps2, ['days']), + makeToolDef('memory_cleanup', '清理无效数据。物理删除已删除状态超过90天的关系和孤立节点。', cleanupProps), + makeToolDef('memory_query_archived', '查询已归档的记忆。返回所有 status=archived 的关系记录。', queryArchivedProps), + makeToolDef('context_rewrite', '压缩本轮对话的工具调用上下文。将冗长的JSON工具结果提炼为简洁摘要。', contextRewriteProps, ['summary']), makeToolDef('persona_update', '更新AI人设属性(语气、风格、性格等)。', personaProps), + makeToolDef('persona_remove', '删除单条人设属性。保留其他人设不变。', personaRemoveProps, ['attribute']), makeToolDef('persona_clear', '清除所有人设信息。', EMPTY_PROPS), makeToolDef('task_create', '创建新的工作记忆任务节点。', createProps, ['taskId', 'description']), makeToolDef('task_set_state', '设置任务状态。', setStateProps, ['taskId', 'state']), @@ -353,7 +389,13 @@ type ToolHandlerName = | 'memoryRecal' | 'memoryCommit' | 'memoryPurge' + | 'memoryIntrospect' + | 'memoryArchive' + | 'memoryCleanup' + | 'memoryQueryArchived' + | 'contextRewrite' | 'personaUpdate' + | 'personaRemove' | 'personaClear' | 'taskCreate' | 'taskSetState' @@ -366,7 +408,13 @@ const TOOL_HANDLER_MAP: Record = { 'memory_recall': 'memoryRecal', 'memory_commit': 'memoryCommit', 'memory_purge': 'memoryPurge', + 'memory_introspect': 'memoryIntrospect', + 'memory_archive': 'memoryArchive', + 'memory_cleanup': 'memoryCleanup', + 'memory_query_archived': 'memoryQueryArchived', + 'context_rewrite': 'contextRewrite', 'persona_update': 'personaUpdate', + 'persona_remove': 'personaRemove', 'persona_clear': 'personaClear', 'task_create': 'taskCreate', 'task_set_state': 'taskSetState', @@ -599,6 +647,56 @@ export class AIAgentService { return result; } + case 'memoryIntrospect': { + const introspectResult = await this.memoryService.memoryIntrospect(args.sessionId as string); + const result: ToolCallResult = { + name: 'memory_introspect', + success: true, + message: `实体: ${introspectResult.entityCount}, 关系: ${introspectResult.relationCount}, 热点: ${introspectResult.hotNodes.length}` + }; + return result; + } + + case 'memoryArchive': { + const archiveResult = await this.memoryService.archive(args.days as number); + const result: ToolCallResult = { + name: 'memory_archive', + success: true, + message: `已归档 ${archiveResult.archived} 条关系` + }; + return result; + } + + case 'memoryCleanup': { + const cleanupResult = await this.memoryService.cleanup((args.dryRun as boolean) !== false); + const result: ToolCallResult = { + name: 'memory_cleanup', + success: true, + message: `清理: ${cleanupResult.cleaned} 条关系, ${cleanupResult.deletedOrphans} 个孤儿节点` + (cleanupResult.dryRun ? ' (预览模式)' : '') + }; + return result; + } + + case 'memoryQueryArchived': { + const qaResult = await this.memoryService.queryArchived(args.days as number, args.keyword as string); + const result: ToolCallResult = { + name: 'memory_query_archived', + success: true, + message: `找到 ${qaResult.length} 条归档记录` + }; + return result; + } + + case 'contextRewrite': { + const summary = args.summary as string; + const result: ToolCallResult = { + name: 'context_rewrite', + success: summary.includes('[工具调用总结'), + message: summary.includes('[工具调用总结') ? '上下文已压缩' : '格式错误:必须包含[工具调用总结]标记' + }; + return result; + } + case 'personaUpdate': { const personaParams: PersonaUpdateParams = { tone: args.tone as string, @@ -616,6 +714,16 @@ export class AIAgentService { return result; } + case 'personaRemove': { + const prResult = await this.memoryService.personaRemove(args.attribute as string); + const result: ToolCallResult = { + name: 'persona_remove', + success: prResult.success, + message: prResult.message + }; + return result; + } + case 'personaClear': { const pcResult = await this.memoryService.personaClear(); const result: ToolCallResult = { diff --git a/entry/src/main/ets/services/GraphMemoryService.ets b/entry/src/main/ets/services/GraphMemoryService.ets index 25e2d41..fd53bc6 100644 --- a/entry/src/main/ets/services/GraphMemoryService.ets +++ b/entry/src/main/ets/services/GraphMemoryService.ets @@ -429,6 +429,20 @@ export class GraphMemoryService { return cleanupResult; } + /** + * 查询已归档的记忆 + * 对应 tools.memory_query_archived + */ + async queryArchived(days?: number, keyword?: string): Promise { + try { + const result = await this.db.queryArchived(days, keyword); + return result; + } catch (e) { + console.error('queryArchived error: ' + JSON.stringify(e)); + return []; + } + } + // ========= 人设管理 ========= /** @@ -521,6 +535,27 @@ export class GraphMemoryService { } } + /** + * 删除单条人设属性 + * 对应 tools.persona_remove + */ + async personaRemove(attribute: string): Promise { + try { + // 将 attribute 转为关系名格式 + const relationName = 'HAS_PERSONA_' + attribute.toUpperCase(); + const result = await this.db.purge({ subject: PERSONA_NODE_NAME, relationType: relationName }, 'hard'); + return { + success: result.deleted_count > 0, + message: result.deleted_count > 0 ? `已删除人设属性: ${attribute}` : `未找到人设属性: ${attribute}` + }; + } catch (e) { + return { + success: false, + message: `删除人设属性失败: ${(e as Error).message || ''}` + }; + } + } + /** * 查询当前人设 */