Spaces:
Paused
Paused
File size: 5,338 Bytes
529090e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | import { neo4jService } from '../database/Neo4jService.js';
import { neuralStream, NeuralEvent } from './NeuralStream.js';
import { metricsService } from './MetricsService.js';
export interface KnowledgePacket {
title: string;
content: string;
source: string;
category: string;
tags: string[];
}
class KnowledgeAcquisitionService {
private static instance: KnowledgeAcquisitionService;
private constructor() {
console.log('🧠 [KnowledgeAcquisition] Cortex Ingestor Online.');
this.setupNeuralListeners();
}
public static getInstance(): KnowledgeAcquisitionService {
if (!KnowledgeAcquisitionService.instance) {
KnowledgeAcquisitionService.instance = new KnowledgeAcquisitionService();
}
return KnowledgeAcquisitionService.instance;
}
/**
* Lytter på nervesystemet efter ny viden fra OmniHarvester eller andre agenter
*/
private setupNeuralListeners() {
// Når OmniHarvester har fundet noget (SYSTEM_HEALED med context 'ActiveLearning')
// eller når vi manuelt pusher viden.
neuralStream.on('KNOWLEDGE_INGEST_REQ', async (event: NeuralEvent) => {
console.log('📥 [Acquisition] Receiving knowledge stream...', event.payload.title);
await this.ingestKnowledge(event.payload as unknown as KnowledgePacket);
});
}
/**
* KERNE-LOGIK: Konverterer rå tekst til Graf-Struktur
* Dette er "Memory Consolidation" processen.
*/
public async ingestKnowledge(packet: KnowledgePacket): Promise<boolean> {
const startTime = Date.now();
try {
// 1. Opret selve videns-noden (Fact / Document)
// Vi bruger MERGE for at undgå duplikater baseret på titel/source
const cypher = `
MERGE (k:Knowledge {title: $title})
SET k.content = $content,
k.source = $source,
k.category = $category,
k.ingestedAt = datetime(),
k.hash = $hash
// 2. Opret kategori-struktur
MERGE (c:Category {name: $category})
MERGE (k)-[:BELONGS_TO]->(c)
// 3. Auto-Tagging (Opretter tags og linker dem)
FOREACH (tagName IN $tags |
MERGE (t:Tag {name: tagName})
MERGE (k)-[:TAGGED_WITH]->(t)
)
`;
// Simpel hash for integritet
const hash = Buffer.from(packet.title + packet.source).toString('base64');
await neo4jService.runQuery(cypher, {
title: packet.title,
content: packet.content,
source: packet.source,
category: packet.category || 'General',
tags: packet.tags || [],
hash
});
// 4. THE MAGIC: Semantic Auto-Linking
// Vi søger efter eksisterende noder, der nævnes i den nye tekst, og linker dem.
await this.createSemanticLinks(packet.title, packet.content);
// 5. Metrics & Feedback
const duration = Date.now() - startTime;
metricsService.incrementCounter('knowledge_ingested');
console.log(`✅ [Acquisition] Absorbed: "${packet.title}" in ${duration}ms`);
neuralStream.emitEvent('SYSTEM_HEALED', 'LOW', {
action: 'MEMORY_CONSOLIDATED',
target: packet.title
}, 'KnowledgeAcquisition');
return true;
} catch (error) {
console.error('❌ [Acquisition] Failed to ingest:', error);
return false;
}
}
/**
* Finder andre noder i grafen, der nævnes i denne tekst, og skaber relationer.
* Dette gør grafen "tættere" og klogere over tid.
*/
private async createSemanticLinks(nodeTitle: string, content: string) {
// Find noder (Personer, Tech, Threats) hvis navne optræder i den nye tekst
// Undgå at linke til sig selv
const linkCypher = `
MATCH (k:Knowledge {title: $title})
MATCH (other)
WHERE other <> k
AND (other:Person OR other:Technology OR other:Threat OR other:Organization)
AND size(other.name) > 3 // Ignorer støj
AND $content CONTAINS other.name
MERGE (k)-[:MENTIONS]->(other)
RETURN count(other) as links
`;
const result = await neo4jService.runQuery(linkCypher, {
title: nodeTitle,
content: content
});
const linksCreated = (result[0]?.links as any)?.toNumber?.() || 0;
if (linksCreated > 0) {
console.log(`🔗 [Acquisition] Auto-linked "${nodeTitle}" to ${linksCreated} existing concepts.`);
}
}
// Stubs for backward compatibility
public async acquire(params: any): Promise<any> { return { success: false, message: 'Deprecated' }; }
public async batchAcquire(params: any): Promise<any> { return []; }
public async semanticSearch(query: string, limit: number): Promise<any> { return []; }
public async getVectorStats(): Promise<any> { return { totalRecords: 0 }; }
public async acquireFromTargets(ids?: string[]): Promise<any> { return []; }
public async acquireSingleTarget(id: string): Promise<any> { return null; }
}
export const knowledgeAcquisition = KnowledgeAcquisitionService.getInstance();
|