rag-memory-epf-mcp 3.1.4 → 3.2.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/dist/index.js +40 -30
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -83,18 +83,10 @@ class RAGKnowledgeGraphManager {
|
|
|
83
83
|
console.error(`✅ ${EMBEDDING_MODEL} model loaded successfully (fp16)`);
|
|
84
84
|
}
|
|
85
85
|
catch (error) {
|
|
86
|
-
console.error('❌ Failed to load embedding model
|
|
87
|
-
|
|
88
|
-
console.error(
|
|
89
|
-
|
|
90
|
-
this.embeddingModel = await pipeline('feature-extraction', FALLBACK_MODEL, { revision: 'main' });
|
|
91
|
-
this.modelInitialized = true;
|
|
92
|
-
console.error(`✅ ${FALLBACK_MODEL} loaded (fallback — 384-dim, English-focused)`);
|
|
93
|
-
}
|
|
94
|
-
catch (retryError) {
|
|
95
|
-
console.error('❌ All embedding models failed to load. Search will not work.', retryError instanceof Error ? retryError.message : retryError);
|
|
96
|
-
this.modelInitialized = false;
|
|
97
|
-
}
|
|
86
|
+
console.error('❌ Failed to load embedding model:', error instanceof Error ? error.message : error);
|
|
87
|
+
console.error('⚠️ Semantic search will be unavailable. Other tools (CRUD, graph queries) still work.');
|
|
88
|
+
console.error('💡 Fix: Ensure ONNX model cache is accessible. Try: rm -rf ~/.npm/_onnx_models && restart.');
|
|
89
|
+
this.modelInitialized = false;
|
|
98
90
|
}
|
|
99
91
|
}
|
|
100
92
|
async runMigrations() {
|
|
@@ -1353,11 +1345,14 @@ class RAGKnowledgeGraphManager {
|
|
|
1353
1345
|
if (!document) {
|
|
1354
1346
|
throw new Error(`Document with ID ${documentId} not found`);
|
|
1355
1347
|
}
|
|
1356
|
-
// Get chunks for this document
|
|
1348
|
+
// Get chunks for this document (with text for chunk-level matching)
|
|
1357
1349
|
const chunks = this.db.prepare(`
|
|
1358
|
-
SELECT rowid FROM chunk_metadata WHERE document_id = ?
|
|
1350
|
+
SELECT rowid, text FROM chunk_metadata WHERE document_id = ?
|
|
1359
1351
|
`).all(documentId);
|
|
1360
1352
|
let linkedCount = 0;
|
|
1353
|
+
const insertStmt = this.db.prepare(`
|
|
1354
|
+
INSERT OR IGNORE INTO chunk_entities (chunk_rowid, entity_id) VALUES (?, ?)
|
|
1355
|
+
`);
|
|
1361
1356
|
for (const entityName of entityNames) {
|
|
1362
1357
|
const entityId = `entity_${entityName.toLowerCase().replace(/[^a-z0-9]/g, '_')}`;
|
|
1363
1358
|
// Verify entity exists
|
|
@@ -1368,14 +1363,17 @@ class RAGKnowledgeGraphManager {
|
|
|
1368
1363
|
console.warn(`Entity ${entityName} not found, skipping`);
|
|
1369
1364
|
continue;
|
|
1370
1365
|
}
|
|
1371
|
-
//
|
|
1366
|
+
// Chunk-level filtering: only link to chunks where entity actually appears
|
|
1367
|
+
const nameMatcher = this.buildEntityMatcher(entityName);
|
|
1368
|
+
let entityLinked = false;
|
|
1372
1369
|
for (const chunk of chunks) {
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1370
|
+
if (nameMatcher(chunk.text)) {
|
|
1371
|
+
insertStmt.run(chunk.rowid, entityId);
|
|
1372
|
+
entityLinked = true;
|
|
1373
|
+
}
|
|
1377
1374
|
}
|
|
1378
|
-
|
|
1375
|
+
if (entityLinked)
|
|
1376
|
+
linkedCount++;
|
|
1379
1377
|
}
|
|
1380
1378
|
console.error(`✅ Entities linked: ${linkedCount} entities linked to document`);
|
|
1381
1379
|
return { documentId, linkedEntities: linkedCount };
|
|
@@ -1876,42 +1874,54 @@ class RAGKnowledgeGraphManager {
|
|
|
1876
1874
|
chunkEntities = [relEntities.source_name, relEntities.target_name];
|
|
1877
1875
|
}
|
|
1878
1876
|
}
|
|
1879
|
-
// Enhanced graph boost calculation
|
|
1877
|
+
// Enhanced graph boost calculation with decay + cap
|
|
1880
1878
|
let graphBoost = 0;
|
|
1881
1879
|
if (useGraph) {
|
|
1882
1880
|
const queryEntities = this.extractTermsFromText(query);
|
|
1883
1881
|
// Base boost for knowledge graph chunks
|
|
1884
1882
|
if (result.chunk_type === 'entity') {
|
|
1885
|
-
graphBoost += 0.15;
|
|
1883
|
+
graphBoost += 0.15;
|
|
1886
1884
|
}
|
|
1887
1885
|
else if (result.chunk_type === 'relationship') {
|
|
1888
|
-
graphBoost += 0.25;
|
|
1886
|
+
graphBoost += 0.25;
|
|
1889
1887
|
}
|
|
1890
|
-
//
|
|
1888
|
+
// Collect per-entity scores (instead of blind accumulation)
|
|
1889
|
+
const entityScores = [];
|
|
1891
1890
|
const queryLower = query.toLowerCase();
|
|
1892
1891
|
for (const entity of chunkEntities) {
|
|
1892
|
+
let score = 0;
|
|
1893
1893
|
const entityLower = entity.toLowerCase();
|
|
1894
1894
|
// Vector-matched entity (cross-lingual: "할랄 인증" → "KMF")
|
|
1895
1895
|
if (queryMatchedEntities.has(entity)) {
|
|
1896
|
-
|
|
1896
|
+
score = 0.3;
|
|
1897
1897
|
}
|
|
1898
1898
|
// Exact text match with extracted terms
|
|
1899
1899
|
else if (queryEntities.some(qe => qe.toLowerCase() === entityLower)) {
|
|
1900
|
-
|
|
1900
|
+
score = 0.3;
|
|
1901
1901
|
}
|
|
1902
1902
|
// Partial match: entity name appears in query or vice versa
|
|
1903
1903
|
else if (queryLower.includes(entityLower) || entityLower.includes(queryLower)) {
|
|
1904
|
-
|
|
1904
|
+
score = 0.2;
|
|
1905
1905
|
}
|
|
1906
1906
|
// Word-level partial match
|
|
1907
1907
|
else if (entityLower.split(/\s+/).some(word => word.length >= 3 && queryLower.includes(word))) {
|
|
1908
|
-
|
|
1908
|
+
score = 0.15;
|
|
1909
1909
|
}
|
|
1910
|
-
// Connected to a vector-matched entity
|
|
1910
|
+
// Connected to a vector-matched entity (additive, independent)
|
|
1911
1911
|
if (connectedEntities.has(entity)) {
|
|
1912
|
-
|
|
1912
|
+
score += 0.15;
|
|
1913
1913
|
}
|
|
1914
|
+
if (score > 0)
|
|
1915
|
+
entityScores.push(score);
|
|
1916
|
+
}
|
|
1917
|
+
// Geometric decay: sort descending, apply 0.5^i decay per entity
|
|
1918
|
+
entityScores.sort((a, b) => b - a);
|
|
1919
|
+
let entityBoost = 0;
|
|
1920
|
+
for (let i = 0; i < entityScores.length; i++) {
|
|
1921
|
+
entityBoost += entityScores[i] * Math.pow(0.5, i);
|
|
1914
1922
|
}
|
|
1923
|
+
// Hard cap to prevent graph domination
|
|
1924
|
+
graphBoost += Math.min(entityBoost, 0.4);
|
|
1915
1925
|
}
|
|
1916
1926
|
// Generate semantic summary
|
|
1917
1927
|
const { summary, keyHighlight, relevanceScore } = await this.generateContentSummary(result.text, primaryQueryEmbedding, chunkEntities, result.chunk_type === 'relationship' ? 1 : 2 // Shorter summary for relationships
|