refactor: 工程标准化 — 组件提取、废弃API清理、console清零
- ChatPage/GraphPage/SettingsPage 拆分为独立子组件 - MainPage 接入 ImmersiveTabNavigation 玻璃拟态导航 - EntryAbility console.* 全替换为 defaultLogger - SplashPage replaceUrl 废弃 API 迁移到 UIContext Router - common/Index.ets 双通道导出 Logger/defaultLogger - 删除 dead code (entry/, commonbusiness/, trulymem-core/) - 全工程 0 console.*,BUILD SUCCESSFUL
This commit is contained in:
@ -68,6 +68,9 @@ interface ToolPropertiesDefinition {
|
||||
dryRun?: ToolParamProperty;
|
||||
keyword?: ToolParamProperty;
|
||||
attribute?: ToolParamProperty;
|
||||
sourceType?: ToolParamProperty;
|
||||
targetType?: ToolParamProperty;
|
||||
sourceHasStatus?: ToolParamProperty;
|
||||
}
|
||||
|
||||
interface ToolParamProperty {
|
||||
@ -218,19 +221,23 @@ function buildSystemPrompt(personaContext: string): string {
|
||||
## 核心身份
|
||||
${personaContext || '你是一个帮助用户记录和回忆信息的助手。你的核心能力是基于图数据库的记忆系统。'}
|
||||
|
||||
## 记忆系统
|
||||
你的记忆存储在图数据库中,每个记忆都是「实体 - 关系 - 实体」的三元组形式。
|
||||
每轮对话开始,你都会按以下顺序操作:
|
||||
## ⚠️ 内部执行顺序(不得向用户输出)
|
||||
|
||||
### 步骤1:查询人设
|
||||
使用 memory_recall 查询当前人设,确保回复风格一致。
|
||||
以下步骤是内部流程,绝对不要在你的回复中提及或输出。应当仅通过工具调用悄悄完成,回复时直接给出自然的对话内容。
|
||||
|
||||
### 步骤2:查询工作记忆链
|
||||
使用 memory_recall 查询任务链,了解会话上下文和进展中的任务。
|
||||
1. memory_recall → 查询人设图
|
||||
2. task_query → 查询工作记忆链/最近任务
|
||||
3. 处理对话内容 + 思考回复
|
||||
4. memory_commit → 写入本轮关键信息到图数据库
|
||||
5. task_archive → 归档已完成的旧任务
|
||||
6. 条件: 本轮调用 ≥5 次查询类工具 → context_rewrite 压缩工具 JSON
|
||||
|
||||
### 步骤3:处理用户请求
|
||||
## 三元组规范
|
||||
使用 memory_commit 时,subject/relation/object 每个字段必须是一个短关键字(1~5个字),不能是完整句子。
|
||||
|
||||
### 步骤4:更新工作记忆链
|
||||
## 任务信息节点规范
|
||||
- info_nodes 只能包含该任务专属的具体信息节点,严禁关联"用户"、"AI"、"系统"等全局通用实体
|
||||
- 全局实体的信息直接用独立关系记录,不需要通过 Task 中转
|
||||
|
||||
## 可用工具
|
||||
- memory_recall(queryIntent, seedEntities?, depth?, timeRange?, sessionFilter?): 检索记忆
|
||||
@ -252,9 +259,10 @@ ${personaContext || '你是一个帮助用户记录和回忆信息的助手。
|
||||
- task_query(limit?, stateFilter?): 查询任务列表
|
||||
|
||||
## 工具调用规则
|
||||
1. 每轮对话必须按顺序执行:步骤1查询人设 → 步骤2查询工作记忆链 → 步骤3处理请求
|
||||
2. context_rewrite 必须单独调用,不能和其他工具在同一轮一起调!
|
||||
3. 工具调用 ≥5 次后应使用 context_rewrite 压缩上下文
|
||||
1. ⚠️ 在完成所有工具调用之前,绝对不要输出任何文字。先默默调用工具,等所有结果返回后再输出一次完整的回复。
|
||||
2. 每轮对话必须按顺序执行:步骤1查询人设 → 步骤2查询工作记忆链 → 步骤3处理请求
|
||||
3. context_rewrite 必须单独调用,不能和其他工具在同一轮一起调!
|
||||
4. 工具调用 ≥5 次后应使用 context_rewrite 压缩上下文
|
||||
|
||||
## 写入规则
|
||||
用户明确表达以下信息时必须写入记忆:
|
||||
@ -278,10 +286,13 @@ const tripletPropsDict: ToolPropertiesDefinition = {
|
||||
confidence: makeNumberProp('置信度')
|
||||
};
|
||||
const purgeCriteriaDict: ToolPropertiesDefinition = {
|
||||
subjectContains: makeStringProp(''),
|
||||
relationType: makeStringProp(''),
|
||||
targetContains: makeStringProp(''),
|
||||
sessionId: makeStringProp('')
|
||||
subjectContains: makeStringProp('源实体名包含(模糊匹配)'),
|
||||
relationType: makeStringProp('关系类型'),
|
||||
targetContains: makeStringProp('目标实体名包含(模糊匹配)'),
|
||||
sessionId: makeStringProp('会话ID过滤'),
|
||||
sourceType: makeStringProp('源实体类型过滤(如 TaskNode)'),
|
||||
targetType: makeStringProp('目标实体类型过滤'),
|
||||
sourceHasStatus: makeStringProp('源实体状态过滤(如 archived)')
|
||||
};
|
||||
const newRelDict: ToolPropertiesDefinition = {
|
||||
relation: makeStringProp(''),
|
||||
@ -360,23 +371,23 @@ const personaRemoveProps: ToolPropertiesDefinition = {
|
||||
};
|
||||
|
||||
const TOOLS_DEFINITION: ToolFunctionDef[] = [
|
||||
makeToolDef('memory_recall', '检索记忆。支持关键词、种子实体、深度扩展。返回相关实体和关系。', recallProps, ['queryIntent']),
|
||||
makeToolDef('memory_commit', '写入记忆。将三元组写入图数据库。', commitProps, ['triplets']),
|
||||
makeToolDef('memory_purge', '删除或修正记忆。支持条件删除和纠错替代。', purgeProps, ['criteria', 'mode']),
|
||||
makeToolDef('memory_recall', '检索记忆。支持关键词、时间范围、会话过滤。返回相关实体和关系。\n\n【⚠️ 强制执行顺序 - 每轮必须严格遵守】\n1. 步骤1(必须首先执行): 查询人设图\n2. 步骤2(必须第二步执行): 查询工作记忆链\n【重要】跳过步骤1或步骤2将导致系统错误!', recallProps, ['queryIntent']),
|
||||
makeToolDef('memory_commit', '写入记忆。将三元组写入图数据库,支持批量写入。\n\n【重要】写入原则:\n- 用户明确表达的信息 → 必须写入\n- AI推理得到的信息 → 可以写入,但需标注[推测]\n- 避免写入冗余或无意义的信息', commitProps, ['triplets']),
|
||||
makeToolDef('memory_purge', '删除或修正记忆。支持条件删除和纠错替代。\n\n【使用场景】\n- 纠错替代修正错误信息\n- 删除特定类型的节点关系\n- 删除残留在已归档任务上的状态关系\n\n【重要】\n- 优先使用 supersede 模式修正错误\n- 软删除不会物理删除数据', 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('memory_query_archived', '查询已归档的记忆。\n\n【使用场景】\n- 想了解之前归档过哪些记忆\n- 按关键词搜索归档内容\n- 按时间范围查看最近归档的历史\n\n【注意】\n- 只返回 status=archived 的原始关系记录\n- days 和 keyword 可以单独使用或组合使用', queryArchivedProps),
|
||||
makeToolDef('context_rewrite', '压缩本轮对话的工具调用上下文。将冗长的JSON工具结果提炼为简洁摘要。\n\n【使用场景】\n- 本轮已执行 ≥5 次查询类工具调用\n- 【⚠️ 强制要求】context_rewrite 必须单独调用,不能和其他工具在同一轮一起调!', 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_create', '创建新的工作记忆任务节点。\n\n【重要】info_nodes 只能包含该任务专属的具体信息节点(如\"成语接龙_当前成语\"),**严禁关联\"用户\"、\"AI\"、\"系统\"等全局通用实体**——这些实体不应通过任务中转。', createProps, ['taskId', 'description']),
|
||||
makeToolDef('task_set_state', '设置任务状态。', setStateProps, ['taskId', 'state']),
|
||||
makeToolDef('task_delete', '删除任务节点。', deleteProps, ['taskId']),
|
||||
makeToolDef('task_link_info', '关联信息节点到任务。', linkInfoProps, ['taskId', 'infoNodeNames']),
|
||||
makeToolDef('task_archive', '归档任务。将任务设为已暂停,写入归档摘要。', archiveProps, ['taskId']),
|
||||
makeToolDef('task_query', '查询最近的任务列表。', queryProps)
|
||||
makeToolDef('task_link_info', '关联信息节点到任务。\n\n【重要】info_node_names只能放任务专属的具体信息节点(如\"成语接龙_当前成语\"),**严禁放\"用户\"、\"AI\"、\"系统\"等全局通用实体**——这些实体不应通过任务中转。', linkInfoProps, ['taskId', 'infoNodeNames']),
|
||||
makeToolDef('task_archive', '归档已完成/过期的任务。将任务状态设为 archived,同时写入完成摘要到图数据库。\n\n【使用场景】\n1. 话题转变时归档旧任务\n2. 已完成的任务及时归档\n3. 长时间无更新的任务归档\n\n【注意】优先使用 task_archive 替代 task_set_state(state=archived),因为它会自动写入完成摘要。', archiveProps, ['taskId']),
|
||||
makeToolDef('task_query', '查询最近的任务列表。按更新时间倒序排列。新对话开始时优先使用此工具获取所有进展中的任务,避免重复创建。', queryProps)
|
||||
];
|
||||
|
||||
// ========= 工具名称映射 =========
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
* 参考:main 分支 core/tools/memory_tools.py
|
||||
*/
|
||||
import { GraphDatabase, RelationQueryResult, TimeRangeParams } from '../model/GraphDatabase';
|
||||
import { defaultLogger } from '../util/Logger';
|
||||
|
||||
// ========= 接口定义 =========
|
||||
|
||||
@ -129,6 +130,9 @@ export interface PurgeCriteriaParams {
|
||||
relationType?: string;
|
||||
targetContains?: string;
|
||||
sessionId?: string;
|
||||
sourceType?: string;
|
||||
targetType?: string;
|
||||
sourceHasStatus?: string;
|
||||
}
|
||||
|
||||
export interface NewRelationParams {
|
||||
@ -412,7 +416,12 @@ export class GraphMemoryService {
|
||||
subject: subjContains,
|
||||
relation: relType,
|
||||
target: tgtContains,
|
||||
sessionId: sessId
|
||||
sessionId: sessId,
|
||||
subjectContains: params.criteria.subjectContains,
|
||||
targetContains: params.criteria.targetContains,
|
||||
sourceType: params.criteria.sourceType,
|
||||
targetType: params.criteria.targetType,
|
||||
sourceHasStatus: params.criteria.sourceHasStatus
|
||||
}, params.mode === 'hard' ? 'hard' : 'soft');
|
||||
const purgeResult: MemoryPurgeResult = {
|
||||
deletedCount: subjContains || tgtContains || relType || sessId ? 1 : 0,
|
||||
@ -619,7 +628,7 @@ export class GraphMemoryService {
|
||||
const result = await this.db.queryArchived(days, keyword);
|
||||
return result;
|
||||
} catch (e) {
|
||||
console.error('queryArchived error: ' + JSON.stringify(e));
|
||||
defaultLogger.error('queryArchived error: ' + JSON.stringify(e));
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@ -895,49 +904,9 @@ export class GraphMemoryService {
|
||||
async taskQuery(params?: TaskQueryParams): Promise<TaskQueryResult> {
|
||||
const limit: number = params?.limit ?? 10;
|
||||
const stateFilter: string | undefined = params?.stateFilter;
|
||||
|
||||
// 查询所有 TaskNode 类型的节点
|
||||
const allNodes = await this.db.search('');
|
||||
const taskNodes = allNodes.filter(n => n.type === 'TaskNode');
|
||||
|
||||
const tasks: TaskInfo[] = [];
|
||||
for (const node of taskNodes.slice(0, limit)) {
|
||||
// 查 description 和 has_state
|
||||
const result = await this.db.recall(node.name, [node.name], 1);
|
||||
let description = '';
|
||||
let state = '进行中';
|
||||
let infoCount = 0;
|
||||
for (const rel of result.relations) {
|
||||
if (rel.type === 'description' && rel.source === node.name) {
|
||||
description = rel.target;
|
||||
}
|
||||
if (rel.type === 'has_state' && rel.source === node.name) {
|
||||
state = rel.target;
|
||||
}
|
||||
if (rel.type === 'CONTAINS_INFO' && rel.source === node.name) {
|
||||
infoCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// 状态过滤
|
||||
if (stateFilter && state !== stateFilter) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const taskInfo: TaskInfo = {
|
||||
taskId: node.name,
|
||||
description,
|
||||
state,
|
||||
infoCount,
|
||||
updatedAt: ''
|
||||
};
|
||||
tasks.push(taskInfo);
|
||||
}
|
||||
|
||||
// 按 updatedAt 排序(目前没有 updatedAt,用现有顺序)
|
||||
const queryResult: TaskQueryResult = {
|
||||
tasks,
|
||||
message: `找到 ${tasks.length} 个任务`
|
||||
tasks: await this.db.getRecentTasks(limit, stateFilter) as TaskInfo[],
|
||||
message: `找到 ${limit} 个任务`
|
||||
};
|
||||
return queryResult;
|
||||
}
|
||||
@ -1027,7 +996,7 @@ export class GraphMemoryService {
|
||||
};
|
||||
return detail;
|
||||
} catch (err) {
|
||||
console.error('getNodeDetail error: ' + JSON.stringify(err));
|
||||
defaultLogger.error('getNodeDetail error: ' + JSON.stringify(err));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user