@retrivora-ai/rag-engine 1.0.2 → 1.0.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/dist/{chunk-OJNAKSQ2.mjs → chunk-6MLZHQZT.mjs} +41 -11
- package/dist/handlers/index.js +41 -11
- package/dist/handlers/index.mjs +1 -1
- package/dist/server.js +41 -11
- package/dist/server.mjs +1 -1
- package/package.json +1 -1
- package/src/rag/EntityExtractor.ts +56 -12
|
@@ -1391,29 +1391,59 @@ var EntityExtractor = class {
|
|
|
1391
1391
|
async extract(text) {
|
|
1392
1392
|
const prompt = `
|
|
1393
1393
|
Extract entities and relationships from the following text.
|
|
1394
|
-
Format the output as JSON with two keys: "nodes"
|
|
1395
|
-
Use the same ID for the same entity.
|
|
1394
|
+
Format the output as a JSON object with exactly two keys: "nodes" and "edges".
|
|
1396
1395
|
|
|
1397
|
-
|
|
1398
|
-
|
|
1396
|
+
Nodes: {id, label, properties}
|
|
1397
|
+
Edges: {source, target, type, properties}
|
|
1399
1398
|
|
|
1400
|
-
|
|
1401
|
-
|
|
1399
|
+
IMPORTANT:
|
|
1400
|
+
- Ensure all property values are simple JSON types (string, number, boolean).
|
|
1401
|
+
- Do not use mathematical expressions or complex nested objects in properties.
|
|
1402
|
+
- If no entities are found, return empty arrays.
|
|
1403
|
+
- RESPOND ONLY WITH THE JSON OBJECT.
|
|
1402
1404
|
|
|
1403
|
-
|
|
1405
|
+
Text to extract from:
|
|
1406
|
+
"${text}"
|
|
1404
1407
|
`;
|
|
1405
1408
|
const response = await this.llm.chat([
|
|
1406
|
-
{ role: "system", content: "You are
|
|
1409
|
+
{ role: "system", content: "You are a precise knowledge graph extraction engine. You always output valid JSON and nothing else." },
|
|
1407
1410
|
{ role: "user", content: prompt }
|
|
1408
|
-
], "");
|
|
1411
|
+
], "", { maxTokens: 4096, temperature: 0.1 });
|
|
1409
1412
|
try {
|
|
1410
|
-
const
|
|
1413
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
1414
|
+
const cleanJson = jsonMatch ? jsonMatch[0] : response.trim();
|
|
1411
1415
|
return JSON.parse(cleanJson);
|
|
1412
1416
|
} catch (e) {
|
|
1413
|
-
|
|
1417
|
+
try {
|
|
1418
|
+
const repaired = this.repairTruncatedJson(response);
|
|
1419
|
+
if (repaired) return JSON.parse(repaired);
|
|
1420
|
+
} catch (e2) {
|
|
1421
|
+
}
|
|
1422
|
+
console.warn(`[EntityExtractor] Failed to parse LLM response. Length: ${response.length} chars.`);
|
|
1423
|
+
console.warn("[EntityExtractor] Snippet:", response.substring(0, 100) + "...");
|
|
1414
1424
|
return { nodes: [], edges: [] };
|
|
1415
1425
|
}
|
|
1416
1426
|
}
|
|
1427
|
+
/**
|
|
1428
|
+
* Attempts to fix JSON that was cut off mid-generation.
|
|
1429
|
+
* Strategy: Find the last valid element in an array and close the structure.
|
|
1430
|
+
*/
|
|
1431
|
+
repairTruncatedJson(json) {
|
|
1432
|
+
let text = json.trim();
|
|
1433
|
+
const startIdx = text.indexOf("{");
|
|
1434
|
+
if (startIdx === -1) return null;
|
|
1435
|
+
text = text.substring(startIdx);
|
|
1436
|
+
const lastCompleteObjectIdx = text.lastIndexOf("}");
|
|
1437
|
+
if (lastCompleteObjectIdx === -1) return null;
|
|
1438
|
+
let repaired = text.substring(0, lastCompleteObjectIdx + 1);
|
|
1439
|
+
const openBrackets = (repaired.match(/\{/g) || []).length;
|
|
1440
|
+
const closedBrackets = (repaired.match(/\}/g) || []).length;
|
|
1441
|
+
const openSquares = (repaired.match(/\[/g) || []).length;
|
|
1442
|
+
const closedSquares = (repaired.match(/\]/g) || []).length;
|
|
1443
|
+
for (let i = 0; i < openSquares - closedSquares; i++) repaired += "]";
|
|
1444
|
+
for (let i = 0; i < openBrackets - closedBrackets; i++) repaired += "}";
|
|
1445
|
+
return repaired;
|
|
1446
|
+
}
|
|
1417
1447
|
};
|
|
1418
1448
|
|
|
1419
1449
|
// src/rag/Reranker.ts
|
package/dist/handlers/index.js
CHANGED
|
@@ -2854,29 +2854,59 @@ var EntityExtractor = class {
|
|
|
2854
2854
|
async extract(text) {
|
|
2855
2855
|
const prompt = `
|
|
2856
2856
|
Extract entities and relationships from the following text.
|
|
2857
|
-
Format the output as JSON with two keys: "nodes"
|
|
2858
|
-
Use the same ID for the same entity.
|
|
2857
|
+
Format the output as a JSON object with exactly two keys: "nodes" and "edges".
|
|
2859
2858
|
|
|
2860
|
-
|
|
2861
|
-
|
|
2859
|
+
Nodes: {id, label, properties}
|
|
2860
|
+
Edges: {source, target, type, properties}
|
|
2862
2861
|
|
|
2863
|
-
|
|
2864
|
-
|
|
2862
|
+
IMPORTANT:
|
|
2863
|
+
- Ensure all property values are simple JSON types (string, number, boolean).
|
|
2864
|
+
- Do not use mathematical expressions or complex nested objects in properties.
|
|
2865
|
+
- If no entities are found, return empty arrays.
|
|
2866
|
+
- RESPOND ONLY WITH THE JSON OBJECT.
|
|
2865
2867
|
|
|
2866
|
-
|
|
2868
|
+
Text to extract from:
|
|
2869
|
+
"${text}"
|
|
2867
2870
|
`;
|
|
2868
2871
|
const response = await this.llm.chat([
|
|
2869
|
-
{ role: "system", content: "You are
|
|
2872
|
+
{ role: "system", content: "You are a precise knowledge graph extraction engine. You always output valid JSON and nothing else." },
|
|
2870
2873
|
{ role: "user", content: prompt }
|
|
2871
|
-
], "");
|
|
2874
|
+
], "", { maxTokens: 4096, temperature: 0.1 });
|
|
2872
2875
|
try {
|
|
2873
|
-
const
|
|
2876
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
2877
|
+
const cleanJson = jsonMatch ? jsonMatch[0] : response.trim();
|
|
2874
2878
|
return JSON.parse(cleanJson);
|
|
2875
2879
|
} catch (e) {
|
|
2876
|
-
|
|
2880
|
+
try {
|
|
2881
|
+
const repaired = this.repairTruncatedJson(response);
|
|
2882
|
+
if (repaired) return JSON.parse(repaired);
|
|
2883
|
+
} catch (e2) {
|
|
2884
|
+
}
|
|
2885
|
+
console.warn(`[EntityExtractor] Failed to parse LLM response. Length: ${response.length} chars.`);
|
|
2886
|
+
console.warn("[EntityExtractor] Snippet:", response.substring(0, 100) + "...");
|
|
2877
2887
|
return { nodes: [], edges: [] };
|
|
2878
2888
|
}
|
|
2879
2889
|
}
|
|
2890
|
+
/**
|
|
2891
|
+
* Attempts to fix JSON that was cut off mid-generation.
|
|
2892
|
+
* Strategy: Find the last valid element in an array and close the structure.
|
|
2893
|
+
*/
|
|
2894
|
+
repairTruncatedJson(json) {
|
|
2895
|
+
let text = json.trim();
|
|
2896
|
+
const startIdx = text.indexOf("{");
|
|
2897
|
+
if (startIdx === -1) return null;
|
|
2898
|
+
text = text.substring(startIdx);
|
|
2899
|
+
const lastCompleteObjectIdx = text.lastIndexOf("}");
|
|
2900
|
+
if (lastCompleteObjectIdx === -1) return null;
|
|
2901
|
+
let repaired = text.substring(0, lastCompleteObjectIdx + 1);
|
|
2902
|
+
const openBrackets = (repaired.match(/\{/g) || []).length;
|
|
2903
|
+
const closedBrackets = (repaired.match(/\}/g) || []).length;
|
|
2904
|
+
const openSquares = (repaired.match(/\[/g) || []).length;
|
|
2905
|
+
const closedSquares = (repaired.match(/\]/g) || []).length;
|
|
2906
|
+
for (let i = 0; i < openSquares - closedSquares; i++) repaired += "]";
|
|
2907
|
+
for (let i = 0; i < openBrackets - closedBrackets; i++) repaired += "}";
|
|
2908
|
+
return repaired;
|
|
2909
|
+
}
|
|
2880
2910
|
};
|
|
2881
2911
|
|
|
2882
2912
|
// src/rag/Reranker.ts
|
package/dist/handlers/index.mjs
CHANGED
package/dist/server.js
CHANGED
|
@@ -2936,29 +2936,59 @@ var EntityExtractor = class {
|
|
|
2936
2936
|
async extract(text) {
|
|
2937
2937
|
const prompt = `
|
|
2938
2938
|
Extract entities and relationships from the following text.
|
|
2939
|
-
Format the output as JSON with two keys: "nodes"
|
|
2940
|
-
Use the same ID for the same entity.
|
|
2939
|
+
Format the output as a JSON object with exactly two keys: "nodes" and "edges".
|
|
2941
2940
|
|
|
2942
|
-
|
|
2943
|
-
|
|
2941
|
+
Nodes: {id, label, properties}
|
|
2942
|
+
Edges: {source, target, type, properties}
|
|
2944
2943
|
|
|
2945
|
-
|
|
2946
|
-
|
|
2944
|
+
IMPORTANT:
|
|
2945
|
+
- Ensure all property values are simple JSON types (string, number, boolean).
|
|
2946
|
+
- Do not use mathematical expressions or complex nested objects in properties.
|
|
2947
|
+
- If no entities are found, return empty arrays.
|
|
2948
|
+
- RESPOND ONLY WITH THE JSON OBJECT.
|
|
2947
2949
|
|
|
2948
|
-
|
|
2950
|
+
Text to extract from:
|
|
2951
|
+
"${text}"
|
|
2949
2952
|
`;
|
|
2950
2953
|
const response = await this.llm.chat([
|
|
2951
|
-
{ role: "system", content: "You are
|
|
2954
|
+
{ role: "system", content: "You are a precise knowledge graph extraction engine. You always output valid JSON and nothing else." },
|
|
2952
2955
|
{ role: "user", content: prompt }
|
|
2953
|
-
], "");
|
|
2956
|
+
], "", { maxTokens: 4096, temperature: 0.1 });
|
|
2954
2957
|
try {
|
|
2955
|
-
const
|
|
2958
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
2959
|
+
const cleanJson = jsonMatch ? jsonMatch[0] : response.trim();
|
|
2956
2960
|
return JSON.parse(cleanJson);
|
|
2957
2961
|
} catch (e) {
|
|
2958
|
-
|
|
2962
|
+
try {
|
|
2963
|
+
const repaired = this.repairTruncatedJson(response);
|
|
2964
|
+
if (repaired) return JSON.parse(repaired);
|
|
2965
|
+
} catch (e2) {
|
|
2966
|
+
}
|
|
2967
|
+
console.warn(`[EntityExtractor] Failed to parse LLM response. Length: ${response.length} chars.`);
|
|
2968
|
+
console.warn("[EntityExtractor] Snippet:", response.substring(0, 100) + "...");
|
|
2959
2969
|
return { nodes: [], edges: [] };
|
|
2960
2970
|
}
|
|
2961
2971
|
}
|
|
2972
|
+
/**
|
|
2973
|
+
* Attempts to fix JSON that was cut off mid-generation.
|
|
2974
|
+
* Strategy: Find the last valid element in an array and close the structure.
|
|
2975
|
+
*/
|
|
2976
|
+
repairTruncatedJson(json) {
|
|
2977
|
+
let text = json.trim();
|
|
2978
|
+
const startIdx = text.indexOf("{");
|
|
2979
|
+
if (startIdx === -1) return null;
|
|
2980
|
+
text = text.substring(startIdx);
|
|
2981
|
+
const lastCompleteObjectIdx = text.lastIndexOf("}");
|
|
2982
|
+
if (lastCompleteObjectIdx === -1) return null;
|
|
2983
|
+
let repaired = text.substring(0, lastCompleteObjectIdx + 1);
|
|
2984
|
+
const openBrackets = (repaired.match(/\{/g) || []).length;
|
|
2985
|
+
const closedBrackets = (repaired.match(/\}/g) || []).length;
|
|
2986
|
+
const openSquares = (repaired.match(/\[/g) || []).length;
|
|
2987
|
+
const closedSquares = (repaired.match(/\]/g) || []).length;
|
|
2988
|
+
for (let i = 0; i < openSquares - closedSquares; i++) repaired += "]";
|
|
2989
|
+
for (let i = 0; i < openBrackets - closedBrackets; i++) repaired += "}";
|
|
2990
|
+
return repaired;
|
|
2991
|
+
}
|
|
2962
2992
|
};
|
|
2963
2993
|
|
|
2964
2994
|
// src/rag/Reranker.ts
|
package/dist/server.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retrivora-ai/rag-engine",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Retrivora AI is a plug-and-play AI engine for RAG chat experiences — generic vector DB + LLM provider, embeddable or standalone.",
|
|
5
5
|
"author": "Abhinav Alkuchi",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,30 +17,74 @@ export class EntityExtractor {
|
|
|
17
17
|
async extract(text: string): Promise<{ nodes: GraphNode[]; edges: Edge[] }> {
|
|
18
18
|
const prompt = `
|
|
19
19
|
Extract entities and relationships from the following text.
|
|
20
|
-
Format the output as JSON with two keys: "nodes"
|
|
21
|
-
Use the same ID for the same entity.
|
|
20
|
+
Format the output as a JSON object with exactly two keys: "nodes" and "edges".
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
Nodes: {id, label, properties}
|
|
23
|
+
Edges: {source, target, type, properties}
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
IMPORTANT:
|
|
26
|
+
- Ensure all property values are simple JSON types (string, number, boolean).
|
|
27
|
+
- Do not use mathematical expressions or complex nested objects in properties.
|
|
28
|
+
- If no entities are found, return empty arrays.
|
|
29
|
+
- RESPOND ONLY WITH THE JSON OBJECT.
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
Text to extract from:
|
|
32
|
+
"${text}"
|
|
30
33
|
`;
|
|
31
34
|
|
|
32
35
|
const response = await this.llm.chat([
|
|
33
|
-
{ role: 'system', content: 'You are
|
|
36
|
+
{ role: 'system', content: 'You are a precise knowledge graph extraction engine. You always output valid JSON and nothing else.' },
|
|
34
37
|
{ role: 'user', content: prompt }
|
|
35
|
-
], '');
|
|
38
|
+
], '', { maxTokens: 4096, temperature: 0.1 });
|
|
36
39
|
|
|
37
40
|
try {
|
|
38
|
-
//
|
|
39
|
-
const
|
|
41
|
+
// 1. Try to find the JSON block using a regex
|
|
42
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
43
|
+
const cleanJson = jsonMatch ? jsonMatch[0] : response.trim();
|
|
44
|
+
|
|
40
45
|
return JSON.parse(cleanJson);
|
|
41
46
|
} catch {
|
|
42
|
-
|
|
47
|
+
// 2. If parsing fails, try to repair truncated JSON
|
|
48
|
+
try {
|
|
49
|
+
const repaired = this.repairTruncatedJson(response);
|
|
50
|
+
if (repaired) return JSON.parse(repaired);
|
|
51
|
+
} catch { /* ignore repair failure */ }
|
|
52
|
+
|
|
53
|
+
console.warn(`[EntityExtractor] Failed to parse LLM response. Length: ${response.length} chars.`);
|
|
54
|
+
console.warn('[EntityExtractor] Snippet:', response.substring(0, 100) + '...');
|
|
43
55
|
return { nodes: [], edges: [] };
|
|
44
56
|
}
|
|
45
57
|
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Attempts to fix JSON that was cut off mid-generation.
|
|
61
|
+
* Strategy: Find the last valid element in an array and close the structure.
|
|
62
|
+
*/
|
|
63
|
+
private repairTruncatedJson(json: string): string | null {
|
|
64
|
+
let text = json.trim();
|
|
65
|
+
|
|
66
|
+
// Find the first { and work from there
|
|
67
|
+
const startIdx = text.indexOf('{');
|
|
68
|
+
if (startIdx === -1) return null;
|
|
69
|
+
text = text.substring(startIdx);
|
|
70
|
+
|
|
71
|
+
// If it's truncated in an array like "nodes": [ ... , { ...
|
|
72
|
+
// We try to find the last complete object before the truncation
|
|
73
|
+
const lastCompleteObjectIdx = text.lastIndexOf('}');
|
|
74
|
+
if (lastCompleteObjectIdx === -1) return null;
|
|
75
|
+
|
|
76
|
+
// Truncate at the last complete object
|
|
77
|
+
let repaired = text.substring(0, lastCompleteObjectIdx + 1);
|
|
78
|
+
|
|
79
|
+
// Close any open structures (arrays or the main object)
|
|
80
|
+
const openBrackets = (repaired.match(/\{/g) || []).length;
|
|
81
|
+
const closedBrackets = (repaired.match(/\}/g) || []).length;
|
|
82
|
+
const openSquares = (repaired.match(/\[/g) || []).length;
|
|
83
|
+
const closedSquares = (repaired.match(/\]/g) || []).length;
|
|
84
|
+
|
|
85
|
+
for (let i = 0; i < openSquares - closedSquares; i++) repaired += ']';
|
|
86
|
+
for (let i = 0; i < openBrackets - closedBrackets; i++) repaired += '}';
|
|
87
|
+
|
|
88
|
+
return repaired;
|
|
89
|
+
}
|
|
46
90
|
}
|