@devilsdev/rag-pipeline-utils 2.1.11 → 2.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.
Files changed (110) hide show
  1. package/.ragrc.schema.json +218 -0
  2. package/README.md +651 -393
  3. package/bin/cli.js +8 -14
  4. package/dist/index.d.ts +237 -0
  5. package/dist/index.mjs +22 -7
  6. package/package.json +17 -13
  7. package/src/ai/adaptive-retrieval.js +191 -0
  8. package/src/ai/federated-learning.js +214 -0
  9. package/src/ai/federation/federated-learning-coordinator.js +345 -0
  10. package/src/ai/federation.js +76 -0
  11. package/src/ai/index-fixed.js +509 -0
  12. package/src/ai/index.js +33 -0
  13. package/src/ai/model-trainer.js +217 -0
  14. package/src/ai/model-training.js +205 -0
  15. package/src/ai/module-template.js +37 -0
  16. package/src/ai/multimodal/multi-modal-processor.js +345 -0
  17. package/src/ai/multimodal-processing.js +268 -0
  18. package/src/ai/multimodal.js +71 -0
  19. package/src/ai/orchestrator.js +70 -0
  20. package/src/ai/retrieval/adaptive-retrieval-engine.js +398 -0
  21. package/src/ai/retrieval-engine.js +69 -0
  22. package/src/ai/training/model-training-orchestrator.js +228 -0
  23. package/src/ci/workflow-analyzer.js +71 -0
  24. package/src/cli/commands/ai-ml.js +967 -0
  25. package/src/cli/commands/docs.js +228 -0
  26. package/src/cli/commands/dx.js +538 -0
  27. package/src/cli/commands/plugin-hub.js +875 -0
  28. package/src/cli/doctor-command.js +639 -0
  29. package/src/cli/enhanced-cli-commands.js +945 -0
  30. package/src/cli/interactive-wizard.js +997 -0
  31. package/src/cli/plugin-marketplace-commands.js +869 -0
  32. package/src/cli.js +17 -0
  33. package/src/config/enhanced-ragrc-schema.js +632 -0
  34. package/src/config/load-config.js +54 -0
  35. package/src/config/load-plugin-config.js +69 -0
  36. package/src/config/normalize-config.js +105 -0
  37. package/src/config/schema-validator.js +315 -0
  38. package/src/config/validate-plugin-schema.js +35 -0
  39. package/src/config/validate-schema.js +113 -0
  40. package/src/contracts/plugin-contracts.js +33 -0
  41. package/src/core/create-pipeline.js +99 -0
  42. package/src/core/dependency-injection.js +242 -0
  43. package/src/core/observability/event-logger.js +241 -0
  44. package/src/core/observability/instrumented-pipeline.js +609 -0
  45. package/src/core/observability/metrics.js +497 -0
  46. package/src/core/observability/tracing.js +781 -0
  47. package/src/core/performance/benchmark.js +516 -0
  48. package/src/core/performance/parallel-processor.js +240 -0
  49. package/src/core/performance/streaming-safeguards.js +611 -0
  50. package/src/core/pipeline-factory.js +60 -0
  51. package/src/core/plugin-contracts.js +89 -0
  52. package/src/core/plugin-marketplace/plugin-metadata.js +485 -0
  53. package/src/core/plugin-marketplace/plugin-publisher.js +574 -0
  54. package/src/core/plugin-marketplace/plugin-registry-format.js +419 -0
  55. package/src/core/plugin-marketplace/version-resolver.js +61 -0
  56. package/src/core/plugin-registry.js +265 -0
  57. package/src/dag/dag-engine.js +954 -0
  58. package/src/dag/dag-node.js +76 -0
  59. package/src/dag/enhanced-dag-engine.js +822 -0
  60. package/src/dx/index.js +40 -0
  61. package/src/dx/integration-templates.js +665 -0
  62. package/src/dx/performance-profiler.js +968 -0
  63. package/src/dx/realtime-debugger.js +755 -0
  64. package/src/dx/visual-pipeline-builder.js +578 -0
  65. package/src/ecosystem/plugin-analytics-dashboard.js +778 -0
  66. package/src/ecosystem/plugin-certification.js +580 -0
  67. package/src/ecosystem/plugin-hub.js +821 -0
  68. package/src/enterprise/audit-logging.js +967 -0
  69. package/src/enterprise/data-governance.js +408 -0
  70. package/src/enterprise/multi-tenancy.js +496 -0
  71. package/src/enterprise/sso-integration.js +903 -0
  72. package/src/evaluate/evaluator.js +52 -0
  73. package/src/evaluate/scoring.js +91 -0
  74. package/src/index.js +67 -0
  75. package/src/ingest.js +59 -0
  76. package/src/loader/csv-loader.js +38 -0
  77. package/src/loader/directory-loader.js +48 -0
  78. package/src/loader/html-loader.js +62 -0
  79. package/src/loader/markdown-loader.js +67 -0
  80. package/src/mocks/openai-embedder.js +119 -0
  81. package/src/mocks/openai-llm.js +77 -0
  82. package/src/mocks/pdf-loader.js +21 -0
  83. package/src/mocks/pinecone-retriever.js +106 -0
  84. package/src/observability/audit-logger.js +758 -0
  85. package/src/observability/dashboard-config.json +675 -0
  86. package/src/observability/event-logger.js +310 -0
  87. package/src/observability/metrics.js +691 -0
  88. package/src/observability/security-monitor.js +830 -0
  89. package/src/observability/slo-monitor.js +319 -0
  90. package/src/observability/telemetry.js +686 -0
  91. package/src/pipeline/pipeline.js +18 -0
  92. package/src/plugins/sample-embedder.js +53 -0
  93. package/src/plugins/sample-llm.js +30 -0
  94. package/src/plugins/sample-loader.js +24 -0
  95. package/src/plugins/sample-retriever.js +84 -0
  96. package/src/query.js +117 -0
  97. package/src/reranker/llm-reranker.js +85 -0
  98. package/src/scripts/script-utilities.js +36 -0
  99. package/src/security/plugin-sandbox.js +586 -0
  100. package/src/security/plugin-signature-verifier.js +414 -0
  101. package/src/security/validator.js +36 -0
  102. package/src/utils/ci/diagnostic-reporter.js +57 -0
  103. package/src/utils/logger.js +211 -0
  104. package/src/utils/performance-monitor.js +561 -0
  105. package/src/utils/plugin-scaffolder.js +447 -0
  106. package/src/utils/retry-policy.js +443 -0
  107. package/src/utils/retry.js +107 -0
  108. package/src/utils/safe-expression-evaluator.js +579 -0
  109. package/src/utils/structured-logger.js +361 -0
  110. package/src/utils/validate-plugin-contract.js +42 -0
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Sample Embedder Plugin
3
+ * Minimal fixture for test compatibility with configurable batch processing
4
+ */
5
+
6
+ class SampleEmbedder {
7
+ constructor(options = {}) {
8
+ this.name = 'sample-embedder';
9
+ this.version = '1.0.0';
10
+ this.options = options;
11
+
12
+ // Configurable batch size from environment or options
13
+ this.batchSize =
14
+ parseInt(process.env.RAG_EMBEDDER_BATCH_SIZE) || options.batchSize || 50; // Default batch size
15
+ }
16
+
17
+ async embed(texts) {
18
+ if (!Array.isArray(texts)) {
19
+ return new Array(384).fill(0).map(() => Math.random());
20
+ }
21
+
22
+ // Process in batches for better memory management
23
+ const results = [];
24
+ for (let i = 0; i < texts.length; i += this.batchSize) {
25
+ const batch = texts.slice(i, i + this.batchSize);
26
+ const batchResults = await this._processBatch(batch);
27
+ results.push(...batchResults);
28
+
29
+ // Optional progress callback
30
+ if (this.options.onProgress) {
31
+ this.options.onProgress({
32
+ processed: Math.min(i + this.batchSize, texts.length),
33
+ total: texts.length,
34
+ stage: 'embedding',
35
+ });
36
+ }
37
+ }
38
+
39
+ return results;
40
+ }
41
+
42
+ async _processBatch(batch) {
43
+ // Simulate batch processing with slight delay for realism
44
+ await new Promise((resolve) => setTimeout(resolve, 10));
45
+ return batch.map(() => new Array(384).fill(0).map(() => Math.random()));
46
+ }
47
+
48
+ async embedQuery(query) {
49
+ return new Array(384).fill(0).map(() => Math.random());
50
+ }
51
+ }
52
+
53
+ module.exports = { SampleEmbedder };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Sample LLM Plugin
3
+ * Minimal fixture for test compatibility
4
+ */
5
+
6
+ class SampleLLM {
7
+ constructor(options = {}) {
8
+ this.name = 'sample-llm';
9
+ this.version = '1.0.0';
10
+ this.options = options;
11
+ }
12
+
13
+ async generate(prompt, context = []) {
14
+ // Mock response for testing
15
+ return `Generated response for: ${prompt.substring(0, 50)}...`;
16
+ }
17
+
18
+ async *generateStream(prompt, context = []) {
19
+ const response = `Generated response for: ${prompt.substring(0, 50)}...`;
20
+ const tokens = response.split(' ');
21
+
22
+ for (const token of tokens) {
23
+ yield token + ' ';
24
+ // Small delay for realistic streaming
25
+ await new Promise((resolve) => setTimeout(resolve, 10));
26
+ }
27
+ }
28
+ }
29
+
30
+ module.exports = { SampleLLM };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Sample Loader Plugin
3
+ * Minimal fixture for test compatibility
4
+ */
5
+
6
+ class SampleLoader {
7
+ constructor(options = {}) {
8
+ this.name = 'sample-loader';
9
+ this.version = '1.0.0';
10
+ this.options = options;
11
+ }
12
+
13
+ async load(filePath) {
14
+ return [
15
+ {
16
+ content: 'Sample document content',
17
+ metadata: { source: filePath },
18
+ chunk: () => ['Sample chunk 1', 'Sample chunk 2'],
19
+ },
20
+ ];
21
+ }
22
+ }
23
+
24
+ module.exports = { SampleLoader };
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Sample Retriever Plugin
3
+ * Minimal fixture for test compatibility with configurable batch processing
4
+ */
5
+
6
+ class SampleRetriever {
7
+ constructor(options = {}) {
8
+ this.name = 'sample-retriever';
9
+ this.version = '1.0.0';
10
+ this.options = options;
11
+ this.storage = [];
12
+
13
+ // Configurable batch size from environment or options
14
+ this.batchSize =
15
+ parseInt(process.env.RAG_RETRIEVER_BATCH_SIZE) ||
16
+ options.batchSize ||
17
+ 100; // Default batch size for retrieval
18
+ }
19
+
20
+ async store(vectors) {
21
+ // Process storage in batches for better memory management
22
+ if (Array.isArray(vectors) && vectors.length > this.batchSize) {
23
+ for (let i = 0; i < vectors.length; i += this.batchSize) {
24
+ const batch = vectors.slice(i, i + this.batchSize);
25
+ this.storage.push(...batch);
26
+
27
+ // Optional progress callback
28
+ if (this.options.onProgress) {
29
+ this.options.onProgress({
30
+ processed: Math.min(i + this.batchSize, vectors.length),
31
+ total: vectors.length,
32
+ stage: 'storing',
33
+ });
34
+ }
35
+
36
+ // Small delay to prevent overwhelming memory
37
+ await new Promise((resolve) => setTimeout(resolve, 5));
38
+ }
39
+ } else {
40
+ this.storage.push(...vectors);
41
+ }
42
+ return true;
43
+ }
44
+
45
+ async retrieve(queryVector, k = 5) {
46
+ // For large result sets, process in batches
47
+ const totalResults = Math.min(k, this.storage.length);
48
+ const results = [];
49
+
50
+ for (let i = 0; i < totalResults; i += this.batchSize) {
51
+ const batchSize = Math.min(this.batchSize, totalResults - i);
52
+ const batchResults = this._retrieveBatch(i, batchSize);
53
+ results.push(...batchResults);
54
+
55
+ // Optional progress callback
56
+ if (this.options.onProgress && totalResults > this.batchSize) {
57
+ this.options.onProgress({
58
+ processed: Math.min(i + this.batchSize, totalResults),
59
+ total: totalResults,
60
+ stage: 'retrieving',
61
+ });
62
+ }
63
+
64
+ // Small delay for large retrievals
65
+ if (totalResults > this.batchSize) {
66
+ await new Promise((resolve) => setTimeout(resolve, 5));
67
+ }
68
+ }
69
+
70
+ return results;
71
+ }
72
+
73
+ _retrieveBatch(startIndex, batchSize) {
74
+ return this.storage
75
+ .slice(startIndex, startIndex + batchSize)
76
+ .map((vector, index) => ({
77
+ content: `Retrieved document ${startIndex + index + 1}`,
78
+ score: Math.random(),
79
+ metadata: { index: startIndex + index },
80
+ }));
81
+ }
82
+ }
83
+
84
+ module.exports = { SampleRetriever };
package/src/query.js ADDED
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Version: 2.0.0
3
+ * Path: /src/query.js
4
+ * Description: Handles querying the RAG pipeline with streaming support
5
+ * Author: Ali Kahwaji
6
+ */
7
+
8
+ const { createRagPipeline } = require('./core/create-pipeline.js');
9
+ // eslint-disable-line global-require
10
+ const { loadPluginsFromJson } = require('./config/load-plugin-config.js');
11
+ // eslint-disable-line global-require
12
+ const { logger } = require('./utils/logger.js');
13
+ // eslint-disable-line global-require
14
+
15
+ /**
16
+ * Query the RAG pipeline with a standard response
17
+ * @param {string} prompt - Query prompt
18
+ * @param {object} config - Pipeline configuration
19
+ * @returns {Promise<string>} Generated response
20
+ */
21
+ async function queryPipeline(_prompt, config) {
22
+ if (!prompt) {
23
+ throw new Error('No prompt provided for query.');
24
+ }
25
+
26
+ if (!config) {
27
+ throw new Error('No configuration provided for query.');
28
+ }
29
+
30
+ try {
31
+ // Load plugins from configuration
32
+ await loadPluginsFromJson(process.cwd());
33
+
34
+ // Extract plugin names from config
35
+ const loaderName = Object.keys(config.loader)[0];
36
+ const embedderName = Object.keys(config.embedder)[0];
37
+ const retrieverName = Object.keys(config.retriever)[0];
38
+ const llmName = Object.keys(config.llm)[0];
39
+
40
+ // Create pipeline instance
41
+ const pipeline = createRagPipeline(
42
+ {
43
+ loader: loaderName,
44
+ embedder: embedderName,
45
+ retriever: retrieverName,
46
+ llm: llmName,
47
+ },
48
+ {
49
+ useRetry: true,
50
+ useLogging: true,
51
+ useReranker: config.useReranker || false,
52
+ },
53
+ );
54
+
55
+ // Execute query
56
+ return await pipeline.query(prompt);
57
+ } catch (error) {
58
+ logger.error('Query pipeline failed', { error: error.message, prompt });
59
+ throw error;
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Query the RAG pipeline with streaming response
65
+ * @param {string} prompt - Query prompt
66
+ * @param {object} config - Pipeline configuration
67
+ * @returns {AsyncIterable<string>} Stream of response tokens
68
+ */
69
+ async function* queryPipelineStream(prompt, config) {
70
+ if (!prompt) {
71
+ throw new Error('No prompt provided for streaming query.');
72
+ }
73
+
74
+ if (!config) {
75
+ throw new Error('No configuration provided for streaming query.');
76
+ }
77
+
78
+ try {
79
+ // Load plugins from configuration
80
+ await loadPluginsFromJson(process.cwd());
81
+
82
+ // Extract plugin names from config
83
+ const loaderName = Object.keys(config.loader)[0];
84
+ const embedderName = Object.keys(config.embedder)[0];
85
+ const retrieverName = Object.keys(config.retriever)[0];
86
+ const llmName = Object.keys(config.llm)[0];
87
+
88
+ // Create pipeline instance
89
+ const pipeline = createRagPipeline(
90
+ {
91
+ loader: loaderName,
92
+ embedder: embedderName,
93
+ retriever: retrieverName,
94
+ llm: llmName,
95
+ },
96
+ {
97
+ useRetry: true,
98
+ useLogging: true,
99
+ useReranker: config.useReranker || false,
100
+ },
101
+ );
102
+
103
+ // Execute streaming query
104
+ yield* pipeline.queryStream(prompt);
105
+ } catch (error) {
106
+ logger.error('Streaming query pipeline failed', {
107
+ error: error.message,
108
+ prompt,
109
+ });
110
+ throw error;
111
+ }
112
+ }
113
+
114
+ module.exports = {
115
+ queryPipeline,
116
+ queryPipelineStream,
117
+ };
@@ -0,0 +1,85 @@
1
+ 'use strict';
2
+
3
+ class LLMReranker {
4
+ constructor(options = {}) {
5
+ this.llm = options.llm;
6
+ }
7
+
8
+ async rerank(query, docs, opts = {}) {
9
+ if (!Array.isArray(docs)) {
10
+ return [];
11
+ }
12
+
13
+ // If no LLM provided, fall back to simple overlap scoring
14
+ if (!this.llm) {
15
+ return this._fallbackRerank(query, docs);
16
+ }
17
+
18
+ try {
19
+ // Use LLM to get reranking order
20
+ const response = await this.llm.generate(query, docs, opts);
21
+ const rankingOrder = JSON.parse(response);
22
+
23
+ // Apply the ranking order
24
+ const reranked = [];
25
+ for (const index of rankingOrder) {
26
+ if (index >= 0 && index < docs.length) {
27
+ reranked.push(docs[index]);
28
+ }
29
+ }
30
+
31
+ return reranked;
32
+ } catch (error) {
33
+ // Fall back to simple overlap scoring on LLM error
34
+ return this._fallbackRerank(query, docs);
35
+ }
36
+ }
37
+
38
+ _fallbackRerank(query, docs) {
39
+ // Simple bag-of-words overlap scoring
40
+ const queryTokens = query
41
+ .toLowerCase()
42
+ .split(/\s+/)
43
+ .filter((t) => t.length > 0);
44
+
45
+ const scored = docs.map((doc, originalIndex) => {
46
+ const text = doc.text || doc.content || '';
47
+ const docTokens = text
48
+ .toLowerCase()
49
+ .split(/\s+/)
50
+ .filter((t) => t.length > 0);
51
+
52
+ // Count overlapping tokens
53
+ let overlap = 0;
54
+ for (const qToken of queryTokens) {
55
+ if (docTokens.includes(qToken)) {
56
+ overlap++;
57
+ }
58
+ }
59
+
60
+ // Add tiny length-based tie-break
61
+ const lengthTieBreak = text.length * 0.0001;
62
+ const score = overlap + lengthTieBreak;
63
+
64
+ return { doc, score, originalIndex };
65
+ });
66
+
67
+ // Sort by score (descending), then by original index (ascending) for stable sort
68
+ scored.sort((a, b) => {
69
+ if (b.score !== a.score) {
70
+ return b.score - a.score;
71
+ }
72
+ return a.originalIndex - b.originalIndex;
73
+ });
74
+
75
+ return scored.map((item) => item.doc);
76
+ }
77
+ }
78
+
79
+ // Create default instance
80
+ const defaultInstance = new LLMReranker();
81
+
82
+ // CJS+ESM interop pattern
83
+ module.exports = defaultInstance;
84
+ module.exports.LLMReranker = LLMReranker;
85
+ module.exports.default = module.exports;
@@ -0,0 +1,36 @@
1
+ // src/scripts/script-utilities.js
2
+
3
+ // default sleeper uses real timers (prod) - unref'd to not block process exit
4
+ const sleep = (ms) =>
5
+ new Promise((resolve) => {
6
+ const t = setTimeout(resolve, ms);
7
+ // critical: don't keep the process alive just because of a timer
8
+ if (typeof t.unref === "function") t.unref();
9
+ });
10
+
11
+ async function retry(fn, opts = {}) {
12
+ const {
13
+ retries = 3,
14
+ baseDelay = 100,
15
+ factor = 2,
16
+ onDelay = () => {},
17
+ sleeper = sleep, // <-- inject for tests
18
+ } = opts;
19
+
20
+ let lastErr;
21
+ for (let attempt = 0; attempt <= retries; attempt++) {
22
+ try {
23
+ // pass attempt if useful for logging/logic
24
+ return await fn(attempt);
25
+ } catch (err) {
26
+ lastErr = err;
27
+ if (attempt === retries) break;
28
+ const delay = baseDelay * Math.pow(factor, attempt);
29
+ onDelay(delay, attempt);
30
+ await sleeper(delay); // <-- no-op in tests
31
+ }
32
+ }
33
+ throw lastErr;
34
+ }
35
+
36
+ module.exports = { retry, sleep };