@soulcraft/brainy 0.56.0 → 0.57.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/README.md +9 -9
- package/bin/{cortex.js → brainy.js} +1 -1
- package/dist/augmentations/cortexSense.d.ts +196 -0
- package/dist/augmentations/cortexSense.js +747 -0
- package/dist/augmentations/cortexSense.js.map +1 -0
- package/dist/cortex/cortex.d.ts +1 -1
- package/dist/cortex/cortex.js +22 -22
- package/dist/cortex/cortex.js.map +1 -1
- package/dist/shared/default-augmentations.d.ts +6 -6
- package/dist/shared/default-augmentations.js +23 -23
- package/dist/shared/default-augmentations.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,747 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cortex SENSE Augmentation - Atomic Age AI-Powered Data Understanding
|
|
3
|
+
*
|
|
4
|
+
* 🧠 The cerebral cortex layer for intelligent data processing
|
|
5
|
+
* ⚛️ Complete with confidence scoring and relationship weight calculation
|
|
6
|
+
*/
|
|
7
|
+
import { NounType, VerbType } from '../types/graphTypes.js';
|
|
8
|
+
import * as fs from 'fs/promises';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
/**
|
|
11
|
+
* Neural Import SENSE Augmentation - The Brain's Perceptual System
|
|
12
|
+
*/
|
|
13
|
+
export class CortexSenseAugmentation {
|
|
14
|
+
constructor(brainy, config = {}) {
|
|
15
|
+
this.name = 'cortex-sense';
|
|
16
|
+
this.description = 'AI-powered cortex for intelligent data understanding';
|
|
17
|
+
this.enabled = true;
|
|
18
|
+
this.brainy = brainy;
|
|
19
|
+
this.config = {
|
|
20
|
+
confidenceThreshold: 0.7,
|
|
21
|
+
enableWeights: true,
|
|
22
|
+
skipDuplicates: true,
|
|
23
|
+
...config
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async initialize() {
|
|
27
|
+
// Initialize the cortex analysis system
|
|
28
|
+
console.log('🧠 Cortex SENSE augmentation initialized');
|
|
29
|
+
}
|
|
30
|
+
async shutDown() {
|
|
31
|
+
console.log('🧠 Neural Import SENSE augmentation shut down');
|
|
32
|
+
}
|
|
33
|
+
async getStatus() {
|
|
34
|
+
return this.enabled ? 'active' : 'inactive';
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Process raw data into structured nouns and verbs using neural analysis
|
|
38
|
+
*/
|
|
39
|
+
async processRawData(rawData, dataType, options) {
|
|
40
|
+
try {
|
|
41
|
+
// Merge options with config
|
|
42
|
+
const mergedConfig = { ...this.config, ...options };
|
|
43
|
+
// Parse the raw data based on type
|
|
44
|
+
const parsedData = await this.parseRawData(rawData, dataType);
|
|
45
|
+
// Perform neural analysis
|
|
46
|
+
const analysis = await this.performNeuralAnalysis(parsedData, mergedConfig);
|
|
47
|
+
// Extract nouns and verbs for the ISenseAugmentation interface
|
|
48
|
+
const nouns = analysis.detectedEntities.map(entity => entity.suggestedId);
|
|
49
|
+
const verbs = analysis.detectedRelationships.map(rel => `${rel.sourceId}->${rel.verbType}->${rel.targetId}`);
|
|
50
|
+
// Store the full analysis for later retrieval
|
|
51
|
+
await this.storeNeuralAnalysis(analysis);
|
|
52
|
+
return {
|
|
53
|
+
success: true,
|
|
54
|
+
data: {
|
|
55
|
+
nouns,
|
|
56
|
+
verbs,
|
|
57
|
+
confidence: analysis.confidence,
|
|
58
|
+
insights: analysis.insights.map((insight) => ({
|
|
59
|
+
type: insight.type,
|
|
60
|
+
description: insight.description,
|
|
61
|
+
confidence: insight.confidence
|
|
62
|
+
})),
|
|
63
|
+
metadata: {
|
|
64
|
+
detectedEntities: analysis.detectedEntities.length,
|
|
65
|
+
detectedRelationships: analysis.detectedRelationships.length,
|
|
66
|
+
timestamp: new Date().toISOString(),
|
|
67
|
+
augmentation: 'neural-import-sense'
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
return {
|
|
74
|
+
success: false,
|
|
75
|
+
data: { nouns: [], verbs: [] },
|
|
76
|
+
error: error instanceof Error ? error.message : 'Neural analysis failed'
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Listen to real-time data feeds and process them
|
|
82
|
+
*/
|
|
83
|
+
async listenToFeed(feedUrl, callback) {
|
|
84
|
+
// For file-based feeds, watch for changes
|
|
85
|
+
if (feedUrl.startsWith('file://')) {
|
|
86
|
+
const filePath = feedUrl.replace('file://', '');
|
|
87
|
+
// Watch file for changes using Node.js fs.watch
|
|
88
|
+
const fsWatch = require('fs');
|
|
89
|
+
const watcher = fsWatch.watch(filePath, async (eventType) => {
|
|
90
|
+
if (eventType === 'change') {
|
|
91
|
+
try {
|
|
92
|
+
const fileContent = await fs.readFile(filePath, 'utf8');
|
|
93
|
+
const result = await this.processRawData(fileContent, this.getDataTypeFromPath(filePath));
|
|
94
|
+
if (result.success) {
|
|
95
|
+
callback({
|
|
96
|
+
nouns: result.data.nouns,
|
|
97
|
+
verbs: result.data.verbs,
|
|
98
|
+
confidence: result.data.confidence
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
console.error('Neural Import feed error:', error);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// For other feed types, implement appropriate listeners
|
|
110
|
+
console.log(`🧠 Neural Import listening to feed: ${feedUrl}`);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Analyze data structure without processing (preview mode)
|
|
114
|
+
*/
|
|
115
|
+
async analyzeStructure(rawData, dataType, options) {
|
|
116
|
+
try {
|
|
117
|
+
// Parse the raw data
|
|
118
|
+
const parsedData = await this.parseRawData(rawData, dataType);
|
|
119
|
+
// Perform lightweight analysis for structure detection
|
|
120
|
+
const analysis = await this.performNeuralAnalysis(parsedData, { ...this.config, ...options });
|
|
121
|
+
// Summarize entity types
|
|
122
|
+
const entityTypeCounts = new Map();
|
|
123
|
+
analysis.detectedEntities.forEach(entity => {
|
|
124
|
+
const existing = entityTypeCounts.get(entity.nounType) || { count: 0, totalConfidence: 0 };
|
|
125
|
+
entityTypeCounts.set(entity.nounType, {
|
|
126
|
+
count: existing.count + 1,
|
|
127
|
+
totalConfidence: existing.totalConfidence + entity.confidence
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
const entityTypes = Array.from(entityTypeCounts.entries()).map(([type, stats]) => ({
|
|
131
|
+
type,
|
|
132
|
+
count: stats.count,
|
|
133
|
+
confidence: stats.totalConfidence / stats.count
|
|
134
|
+
}));
|
|
135
|
+
// Summarize relationship types
|
|
136
|
+
const relationshipTypeCounts = new Map();
|
|
137
|
+
analysis.detectedRelationships.forEach(rel => {
|
|
138
|
+
const existing = relationshipTypeCounts.get(rel.verbType) || { count: 0, totalConfidence: 0 };
|
|
139
|
+
relationshipTypeCounts.set(rel.verbType, {
|
|
140
|
+
count: existing.count + 1,
|
|
141
|
+
totalConfidence: existing.totalConfidence + rel.confidence
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
const relationshipTypes = Array.from(relationshipTypeCounts.entries()).map(([type, stats]) => ({
|
|
145
|
+
type,
|
|
146
|
+
count: stats.count,
|
|
147
|
+
confidence: stats.totalConfidence / stats.count
|
|
148
|
+
}));
|
|
149
|
+
// Assess data quality
|
|
150
|
+
const dataQuality = this.assessDataQuality(parsedData, analysis);
|
|
151
|
+
// Generate recommendations
|
|
152
|
+
const recommendations = this.generateRecommendations(parsedData, analysis, entityTypes, relationshipTypes);
|
|
153
|
+
return {
|
|
154
|
+
success: true,
|
|
155
|
+
data: {
|
|
156
|
+
entityTypes,
|
|
157
|
+
relationshipTypes,
|
|
158
|
+
dataQuality,
|
|
159
|
+
recommendations
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
return {
|
|
165
|
+
success: false,
|
|
166
|
+
data: {
|
|
167
|
+
entityTypes: [],
|
|
168
|
+
relationshipTypes: [],
|
|
169
|
+
dataQuality: { completeness: 0, consistency: 0, accuracy: 0 },
|
|
170
|
+
recommendations: []
|
|
171
|
+
},
|
|
172
|
+
error: error instanceof Error ? error.message : 'Structure analysis failed'
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Validate data compatibility with current knowledge base
|
|
178
|
+
*/
|
|
179
|
+
async validateCompatibility(rawData, dataType) {
|
|
180
|
+
try {
|
|
181
|
+
// Parse the raw data
|
|
182
|
+
const parsedData = await this.parseRawData(rawData, dataType);
|
|
183
|
+
// Perform neural analysis
|
|
184
|
+
const analysis = await this.performNeuralAnalysis(parsedData);
|
|
185
|
+
const issues = [];
|
|
186
|
+
const suggestions = [];
|
|
187
|
+
// Check for low confidence entities
|
|
188
|
+
const lowConfidenceEntities = analysis.detectedEntities.filter((e) => e.confidence < 0.5);
|
|
189
|
+
if (lowConfidenceEntities.length > 0) {
|
|
190
|
+
issues.push({
|
|
191
|
+
type: 'confidence',
|
|
192
|
+
description: `${lowConfidenceEntities.length} entities have low confidence scores`,
|
|
193
|
+
severity: 'medium'
|
|
194
|
+
});
|
|
195
|
+
suggestions.push('Consider reviewing field names and data structure for better entity detection');
|
|
196
|
+
}
|
|
197
|
+
// Check for missing relationships
|
|
198
|
+
if (analysis.detectedRelationships.length === 0 && analysis.detectedEntities.length > 1) {
|
|
199
|
+
issues.push({
|
|
200
|
+
type: 'relationships',
|
|
201
|
+
description: 'No relationships detected between entities',
|
|
202
|
+
severity: 'low'
|
|
203
|
+
});
|
|
204
|
+
suggestions.push('Consider adding contextual fields that describe entity relationships');
|
|
205
|
+
}
|
|
206
|
+
// Check for data type compatibility
|
|
207
|
+
const supportedTypes = ['json', 'csv', 'yaml', 'text'];
|
|
208
|
+
if (!supportedTypes.includes(dataType.toLowerCase())) {
|
|
209
|
+
issues.push({
|
|
210
|
+
type: 'format',
|
|
211
|
+
description: `Data type '${dataType}' may not be fully supported`,
|
|
212
|
+
severity: 'high'
|
|
213
|
+
});
|
|
214
|
+
suggestions.push(`Convert data to one of: ${supportedTypes.join(', ')}`);
|
|
215
|
+
}
|
|
216
|
+
// Check for data completeness
|
|
217
|
+
const incompleteEntities = analysis.detectedEntities.filter((e) => !e.originalData || Object.keys(e.originalData).length < 2);
|
|
218
|
+
if (incompleteEntities.length > 0) {
|
|
219
|
+
issues.push({
|
|
220
|
+
type: 'completeness',
|
|
221
|
+
description: `${incompleteEntities.length} entities have insufficient data`,
|
|
222
|
+
severity: 'medium'
|
|
223
|
+
});
|
|
224
|
+
suggestions.push('Ensure each entity has multiple descriptive fields');
|
|
225
|
+
}
|
|
226
|
+
const compatible = issues.filter(i => i.severity === 'high').length === 0;
|
|
227
|
+
return {
|
|
228
|
+
success: true,
|
|
229
|
+
data: {
|
|
230
|
+
compatible,
|
|
231
|
+
issues,
|
|
232
|
+
suggestions
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
return {
|
|
238
|
+
success: false,
|
|
239
|
+
data: {
|
|
240
|
+
compatible: false,
|
|
241
|
+
issues: [{
|
|
242
|
+
type: 'error',
|
|
243
|
+
description: error instanceof Error ? error.message : 'Validation failed',
|
|
244
|
+
severity: 'high'
|
|
245
|
+
}],
|
|
246
|
+
suggestions: []
|
|
247
|
+
},
|
|
248
|
+
error: error instanceof Error ? error.message : 'Compatibility validation failed'
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Get the full neural analysis result (custom method for Cortex integration)
|
|
254
|
+
*/
|
|
255
|
+
async getNeuralAnalysis(rawData, dataType) {
|
|
256
|
+
const parsedData = await this.parseRawData(rawData, dataType);
|
|
257
|
+
return await this.performNeuralAnalysis(parsedData);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Parse raw data based on type
|
|
261
|
+
*/
|
|
262
|
+
async parseRawData(rawData, dataType) {
|
|
263
|
+
const content = typeof rawData === 'string' ? rawData : rawData.toString('utf8');
|
|
264
|
+
switch (dataType.toLowerCase()) {
|
|
265
|
+
case 'json':
|
|
266
|
+
const jsonData = JSON.parse(content);
|
|
267
|
+
return Array.isArray(jsonData) ? jsonData : [jsonData];
|
|
268
|
+
case 'csv':
|
|
269
|
+
return this.parseCSV(content);
|
|
270
|
+
case 'yaml':
|
|
271
|
+
case 'yml':
|
|
272
|
+
// For now, basic YAML support - in full implementation would use yaml parser
|
|
273
|
+
return JSON.parse(content); // Placeholder
|
|
274
|
+
case 'txt':
|
|
275
|
+
case 'text':
|
|
276
|
+
// Split text into sentences/paragraphs for analysis
|
|
277
|
+
return content.split(/\n+/).filter(line => line.trim()).map(line => ({ text: line }));
|
|
278
|
+
default:
|
|
279
|
+
throw new Error(`Unsupported data type: ${dataType}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Basic CSV parser
|
|
284
|
+
*/
|
|
285
|
+
parseCSV(content) {
|
|
286
|
+
const lines = content.split('\n').filter(line => line.trim());
|
|
287
|
+
if (lines.length < 2)
|
|
288
|
+
return [];
|
|
289
|
+
const headers = lines[0].split(',').map(h => h.trim().replace(/"/g, ''));
|
|
290
|
+
const data = [];
|
|
291
|
+
for (let i = 1; i < lines.length; i++) {
|
|
292
|
+
const values = lines[i].split(',').map(v => v.trim().replace(/"/g, ''));
|
|
293
|
+
const row = {};
|
|
294
|
+
headers.forEach((header, index) => {
|
|
295
|
+
row[header] = values[index] || '';
|
|
296
|
+
});
|
|
297
|
+
data.push(row);
|
|
298
|
+
}
|
|
299
|
+
return data;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Perform neural analysis on parsed data
|
|
303
|
+
*/
|
|
304
|
+
async performNeuralAnalysis(parsedData, config = this.config) {
|
|
305
|
+
// Phase 1: Neural Entity Detection
|
|
306
|
+
const detectedEntities = await this.detectEntitiesWithNeuralAnalysis(parsedData, config);
|
|
307
|
+
// Phase 2: Neural Relationship Detection
|
|
308
|
+
const detectedRelationships = await this.detectRelationshipsWithNeuralAnalysis(detectedEntities, parsedData, config);
|
|
309
|
+
// Phase 3: Neural Insights Generation
|
|
310
|
+
const insights = await this.generateCortexInsights(detectedEntities, detectedRelationships);
|
|
311
|
+
// Phase 4: Confidence Scoring
|
|
312
|
+
const overallConfidence = this.calculateOverallConfidence(detectedEntities, detectedRelationships);
|
|
313
|
+
return {
|
|
314
|
+
detectedEntities,
|
|
315
|
+
detectedRelationships,
|
|
316
|
+
confidence: overallConfidence,
|
|
317
|
+
insights
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Neural Entity Detection - The Core AI Engine
|
|
322
|
+
*/
|
|
323
|
+
async detectEntitiesWithNeuralAnalysis(rawData, config = this.config) {
|
|
324
|
+
const entities = [];
|
|
325
|
+
const nounTypes = Object.values(NounType);
|
|
326
|
+
for (const [index, dataItem] of rawData.entries()) {
|
|
327
|
+
const mainText = this.extractMainText(dataItem);
|
|
328
|
+
const detections = [];
|
|
329
|
+
// Test against all noun types using semantic similarity
|
|
330
|
+
for (const nounType of nounTypes) {
|
|
331
|
+
const confidence = await this.calculateEntityTypeConfidence(mainText, dataItem, nounType);
|
|
332
|
+
if (confidence >= config.confidenceThreshold - 0.2) { // Allow slightly lower for alternatives
|
|
333
|
+
const reasoning = await this.generateEntityReasoning(mainText, dataItem, nounType);
|
|
334
|
+
detections.push({ type: nounType, confidence, reasoning });
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (detections.length > 0) {
|
|
338
|
+
// Sort by confidence
|
|
339
|
+
detections.sort((a, b) => b.confidence - a.confidence);
|
|
340
|
+
const primaryType = detections[0];
|
|
341
|
+
const alternatives = detections.slice(1, 3); // Top 2 alternatives
|
|
342
|
+
entities.push({
|
|
343
|
+
originalData: dataItem,
|
|
344
|
+
nounType: primaryType.type,
|
|
345
|
+
confidence: primaryType.confidence,
|
|
346
|
+
suggestedId: this.generateSmartId(dataItem, primaryType.type, index),
|
|
347
|
+
reasoning: primaryType.reasoning,
|
|
348
|
+
alternativeTypes: alternatives
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return entities;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Calculate entity type confidence using AI
|
|
356
|
+
*/
|
|
357
|
+
async calculateEntityTypeConfidence(text, data, nounType) {
|
|
358
|
+
// Base semantic similarity using search
|
|
359
|
+
const searchResults = await this.brainy.search(text + ' ' + nounType, 1);
|
|
360
|
+
const textSimilarity = searchResults.length > 0 ? searchResults[0].score : 0.5;
|
|
361
|
+
// Field-based confidence boost
|
|
362
|
+
const fieldBoost = this.calculateFieldBasedConfidence(data, nounType);
|
|
363
|
+
// Pattern-based confidence boost
|
|
364
|
+
const patternBoost = this.calculatePatternBasedConfidence(text, data, nounType);
|
|
365
|
+
// Combine confidences with weights
|
|
366
|
+
const combined = (textSimilarity * 0.5) + (fieldBoost * 0.3) + (patternBoost * 0.2);
|
|
367
|
+
return Math.min(combined, 1.0);
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Field-based confidence calculation
|
|
371
|
+
*/
|
|
372
|
+
calculateFieldBasedConfidence(data, nounType) {
|
|
373
|
+
const fields = Object.keys(data);
|
|
374
|
+
let boost = 0;
|
|
375
|
+
// Field patterns that boost confidence for specific noun types
|
|
376
|
+
const fieldPatterns = {
|
|
377
|
+
[NounType.Person]: ['name', 'email', 'phone', 'age', 'firstname', 'lastname', 'employee'],
|
|
378
|
+
[NounType.Organization]: ['company', 'organization', 'corp', 'inc', 'ltd', 'department', 'team'],
|
|
379
|
+
[NounType.Project]: ['project', 'task', 'deadline', 'status', 'milestone', 'deliverable'],
|
|
380
|
+
[NounType.Location]: ['address', 'city', 'country', 'state', 'zip', 'location', 'coordinates'],
|
|
381
|
+
[NounType.Product]: ['product', 'price', 'sku', 'inventory', 'category', 'brand'],
|
|
382
|
+
[NounType.Event]: ['date', 'time', 'venue', 'event', 'meeting', 'conference', 'schedule']
|
|
383
|
+
};
|
|
384
|
+
const relevantPatterns = fieldPatterns[nounType] || [];
|
|
385
|
+
for (const field of fields) {
|
|
386
|
+
for (const pattern of relevantPatterns) {
|
|
387
|
+
if (field.toLowerCase().includes(pattern)) {
|
|
388
|
+
boost += 0.1;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return Math.min(boost, 0.5);
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Pattern-based confidence calculation
|
|
396
|
+
*/
|
|
397
|
+
calculatePatternBasedConfidence(text, data, nounType) {
|
|
398
|
+
let boost = 0;
|
|
399
|
+
// Content patterns that indicate entity types
|
|
400
|
+
const patterns = {
|
|
401
|
+
[NounType.Person]: [
|
|
402
|
+
/@.*\.com/i, // Email pattern
|
|
403
|
+
/\b[A-Z][a-z]+ [A-Z][a-z]+\b/, // Name pattern
|
|
404
|
+
/Mr\.|Mrs\.|Dr\.|Prof\./i // Title pattern
|
|
405
|
+
],
|
|
406
|
+
[NounType.Organization]: [
|
|
407
|
+
/\bInc\.|Corp\.|LLC\.|Ltd\./i, // Corporate suffixes
|
|
408
|
+
/Company|Corporation|Enterprise/i
|
|
409
|
+
],
|
|
410
|
+
[NounType.Location]: [
|
|
411
|
+
/\b\d{5}(-\d{4})?\b/, // ZIP code
|
|
412
|
+
/Street|Ave|Road|Blvd/i
|
|
413
|
+
]
|
|
414
|
+
};
|
|
415
|
+
const relevantPatterns = patterns[nounType] || [];
|
|
416
|
+
for (const pattern of relevantPatterns) {
|
|
417
|
+
if (pattern.test(text)) {
|
|
418
|
+
boost += 0.15;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return Math.min(boost, 0.3);
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Generate reasoning for entity type selection
|
|
425
|
+
*/
|
|
426
|
+
async generateEntityReasoning(text, data, nounType) {
|
|
427
|
+
const reasons = [];
|
|
428
|
+
// Semantic similarity reason
|
|
429
|
+
const searchResults = await this.brainy.search(text + ' ' + nounType, 1);
|
|
430
|
+
const similarity = searchResults.length > 0 ? searchResults[0].score : 0.5;
|
|
431
|
+
if (similarity > 0.7) {
|
|
432
|
+
reasons.push(`High semantic similarity (${(similarity * 100).toFixed(1)}%)`);
|
|
433
|
+
}
|
|
434
|
+
// Field-based reasons
|
|
435
|
+
const relevantFields = this.getRelevantFields(data, nounType);
|
|
436
|
+
if (relevantFields.length > 0) {
|
|
437
|
+
reasons.push(`Contains ${nounType}-specific fields: ${relevantFields.join(', ')}`);
|
|
438
|
+
}
|
|
439
|
+
// Pattern-based reasons
|
|
440
|
+
const matchedPatterns = this.getMatchedPatterns(text, data, nounType);
|
|
441
|
+
if (matchedPatterns.length > 0) {
|
|
442
|
+
reasons.push(`Matches ${nounType} patterns: ${matchedPatterns.join(', ')}`);
|
|
443
|
+
}
|
|
444
|
+
return reasons.length > 0 ? reasons.join('; ') : 'General semantic match';
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Neural Relationship Detection
|
|
448
|
+
*/
|
|
449
|
+
async detectRelationshipsWithNeuralAnalysis(entities, rawData, config = this.config) {
|
|
450
|
+
const relationships = [];
|
|
451
|
+
const verbTypes = Object.values(VerbType);
|
|
452
|
+
// For each pair of entities, test relationship possibilities
|
|
453
|
+
for (let i = 0; i < entities.length; i++) {
|
|
454
|
+
for (let j = i + 1; j < entities.length; j++) {
|
|
455
|
+
const sourceEntity = entities[i];
|
|
456
|
+
const targetEntity = entities[j];
|
|
457
|
+
// Extract context for relationship detection
|
|
458
|
+
const context = this.extractRelationshipContext(sourceEntity.originalData, targetEntity.originalData, rawData);
|
|
459
|
+
// Test all verb types
|
|
460
|
+
for (const verbType of verbTypes) {
|
|
461
|
+
const confidence = await this.calculateRelationshipConfidence(sourceEntity, targetEntity, verbType, context);
|
|
462
|
+
if (confidence >= config.confidenceThreshold - 0.1) { // Slightly lower threshold for relationships
|
|
463
|
+
const weight = config.enableWeights ?
|
|
464
|
+
this.calculateRelationshipWeight(sourceEntity, targetEntity, verbType, context) :
|
|
465
|
+
0.5;
|
|
466
|
+
const reasoning = await this.generateRelationshipReasoning(sourceEntity, targetEntity, verbType, context);
|
|
467
|
+
relationships.push({
|
|
468
|
+
sourceId: sourceEntity.suggestedId,
|
|
469
|
+
targetId: targetEntity.suggestedId,
|
|
470
|
+
verbType,
|
|
471
|
+
confidence,
|
|
472
|
+
weight,
|
|
473
|
+
reasoning,
|
|
474
|
+
context,
|
|
475
|
+
metadata: this.extractRelationshipMetadata(sourceEntity.originalData, targetEntity.originalData, verbType)
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
// Sort by confidence and remove duplicates/conflicts
|
|
482
|
+
return this.pruneRelationships(relationships);
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Calculate relationship confidence
|
|
486
|
+
*/
|
|
487
|
+
async calculateRelationshipConfidence(source, target, verbType, context) {
|
|
488
|
+
// Semantic similarity between entities and verb type
|
|
489
|
+
const relationshipText = `${this.extractMainText(source.originalData)} ${verbType} ${this.extractMainText(target.originalData)}`;
|
|
490
|
+
const directResults = await this.brainy.search(relationshipText, 1);
|
|
491
|
+
const directSimilarity = directResults.length > 0 ? directResults[0].score : 0.5;
|
|
492
|
+
// Context-based similarity
|
|
493
|
+
const contextResults = await this.brainy.search(context + ' ' + verbType, 1);
|
|
494
|
+
const contextSimilarity = contextResults.length > 0 ? contextResults[0].score : 0.5;
|
|
495
|
+
// Entity type compatibility
|
|
496
|
+
const typeCompatibility = this.calculateTypeCompatibility(source.nounType, target.nounType, verbType);
|
|
497
|
+
// Combine with weights
|
|
498
|
+
return (directSimilarity * 0.4) + (contextSimilarity * 0.4) + (typeCompatibility * 0.2);
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Calculate relationship weight/strength
|
|
502
|
+
*/
|
|
503
|
+
calculateRelationshipWeight(source, target, verbType, context) {
|
|
504
|
+
let weight = 0.5; // Base weight
|
|
505
|
+
// Context richness (more descriptive = stronger)
|
|
506
|
+
const contextWords = context.split(' ').length;
|
|
507
|
+
weight += Math.min(contextWords / 20, 0.2);
|
|
508
|
+
// Entity importance (higher confidence entities = stronger relationships)
|
|
509
|
+
const avgEntityConfidence = (source.confidence + target.confidence) / 2;
|
|
510
|
+
weight += avgEntityConfidence * 0.2;
|
|
511
|
+
// Verb type specificity (more specific verbs = stronger)
|
|
512
|
+
const verbSpecificity = this.getVerbSpecificity(verbType);
|
|
513
|
+
weight += verbSpecificity * 0.1;
|
|
514
|
+
return Math.min(weight, 1.0);
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Generate Neural Insights - The Intelligence Layer
|
|
518
|
+
*/
|
|
519
|
+
async generateCortexInsights(entities, relationships) {
|
|
520
|
+
const insights = [];
|
|
521
|
+
// Detect hierarchies
|
|
522
|
+
const hierarchies = this.detectHierarchies(relationships);
|
|
523
|
+
hierarchies.forEach(hierarchy => {
|
|
524
|
+
insights.push({
|
|
525
|
+
type: 'hierarchy',
|
|
526
|
+
description: `Detected ${hierarchy.type} hierarchy with ${hierarchy.levels} levels`,
|
|
527
|
+
confidence: hierarchy.confidence,
|
|
528
|
+
affectedEntities: hierarchy.entities,
|
|
529
|
+
recommendation: `Consider visualizing the ${hierarchy.type} structure`
|
|
530
|
+
});
|
|
531
|
+
});
|
|
532
|
+
// Detect clusters
|
|
533
|
+
const clusters = this.detectClusters(entities, relationships);
|
|
534
|
+
clusters.forEach(cluster => {
|
|
535
|
+
insights.push({
|
|
536
|
+
type: 'cluster',
|
|
537
|
+
description: `Found cluster of ${cluster.size} ${cluster.primaryType} entities`,
|
|
538
|
+
confidence: cluster.confidence,
|
|
539
|
+
affectedEntities: cluster.entities,
|
|
540
|
+
recommendation: `These ${cluster.primaryType}s might form a natural grouping`
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
// Detect patterns
|
|
544
|
+
const patterns = this.detectPatterns(relationships);
|
|
545
|
+
patterns.forEach(pattern => {
|
|
546
|
+
insights.push({
|
|
547
|
+
type: 'pattern',
|
|
548
|
+
description: `Common relationship pattern: ${pattern.description}`,
|
|
549
|
+
confidence: pattern.confidence,
|
|
550
|
+
affectedEntities: pattern.entities,
|
|
551
|
+
recommendation: pattern.recommendation
|
|
552
|
+
});
|
|
553
|
+
});
|
|
554
|
+
return insights;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Helper methods for the neural system
|
|
558
|
+
*/
|
|
559
|
+
extractMainText(data) {
|
|
560
|
+
// Extract the most relevant text from a data object
|
|
561
|
+
const textFields = ['name', 'title', 'description', 'content', 'text', 'label'];
|
|
562
|
+
for (const field of textFields) {
|
|
563
|
+
if (data[field] && typeof data[field] === 'string') {
|
|
564
|
+
return data[field];
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
// Fallback: concatenate all string values
|
|
568
|
+
return Object.values(data)
|
|
569
|
+
.filter(v => typeof v === 'string')
|
|
570
|
+
.join(' ')
|
|
571
|
+
.substring(0, 200); // Limit length
|
|
572
|
+
}
|
|
573
|
+
generateSmartId(data, nounType, index) {
|
|
574
|
+
const mainText = this.extractMainText(data);
|
|
575
|
+
const cleanText = mainText.toLowerCase().replace(/[^a-z0-9]/g, '_').substring(0, 20);
|
|
576
|
+
return `${nounType}_${cleanText}_${index}`;
|
|
577
|
+
}
|
|
578
|
+
extractRelationshipContext(source, target, allData) {
|
|
579
|
+
// Extract context for relationship detection
|
|
580
|
+
return [
|
|
581
|
+
this.extractMainText(source),
|
|
582
|
+
this.extractMainText(target),
|
|
583
|
+
// Add more contextual information
|
|
584
|
+
].join(' ');
|
|
585
|
+
}
|
|
586
|
+
calculateTypeCompatibility(sourceType, targetType, verbType) {
|
|
587
|
+
// Define type compatibility matrix for relationships
|
|
588
|
+
const compatibilityMatrix = {
|
|
589
|
+
[NounType.Person]: {
|
|
590
|
+
[NounType.Organization]: [VerbType.MemberOf, VerbType.WorksWith],
|
|
591
|
+
[NounType.Project]: [VerbType.WorksWith, VerbType.Creates],
|
|
592
|
+
[NounType.Person]: [VerbType.WorksWith, VerbType.Mentors, VerbType.ReportsTo]
|
|
593
|
+
}
|
|
594
|
+
// Add more compatibility rules
|
|
595
|
+
};
|
|
596
|
+
const sourceCompatibility = compatibilityMatrix[sourceType];
|
|
597
|
+
if (sourceCompatibility && sourceCompatibility[targetType]) {
|
|
598
|
+
return sourceCompatibility[targetType].includes(verbType) ? 1.0 : 0.3;
|
|
599
|
+
}
|
|
600
|
+
return 0.5; // Default compatibility
|
|
601
|
+
}
|
|
602
|
+
getVerbSpecificity(verbType) {
|
|
603
|
+
// More specific verbs get higher scores
|
|
604
|
+
const specificityScores = {
|
|
605
|
+
[VerbType.RelatedTo]: 0.1, // Very generic
|
|
606
|
+
[VerbType.WorksWith]: 0.7, // Specific
|
|
607
|
+
[VerbType.Mentors]: 0.9, // Very specific
|
|
608
|
+
[VerbType.ReportsTo]: 0.9, // Very specific
|
|
609
|
+
[VerbType.Supervises]: 0.9 // Very specific
|
|
610
|
+
};
|
|
611
|
+
return specificityScores[verbType] || 0.5;
|
|
612
|
+
}
|
|
613
|
+
getRelevantFields(data, nounType) {
|
|
614
|
+
// Implementation for finding relevant fields
|
|
615
|
+
return [];
|
|
616
|
+
}
|
|
617
|
+
getMatchedPatterns(text, data, nounType) {
|
|
618
|
+
// Implementation for finding matched patterns
|
|
619
|
+
return [];
|
|
620
|
+
}
|
|
621
|
+
pruneRelationships(relationships) {
|
|
622
|
+
// Remove duplicates and low-confidence relationships
|
|
623
|
+
return relationships
|
|
624
|
+
.sort((a, b) => b.confidence - a.confidence)
|
|
625
|
+
.slice(0, 1000); // Limit to top 1000 relationships
|
|
626
|
+
}
|
|
627
|
+
detectHierarchies(relationships) {
|
|
628
|
+
// Detect hierarchical structures
|
|
629
|
+
return [];
|
|
630
|
+
}
|
|
631
|
+
detectClusters(entities, relationships) {
|
|
632
|
+
// Detect entity clusters
|
|
633
|
+
return [];
|
|
634
|
+
}
|
|
635
|
+
detectPatterns(relationships) {
|
|
636
|
+
// Detect relationship patterns
|
|
637
|
+
return [];
|
|
638
|
+
}
|
|
639
|
+
calculateOverallConfidence(entities, relationships) {
|
|
640
|
+
if (entities.length === 0)
|
|
641
|
+
return 0;
|
|
642
|
+
const entityConfidence = entities.reduce((sum, e) => sum + e.confidence, 0) / entities.length;
|
|
643
|
+
if (relationships.length === 0)
|
|
644
|
+
return entityConfidence;
|
|
645
|
+
const relationshipConfidence = relationships.reduce((sum, r) => sum + r.confidence, 0) / relationships.length;
|
|
646
|
+
return (entityConfidence + relationshipConfidence) / 2;
|
|
647
|
+
}
|
|
648
|
+
async storeNeuralAnalysis(analysis) {
|
|
649
|
+
// Store the full analysis result for later retrieval by Cortex or other systems
|
|
650
|
+
// This could be stored in the brainy instance metadata or a separate analysis store
|
|
651
|
+
}
|
|
652
|
+
getDataTypeFromPath(filePath) {
|
|
653
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
654
|
+
switch (ext) {
|
|
655
|
+
case '.json': return 'json';
|
|
656
|
+
case '.csv': return 'csv';
|
|
657
|
+
case '.yaml':
|
|
658
|
+
case '.yml': return 'yaml';
|
|
659
|
+
case '.txt': return 'text';
|
|
660
|
+
default: return 'text';
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
async generateRelationshipReasoning(source, target, verbType, context) {
|
|
664
|
+
return `Neural analysis detected ${verbType} relationship based on semantic context`;
|
|
665
|
+
}
|
|
666
|
+
extractRelationshipMetadata(sourceData, targetData, verbType) {
|
|
667
|
+
return {
|
|
668
|
+
sourceType: typeof sourceData,
|
|
669
|
+
targetType: typeof targetData,
|
|
670
|
+
detectedBy: 'neural-import-sense',
|
|
671
|
+
timestamp: new Date().toISOString()
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Assess data quality metrics
|
|
676
|
+
*/
|
|
677
|
+
assessDataQuality(parsedData, analysis) {
|
|
678
|
+
// Completeness: ratio of fields with data
|
|
679
|
+
let totalFields = 0;
|
|
680
|
+
let filledFields = 0;
|
|
681
|
+
parsedData.forEach(item => {
|
|
682
|
+
const fields = Object.keys(item);
|
|
683
|
+
totalFields += fields.length;
|
|
684
|
+
filledFields += fields.filter(field => item[field] !== null &&
|
|
685
|
+
item[field] !== undefined &&
|
|
686
|
+
item[field] !== '').length;
|
|
687
|
+
});
|
|
688
|
+
const completeness = totalFields > 0 ? filledFields / totalFields : 0;
|
|
689
|
+
// Consistency: variance in field structure
|
|
690
|
+
const fieldSets = parsedData.map(item => new Set(Object.keys(item)));
|
|
691
|
+
const allFields = new Set(fieldSets.flatMap(set => Array.from(set)));
|
|
692
|
+
let consistencyScore = 0;
|
|
693
|
+
if (fieldSets.length > 0) {
|
|
694
|
+
consistencyScore = Array.from(allFields).reduce((score, field) => {
|
|
695
|
+
const hasField = fieldSets.filter(set => set.has(field)).length;
|
|
696
|
+
return score + (hasField / fieldSets.length);
|
|
697
|
+
}, 0) / allFields.size;
|
|
698
|
+
}
|
|
699
|
+
// Accuracy: average confidence of detected entities
|
|
700
|
+
const accuracy = analysis.detectedEntities.length > 0 ?
|
|
701
|
+
analysis.detectedEntities.reduce((sum, e) => sum + e.confidence, 0) / analysis.detectedEntities.length :
|
|
702
|
+
0;
|
|
703
|
+
return {
|
|
704
|
+
completeness,
|
|
705
|
+
consistency: consistencyScore,
|
|
706
|
+
accuracy
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Generate recommendations based on analysis
|
|
711
|
+
*/
|
|
712
|
+
generateRecommendations(parsedData, analysis, entityTypes, relationshipTypes) {
|
|
713
|
+
const recommendations = [];
|
|
714
|
+
// Low entity confidence recommendations
|
|
715
|
+
const lowConfidenceEntities = entityTypes.filter(et => et.confidence < 0.7);
|
|
716
|
+
if (lowConfidenceEntities.length > 0) {
|
|
717
|
+
recommendations.push(`Consider improving field names for ${lowConfidenceEntities.map(e => e.type).join(', ')} entities`);
|
|
718
|
+
}
|
|
719
|
+
// Missing relationships recommendations
|
|
720
|
+
if (relationshipTypes.length === 0 && entityTypes.length > 1) {
|
|
721
|
+
recommendations.push('Add fields that describe how entities relate to each other');
|
|
722
|
+
}
|
|
723
|
+
// Data structure recommendations
|
|
724
|
+
if (parsedData.length > 0) {
|
|
725
|
+
const firstItem = parsedData[0];
|
|
726
|
+
const fieldCount = Object.keys(firstItem).length;
|
|
727
|
+
if (fieldCount < 3) {
|
|
728
|
+
recommendations.push('Consider adding more descriptive fields to each entity');
|
|
729
|
+
}
|
|
730
|
+
if (fieldCount > 20) {
|
|
731
|
+
recommendations.push('Consider grouping related fields or splitting complex entities');
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
// Entity distribution recommendations
|
|
735
|
+
const dominantEntityType = entityTypes.reduce((max, current) => current.count > max.count ? current : max, entityTypes[0] || { count: 0 });
|
|
736
|
+
if (dominantEntityType && dominantEntityType.count > parsedData.length * 0.8) {
|
|
737
|
+
recommendations.push(`Consider diversifying entity types - ${dominantEntityType.type} dominates the dataset`);
|
|
738
|
+
}
|
|
739
|
+
// Relationship quality recommendations
|
|
740
|
+
const lowWeightRelationships = relationshipTypes.filter(rt => rt.confidence < 0.6);
|
|
741
|
+
if (lowWeightRelationships.length > 0) {
|
|
742
|
+
recommendations.push('Consider adding more contextual information to strengthen relationship detection');
|
|
743
|
+
}
|
|
744
|
+
return recommendations;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
//# sourceMappingURL=cortexSense.js.map
|