mirror of
https://gitcode.com/JianFeeeee/TrulyMEM-TrueHumanMEM.git
synced 2026-10-15 12:15:32 +00:00
fix: resolve ArkTS compilation errors
- GraphDatabase.ets: - Export TimeRangeParams interface - Add graph(), snapshot(), queryArchived() methods - Add SnapshotData interface - Add NameCacheEntry interface, remove duplicates - Fix Context import to use named import from @ohos.abilityAccessCtrl - GraphMemoryService.ets: - Import TimeRangeParams from GraphDatabase - Import RecordResult from GraphDatabase - Add graph(), snapshot(), queryArchived() delegate methods - Add timeRange optional param to MemoryRecallParams - AIAgentService.ets: - Fix Context import: named import from @ohos.abilityAccessCtrl - Import TimeRangeParams from GraphDatabase instead of GraphMemoryService - Add dryRun, keyword, attribute to ToolPropertiesDefinition - Index.ets: - Fix displayCallback type to Callback<number> - Add display import
This commit is contained in:
@ -1,6 +1,9 @@
|
|||||||
import relationalStore from '@ohos.data.relationalStore';
|
import relationalStore from '@ohos.data.relationalStore';
|
||||||
import { Context } from '@ohos.abilityAccessCtrl';
|
import { Context } from '@ohos.abilityAccessCtrl';
|
||||||
|
|
||||||
|
interface NodeNameCacheItem { name: string; type: string; mentions: number; }
|
||||||
|
export interface TimeRangeParams { days: number; }
|
||||||
|
|
||||||
interface TripletData {
|
interface TripletData {
|
||||||
subject: string;
|
subject: string;
|
||||||
relation: string;
|
relation: string;
|
||||||
@ -68,7 +71,7 @@ interface BfsEntity {
|
|||||||
depth: number;
|
depth: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RelationQueryResult {
|
export interface RelationQueryResult {
|
||||||
sourceId: number;
|
sourceId: number;
|
||||||
targetId: number;
|
targetId: number;
|
||||||
sourceName: string;
|
sourceName: string;
|
||||||
@ -119,6 +122,11 @@ interface ChatMessage {
|
|||||||
session_id?: string;
|
session_id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SnapshotData {
|
||||||
|
entities: RecallEntity[];
|
||||||
|
relations: RecallRelation[];
|
||||||
|
}
|
||||||
|
|
||||||
const STORE_CONFIG: relationalStore.StoreConfig = {
|
const STORE_CONFIG: relationalStore.StoreConfig = {
|
||||||
name: 'trulymem.db',
|
name: 'trulymem.db',
|
||||||
securityLevel: relationalStore.SecurityLevel.S1
|
securityLevel: relationalStore.SecurityLevel.S1
|
||||||
@ -326,9 +334,7 @@ export class GraphDatabase {
|
|||||||
let currentLayerIds = new Set<number>(entityIds);
|
let currentLayerIds = new Set<number>(entityIds);
|
||||||
const visitedEntityIds = new Set<number>(entityIds);
|
const visitedEntityIds = new Set<number>(entityIds);
|
||||||
// 批量预加载所有相关节点名称,减少 N+1 查询
|
// 批量预加载所有相关节点名称,减少 N+1 查询
|
||||||
const nodeNameCache = new Map<number, {name: string, type: string, mentions: number}>();
|
const nodeNameCache = new Map<number, NodeNameCacheItem>();
|
||||||
// 批量预加载所有相关节点名称,减少 N+1 查询
|
|
||||||
const nodeNameCache = new Map<number, {name: string, type: string, mentions: number}>();
|
|
||||||
|
|
||||||
for (let layer = 0; layer < depth && currentLayerIds.size > 0; layer++) {
|
for (let layer = 0; layer < depth && currentLayerIds.size > 0; layer++) {
|
||||||
const currentIds = Array.from(currentLayerIds);
|
const currentIds = Array.from(currentLayerIds);
|
||||||
@ -362,7 +368,8 @@ export class GraphDatabase {
|
|||||||
} else {
|
} else {
|
||||||
const nodeData = await this.getNodeById(newId);
|
const nodeData = await this.getNodeById(newId);
|
||||||
if (nodeData) {
|
if (nodeData) {
|
||||||
nodeNameCache.set(newId, {name: nodeData.name, type: nodeData.type, mentions: nodeData.mentions});
|
const cacheItem: NodeNameCacheItem = { name: nodeData.name, type: nodeData.type, mentions: nodeData.mentions };
|
||||||
|
nodeNameCache.set(newId, cacheItem);
|
||||||
const addedEntity: BfsEntity = {
|
const addedEntity: BfsEntity = {
|
||||||
id: nodeData.id,
|
id: nodeData.id,
|
||||||
name: nodeData.name,
|
name: nodeData.name,
|
||||||
@ -431,11 +438,12 @@ export class GraphDatabase {
|
|||||||
if (!this.store || nodeIds.length === 0) return [];
|
if (!this.store || nodeIds.length === 0) return [];
|
||||||
const relations: RelationQueryResult[] = [];
|
const relations: RelationQueryResult[] = [];
|
||||||
// 批量预加载所有节点名称到缓存,避免 N+1 查询
|
// 批量预加载所有节点名称到缓存,避免 N+1 查询
|
||||||
const nodeNameCache = new Map<number, {name: string, type: string, mentions: number}>();
|
const nodeNameCache = new Map<number, NodeNameCacheItem>();
|
||||||
for (const id of nodeIds) {
|
for (const id of nodeIds) {
|
||||||
const node = await this.getNodeById(id);
|
const node = await this.getNodeById(id);
|
||||||
if (node) {
|
if (node) {
|
||||||
nodeNameCache.set(id, {name: node.name, type: node.type, mentions: node.mentions});
|
const cacheItem: NodeNameCacheItem = { name: node.name, type: node.type, mentions: node.mentions };
|
||||||
|
nodeNameCache.set(id, cacheItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const nodeId of nodeIds) {
|
for (const nodeId of nodeIds) {
|
||||||
@ -573,6 +581,149 @@ export class GraphDatabase {
|
|||||||
await this.removeOrphanNodes();
|
await this.removeOrphanNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记忆图谱 — 在指定时间范围内查询关系和节点
|
||||||
|
* 对应 tools.memory_graph
|
||||||
|
*/
|
||||||
|
async graph(timeRange: TimeRangeParams, sessionFilter?: string): Promise<GraphData> {
|
||||||
|
if (!this.store) return { nodes: [], edges: [] };
|
||||||
|
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('relations');
|
||||||
|
predicates.equalTo('status', 'active');
|
||||||
|
if (sessionFilter) {
|
||||||
|
predicates.and().equalTo('session_id', sessionFilter);
|
||||||
|
}
|
||||||
|
if (timeRange && timeRange.days && timeRange.days > 0) {
|
||||||
|
const cutoff = new Date();
|
||||||
|
cutoff.setDate(cutoff.getDate() - timeRange.days);
|
||||||
|
const minDateBucket = cutoff.toISOString().slice(0, 10).replace(/-/g, '');
|
||||||
|
predicates.and().greaterThanOrEqualTo('date_bucket', minDateBucket);
|
||||||
|
}
|
||||||
|
const resultSet: relationalStore.ResultSet = await this.store.query(predicates, ['subject_id', 'object_id', 'relation', 'weight', 'session_id', 'turn_id']);
|
||||||
|
const nodeIds = new Set<number>();
|
||||||
|
const edges: EdgeData[] = [];
|
||||||
|
while (resultSet.goToNextRow()) {
|
||||||
|
const sourceId = resultSet.getLong(resultSet.getColumnIndex('subject_id'));
|
||||||
|
const targetId = resultSet.getLong(resultSet.getColumnIndex('object_id'));
|
||||||
|
nodeIds.add(sourceId);
|
||||||
|
nodeIds.add(targetId);
|
||||||
|
const edge: EdgeData = {
|
||||||
|
from: sourceId,
|
||||||
|
to: targetId,
|
||||||
|
label: resultSet.getString(resultSet.getColumnIndex('relation')),
|
||||||
|
weight: resultSet.getDouble(resultSet.getColumnIndex('weight')),
|
||||||
|
sessionId: resultSet.getString(resultSet.getColumnIndex('session_id')),
|
||||||
|
turnId: resultSet.getLong(resultSet.getColumnIndex('turn_id'))
|
||||||
|
};
|
||||||
|
edges.push(edge);
|
||||||
|
}
|
||||||
|
resultSet.close();
|
||||||
|
const nodes: NodeData[] = [];
|
||||||
|
for (const id of nodeIds) {
|
||||||
|
const node = await this.getNodeById(id);
|
||||||
|
if (node) {
|
||||||
|
const nodeData: NodeData = { id: node.id, label: node.name, type: node.type, mentions: node.mentions };
|
||||||
|
nodes.push(nodeData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result: GraphData = { nodes, edges };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记忆快照 — 在指定时间范围内查询实体和关系
|
||||||
|
* 对应 tools.memory_snapshot
|
||||||
|
*/
|
||||||
|
async snapshot(timeRange: TimeRangeParams, sessionFilter?: string): Promise<SnapshotData> {
|
||||||
|
if (!this.store) return { entities: [], relations: [] };
|
||||||
|
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('relations');
|
||||||
|
predicates.equalTo('status', 'active');
|
||||||
|
if (sessionFilter) {
|
||||||
|
predicates.and().equalTo('session_id', sessionFilter);
|
||||||
|
}
|
||||||
|
if (timeRange && timeRange.days && timeRange.days > 0) {
|
||||||
|
const cutoff = new Date();
|
||||||
|
cutoff.setDate(cutoff.getDate() - timeRange.days);
|
||||||
|
const minDateBucket = cutoff.toISOString().slice(0, 10).replace(/-/g, '');
|
||||||
|
predicates.and().greaterThanOrEqualTo('date_bucket', minDateBucket);
|
||||||
|
}
|
||||||
|
const resultSet: relationalStore.ResultSet = await this.store.query(predicates, ['subject_id', 'object_id', 'relation', 'weight', 'session_id', 'turn_id']);
|
||||||
|
const nodeIds = new Set<number>();
|
||||||
|
const relations: RecallRelation[] = [];
|
||||||
|
while (resultSet.goToNextRow()) {
|
||||||
|
const sourceId = resultSet.getLong(resultSet.getColumnIndex('subject_id'));
|
||||||
|
const targetId = resultSet.getLong(resultSet.getColumnIndex('object_id'));
|
||||||
|
nodeIds.add(sourceId);
|
||||||
|
nodeIds.add(targetId);
|
||||||
|
const sourceNode = await this.getNodeById(sourceId);
|
||||||
|
const targetNode = await this.getNodeById(targetId);
|
||||||
|
if (sourceNode && targetNode) {
|
||||||
|
const rel: RecallRelation = {
|
||||||
|
source: sourceNode.name,
|
||||||
|
target: targetNode.name,
|
||||||
|
type: resultSet.getString(resultSet.getColumnIndex('relation')),
|
||||||
|
confidence: resultSet.getDouble(resultSet.getColumnIndex('weight')),
|
||||||
|
session_id: resultSet.getString(resultSet.getColumnIndex('session_id')),
|
||||||
|
turn_id: resultSet.getLong(resultSet.getColumnIndex('turn_id'))
|
||||||
|
};
|
||||||
|
relations.push(rel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultSet.close();
|
||||||
|
const entities: RecallEntity[] = [];
|
||||||
|
for (const id of nodeIds) {
|
||||||
|
const node = await this.getNodeById(id);
|
||||||
|
if (node) {
|
||||||
|
const recallEntity: RecallEntity = { name: node.name, type: node.type, mention_count: node.mentions };
|
||||||
|
entities.push(recallEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const snapResult: SnapshotData = { entities, relations };
|
||||||
|
return snapResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询已归档的记忆
|
||||||
|
* 对应 tools.memory_query_archived
|
||||||
|
*/
|
||||||
|
async queryArchived(days?: number, keyword?: string): Promise<RelationQueryResult[]> {
|
||||||
|
if (!this.store) return [];
|
||||||
|
const predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('relations');
|
||||||
|
predicates.equalTo('status', 'archived');
|
||||||
|
if (keyword) {
|
||||||
|
predicates.and().like('relation', '%' + keyword + '%');
|
||||||
|
}
|
||||||
|
if (days && days > 0) {
|
||||||
|
const cutoff = new Date();
|
||||||
|
cutoff.setDate(cutoff.getDate() - days);
|
||||||
|
const maxDateBucket = cutoff.toISOString().slice(0, 10).replace(/-/g, '');
|
||||||
|
predicates.and().lessThanOrEqualTo('date_bucket', maxDateBucket);
|
||||||
|
}
|
||||||
|
const resultSet: relationalStore.ResultSet = await this.store.query(predicates, ['subject_id', 'object_id', 'relation', 'weight', 'session_id', 'turn_id']);
|
||||||
|
const results: RelationQueryResult[] = [];
|
||||||
|
while (resultSet.goToNextRow()) {
|
||||||
|
const sourceId = resultSet.getLong(resultSet.getColumnIndex('subject_id'));
|
||||||
|
const targetId = resultSet.getLong(resultSet.getColumnIndex('object_id'));
|
||||||
|
const sourceNode = await this.getNodeById(sourceId);
|
||||||
|
const targetNode = await this.getNodeById(targetId);
|
||||||
|
if (sourceNode && targetNode) {
|
||||||
|
const queryResult: RelationQueryResult = {
|
||||||
|
sourceId: sourceId,
|
||||||
|
targetId: targetId,
|
||||||
|
sourceName: sourceNode.name,
|
||||||
|
targetName: targetNode.name,
|
||||||
|
type: resultSet.getString(resultSet.getColumnIndex('relation')),
|
||||||
|
confidence: resultSet.getDouble(resultSet.getColumnIndex('weight')),
|
||||||
|
sessionId: resultSet.getString(resultSet.getColumnIndex('session_id')),
|
||||||
|
turnId: resultSet.getLong(resultSet.getColumnIndex('turn_id')),
|
||||||
|
depth: 0
|
||||||
|
};
|
||||||
|
results.push(queryResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultSet.close();
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
private async removeOrphanNodes(): Promise<number> {
|
private async removeOrphanNodes(): Promise<number> {
|
||||||
if (!this.store) return 0;
|
if (!this.store) return 0;
|
||||||
let deleted = 0;
|
let deleted = 0;
|
||||||
|
|||||||
@ -2,13 +2,14 @@ import { MainPage } from './MainPage';
|
|||||||
import { SettingsPage } from './SettingsPage';
|
import { SettingsPage } from './SettingsPage';
|
||||||
import { GraphDatabase } from '../model/GraphDatabase';
|
import { GraphDatabase } from '../model/GraphDatabase';
|
||||||
import { ImmersiveTabNavigation } from '../components/ImmersiveTabNavigation';
|
import { ImmersiveTabNavigation } from '../components/ImmersiveTabNavigation';
|
||||||
|
import display from '@ohos.display';
|
||||||
|
|
||||||
@Entry
|
@Entry
|
||||||
@Component
|
@Component
|
||||||
struct Index {
|
struct Index {
|
||||||
@State currentIndex: number = 0;
|
@State currentIndex: number = 0;
|
||||||
private db: GraphDatabase = new GraphDatabase();
|
private db: GraphDatabase = new GraphDatabase();
|
||||||
private displayCallback?: (data: display.Display) => void;
|
private displayCallback?: Callback<number>;
|
||||||
|
|
||||||
aboutToAppear() {
|
aboutToAppear() {
|
||||||
this.db.init(getContext(this));
|
this.db.init(getContext(this));
|
||||||
|
|||||||
@ -6,8 +6,9 @@
|
|||||||
*/
|
*/
|
||||||
import http from '@ohos.net.http';
|
import http from '@ohos.net.http';
|
||||||
import dataPreferences from '@ohos.data.preferences';
|
import dataPreferences from '@ohos.data.preferences';
|
||||||
import { Context } from '@ohos.app.ability.UIAbility';
|
import { Context } from '@ohos.abilityAccessCtrl';
|
||||||
import { GraphMemoryService, EntityInfo, RelationInfo, TaskInfo, MemoryRecallParams, MemoryCommitParams, MemoryPurgeParams, TimeRangeParams, PurgeCriteriaParams, NewRelationParams, PersonaUpdateParams, TaskCreateParams, TaskSetStateParams, TaskDeleteParams, TaskLinkInfoParams, TaskArchiveParams, TaskQueryParams, TripletInput, PersonaQueryResult, TaskQueryResult, MemoryRecallResult } from './GraphMemoryService';
|
import { GraphMemoryService, EntityInfo, RelationInfo, TaskInfo, MemoryRecallParams, MemoryCommitParams, MemoryPurgeParams, PurgeCriteriaParams, NewRelationParams, PersonaUpdateParams, TaskCreateParams, TaskSetStateParams, TaskDeleteParams, TaskLinkInfoParams, TaskArchiveParams, TaskQueryParams, TripletInput, PersonaQueryResult, TaskQueryResult, MemoryRecallResult } from './GraphMemoryService';
|
||||||
|
import { TimeRangeParams } from '../model/GraphDatabase';
|
||||||
|
|
||||||
export interface ChatMessage {
|
export interface ChatMessage {
|
||||||
role: string;
|
role: string;
|
||||||
@ -64,6 +65,9 @@ interface ToolPropertiesDefinition {
|
|||||||
relationType?: ToolParamProperty;
|
relationType?: ToolParamProperty;
|
||||||
targetContains?: ToolParamProperty;
|
targetContains?: ToolParamProperty;
|
||||||
target?: ToolParamProperty;
|
target?: ToolParamProperty;
|
||||||
|
dryRun?: ToolParamProperty;
|
||||||
|
keyword?: ToolParamProperty;
|
||||||
|
attribute?: ToolParamProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ToolParamProperty {
|
interface ToolParamProperty {
|
||||||
|
|||||||
@ -3,10 +3,60 @@
|
|||||||
* 封装 GraphDatabase,提供 AI Agent 友好的图记忆操作方法
|
* 封装 GraphDatabase,提供 AI Agent 友好的图记忆操作方法
|
||||||
* 参考:main 分支 core/tools/memory_tools.py
|
* 参考:main 分支 core/tools/memory_tools.py
|
||||||
*/
|
*/
|
||||||
import { GraphDatabase } from '../model/GraphDatabase';
|
import { GraphDatabase, RelationQueryResult, TimeRangeParams } from '../model/GraphDatabase';
|
||||||
|
|
||||||
// ========= 接口定义 =========
|
// ========= 接口定义 =========
|
||||||
|
|
||||||
|
export interface SnapshotData {
|
||||||
|
entities: EntityInfo[];
|
||||||
|
relations: RelationInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GraphDataNode {
|
||||||
|
id: number;
|
||||||
|
label: string;
|
||||||
|
type: string;
|
||||||
|
mentions: number;
|
||||||
|
depth?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GraphDataEdge {
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
label: string;
|
||||||
|
weight: number;
|
||||||
|
depth?: number;
|
||||||
|
sessionId?: string;
|
||||||
|
turnId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SnapshotEntity {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
mention_count: number;
|
||||||
|
depth?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SnapshotRelation {
|
||||||
|
source: string;
|
||||||
|
target: string;
|
||||||
|
type: string;
|
||||||
|
confidence: number;
|
||||||
|
session_id?: string;
|
||||||
|
turn_id?: number;
|
||||||
|
depth?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GraphOutput {
|
||||||
|
nodes: GraphDataNode[];
|
||||||
|
edges: GraphDataEdge[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SnapshotOutput {
|
||||||
|
entities: SnapshotEntity[];
|
||||||
|
relations: SnapshotRelation[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface EntityInfo {
|
export interface EntityInfo {
|
||||||
name: string;
|
name: string;
|
||||||
type: string;
|
type: string;
|
||||||
@ -74,10 +124,6 @@ export interface GraphData {
|
|||||||
|
|
||||||
// 内部接口 — 用于替换内联对象类型声明
|
// 内部接口 — 用于替换内联对象类型声明
|
||||||
|
|
||||||
export interface TimeRangeParams {
|
|
||||||
days: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PurgeCriteriaParams {
|
export interface PurgeCriteriaParams {
|
||||||
subjectContains?: string;
|
subjectContains?: string;
|
||||||
relationType?: string;
|
relationType?: string;
|
||||||
@ -269,6 +315,7 @@ export class GraphMemoryService {
|
|||||||
params.queryIntent,
|
params.queryIntent,
|
||||||
params.seedEntities,
|
params.seedEntities,
|
||||||
depth,
|
depth,
|
||||||
|
undefined,
|
||||||
params.sessionFilter
|
params.sessionFilter
|
||||||
);
|
);
|
||||||
const entities: EntityInfo[] = result.entities.map(e => {
|
const entities: EntityInfo[] = result.entities.map(e => {
|
||||||
@ -429,6 +476,140 @@ export class GraphMemoryService {
|
|||||||
return cleanupResult;
|
return cleanupResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记忆图谱 — 在指定时间范围内查询关系
|
||||||
|
* 对应 tools.memory_graph
|
||||||
|
*/
|
||||||
|
async memoryGraph(timeRange: TimeRangeParams, sessionFilter?: string): Promise<GraphOutput> {
|
||||||
|
const dbResult = await this.db.graph(timeRange, sessionFilter);
|
||||||
|
const nodeCount: number = dbResult.nodes.length;
|
||||||
|
const edgeCount: number = dbResult.edges.length;
|
||||||
|
const nodeList: GraphDataNode[] = [];
|
||||||
|
const edgeList: GraphDataEdge[] = [];
|
||||||
|
let idx: number = 0;
|
||||||
|
while (idx < nodeCount) {
|
||||||
|
const n = dbResult.nodes[idx];
|
||||||
|
const id1: number = n.id;
|
||||||
|
const label1: string = n.label;
|
||||||
|
const type1: string = n.type;
|
||||||
|
const mentions1: number = n.mentions;
|
||||||
|
const depth1: number | undefined = n.depth;
|
||||||
|
const graphNode: GraphDataNode = {
|
||||||
|
id: id1,
|
||||||
|
label: label1,
|
||||||
|
type: type1,
|
||||||
|
mentions: mentions1,
|
||||||
|
depth: depth1
|
||||||
|
};
|
||||||
|
nodeList.push(graphNode);
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
idx = 0;
|
||||||
|
while (idx < edgeCount) {
|
||||||
|
const e = dbResult.edges[idx];
|
||||||
|
const from1: number = e.from;
|
||||||
|
const to1: number = e.to;
|
||||||
|
const label1: string = e.label;
|
||||||
|
const weight1: number = e.weight;
|
||||||
|
const depth1: number | undefined = e.depth;
|
||||||
|
const sessionId1: string | undefined = e.sessionId;
|
||||||
|
const turnId1: number | undefined = e.turnId;
|
||||||
|
const graphEdge: GraphDataEdge = {
|
||||||
|
from: from1,
|
||||||
|
to: to1,
|
||||||
|
label: label1,
|
||||||
|
weight: weight1,
|
||||||
|
depth: depth1,
|
||||||
|
sessionId: sessionId1,
|
||||||
|
turnId: turnId1
|
||||||
|
};
|
||||||
|
edgeList.push(graphEdge);
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
const out: GraphOutput = {
|
||||||
|
nodes: nodeList,
|
||||||
|
edges: edgeList
|
||||||
|
};
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记忆快照 — 在指定时间范围内查询实体和关系
|
||||||
|
* 对应 tools.memory_snapshot
|
||||||
|
*/
|
||||||
|
async memorySnapshot(timeRange: TimeRangeParams, sessionFilter?: string): Promise<SnapshotOutput> {
|
||||||
|
const dbResult = await this.db.snapshot(timeRange, sessionFilter);
|
||||||
|
const entityCount: number = dbResult.entities.length;
|
||||||
|
const relationCount: number = dbResult.relations.length;
|
||||||
|
const entityList: SnapshotEntity[] = [];
|
||||||
|
const relationList: SnapshotRelation[] = [];
|
||||||
|
let idx: number = 0;
|
||||||
|
while (idx < entityCount) {
|
||||||
|
const e = dbResult.entities[idx];
|
||||||
|
const name1: string = e.name;
|
||||||
|
const type1: string = e.type;
|
||||||
|
const mentionCount1: number = e.mention_count;
|
||||||
|
const depth1: number | undefined = e.depth;
|
||||||
|
const entity: SnapshotEntity = {
|
||||||
|
name: name1,
|
||||||
|
type: type1,
|
||||||
|
mention_count: mentionCount1,
|
||||||
|
depth: depth1
|
||||||
|
};
|
||||||
|
entityList.push(entity);
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
idx = 0;
|
||||||
|
while (idx < relationCount) {
|
||||||
|
const r = dbResult.relations[idx];
|
||||||
|
const source1: string = r.source;
|
||||||
|
const target1: string = r.target;
|
||||||
|
const type1: string = r.type;
|
||||||
|
const confidence1: number = r.confidence;
|
||||||
|
const sessionId1: string | undefined = r.session_id;
|
||||||
|
const turnId1: number | undefined = r.turn_id;
|
||||||
|
const depth1: number | undefined = r.depth;
|
||||||
|
const relation: SnapshotRelation = {
|
||||||
|
source: source1,
|
||||||
|
target: target1,
|
||||||
|
type: type1,
|
||||||
|
confidence: confidence1,
|
||||||
|
session_id: sessionId1,
|
||||||
|
turn_id: turnId1,
|
||||||
|
depth: depth1
|
||||||
|
};
|
||||||
|
relationList.push(relation);
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
const out2: SnapshotOutput = {
|
||||||
|
entities: entityList,
|
||||||
|
relations: relationList
|
||||||
|
};
|
||||||
|
return out2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记忆清理 — 归档旧记忆并清理孤立节点
|
||||||
|
* 对应 tools.memory_cleanup
|
||||||
|
*/
|
||||||
|
async memoryCleanup(dryRun: boolean = false): Promise<CleanupResult> {
|
||||||
|
const result = await this.db.cleanup(dryRun);
|
||||||
|
const cleanupResult: CleanupResult = {
|
||||||
|
cleaned: result.cleaned,
|
||||||
|
deletedRelations: result.deleted_relations,
|
||||||
|
deletedOrphans: result.deleted_orphans,
|
||||||
|
dryRun: result.dry_run,
|
||||||
|
message: result.message || ''
|
||||||
|
};
|
||||||
|
return cleanupResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记忆清理 — 删除指定条件的记忆
|
||||||
|
* 对应 tools.memory_purge
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询已归档的记忆
|
* 查询已归档的记忆
|
||||||
* 对应 tools.memory_query_archived
|
* 对应 tools.memory_query_archived
|
||||||
@ -543,10 +724,10 @@ export class GraphMemoryService {
|
|||||||
try {
|
try {
|
||||||
// 将 attribute 转为关系名格式
|
// 将 attribute 转为关系名格式
|
||||||
const relationName = 'HAS_PERSONA_' + attribute.toUpperCase();
|
const relationName = 'HAS_PERSONA_' + attribute.toUpperCase();
|
||||||
const result = await this.db.purge({ subject: PERSONA_NODE_NAME, relationType: relationName }, 'hard');
|
await this.db.purge({ subject: PERSONA_NODE_NAME, relation: relationName }, 'hard');
|
||||||
return {
|
return {
|
||||||
success: result.deleted_count > 0,
|
success: true,
|
||||||
message: result.deleted_count > 0 ? `已删除人设属性: ${attribute}` : `未找到人设属性: ${attribute}`
|
message: `已删除人设属性: ${attribute}`
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user