n8n-nodes-engram 0.2.2 → 0.2.4
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 +22 -6
- package/dist/extraction/ContradictionDetector.d.ts +1 -1
- package/dist/extraction/ContradictionDetector.js +2 -2
- package/dist/extraction/ContradictionDetector.js.map +1 -1
- package/dist/extraction/EdgeDeduplicator.d.ts +13 -0
- package/dist/extraction/EdgeDeduplicator.js +52 -0
- package/dist/extraction/EdgeDeduplicator.js.map +1 -0
- package/dist/extraction/ExtractionPipeline.d.ts +3 -0
- package/dist/extraction/ExtractionPipeline.js +89 -9
- package/dist/extraction/ExtractionPipeline.js.map +1 -1
- package/dist/extraction/prompts.d.ts +5 -1
- package/dist/extraction/prompts.js +75 -9
- package/dist/extraction/prompts.js.map +1 -1
- package/dist/nodes/EngramAdmin/EngramAdmin.node.js +511 -399
- package/dist/nodes/EngramAdmin/EngramAdmin.node.js.map +1 -1
- package/dist/nodes/EngramExplorer/EngramExplorer.node.js +143 -3
- package/dist/nodes/EngramExplorer/EngramExplorer.node.js.map +1 -1
- package/dist/search/HybridSearchEngine.d.ts +7 -11
- package/dist/search/HybridSearchEngine.js +6 -0
- package/dist/search/HybridSearchEngine.js.map +1 -1
- package/dist/storage/GraphologyStorage.d.ts +5 -1
- package/dist/storage/GraphologyStorage.js +84 -0
- package/dist/storage/GraphologyStorage.js.map +1 -1
- package/dist/storage/IGraphStorage.d.ts +19 -0
- package/dist/storage/Neo4jStorage.d.ts +5 -1
- package/dist/storage/Neo4jStorage.js +122 -6
- package/dist/storage/Neo4jStorage.js.map +1 -1
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.js.map +1 -1
- package/dist/utils/logWrapper.js.map +1 -1
- package/dist/utils/temporal.d.ts +1 -0
- package/dist/utils/temporal.js +11 -0
- package/dist/utils/temporal.js.map +1 -1
- package/package.json +4 -6
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ Every conversation is stored as an episode. An optional LLM extraction pipeline
|
|
|
53
53
|
| **2** | Storage Backends | Embedded (zero-setup) or Neo4j (production) |
|
|
54
54
|
| **5** | Extraction Stages | Entity, dedup, relationships, contradictions, embeddings |
|
|
55
55
|
| **3** | Search Modes | Full-text, vector, hybrid RRF fusion |
|
|
56
|
-
| **
|
|
56
|
+
| **198** | Tests | Unit + integration across 19 test suites |
|
|
57
57
|
|
|
58
58
|
---
|
|
59
59
|
|
|
@@ -136,21 +136,21 @@ On each conversation turn, Engram Memory:
|
|
|
136
136
|
| Resource | Operations |
|
|
137
137
|
| --- | --- |
|
|
138
138
|
| **Entity** | Create, Get, Get by Name, List, Search, Update, Delete |
|
|
139
|
-
| **Relationship** | Create, Get, Get Between, Get for Entity, Search, Update, Delete |
|
|
140
|
-
| **Episode** | Get, Get Recent, Get Count |
|
|
139
|
+
| **Relationship** | Create, Get, Get Between, Get for Entity, Search, Update, Delete, Get Changelog |
|
|
140
|
+
| **Episode** | Get, Get Recent, Get by Date Range, Get Count |
|
|
141
141
|
| **Traversal** | BFS from Entity, BFS from Episodes |
|
|
142
142
|
|
|
143
143
|
### Engram Admin
|
|
144
144
|
|
|
145
145
|
> Regular node—administration and analysis.
|
|
146
146
|
|
|
147
|
-
|
|
|
147
|
+
| Resource | Operations |
|
|
148
148
|
| --- | --- |
|
|
149
149
|
| **Monitoring** | Stats, List Groups, Group Stats |
|
|
150
|
-
| **Lifecycle** | Apply Retention, Clear Group, Bulk Clear, Clear All |
|
|
150
|
+
| **Lifecycle** | Apply Retention, Clear Group, Bulk Clear Groups, Clear All |
|
|
151
151
|
| **Hygiene** | Orphaned Entities, Duplicate Entities, Expire Stale Edges |
|
|
152
|
+
| **Portability** | Export, Import |
|
|
152
153
|
| **Analysis** | Detect Communities |
|
|
153
|
-
| **Portability** | Export (JSON), Import (JSON) |
|
|
154
154
|
|
|
155
155
|
### Engram Trigger
|
|
156
156
|
|
|
@@ -206,6 +206,22 @@ User message + AI response
|
|
|
206
206
|
|
|
207
207
|
Hybrid search automatically activates when both text and vector search are available.
|
|
208
208
|
|
|
209
|
+
All search operations support optional **temporal filters** (`valid_after`, `valid_before`, `created_after`, `created_before`) to scope results by time.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Temporal Queries
|
|
214
|
+
|
|
215
|
+
Engram tracks when facts are valid (`valid_at`, `invalid_at`) and when they were superseded (`expired_at`). You can query the graph by time:
|
|
216
|
+
|
|
217
|
+
| Operation | Node | Description |
|
|
218
|
+
| --- | --- | --- |
|
|
219
|
+
| **Get by Date Range** | Explorer > Episode | Retrieve episodes within a time window by `reference_time` |
|
|
220
|
+
| **Get Changelog** | Explorer > Relationship | Get recently created, expired, or invalidated relationships since a given date |
|
|
221
|
+
| **Search with date filters** | Explorer > Entity/Relationship Search | Filter search results by `valid_after`, `valid_before`, or `created_after` |
|
|
222
|
+
|
|
223
|
+
Date parameters use ISO 8601 format (e.g. `2026-01-15T00:00:00.000Z`). The LLM agent can convert natural language like "last week" into concrete dates before calling these operations.
|
|
224
|
+
|
|
209
225
|
---
|
|
210
226
|
|
|
211
227
|
## Community Detection
|
|
@@ -7,5 +7,5 @@ export interface ContradictionResolution {
|
|
|
7
7
|
export declare class ContradictionDetector {
|
|
8
8
|
private llm;
|
|
9
9
|
constructor(llm: LlmClient);
|
|
10
|
-
detect(existingFact: string, newFact: string, sourceEntity: string, targetEntity: string): Promise<ContradictionResolution>;
|
|
10
|
+
detect(existingFact: string, newFact: string, sourceEntity: string, targetEntity: string, existingEdgeName?: string, newEdgeName?: string): Promise<ContradictionResolution>;
|
|
11
11
|
}
|
|
@@ -7,13 +7,13 @@ class ContradictionDetector {
|
|
|
7
7
|
constructor(llm) {
|
|
8
8
|
this.llm = llm;
|
|
9
9
|
}
|
|
10
|
-
async detect(existingFact, newFact, sourceEntity, targetEntity) {
|
|
10
|
+
async detect(existingFact, newFact, sourceEntity, targetEntity, existingEdgeName, newEdgeName) {
|
|
11
11
|
try {
|
|
12
12
|
const result = await this.llm.chatJson([
|
|
13
13
|
{ role: 'system', content: prompts_1.CONTRADICTION_SYSTEM },
|
|
14
14
|
{
|
|
15
15
|
role: 'user',
|
|
16
|
-
content: (0, prompts_1.contradictionUser)(existingFact, newFact, sourceEntity, targetEntity),
|
|
16
|
+
content: (0, prompts_1.contradictionUser)(existingFact, newFact, sourceEntity, targetEntity, existingEdgeName, newEdgeName),
|
|
17
17
|
},
|
|
18
18
|
]);
|
|
19
19
|
if (result.is_contradiction) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContradictionDetector.js","sourceRoot":"","sources":["../../src/extraction/ContradictionDetector.ts"],"names":[],"mappings":";;;AACA,uCAAoE;AACpE,gDAA2C;AAc3C,MAAa,qBAAqB;IAGhC,YAAY,GAAc;QACxB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAMD,KAAK,CAAC,MAAM,CACV,YAAoB,EACpB,OAAe,EACf,YAAoB,EACpB,YAAoB;QAEpB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAsB;gBAC1D,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,8BAAoB,EAAE;gBACjD;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,IAAA,2BAAiB,
|
|
1
|
+
{"version":3,"file":"ContradictionDetector.js","sourceRoot":"","sources":["../../src/extraction/ContradictionDetector.ts"],"names":[],"mappings":";;;AACA,uCAAoE;AACpE,gDAA2C;AAc3C,MAAa,qBAAqB;IAGhC,YAAY,GAAc;QACxB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAMD,KAAK,CAAC,MAAM,CACV,YAAoB,EACpB,OAAe,EACf,YAAoB,EACpB,YAAoB,EACpB,gBAAyB,EACzB,WAAoB;QAEpB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAsB;gBAC1D,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,8BAAoB,EAAE;gBACjD;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,IAAA,2BAAiB,EACxB,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,WAAW,CACZ;iBACF;aACF,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;gBAC5B,OAAO;oBACL,eAAe,EAAE,IAAI;oBACrB,WAAW,EAAE,MAAM,CAAC,WAAW;oBAC/B,SAAS,EAAE,IAAA,iBAAM,GAAE;iBACpB,CAAC;YACJ,CAAC;YAED,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAEf,OAAO,CAAC,IAAI,CAAC,yCAAyC,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;YAClF,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;QACpC,CAAC;IACH,CAAC;CACF;AAlDD,sDAkDC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LlmClient } from './LlmClient';
|
|
2
|
+
export declare class EdgeDeduplicator {
|
|
3
|
+
private llm;
|
|
4
|
+
constructor(llm: LlmClient);
|
|
5
|
+
isDuplicate(existingFact: string, newFact: string, edgeName: string, sourceEntity: string, targetEntity: string): Promise<{
|
|
6
|
+
isDuplicate: boolean;
|
|
7
|
+
mergedFact?: string;
|
|
8
|
+
}>;
|
|
9
|
+
isDuplicateCrossName(existingFact: string, newFact: string, existingEdgeName: string, newEdgeName: string, sourceEntity: string, targetEntity: string): Promise<{
|
|
10
|
+
isDuplicate: boolean;
|
|
11
|
+
mergedFact?: string;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EdgeDeduplicator = void 0;
|
|
4
|
+
const prompts_1 = require("./prompts");
|
|
5
|
+
class EdgeDeduplicator {
|
|
6
|
+
constructor(llm) {
|
|
7
|
+
this.llm = llm;
|
|
8
|
+
}
|
|
9
|
+
async isDuplicate(existingFact, newFact, edgeName, sourceEntity, targetEntity) {
|
|
10
|
+
if (existingFact.toLowerCase().trim() === newFact.toLowerCase().trim()) {
|
|
11
|
+
return { isDuplicate: true };
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
const result = await this.llm.chatJson([
|
|
15
|
+
{ role: 'system', content: prompts_1.EDGE_DEDUP_SYSTEM },
|
|
16
|
+
{
|
|
17
|
+
role: 'user',
|
|
18
|
+
content: (0, prompts_1.edgeDedupUser)(existingFact, newFact, edgeName, sourceEntity, targetEntity),
|
|
19
|
+
},
|
|
20
|
+
]);
|
|
21
|
+
return {
|
|
22
|
+
isDuplicate: result.is_duplicate === true,
|
|
23
|
+
mergedFact: result.is_duplicate ? result.merged_fact : undefined,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.warn('Engram: Edge deduplication failed:', error.message);
|
|
28
|
+
return { isDuplicate: false };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async isDuplicateCrossName(existingFact, newFact, existingEdgeName, newEdgeName, sourceEntity, targetEntity) {
|
|
32
|
+
try {
|
|
33
|
+
const result = await this.llm.chatJson([
|
|
34
|
+
{ role: 'system', content: prompts_1.CROSS_NAME_EDGE_DEDUP_SYSTEM },
|
|
35
|
+
{
|
|
36
|
+
role: 'user',
|
|
37
|
+
content: (0, prompts_1.crossNameEdgeDedupUser)(existingFact, newFact, existingEdgeName, newEdgeName, sourceEntity, targetEntity),
|
|
38
|
+
},
|
|
39
|
+
]);
|
|
40
|
+
return {
|
|
41
|
+
isDuplicate: result.is_duplicate === true,
|
|
42
|
+
mergedFact: result.is_duplicate ? result.merged_fact : undefined,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.warn('Engram: Cross-name edge deduplication failed:', error.message);
|
|
47
|
+
return { isDuplicate: false };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.EdgeDeduplicator = EdgeDeduplicator;
|
|
52
|
+
//# sourceMappingURL=EdgeDeduplicator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EdgeDeduplicator.js","sourceRoot":"","sources":["../../src/extraction/EdgeDeduplicator.ts"],"names":[],"mappings":";;;AACA,uCAKmB;AAOnB,MAAa,gBAAgB;IAG3B,YAAY,GAAc;QACxB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAMD,KAAK,CAAC,WAAW,CACf,YAAoB,EACpB,OAAe,EACf,QAAgB,EAChB,YAAoB,EACpB,YAAoB;QAGpB,IAAI,YAAY,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;YACvE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QAC/B,CAAC;QAGD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAkB;gBACtD,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAAiB,EAAE;gBAC9C;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,IAAA,uBAAa,EAAC,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,CAAC;iBACpF;aACF,CAAC,CAAC;YAEH,OAAO;gBACL,WAAW,EAAE,MAAM,CAAC,YAAY,KAAK,IAAI;gBACzC,UAAU,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;aACjE,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAEf,OAAO,CAAC,IAAI,CAAC,oCAAoC,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;YAC7E,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QAChC,CAAC;IACH,CAAC;IAYD,KAAK,CAAC,oBAAoB,CACxB,YAAoB,EACpB,OAAe,EACf,gBAAwB,EACxB,WAAmB,EACnB,YAAoB,EACpB,YAAoB;QAEpB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAkB;gBACtD,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,sCAA4B,EAAE;gBACzD;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,IAAA,gCAAsB,EAC7B,YAAY,EACZ,OAAO,EACP,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,YAAY,CACb;iBACF;aACF,CAAC,CAAC;YAEH,OAAO;gBACL,WAAW,EAAE,MAAM,CAAC,YAAY,KAAK,IAAI;gBACzC,UAAU,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;aACjE,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAEf,OAAO,CAAC,IAAI,CAAC,+CAA+C,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;YACxF,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QAChC,CAAC;IACH,CAAC;CACF;AAxFD,4CAwFC"}
|
|
@@ -13,12 +13,15 @@ export declare class ExtractionPipeline {
|
|
|
13
13
|
private relationshipExtractor;
|
|
14
14
|
private deduplicator;
|
|
15
15
|
private contradictionDetector;
|
|
16
|
+
private edgeDeduplicator;
|
|
16
17
|
private embeddingService;
|
|
17
18
|
private entityTypes;
|
|
18
19
|
private groupId;
|
|
19
20
|
constructor(storage: IGraphStorage, config: ExtractionPipelineConfig);
|
|
20
21
|
process(humanMessage: string, aiMessage: string, episodeUuid?: string): Promise<void>;
|
|
21
22
|
private resolveEntity;
|
|
23
|
+
private expireContradictedEdges;
|
|
22
24
|
private persistRelationship;
|
|
25
|
+
private buildEdgeUpdates;
|
|
23
26
|
private findEntity;
|
|
24
27
|
}
|
|
@@ -6,6 +6,7 @@ const EntityExtractor_1 = require("./EntityExtractor");
|
|
|
6
6
|
const RelationshipExtractor_1 = require("./RelationshipExtractor");
|
|
7
7
|
const EntityDeduplicator_1 = require("./EntityDeduplicator");
|
|
8
8
|
const ContradictionDetector_1 = require("./ContradictionDetector");
|
|
9
|
+
const EdgeDeduplicator_1 = require("./EdgeDeduplicator");
|
|
9
10
|
const embeddings_1 = require("../embeddings");
|
|
10
11
|
const temporal_1 = require("../utils/temporal");
|
|
11
12
|
class ExtractionPipeline {
|
|
@@ -17,6 +18,7 @@ class ExtractionPipeline {
|
|
|
17
18
|
this.relationshipExtractor = new RelationshipExtractor_1.RelationshipExtractor(llm);
|
|
18
19
|
this.deduplicator = new EntityDeduplicator_1.EntityDeduplicator(llm);
|
|
19
20
|
this.contradictionDetector = new ContradictionDetector_1.ContradictionDetector(llm);
|
|
21
|
+
this.edgeDeduplicator = new EdgeDeduplicator_1.EdgeDeduplicator(llm);
|
|
20
22
|
this.entityTypes = config.entityTypes;
|
|
21
23
|
this.groupId = config.groupId;
|
|
22
24
|
if (config.embeddingConfig) {
|
|
@@ -76,16 +78,11 @@ class ExtractionPipeline {
|
|
|
76
78
|
name_embedding: nameEmbedding !== null && nameEmbedding !== void 0 ? nameEmbedding : null,
|
|
77
79
|
});
|
|
78
80
|
}
|
|
79
|
-
async
|
|
80
|
-
const
|
|
81
|
-
const targetEntity = this.findEntity(rel.target_entity, resolvedEntities, existingEntities);
|
|
82
|
-
if (!sourceEntity || !targetEntity)
|
|
83
|
-
return;
|
|
84
|
-
const existingEdges = await this.storage.getEdgesBetween(sourceEntity.uuid, targetEntity.uuid);
|
|
85
|
-
for (const existingEdge of existingEdges) {
|
|
81
|
+
async expireContradictedEdges(edges, newFact, sourceEntityName, targetEntityName, newEdgeName) {
|
|
82
|
+
for (const existingEdge of edges) {
|
|
86
83
|
if (existingEdge.expired_at)
|
|
87
84
|
continue;
|
|
88
|
-
const resolution = await this.contradictionDetector.detect(existingEdge.fact,
|
|
85
|
+
const resolution = await this.contradictionDetector.detect(existingEdge.fact, newFact, sourceEntityName, targetEntityName, existingEdge.name, newEdgeName);
|
|
89
86
|
if (resolution.isContradiction && resolution.expiredAt) {
|
|
90
87
|
await this.storage.updateEdge(existingEdge.uuid, {
|
|
91
88
|
expired_at: resolution.expiredAt,
|
|
@@ -93,6 +90,67 @@ class ExtractionPipeline {
|
|
|
93
90
|
});
|
|
94
91
|
}
|
|
95
92
|
}
|
|
93
|
+
}
|
|
94
|
+
async persistRelationship(rel, resolvedEntities, existingEntities, episodeUuid) {
|
|
95
|
+
const sourceEntity = this.findEntity(rel.source_entity, resolvedEntities, existingEntities);
|
|
96
|
+
const targetEntity = this.findEntity(rel.target_entity, resolvedEntities, existingEntities);
|
|
97
|
+
if (!sourceEntity || !targetEntity)
|
|
98
|
+
return;
|
|
99
|
+
const normalizedNewEdgeName = rel.name.toUpperCase().replace(/\s+/g, '_');
|
|
100
|
+
let samePairEdges = [];
|
|
101
|
+
try {
|
|
102
|
+
samePairEdges = await this.storage.getEdgesBetween(sourceEntity.uuid, targetEntity.uuid);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.warn('Engram: Failed to fetch edges between', sourceEntity.name, 'and', targetEntity.name + ':', error.message);
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const existingMatchingEdge = samePairEdges.find((e) => e.name === normalizedNewEdgeName && !e.expired_at);
|
|
109
|
+
if (existingMatchingEdge) {
|
|
110
|
+
const { isDuplicate, mergedFact } = await this.edgeDeduplicator.isDuplicate(existingMatchingEdge.fact, rel.fact, normalizedNewEdgeName, sourceEntity.name, targetEntity.name);
|
|
111
|
+
if (isDuplicate) {
|
|
112
|
+
const updates = await this.buildEdgeUpdates(existingMatchingEdge, mergedFact || rel.fact, episodeUuid);
|
|
113
|
+
if (Object.keys(updates).length > 0) {
|
|
114
|
+
await this.storage.updateEdge(existingMatchingEdge.uuid, updates);
|
|
115
|
+
}
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
console.warn('Engram: Edge deduplication failed for', sourceEntity.name, '->', targetEntity.name + ':', error.message);
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
const crossNameCandidates = samePairEdges.filter((e) => e.name !== normalizedNewEdgeName && !e.expired_at);
|
|
125
|
+
if (crossNameCandidates.length > 0) {
|
|
126
|
+
const candidate = crossNameCandidates[0];
|
|
127
|
+
const { isDuplicate, mergedFact } = await this.edgeDeduplicator.isDuplicateCrossName(candidate.fact, rel.fact, candidate.name, normalizedNewEdgeName, sourceEntity.name, targetEntity.name);
|
|
128
|
+
if (isDuplicate) {
|
|
129
|
+
const updates = await this.buildEdgeUpdates(candidate, mergedFact || rel.fact, episodeUuid);
|
|
130
|
+
if (Object.keys(updates).length > 0) {
|
|
131
|
+
await this.storage.updateEdge(candidate.uuid, updates);
|
|
132
|
+
}
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
console.warn('Engram: Cross-name edge deduplication failed for', sourceEntity.name, '->', targetEntity.name + ':', error.message);
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
await this.expireContradictedEdges(samePairEdges, rel.fact, sourceEntity.name, targetEntity.name, normalizedNewEdgeName);
|
|
142
|
+
const checkedUuids = new Set(samePairEdges.map((e) => e.uuid));
|
|
143
|
+
const allSourceEdges = await this.storage.getEdgesForEntity(sourceEntity.uuid);
|
|
144
|
+
const crossTargetEdges = allSourceEdges.filter((e) => e.source_node_uuid === sourceEntity.uuid &&
|
|
145
|
+
e.name === normalizedNewEdgeName &&
|
|
146
|
+
e.target_node_uuid !== targetEntity.uuid &&
|
|
147
|
+
!e.expired_at &&
|
|
148
|
+
!checkedUuids.has(e.uuid));
|
|
149
|
+
await this.expireContradictedEdges(crossTargetEdges, rel.fact, sourceEntity.name, targetEntity.name, normalizedNewEdgeName);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
console.warn('Engram: Contradiction detection failed for edge between', sourceEntity.name, 'and', targetEntity.name + ':', error.message);
|
|
153
|
+
}
|
|
96
154
|
let factEmbedding;
|
|
97
155
|
if (this.embeddingService) {
|
|
98
156
|
try {
|
|
@@ -107,13 +165,35 @@ class ExtractionPipeline {
|
|
|
107
165
|
group_id: this.groupId,
|
|
108
166
|
source_node_uuid: sourceEntity.uuid,
|
|
109
167
|
target_node_uuid: targetEntity.uuid,
|
|
110
|
-
name:
|
|
168
|
+
name: normalizedNewEdgeName,
|
|
111
169
|
fact: rel.fact,
|
|
112
170
|
fact_embedding: factEmbedding !== null && factEmbedding !== void 0 ? factEmbedding : null,
|
|
113
171
|
valid_at: (0, temporal_1.nowIso)(),
|
|
114
172
|
episodes: episodeUuid ? [episodeUuid] : [],
|
|
115
173
|
});
|
|
116
174
|
}
|
|
175
|
+
async buildEdgeUpdates(existingEdge, effectiveFact, episodeUuid) {
|
|
176
|
+
const updates = {};
|
|
177
|
+
if (effectiveFact !== existingEdge.fact) {
|
|
178
|
+
updates.fact = effectiveFact;
|
|
179
|
+
if (this.embeddingService) {
|
|
180
|
+
try {
|
|
181
|
+
const result = await this.embeddingService.embed(effectiveFact);
|
|
182
|
+
updates.fact_embedding = result.embedding;
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
console.warn('Engram: Failed to regenerate edge embedding:', error.message);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (episodeUuid) {
|
|
190
|
+
const existingEpisodes = existingEdge.episodes || [];
|
|
191
|
+
if (!existingEpisodes.includes(episodeUuid)) {
|
|
192
|
+
updates.episodes = [...existingEpisodes, episodeUuid];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return updates;
|
|
196
|
+
}
|
|
117
197
|
findEntity(name, resolvedEntities, existingEntities) {
|
|
118
198
|
const normalized = name.toLowerCase().trim();
|
|
119
199
|
const resolved = resolvedEntities.get(normalized);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExtractionPipeline.js","sourceRoot":"","sources":["../../src/extraction/ExtractionPipeline.ts"],"names":[],"mappings":";;;AAEA,2CAA8D;AAC9D,uDAAoD;AACpD,mEAAgE;AAChE,6DAA0D;AAC1D,mEAAgE;AAChE,8CAAuE;AACvE,gDAA2C;AAmB3C,MAAa,kBAAkB;
|
|
1
|
+
{"version":3,"file":"ExtractionPipeline.js","sourceRoot":"","sources":["../../src/extraction/ExtractionPipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,5 +12,9 @@ export declare function deduplicationUser(entity1: {
|
|
|
12
12
|
summary: string;
|
|
13
13
|
entity_type: string;
|
|
14
14
|
}): string;
|
|
15
|
+
export declare const EDGE_DEDUP_SYSTEM: string;
|
|
16
|
+
export declare function edgeDedupUser(existingFact: string, newFact: string, edgeName: string, sourceEntity: string, targetEntity: string): string;
|
|
15
17
|
export declare const CONTRADICTION_SYSTEM: string;
|
|
16
|
-
export declare function contradictionUser(existingFact: string, newFact: string, sourceEntity: string, targetEntity: string): string;
|
|
18
|
+
export declare function contradictionUser(existingFact: string, newFact: string, sourceEntity: string, targetEntity: string, existingEdgeName?: string, newEdgeName?: string): string;
|
|
19
|
+
export declare const CROSS_NAME_EDGE_DEDUP_SYSTEM: string;
|
|
20
|
+
export declare function crossNameEdgeDedupUser(existingFact: string, newFact: string, existingEdgeName: string, newEdgeName: string, sourceEntity: string, targetEntity: string): string;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CONTRADICTION_SYSTEM = exports.DEDUPLICATION_SYSTEM = exports.RELATIONSHIP_EXTRACTION_SYSTEM = exports.ENTITY_EXTRACTION_SYSTEM = void 0;
|
|
3
|
+
exports.CROSS_NAME_EDGE_DEDUP_SYSTEM = exports.CONTRADICTION_SYSTEM = exports.EDGE_DEDUP_SYSTEM = exports.DEDUPLICATION_SYSTEM = exports.RELATIONSHIP_EXTRACTION_SYSTEM = exports.ENTITY_EXTRACTION_SYSTEM = void 0;
|
|
4
4
|
exports.entityExtractionUser = entityExtractionUser;
|
|
5
5
|
exports.relationshipExtractionUser = relationshipExtractionUser;
|
|
6
6
|
exports.deduplicationUser = deduplicationUser;
|
|
7
|
+
exports.edgeDedupUser = edgeDedupUser;
|
|
7
8
|
exports.contradictionUser = contradictionUser;
|
|
9
|
+
exports.crossNameEdgeDedupUser = crossNameEdgeDedupUser;
|
|
8
10
|
exports.ENTITY_EXTRACTION_SYSTEM = [
|
|
9
11
|
'You are an entity extraction system. Extract entities from the conversation.',
|
|
10
12
|
'',
|
|
@@ -76,26 +78,90 @@ function deduplicationUser(entity1, entity2) {
|
|
|
76
78
|
];
|
|
77
79
|
return parts.join('\n');
|
|
78
80
|
}
|
|
79
|
-
exports.
|
|
80
|
-
'You are
|
|
81
|
+
exports.EDGE_DEDUP_SYSTEM = [
|
|
82
|
+
'You are an edge deduplication system. Determine if a new fact about a relationship between two entities is a duplicate of an existing fact.',
|
|
81
83
|
'',
|
|
82
84
|
'Rules:',
|
|
83
|
-
'- A
|
|
84
|
-
'-
|
|
85
|
-
'- Example: "Alice
|
|
85
|
+
'- A duplicate means the new fact describes the same relationship, possibly with updated details',
|
|
86
|
+
'- If duplicate, provide a merged_fact that keeps the most current and complete information',
|
|
87
|
+
'- Example: "Alice works at Google as a senior engineer" and "Alice works at Google as VP of Engineering" are duplicates (same employment, role updated). merged_fact: "Alice works at Google as VP of Engineering"',
|
|
88
|
+
'- Example: "Alice lives in London" and "Alice has a flat in London" are duplicates (same residency). merged_fact: "Alice lives in London and has a flat there"',
|
|
89
|
+
'- Example: "Alice knows Python" and "Alice knows Java" are NOT duplicates (different skills)',
|
|
90
|
+
'- Example: "Bob earns 120k" and "Bob earns 250k" are duplicates (same salary relationship, amount updated). merged_fact: "Bob earns 250k"',
|
|
86
91
|
'- Return ONLY valid JSON',
|
|
87
92
|
'',
|
|
88
93
|
'Output format:',
|
|
89
|
-
'{"
|
|
94
|
+
'{"is_duplicate": true, "merged_fact": "The most current and complete version of the fact"}',
|
|
90
95
|
].join('\n');
|
|
91
|
-
function
|
|
96
|
+
function edgeDedupUser(existingFact, newFact, edgeName, sourceEntity, targetEntity) {
|
|
92
97
|
const parts = [
|
|
93
|
-
'
|
|
98
|
+
'Is the new fact a duplicate of the existing fact?',
|
|
94
99
|
'',
|
|
95
100
|
'Entities: ' + sourceEntity + ' -> ' + targetEntity,
|
|
101
|
+
'Relationship type: ' + edgeName,
|
|
96
102
|
'Existing fact: ' + existingFact,
|
|
97
103
|
'New fact: ' + newFact,
|
|
98
104
|
];
|
|
99
105
|
return parts.join('\n');
|
|
100
106
|
}
|
|
107
|
+
exports.CONTRADICTION_SYSTEM = [
|
|
108
|
+
'You are a contradiction detection system. Determine if a new fact contradicts an existing fact between the same entities.',
|
|
109
|
+
'',
|
|
110
|
+
'Rules:',
|
|
111
|
+
'- A contradiction means the new fact makes the old fact no longer true or no longer current',
|
|
112
|
+
'- Consider the relationship types when provided. A change in relationship type between the same entities is a strong signal of contradiction.',
|
|
113
|
+
'- Temporal/status changes count as contradictions: if someone WORKS_AT a place and a new fact says they WORKED_AT that place (past tense), the current employment is contradicted.',
|
|
114
|
+
'- Example: "Alice lives in London" (LIVES_IN) contradicts "Alice lives in Tokyo" (LIVES_IN) — can only live in one place',
|
|
115
|
+
'- Example: "Bob works at Google" (WORKS_AT) is contradicted by "Bob worked at Google before quitting" (WORKED_AT) — present-tense employment is no longer true',
|
|
116
|
+
'- Example: "Alice knows Python" (KNOWS) does NOT contradict "Alice knows JavaScript" (KNOWS) — can know both',
|
|
117
|
+
'- Example: "Alice manages Bob" (MANAGES) does NOT contradict "Alice mentors Bob" (MENTORS) — different coexisting relationships',
|
|
118
|
+
'- When relationship types differ, ask: does the new relationship type imply the old one is no longer active?',
|
|
119
|
+
'- Return ONLY valid JSON',
|
|
120
|
+
'',
|
|
121
|
+
'Output format:',
|
|
122
|
+
'{"is_contradiction": true, "explanation": "The new fact about past employment replaces the current employment status"}',
|
|
123
|
+
].join('\n');
|
|
124
|
+
function contradictionUser(existingFact, newFact, sourceEntity, targetEntity, existingEdgeName, newEdgeName) {
|
|
125
|
+
const parts = [
|
|
126
|
+
'Does the new fact contradict the existing fact?',
|
|
127
|
+
'',
|
|
128
|
+
'Entities: ' + sourceEntity + ' -> ' + targetEntity,
|
|
129
|
+
];
|
|
130
|
+
if (existingEdgeName) {
|
|
131
|
+
parts.push('Existing relationship type: ' + existingEdgeName);
|
|
132
|
+
}
|
|
133
|
+
parts.push('Existing fact: ' + existingFact);
|
|
134
|
+
if (newEdgeName) {
|
|
135
|
+
parts.push('New relationship type: ' + newEdgeName);
|
|
136
|
+
}
|
|
137
|
+
parts.push('New fact: ' + newFact);
|
|
138
|
+
return parts.join('\n');
|
|
139
|
+
}
|
|
140
|
+
exports.CROSS_NAME_EDGE_DEDUP_SYSTEM = [
|
|
141
|
+
'You are an edge deduplication system. Determine if two facts about the same entities describe the same underlying relationship, even though they use different relationship names.',
|
|
142
|
+
'',
|
|
143
|
+
'Rules:',
|
|
144
|
+
'- Two edges are duplicates if they describe the SAME core relationship, even with different labels',
|
|
145
|
+
'- Example: "WORKS_AT" and "EMPLOYED_BY" between Person->Company are duplicates (same employment relationship)',
|
|
146
|
+
'- Example: "HAS_ROLE" and "HOLDS_POSITION" between Person->Company are duplicates (same position relationship)',
|
|
147
|
+
'- Example: "WORKS_AT" and "MANAGES" between Person->Company are NOT duplicates (employment vs management are different relationships)',
|
|
148
|
+
'- Example: "LIVES_IN" and "RESIDES_AT" between Person->City are duplicates (same residency relationship)',
|
|
149
|
+
'- Example: "VISITED" and "LIVES_IN" between Person->City are NOT duplicates (visiting vs living are fundamentally different)',
|
|
150
|
+
'- When in doubt, say NOT duplicate — it is safer to keep both edges than to incorrectly merge',
|
|
151
|
+
'- If duplicate, provide a merged_fact combining the most complete and current information from both facts',
|
|
152
|
+
'- Return ONLY valid JSON',
|
|
153
|
+
'',
|
|
154
|
+
'Output format:',
|
|
155
|
+
'{"is_duplicate": true, "merged_fact": "The most current and complete version of the fact"}',
|
|
156
|
+
].join('\n');
|
|
157
|
+
function crossNameEdgeDedupUser(existingFact, newFact, existingEdgeName, newEdgeName, sourceEntity, targetEntity) {
|
|
158
|
+
const parts = [
|
|
159
|
+
'Are these two relationships about the same entities duplicates, despite having different names?',
|
|
160
|
+
'',
|
|
161
|
+
'Entities: ' + sourceEntity + ' -> ' + targetEntity,
|
|
162
|
+
'Existing relationship: ' + existingEdgeName + ' — "' + existingFact + '"',
|
|
163
|
+
'New relationship: ' + newEdgeName + ' — "' + newFact + '"',
|
|
164
|
+
];
|
|
165
|
+
return parts.join('\n');
|
|
166
|
+
}
|
|
101
167
|
//# sourceMappingURL=prompts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/extraction/prompts.ts"],"names":[],"mappings":";;;AAmBA,oDAmBC;AAiBD,gEAcC;AAcD,8CAWC;
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/extraction/prompts.ts"],"names":[],"mappings":"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"}
|