@cmdoss/memwal-sdk 0.6.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +547 -547
- package/BENCHMARKS.md +238 -238
- package/README.md +310 -181
- package/dist/ai-sdk/tools.d.ts +2 -2
- package/dist/ai-sdk/tools.js +2 -2
- package/dist/client/ClientMemoryManager.js +2 -2
- package/dist/client/ClientMemoryManager.js.map +1 -1
- package/dist/client/PersonalDataWallet.d.ts.map +1 -1
- package/dist/client/SimplePDWClient.d.ts +29 -1
- package/dist/client/SimplePDWClient.d.ts.map +1 -1
- package/dist/client/SimplePDWClient.js +45 -13
- package/dist/client/SimplePDWClient.js.map +1 -1
- package/dist/client/namespaces/EmbeddingsNamespace.d.ts +1 -1
- package/dist/client/namespaces/EmbeddingsNamespace.js +1 -1
- package/dist/client/namespaces/MemoryNamespace.d.ts +31 -0
- package/dist/client/namespaces/MemoryNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/MemoryNamespace.js +272 -39
- package/dist/client/namespaces/MemoryNamespace.js.map +1 -1
- package/dist/client/namespaces/consolidated/AINamespace.d.ts +2 -2
- package/dist/client/namespaces/consolidated/AINamespace.js +2 -2
- package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts +12 -2
- package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/consolidated/BlockchainNamespace.js +62 -4
- package/dist/client/namespaces/consolidated/BlockchainNamespace.js.map +1 -1
- package/dist/client/namespaces/consolidated/StorageNamespace.d.ts +67 -2
- package/dist/client/namespaces/consolidated/StorageNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/consolidated/StorageNamespace.js +549 -16
- package/dist/client/namespaces/consolidated/StorageNamespace.js.map +1 -1
- package/dist/config/ConfigurationHelper.js +61 -61
- package/dist/config/defaults.js +2 -2
- package/dist/config/defaults.js.map +1 -1
- package/dist/graph/GraphService.js +21 -21
- package/dist/graph/GraphService.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/seal/EncryptionService.d.ts +9 -5
- package/dist/infrastructure/seal/EncryptionService.d.ts.map +1 -1
- package/dist/infrastructure/seal/EncryptionService.js +37 -15
- package/dist/infrastructure/seal/EncryptionService.js.map +1 -1
- package/dist/infrastructure/seal/SealService.d.ts +13 -5
- package/dist/infrastructure/seal/SealService.d.ts.map +1 -1
- package/dist/infrastructure/seal/SealService.js +36 -34
- package/dist/infrastructure/seal/SealService.js.map +1 -1
- package/dist/langchain/createPDWRAG.js +30 -30
- package/dist/retrieval/MemoryDecryptionPipeline.d.ts.map +1 -1
- package/dist/retrieval/MemoryDecryptionPipeline.js +2 -1
- package/dist/retrieval/MemoryDecryptionPipeline.js.map +1 -1
- package/dist/retrieval/MemoryRetrievalService.d.ts +31 -0
- package/dist/retrieval/MemoryRetrievalService.d.ts.map +1 -1
- package/dist/retrieval/MemoryRetrievalService.js +44 -4
- package/dist/retrieval/MemoryRetrievalService.js.map +1 -1
- package/dist/services/CapabilityService.d.ts.map +1 -1
- package/dist/services/CapabilityService.js +30 -14
- package/dist/services/CapabilityService.js.map +1 -1
- package/dist/services/CrossContextPermissionService.d.ts.map +1 -1
- package/dist/services/CrossContextPermissionService.js +9 -7
- package/dist/services/CrossContextPermissionService.js.map +1 -1
- package/dist/services/EmbeddingService.d.ts +28 -1
- package/dist/services/EmbeddingService.d.ts.map +1 -1
- package/dist/services/EmbeddingService.js +54 -0
- package/dist/services/EmbeddingService.js.map +1 -1
- package/dist/services/EncryptionService.d.ts.map +1 -1
- package/dist/services/EncryptionService.js +6 -5
- package/dist/services/EncryptionService.js.map +1 -1
- package/dist/services/GeminiAIService.js +309 -309
- package/dist/services/IndexManager.d.ts +5 -1
- package/dist/services/IndexManager.d.ts.map +1 -1
- package/dist/services/IndexManager.js +17 -40
- package/dist/services/IndexManager.js.map +1 -1
- package/dist/services/QueryService.js +1 -1
- package/dist/services/QueryService.js.map +1 -1
- package/dist/services/StorageService.d.ts +11 -0
- package/dist/services/StorageService.d.ts.map +1 -1
- package/dist/services/StorageService.js +73 -10
- package/dist/services/StorageService.js.map +1 -1
- package/dist/services/TransactionService.d.ts +20 -0
- package/dist/services/TransactionService.d.ts.map +1 -1
- package/dist/services/TransactionService.js +43 -0
- package/dist/services/TransactionService.js.map +1 -1
- package/dist/services/ViewService.js +2 -2
- package/dist/services/ViewService.js.map +1 -1
- package/dist/services/storage/QuiltBatchManager.d.ts +101 -1
- package/dist/services/storage/QuiltBatchManager.d.ts.map +1 -1
- package/dist/services/storage/QuiltBatchManager.js +410 -20
- package/dist/services/storage/QuiltBatchManager.js.map +1 -1
- package/dist/services/storage/index.d.ts +1 -1
- package/dist/services/storage/index.d.ts.map +1 -1
- package/dist/services/storage/index.js.map +1 -1
- package/dist/utils/LRUCache.d.ts +106 -0
- package/dist/utils/LRUCache.d.ts.map +1 -0
- package/dist/utils/LRUCache.js +281 -0
- package/dist/utils/LRUCache.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/memoryIndexOnChain.d.ts +212 -0
- package/dist/utils/memoryIndexOnChain.d.ts.map +1 -0
- package/dist/utils/memoryIndexOnChain.js +312 -0
- package/dist/utils/memoryIndexOnChain.js.map +1 -0
- package/dist/utils/rebuildIndexNode.d.ts +29 -0
- package/dist/utils/rebuildIndexNode.d.ts.map +1 -1
- package/dist/utils/rebuildIndexNode.js +366 -98
- package/dist/utils/rebuildIndexNode.js.map +1 -1
- package/dist/vector/HnswWasmService.d.ts +20 -5
- package/dist/vector/HnswWasmService.d.ts.map +1 -1
- package/dist/vector/HnswWasmService.js +73 -40
- package/dist/vector/HnswWasmService.js.map +1 -1
- package/dist/vector/IHnswService.d.ts +10 -1
- package/dist/vector/IHnswService.d.ts.map +1 -1
- package/dist/vector/IHnswService.js.map +1 -1
- package/dist/vector/NodeHnswService.d.ts +16 -0
- package/dist/vector/NodeHnswService.d.ts.map +1 -1
- package/dist/vector/NodeHnswService.js +84 -5
- package/dist/vector/NodeHnswService.js.map +1 -1
- package/dist/vector/createHnswService.d.ts +1 -1
- package/dist/vector/createHnswService.js +1 -1
- package/dist/vector/index.d.ts +1 -1
- package/dist/vector/index.js +1 -1
- package/package.json +157 -157
- package/src/access/PermissionService.ts +635 -635
- package/src/aggregation/AggregationService.ts +389 -389
- package/src/ai-sdk/PDWVectorStore.ts +715 -715
- package/src/ai-sdk/index.ts +65 -65
- package/src/ai-sdk/tools.ts +460 -460
- package/src/ai-sdk/types.ts +404 -404
- package/src/batch/BatchManager.ts +597 -597
- package/src/batch/BatchingService.ts +429 -429
- package/src/batch/MemoryProcessingCache.ts +492 -492
- package/src/batch/index.ts +30 -30
- package/src/browser.ts +200 -200
- package/src/client/ClientMemoryManager.ts +987 -987
- package/src/client/PersonalDataWallet.ts +345 -345
- package/src/client/SimplePDWClient.ts +1289 -1222
- package/src/client/factory.ts +154 -154
- package/src/client/namespaces/AnalyticsNamespace.ts +377 -377
- package/src/client/namespaces/BatchNamespace.ts +356 -356
- package/src/client/namespaces/CacheNamespace.ts +123 -123
- package/src/client/namespaces/CapabilityNamespace.ts +217 -217
- package/src/client/namespaces/ClassifyNamespace.ts +169 -169
- package/src/client/namespaces/ContextNamespace.ts +297 -297
- package/src/client/namespaces/EmbeddingsNamespace.ts +99 -99
- package/src/client/namespaces/EncryptionNamespace.ts +221 -221
- package/src/client/namespaces/GraphNamespace.ts +468 -468
- package/src/client/namespaces/IndexNamespace.ts +361 -361
- package/src/client/namespaces/MemoryNamespace.ts +1422 -1135
- package/src/client/namespaces/PermissionsNamespace.ts +254 -254
- package/src/client/namespaces/PipelineNamespace.ts +220 -220
- package/src/client/namespaces/SearchNamespace.ts +1049 -1049
- package/src/client/namespaces/StorageNamespace.ts +458 -458
- package/src/client/namespaces/TxNamespace.ts +260 -260
- package/src/client/namespaces/WalletNamespace.ts +243 -243
- package/src/client/namespaces/consolidated/AINamespace.ts +449 -449
- package/src/client/namespaces/consolidated/BlockchainNamespace.ts +607 -546
- package/src/client/namespaces/consolidated/SecurityNamespace.ts +648 -648
- package/src/client/namespaces/consolidated/StorageNamespace.ts +1141 -497
- package/src/client/namespaces/consolidated/index.ts +39 -39
- package/src/client/signers/KeypairSigner.ts +108 -108
- package/src/client/signers/UnifiedSigner.ts +110 -110
- package/src/client/signers/WalletAdapterSigner.ts +159 -159
- package/src/client/signers/index.ts +26 -26
- package/src/config/ConfigurationHelper.ts +412 -412
- package/src/config/defaults.ts +51 -51
- package/src/config/index.ts +8 -8
- package/src/config/validation.ts +70 -70
- package/src/core/index.ts +14 -14
- package/src/core/interfaces/IService.ts +307 -307
- package/src/core/interfaces/index.ts +8 -8
- package/src/core/types/capability.ts +297 -297
- package/src/core/types/index.ts +870 -870
- package/src/core/types/wallet.ts +270 -270
- package/src/core/types.ts +9 -9
- package/src/core/wallet.ts +222 -222
- package/src/embedding/index.ts +19 -19
- package/src/embedding/types.ts +357 -357
- package/src/errors/index.ts +602 -602
- package/src/errors/recovery.ts +461 -461
- package/src/errors/validation.ts +567 -567
- package/src/generated/pdw/capability.ts +319 -319
- package/src/graph/GraphService.ts +887 -887
- package/src/graph/KnowledgeGraphManager.ts +728 -728
- package/src/graph/index.ts +25 -25
- package/src/index.ts +498 -474
- package/src/infrastructure/index.ts +22 -22
- package/src/infrastructure/seal/EncryptionService.ts +628 -603
- package/src/infrastructure/seal/SealService.ts +613 -615
- package/src/infrastructure/seal/index.ts +9 -9
- package/src/infrastructure/sui/BlockchainManager.ts +627 -627
- package/src/infrastructure/sui/SuiService.ts +888 -888
- package/src/infrastructure/sui/index.ts +9 -9
- package/src/infrastructure/walrus/StorageManager.ts +604 -604
- package/src/infrastructure/walrus/WalrusStorageService.ts +612 -612
- package/src/infrastructure/walrus/index.ts +9 -9
- package/src/langchain/PDWEmbeddings.ts +145 -145
- package/src/langchain/PDWVectorStore.ts +456 -456
- package/src/langchain/createPDWRAG.ts +303 -303
- package/src/langchain/index.ts +47 -47
- package/src/permissions/ConsentRepository.browser.ts +249 -249
- package/src/permissions/ConsentRepository.ts +364 -364
- package/src/pipeline/MemoryPipeline.ts +862 -862
- package/src/pipeline/PipelineManager.ts +683 -683
- package/src/pipeline/index.ts +26 -26
- package/src/retrieval/AdvancedSearchService.ts +629 -629
- package/src/retrieval/MemoryAnalyticsService.ts +711 -711
- package/src/retrieval/MemoryDecryptionPipeline.ts +825 -824
- package/src/retrieval/MemoryRetrievalService.ts +904 -830
- package/src/retrieval/index.ts +42 -42
- package/src/services/BatchService.ts +352 -352
- package/src/services/CapabilityService.ts +464 -448
- package/src/services/ClassifierService.ts +465 -465
- package/src/services/CrossContextPermissionService.ts +486 -484
- package/src/services/EmbeddingService.ts +771 -706
- package/src/services/EncryptionService.ts +712 -711
- package/src/services/GeminiAIService.ts +753 -753
- package/src/services/IndexManager.ts +977 -1004
- package/src/services/MemoryIndexService.ts +1003 -1003
- package/src/services/MemoryService.ts +369 -369
- package/src/services/QueryService.ts +890 -890
- package/src/services/StorageService.ts +1182 -1111
- package/src/services/TransactionService.ts +838 -790
- package/src/services/VectorService.ts +462 -462
- package/src/services/ViewService.ts +484 -484
- package/src/services/index.ts +25 -25
- package/src/services/storage/BlobAttributesManager.ts +333 -333
- package/src/services/storage/KnowledgeGraphManager.ts +425 -425
- package/src/services/storage/MemorySearchManager.ts +387 -387
- package/src/services/storage/QuiltBatchManager.ts +1130 -660
- package/src/services/storage/WalrusMetadataManager.ts +268 -268
- package/src/services/storage/WalrusStorageManager.ts +287 -287
- package/src/services/storage/index.ts +57 -52
- package/src/types/index.ts +13 -13
- package/src/utils/LRUCache.ts +378 -0
- package/src/utils/index.ts +76 -68
- package/src/utils/memoryIndexOnChain.ts +507 -0
- package/src/utils/rebuildIndex.ts +290 -290
- package/src/utils/rebuildIndexNode.ts +771 -424
- package/src/vector/BrowserHnswIndexService.ts +758 -758
- package/src/vector/HnswWasmService.ts +731 -679
- package/src/vector/IHnswService.ts +233 -224
- package/src/vector/NodeHnswService.ts +833 -735
- package/src/vector/VectorManager.ts +478 -478
- package/src/vector/createHnswService.ts +135 -135
- package/src/vector/index.ts +56 -56
- package/src/wallet/ContextWalletService.ts +656 -656
- package/src/wallet/MainWalletService.ts +317 -317
|
@@ -1,425 +1,425 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* KnowledgeGraphManager - Knowledge Graph Operations
|
|
3
|
-
*
|
|
4
|
-
* Handles entity extraction, relationship mapping, and graph querying.
|
|
5
|
-
* Extracted from StorageService for better separation of concerns.
|
|
6
|
-
*
|
|
7
|
-
* Features:
|
|
8
|
-
* - AI-powered entity/relationship extraction
|
|
9
|
-
* - In-memory graph storage with Walrus persistence
|
|
10
|
-
* - Graph traversal and querying
|
|
11
|
-
* - Batch extraction from multiple memories
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import type { GraphService, KnowledgeGraph, Entity, Relationship, GraphExtractionResult } from '../../graph/GraphService';
|
|
15
|
-
import type { EmbeddingService } from '../EmbeddingService';
|
|
16
|
-
|
|
17
|
-
export interface GraphCache {
|
|
18
|
-
graph: KnowledgeGraph;
|
|
19
|
-
lastSaved: Date;
|
|
20
|
-
isDirty: boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface GraphQueryOptions {
|
|
24
|
-
keywords?: string[];
|
|
25
|
-
entityTypes?: string[];
|
|
26
|
-
relationshipTypes?: string[];
|
|
27
|
-
searchText?: string;
|
|
28
|
-
maxHops?: number;
|
|
29
|
-
limit?: number;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface GraphInitConfig {
|
|
33
|
-
confidenceThreshold?: number;
|
|
34
|
-
maxHops?: number;
|
|
35
|
-
deduplicationThreshold?: number;
|
|
36
|
-
geminiApiKey?: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* KnowledgeGraphManager - Manages knowledge graph operations
|
|
41
|
-
*
|
|
42
|
-
* Coordinates:
|
|
43
|
-
* - GraphService for entity/relationship extraction
|
|
44
|
-
* - In-memory graph storage and caching
|
|
45
|
-
* - Walrus persistence for cross-device sync
|
|
46
|
-
*/
|
|
47
|
-
export class KnowledgeGraphManager {
|
|
48
|
-
private graphService?: GraphService;
|
|
49
|
-
private knowledgeGraphs = new Map<string, KnowledgeGraph>();
|
|
50
|
-
private graphCache = new Map<string, GraphCache>();
|
|
51
|
-
|
|
52
|
-
constructor() {
|
|
53
|
-
// GraphService will be initialized via initializeKnowledgeGraph()
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Initialize knowledge graph capabilities
|
|
58
|
-
*/
|
|
59
|
-
async initializeKnowledgeGraph(
|
|
60
|
-
embeddingService?: EmbeddingService,
|
|
61
|
-
graphConfig?: GraphInitConfig
|
|
62
|
-
) {
|
|
63
|
-
try {
|
|
64
|
-
if (!this.graphService) {
|
|
65
|
-
const { GraphService } = await import('../../graph/GraphService');
|
|
66
|
-
|
|
67
|
-
this.graphService = new GraphService({
|
|
68
|
-
enableEmbeddings: !!embeddingService,
|
|
69
|
-
confidenceThreshold: graphConfig?.confidenceThreshold || 0.7,
|
|
70
|
-
maxHops: graphConfig?.maxHops || 3,
|
|
71
|
-
deduplicationThreshold: graphConfig?.deduplicationThreshold || 0.85,
|
|
72
|
-
geminiApiKey: graphConfig?.geminiApiKey,
|
|
73
|
-
...graphConfig
|
|
74
|
-
}, embeddingService);
|
|
75
|
-
|
|
76
|
-
console.log('✅ KnowledgeGraphManager: Graph capabilities initialized');
|
|
77
|
-
console.log(' 📊 Storage: In-memory with Walrus persistence');
|
|
78
|
-
console.log(' 🔗 AI extraction: Entity/relationship detection');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return this.graphService;
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.error('❌ Failed to initialize Knowledge Graph:', error);
|
|
84
|
-
throw error;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Extract entities and relationships from text content
|
|
90
|
-
*/
|
|
91
|
-
async extractKnowledgeGraph(
|
|
92
|
-
content: string,
|
|
93
|
-
memoryId: string,
|
|
94
|
-
options: {
|
|
95
|
-
confidenceThreshold?: number;
|
|
96
|
-
includeEmbeddings?: boolean;
|
|
97
|
-
} = {}
|
|
98
|
-
): Promise<GraphExtractionResult> {
|
|
99
|
-
if (!this.graphService) {
|
|
100
|
-
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
console.log(`🔍 Extracting knowledge graph from memory ${memoryId}`);
|
|
105
|
-
|
|
106
|
-
const result = await this.graphService.extractEntitiesAndRelationships(
|
|
107
|
-
content,
|
|
108
|
-
memoryId,
|
|
109
|
-
options
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
console.log(`✅ Extracted ${result.entities.length} entities and ${result.relationships.length} relationships`);
|
|
113
|
-
console.log(` Confidence: ${(result.confidence * 100).toFixed(1)}%`);
|
|
114
|
-
console.log(` Processing time: ${result.processingTimeMs}ms`);
|
|
115
|
-
|
|
116
|
-
return result;
|
|
117
|
-
} catch (error) {
|
|
118
|
-
console.error('❌ Knowledge graph extraction failed:', error);
|
|
119
|
-
throw error;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Get or load user's knowledge graph
|
|
125
|
-
*/
|
|
126
|
-
async getUserKnowledgeGraph(userAddress: string): Promise<KnowledgeGraph> {
|
|
127
|
-
if (!this.graphService) {
|
|
128
|
-
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Check in-memory cache first
|
|
132
|
-
let graph = this.knowledgeGraphs.get(userAddress);
|
|
133
|
-
|
|
134
|
-
if (!graph) {
|
|
135
|
-
// Create new graph if none found
|
|
136
|
-
graph = this.graphService.createGraph(userAddress);
|
|
137
|
-
this.knowledgeGraphs.set(userAddress, graph);
|
|
138
|
-
this.graphCache.set(userAddress, {
|
|
139
|
-
graph,
|
|
140
|
-
lastSaved: new Date(),
|
|
141
|
-
isDirty: false
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return graph;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Add extraction results to user's knowledge graph
|
|
150
|
-
*/
|
|
151
|
-
addToUserGraph(
|
|
152
|
-
userAddress: string,
|
|
153
|
-
entities: Entity[],
|
|
154
|
-
relationships: Relationship[],
|
|
155
|
-
sourceMemoryId: string
|
|
156
|
-
): KnowledgeGraph {
|
|
157
|
-
if (!this.graphService) {
|
|
158
|
-
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const userGraph = this.knowledgeGraphs.get(userAddress);
|
|
162
|
-
if (!userGraph) {
|
|
163
|
-
throw new Error(`No graph found for user ${userAddress}`);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const updatedGraph = this.graphService.addToGraph(
|
|
167
|
-
userGraph,
|
|
168
|
-
entities,
|
|
169
|
-
relationships,
|
|
170
|
-
sourceMemoryId
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
this.knowledgeGraphs.set(userAddress, updatedGraph);
|
|
174
|
-
this.graphCache.set(userAddress, {
|
|
175
|
-
graph: updatedGraph,
|
|
176
|
-
lastSaved: new Date(),
|
|
177
|
-
isDirty: true
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
return updatedGraph;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Search knowledge graph with semantic queries
|
|
185
|
-
*/
|
|
186
|
-
async searchKnowledgeGraph(
|
|
187
|
-
userAddress: string,
|
|
188
|
-
query: GraphQueryOptions
|
|
189
|
-
) {
|
|
190
|
-
if (!this.graphService) {
|
|
191
|
-
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
try {
|
|
195
|
-
console.log(`🔍 Searching knowledge graph for user ${userAddress}`);
|
|
196
|
-
|
|
197
|
-
const userGraph = await this.getUserKnowledgeGraph(userAddress);
|
|
198
|
-
|
|
199
|
-
const results = this.graphService.queryGraph(userGraph, {
|
|
200
|
-
entityTypes: query.entityTypes,
|
|
201
|
-
relationshipTypes: query.relationshipTypes,
|
|
202
|
-
searchText: query.searchText || query.keywords?.join(' '),
|
|
203
|
-
limit: query.limit || 50
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
console.log(`✅ Found ${results.entities.length} entities and ${results.relationships.length} relationships`);
|
|
207
|
-
|
|
208
|
-
return results;
|
|
209
|
-
} catch (error) {
|
|
210
|
-
console.error('❌ Knowledge graph search failed:', error);
|
|
211
|
-
throw error;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Find related entities using graph traversal
|
|
217
|
-
*/
|
|
218
|
-
async findRelatedEntities(
|
|
219
|
-
userAddress: string,
|
|
220
|
-
seedEntityIds: string[],
|
|
221
|
-
options: {
|
|
222
|
-
maxHops?: number;
|
|
223
|
-
relationshipTypes?: string[];
|
|
224
|
-
includeWeights?: boolean;
|
|
225
|
-
} = {}
|
|
226
|
-
) {
|
|
227
|
-
if (!this.graphService) {
|
|
228
|
-
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
console.log(`🔗 Finding related entities for user ${userAddress}`);
|
|
233
|
-
console.log(` Seed entities: ${seedEntityIds.join(', ')}`);
|
|
234
|
-
|
|
235
|
-
const userGraph = await this.getUserKnowledgeGraph(userAddress);
|
|
236
|
-
const results = this.graphService.findRelatedEntities(userGraph, seedEntityIds, options);
|
|
237
|
-
|
|
238
|
-
console.log(`✅ Found ${results.entities.length} related entities`);
|
|
239
|
-
|
|
240
|
-
return results;
|
|
241
|
-
} catch (error) {
|
|
242
|
-
console.error('❌ Failed to find related entities:', error);
|
|
243
|
-
throw error;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Batch extract knowledge graphs from multiple memories
|
|
249
|
-
*/
|
|
250
|
-
async extractKnowledgeGraphBatch(
|
|
251
|
-
memories: Array<{ id: string; content: string }>,
|
|
252
|
-
userAddress: string,
|
|
253
|
-
options: {
|
|
254
|
-
batchSize?: number;
|
|
255
|
-
delayMs?: number;
|
|
256
|
-
confidenceThreshold?: number;
|
|
257
|
-
} = {}
|
|
258
|
-
): Promise<GraphExtractionResult[]> {
|
|
259
|
-
if (!this.graphService) {
|
|
260
|
-
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
try {
|
|
264
|
-
console.log(`📊 Batch extracting knowledge graphs from ${memories.length} memories`);
|
|
265
|
-
|
|
266
|
-
const results = await this.graphService.extractFromMemoriesBatch(memories, {
|
|
267
|
-
batchSize: options.batchSize || 5,
|
|
268
|
-
delayMs: options.delayMs || 1000
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
// Aggregate all results into user's knowledge graph
|
|
272
|
-
let userGraph = await this.getUserKnowledgeGraph(userAddress);
|
|
273
|
-
let totalEntities = 0;
|
|
274
|
-
let totalRelationships = 0;
|
|
275
|
-
|
|
276
|
-
for (const result of results) {
|
|
277
|
-
if (result.confidence > (options.confidenceThreshold || 0.5)) {
|
|
278
|
-
userGraph = this.graphService.addToGraph(
|
|
279
|
-
userGraph,
|
|
280
|
-
result.entities,
|
|
281
|
-
result.relationships,
|
|
282
|
-
result.extractedFromMemory
|
|
283
|
-
);
|
|
284
|
-
totalEntities += result.entities.length;
|
|
285
|
-
totalRelationships += result.relationships.length;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Update cached graph
|
|
290
|
-
this.knowledgeGraphs.set(userAddress, userGraph);
|
|
291
|
-
this.graphCache.set(userAddress, {
|
|
292
|
-
graph: userGraph,
|
|
293
|
-
lastSaved: new Date(),
|
|
294
|
-
isDirty: true
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
console.log(`✅ Batch extraction complete: ${totalEntities} entities, ${totalRelationships} relationships added`);
|
|
298
|
-
|
|
299
|
-
return results;
|
|
300
|
-
} catch (error) {
|
|
301
|
-
console.error('❌ Batch knowledge graph extraction failed:', error);
|
|
302
|
-
throw error;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Get graph statistics
|
|
308
|
-
*/
|
|
309
|
-
getGraphStatistics(userAddress: string) {
|
|
310
|
-
if (!this.graphService) {
|
|
311
|
-
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
const graph = this.knowledgeGraphs.get(userAddress);
|
|
315
|
-
if (!graph) {
|
|
316
|
-
return {
|
|
317
|
-
totalEntities: 0,
|
|
318
|
-
totalRelationships: 0,
|
|
319
|
-
entityTypes: {},
|
|
320
|
-
relationshipTypes: {},
|
|
321
|
-
averageConnections: 0,
|
|
322
|
-
graphDensity: 0,
|
|
323
|
-
extractionStats: null,
|
|
324
|
-
lastUpdated: null
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
return this.graphService.getGraphStats(graph);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Get analytics about the knowledge graph
|
|
333
|
-
*/
|
|
334
|
-
getKnowledgeGraphAnalytics(userAddress: string) {
|
|
335
|
-
const graph = this.knowledgeGraphs.get(userAddress);
|
|
336
|
-
|
|
337
|
-
if (!graph) {
|
|
338
|
-
return {
|
|
339
|
-
totalEntities: 0,
|
|
340
|
-
totalRelationships: 0,
|
|
341
|
-
entityTypes: {},
|
|
342
|
-
relationshipTypes: {},
|
|
343
|
-
connectedComponents: 0,
|
|
344
|
-
averageConnections: 0,
|
|
345
|
-
lastUpdated: null
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// Analyze entity types
|
|
350
|
-
const entityTypes: Record<string, number> = {};
|
|
351
|
-
graph.entities.forEach((entity: any) => {
|
|
352
|
-
entityTypes[entity.type] = (entityTypes[entity.type] || 0) + 1;
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
// Analyze relationship types
|
|
356
|
-
const relationshipTypes: Record<string, number> = {};
|
|
357
|
-
graph.relationships.forEach((rel: any) => {
|
|
358
|
-
relationshipTypes[rel.type || rel.label] = (relationshipTypes[rel.type || rel.label] || 0) + 1;
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
// Calculate average connections
|
|
362
|
-
const connectionCounts = new Map();
|
|
363
|
-
graph.relationships.forEach((rel: any) => {
|
|
364
|
-
connectionCounts.set(rel.source, (connectionCounts.get(rel.source) || 0) + 1);
|
|
365
|
-
connectionCounts.set(rel.target, (connectionCounts.get(rel.target) || 0) + 1);
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
const averageConnections = connectionCounts.size > 0
|
|
369
|
-
? Array.from(connectionCounts.values()).reduce((sum, count) => sum + count, 0) / connectionCounts.size
|
|
370
|
-
: 0;
|
|
371
|
-
|
|
372
|
-
return {
|
|
373
|
-
totalEntities: graph.entities.length,
|
|
374
|
-
totalRelationships: graph.relationships.length,
|
|
375
|
-
entityTypes,
|
|
376
|
-
relationshipTypes,
|
|
377
|
-
connectedComponents: connectionCounts.size,
|
|
378
|
-
averageConnections: Math.round(averageConnections * 100) / 100,
|
|
379
|
-
lastUpdated: graph.metadata.lastUpdated
|
|
380
|
-
};
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Check if graph needs to be saved
|
|
385
|
-
*/
|
|
386
|
-
isGraphDirty(userAddress: string): boolean {
|
|
387
|
-
return this.graphCache.get(userAddress)?.isDirty || false;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* Mark graph as saved
|
|
392
|
-
*/
|
|
393
|
-
markGraphAsSaved(userAddress: string) {
|
|
394
|
-
const cacheEntry = this.graphCache.get(userAddress);
|
|
395
|
-
if (cacheEntry) {
|
|
396
|
-
cacheEntry.lastSaved = new Date();
|
|
397
|
-
cacheEntry.isDirty = false;
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
/**
|
|
402
|
-
* Get all user addresses with cached graphs
|
|
403
|
-
*/
|
|
404
|
-
getCachedUsers(): string[] {
|
|
405
|
-
return Array.from(this.knowledgeGraphs.keys());
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* Clear graph cache for a user
|
|
410
|
-
*/
|
|
411
|
-
clearUserGraph(userAddress: string) {
|
|
412
|
-
this.knowledgeGraphs.delete(userAddress);
|
|
413
|
-
this.graphCache.delete(userAddress);
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* Serialize graph for storage
|
|
418
|
-
*/
|
|
419
|
-
serializeGraph(userAddress: string): string | null {
|
|
420
|
-
const graph = this.knowledgeGraphs.get(userAddress);
|
|
421
|
-
if (!graph) return null;
|
|
422
|
-
|
|
423
|
-
return JSON.stringify(graph, null, 2);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* KnowledgeGraphManager - Knowledge Graph Operations
|
|
3
|
+
*
|
|
4
|
+
* Handles entity extraction, relationship mapping, and graph querying.
|
|
5
|
+
* Extracted from StorageService for better separation of concerns.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - AI-powered entity/relationship extraction
|
|
9
|
+
* - In-memory graph storage with Walrus persistence
|
|
10
|
+
* - Graph traversal and querying
|
|
11
|
+
* - Batch extraction from multiple memories
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { GraphService, KnowledgeGraph, Entity, Relationship, GraphExtractionResult } from '../../graph/GraphService';
|
|
15
|
+
import type { EmbeddingService } from '../EmbeddingService';
|
|
16
|
+
|
|
17
|
+
export interface GraphCache {
|
|
18
|
+
graph: KnowledgeGraph;
|
|
19
|
+
lastSaved: Date;
|
|
20
|
+
isDirty: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface GraphQueryOptions {
|
|
24
|
+
keywords?: string[];
|
|
25
|
+
entityTypes?: string[];
|
|
26
|
+
relationshipTypes?: string[];
|
|
27
|
+
searchText?: string;
|
|
28
|
+
maxHops?: number;
|
|
29
|
+
limit?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface GraphInitConfig {
|
|
33
|
+
confidenceThreshold?: number;
|
|
34
|
+
maxHops?: number;
|
|
35
|
+
deduplicationThreshold?: number;
|
|
36
|
+
geminiApiKey?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* KnowledgeGraphManager - Manages knowledge graph operations
|
|
41
|
+
*
|
|
42
|
+
* Coordinates:
|
|
43
|
+
* - GraphService for entity/relationship extraction
|
|
44
|
+
* - In-memory graph storage and caching
|
|
45
|
+
* - Walrus persistence for cross-device sync
|
|
46
|
+
*/
|
|
47
|
+
export class KnowledgeGraphManager {
|
|
48
|
+
private graphService?: GraphService;
|
|
49
|
+
private knowledgeGraphs = new Map<string, KnowledgeGraph>();
|
|
50
|
+
private graphCache = new Map<string, GraphCache>();
|
|
51
|
+
|
|
52
|
+
constructor() {
|
|
53
|
+
// GraphService will be initialized via initializeKnowledgeGraph()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Initialize knowledge graph capabilities
|
|
58
|
+
*/
|
|
59
|
+
async initializeKnowledgeGraph(
|
|
60
|
+
embeddingService?: EmbeddingService,
|
|
61
|
+
graphConfig?: GraphInitConfig
|
|
62
|
+
) {
|
|
63
|
+
try {
|
|
64
|
+
if (!this.graphService) {
|
|
65
|
+
const { GraphService } = await import('../../graph/GraphService');
|
|
66
|
+
|
|
67
|
+
this.graphService = new GraphService({
|
|
68
|
+
enableEmbeddings: !!embeddingService,
|
|
69
|
+
confidenceThreshold: graphConfig?.confidenceThreshold || 0.7,
|
|
70
|
+
maxHops: graphConfig?.maxHops || 3,
|
|
71
|
+
deduplicationThreshold: graphConfig?.deduplicationThreshold || 0.85,
|
|
72
|
+
geminiApiKey: graphConfig?.geminiApiKey,
|
|
73
|
+
...graphConfig
|
|
74
|
+
}, embeddingService);
|
|
75
|
+
|
|
76
|
+
console.log('✅ KnowledgeGraphManager: Graph capabilities initialized');
|
|
77
|
+
console.log(' 📊 Storage: In-memory with Walrus persistence');
|
|
78
|
+
console.log(' 🔗 AI extraction: Entity/relationship detection');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return this.graphService;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error('❌ Failed to initialize Knowledge Graph:', error);
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Extract entities and relationships from text content
|
|
90
|
+
*/
|
|
91
|
+
async extractKnowledgeGraph(
|
|
92
|
+
content: string,
|
|
93
|
+
memoryId: string,
|
|
94
|
+
options: {
|
|
95
|
+
confidenceThreshold?: number;
|
|
96
|
+
includeEmbeddings?: boolean;
|
|
97
|
+
} = {}
|
|
98
|
+
): Promise<GraphExtractionResult> {
|
|
99
|
+
if (!this.graphService) {
|
|
100
|
+
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
console.log(`🔍 Extracting knowledge graph from memory ${memoryId}`);
|
|
105
|
+
|
|
106
|
+
const result = await this.graphService.extractEntitiesAndRelationships(
|
|
107
|
+
content,
|
|
108
|
+
memoryId,
|
|
109
|
+
options
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
console.log(`✅ Extracted ${result.entities.length} entities and ${result.relationships.length} relationships`);
|
|
113
|
+
console.log(` Confidence: ${(result.confidence * 100).toFixed(1)}%`);
|
|
114
|
+
console.log(` Processing time: ${result.processingTimeMs}ms`);
|
|
115
|
+
|
|
116
|
+
return result;
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.error('❌ Knowledge graph extraction failed:', error);
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Get or load user's knowledge graph
|
|
125
|
+
*/
|
|
126
|
+
async getUserKnowledgeGraph(userAddress: string): Promise<KnowledgeGraph> {
|
|
127
|
+
if (!this.graphService) {
|
|
128
|
+
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Check in-memory cache first
|
|
132
|
+
let graph = this.knowledgeGraphs.get(userAddress);
|
|
133
|
+
|
|
134
|
+
if (!graph) {
|
|
135
|
+
// Create new graph if none found
|
|
136
|
+
graph = this.graphService.createGraph(userAddress);
|
|
137
|
+
this.knowledgeGraphs.set(userAddress, graph);
|
|
138
|
+
this.graphCache.set(userAddress, {
|
|
139
|
+
graph,
|
|
140
|
+
lastSaved: new Date(),
|
|
141
|
+
isDirty: false
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return graph;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Add extraction results to user's knowledge graph
|
|
150
|
+
*/
|
|
151
|
+
addToUserGraph(
|
|
152
|
+
userAddress: string,
|
|
153
|
+
entities: Entity[],
|
|
154
|
+
relationships: Relationship[],
|
|
155
|
+
sourceMemoryId: string
|
|
156
|
+
): KnowledgeGraph {
|
|
157
|
+
if (!this.graphService) {
|
|
158
|
+
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const userGraph = this.knowledgeGraphs.get(userAddress);
|
|
162
|
+
if (!userGraph) {
|
|
163
|
+
throw new Error(`No graph found for user ${userAddress}`);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const updatedGraph = this.graphService.addToGraph(
|
|
167
|
+
userGraph,
|
|
168
|
+
entities,
|
|
169
|
+
relationships,
|
|
170
|
+
sourceMemoryId
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
this.knowledgeGraphs.set(userAddress, updatedGraph);
|
|
174
|
+
this.graphCache.set(userAddress, {
|
|
175
|
+
graph: updatedGraph,
|
|
176
|
+
lastSaved: new Date(),
|
|
177
|
+
isDirty: true
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
return updatedGraph;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Search knowledge graph with semantic queries
|
|
185
|
+
*/
|
|
186
|
+
async searchKnowledgeGraph(
|
|
187
|
+
userAddress: string,
|
|
188
|
+
query: GraphQueryOptions
|
|
189
|
+
) {
|
|
190
|
+
if (!this.graphService) {
|
|
191
|
+
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
console.log(`🔍 Searching knowledge graph for user ${userAddress}`);
|
|
196
|
+
|
|
197
|
+
const userGraph = await this.getUserKnowledgeGraph(userAddress);
|
|
198
|
+
|
|
199
|
+
const results = this.graphService.queryGraph(userGraph, {
|
|
200
|
+
entityTypes: query.entityTypes,
|
|
201
|
+
relationshipTypes: query.relationshipTypes,
|
|
202
|
+
searchText: query.searchText || query.keywords?.join(' '),
|
|
203
|
+
limit: query.limit || 50
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
console.log(`✅ Found ${results.entities.length} entities and ${results.relationships.length} relationships`);
|
|
207
|
+
|
|
208
|
+
return results;
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error('❌ Knowledge graph search failed:', error);
|
|
211
|
+
throw error;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Find related entities using graph traversal
|
|
217
|
+
*/
|
|
218
|
+
async findRelatedEntities(
|
|
219
|
+
userAddress: string,
|
|
220
|
+
seedEntityIds: string[],
|
|
221
|
+
options: {
|
|
222
|
+
maxHops?: number;
|
|
223
|
+
relationshipTypes?: string[];
|
|
224
|
+
includeWeights?: boolean;
|
|
225
|
+
} = {}
|
|
226
|
+
) {
|
|
227
|
+
if (!this.graphService) {
|
|
228
|
+
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
try {
|
|
232
|
+
console.log(`🔗 Finding related entities for user ${userAddress}`);
|
|
233
|
+
console.log(` Seed entities: ${seedEntityIds.join(', ')}`);
|
|
234
|
+
|
|
235
|
+
const userGraph = await this.getUserKnowledgeGraph(userAddress);
|
|
236
|
+
const results = this.graphService.findRelatedEntities(userGraph, seedEntityIds, options);
|
|
237
|
+
|
|
238
|
+
console.log(`✅ Found ${results.entities.length} related entities`);
|
|
239
|
+
|
|
240
|
+
return results;
|
|
241
|
+
} catch (error) {
|
|
242
|
+
console.error('❌ Failed to find related entities:', error);
|
|
243
|
+
throw error;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Batch extract knowledge graphs from multiple memories
|
|
249
|
+
*/
|
|
250
|
+
async extractKnowledgeGraphBatch(
|
|
251
|
+
memories: Array<{ id: string; content: string }>,
|
|
252
|
+
userAddress: string,
|
|
253
|
+
options: {
|
|
254
|
+
batchSize?: number;
|
|
255
|
+
delayMs?: number;
|
|
256
|
+
confidenceThreshold?: number;
|
|
257
|
+
} = {}
|
|
258
|
+
): Promise<GraphExtractionResult[]> {
|
|
259
|
+
if (!this.graphService) {
|
|
260
|
+
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
try {
|
|
264
|
+
console.log(`📊 Batch extracting knowledge graphs from ${memories.length} memories`);
|
|
265
|
+
|
|
266
|
+
const results = await this.graphService.extractFromMemoriesBatch(memories, {
|
|
267
|
+
batchSize: options.batchSize || 5,
|
|
268
|
+
delayMs: options.delayMs || 1000
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Aggregate all results into user's knowledge graph
|
|
272
|
+
let userGraph = await this.getUserKnowledgeGraph(userAddress);
|
|
273
|
+
let totalEntities = 0;
|
|
274
|
+
let totalRelationships = 0;
|
|
275
|
+
|
|
276
|
+
for (const result of results) {
|
|
277
|
+
if (result.confidence > (options.confidenceThreshold || 0.5)) {
|
|
278
|
+
userGraph = this.graphService.addToGraph(
|
|
279
|
+
userGraph,
|
|
280
|
+
result.entities,
|
|
281
|
+
result.relationships,
|
|
282
|
+
result.extractedFromMemory
|
|
283
|
+
);
|
|
284
|
+
totalEntities += result.entities.length;
|
|
285
|
+
totalRelationships += result.relationships.length;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Update cached graph
|
|
290
|
+
this.knowledgeGraphs.set(userAddress, userGraph);
|
|
291
|
+
this.graphCache.set(userAddress, {
|
|
292
|
+
graph: userGraph,
|
|
293
|
+
lastSaved: new Date(),
|
|
294
|
+
isDirty: true
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
console.log(`✅ Batch extraction complete: ${totalEntities} entities, ${totalRelationships} relationships added`);
|
|
298
|
+
|
|
299
|
+
return results;
|
|
300
|
+
} catch (error) {
|
|
301
|
+
console.error('❌ Batch knowledge graph extraction failed:', error);
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Get graph statistics
|
|
308
|
+
*/
|
|
309
|
+
getGraphStatistics(userAddress: string) {
|
|
310
|
+
if (!this.graphService) {
|
|
311
|
+
throw new Error('Knowledge Graph not initialized. Call initializeKnowledgeGraph() first.');
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const graph = this.knowledgeGraphs.get(userAddress);
|
|
315
|
+
if (!graph) {
|
|
316
|
+
return {
|
|
317
|
+
totalEntities: 0,
|
|
318
|
+
totalRelationships: 0,
|
|
319
|
+
entityTypes: {},
|
|
320
|
+
relationshipTypes: {},
|
|
321
|
+
averageConnections: 0,
|
|
322
|
+
graphDensity: 0,
|
|
323
|
+
extractionStats: null,
|
|
324
|
+
lastUpdated: null
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return this.graphService.getGraphStats(graph);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Get analytics about the knowledge graph
|
|
333
|
+
*/
|
|
334
|
+
getKnowledgeGraphAnalytics(userAddress: string) {
|
|
335
|
+
const graph = this.knowledgeGraphs.get(userAddress);
|
|
336
|
+
|
|
337
|
+
if (!graph) {
|
|
338
|
+
return {
|
|
339
|
+
totalEntities: 0,
|
|
340
|
+
totalRelationships: 0,
|
|
341
|
+
entityTypes: {},
|
|
342
|
+
relationshipTypes: {},
|
|
343
|
+
connectedComponents: 0,
|
|
344
|
+
averageConnections: 0,
|
|
345
|
+
lastUpdated: null
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Analyze entity types
|
|
350
|
+
const entityTypes: Record<string, number> = {};
|
|
351
|
+
graph.entities.forEach((entity: any) => {
|
|
352
|
+
entityTypes[entity.type] = (entityTypes[entity.type] || 0) + 1;
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// Analyze relationship types
|
|
356
|
+
const relationshipTypes: Record<string, number> = {};
|
|
357
|
+
graph.relationships.forEach((rel: any) => {
|
|
358
|
+
relationshipTypes[rel.type || rel.label] = (relationshipTypes[rel.type || rel.label] || 0) + 1;
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// Calculate average connections
|
|
362
|
+
const connectionCounts = new Map();
|
|
363
|
+
graph.relationships.forEach((rel: any) => {
|
|
364
|
+
connectionCounts.set(rel.source, (connectionCounts.get(rel.source) || 0) + 1);
|
|
365
|
+
connectionCounts.set(rel.target, (connectionCounts.get(rel.target) || 0) + 1);
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
const averageConnections = connectionCounts.size > 0
|
|
369
|
+
? Array.from(connectionCounts.values()).reduce((sum, count) => sum + count, 0) / connectionCounts.size
|
|
370
|
+
: 0;
|
|
371
|
+
|
|
372
|
+
return {
|
|
373
|
+
totalEntities: graph.entities.length,
|
|
374
|
+
totalRelationships: graph.relationships.length,
|
|
375
|
+
entityTypes,
|
|
376
|
+
relationshipTypes,
|
|
377
|
+
connectedComponents: connectionCounts.size,
|
|
378
|
+
averageConnections: Math.round(averageConnections * 100) / 100,
|
|
379
|
+
lastUpdated: graph.metadata.lastUpdated
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Check if graph needs to be saved
|
|
385
|
+
*/
|
|
386
|
+
isGraphDirty(userAddress: string): boolean {
|
|
387
|
+
return this.graphCache.get(userAddress)?.isDirty || false;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Mark graph as saved
|
|
392
|
+
*/
|
|
393
|
+
markGraphAsSaved(userAddress: string) {
|
|
394
|
+
const cacheEntry = this.graphCache.get(userAddress);
|
|
395
|
+
if (cacheEntry) {
|
|
396
|
+
cacheEntry.lastSaved = new Date();
|
|
397
|
+
cacheEntry.isDirty = false;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Get all user addresses with cached graphs
|
|
403
|
+
*/
|
|
404
|
+
getCachedUsers(): string[] {
|
|
405
|
+
return Array.from(this.knowledgeGraphs.keys());
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Clear graph cache for a user
|
|
410
|
+
*/
|
|
411
|
+
clearUserGraph(userAddress: string) {
|
|
412
|
+
this.knowledgeGraphs.delete(userAddress);
|
|
413
|
+
this.graphCache.delete(userAddress);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Serialize graph for storage
|
|
418
|
+
*/
|
|
419
|
+
serializeGraph(userAddress: string): string | null {
|
|
420
|
+
const graph = this.knowledgeGraphs.get(userAddress);
|
|
421
|
+
if (!graph) return null;
|
|
422
|
+
|
|
423
|
+
return JSON.stringify(graph, null, 2);
|
|
424
|
+
}
|
|
425
|
+
}
|