@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.
- package/.ragrc.schema.json +218 -0
- package/README.md +651 -393
- package/bin/cli.js +8 -14
- package/dist/index.d.ts +237 -0
- package/dist/index.mjs +22 -7
- package/package.json +17 -13
- package/src/ai/adaptive-retrieval.js +191 -0
- package/src/ai/federated-learning.js +214 -0
- package/src/ai/federation/federated-learning-coordinator.js +345 -0
- package/src/ai/federation.js +76 -0
- package/src/ai/index-fixed.js +509 -0
- package/src/ai/index.js +33 -0
- package/src/ai/model-trainer.js +217 -0
- package/src/ai/model-training.js +205 -0
- package/src/ai/module-template.js +37 -0
- package/src/ai/multimodal/multi-modal-processor.js +345 -0
- package/src/ai/multimodal-processing.js +268 -0
- package/src/ai/multimodal.js +71 -0
- package/src/ai/orchestrator.js +70 -0
- package/src/ai/retrieval/adaptive-retrieval-engine.js +398 -0
- package/src/ai/retrieval-engine.js +69 -0
- package/src/ai/training/model-training-orchestrator.js +228 -0
- package/src/ci/workflow-analyzer.js +71 -0
- package/src/cli/commands/ai-ml.js +967 -0
- package/src/cli/commands/docs.js +228 -0
- package/src/cli/commands/dx.js +538 -0
- package/src/cli/commands/plugin-hub.js +875 -0
- package/src/cli/doctor-command.js +639 -0
- package/src/cli/enhanced-cli-commands.js +945 -0
- package/src/cli/interactive-wizard.js +997 -0
- package/src/cli/plugin-marketplace-commands.js +869 -0
- package/src/cli.js +17 -0
- package/src/config/enhanced-ragrc-schema.js +632 -0
- package/src/config/load-config.js +54 -0
- package/src/config/load-plugin-config.js +69 -0
- package/src/config/normalize-config.js +105 -0
- package/src/config/schema-validator.js +315 -0
- package/src/config/validate-plugin-schema.js +35 -0
- package/src/config/validate-schema.js +113 -0
- package/src/contracts/plugin-contracts.js +33 -0
- package/src/core/create-pipeline.js +99 -0
- package/src/core/dependency-injection.js +242 -0
- package/src/core/observability/event-logger.js +241 -0
- package/src/core/observability/instrumented-pipeline.js +609 -0
- package/src/core/observability/metrics.js +497 -0
- package/src/core/observability/tracing.js +781 -0
- package/src/core/performance/benchmark.js +516 -0
- package/src/core/performance/parallel-processor.js +240 -0
- package/src/core/performance/streaming-safeguards.js +611 -0
- package/src/core/pipeline-factory.js +60 -0
- package/src/core/plugin-contracts.js +89 -0
- package/src/core/plugin-marketplace/plugin-metadata.js +485 -0
- package/src/core/plugin-marketplace/plugin-publisher.js +574 -0
- package/src/core/plugin-marketplace/plugin-registry-format.js +419 -0
- package/src/core/plugin-marketplace/version-resolver.js +61 -0
- package/src/core/plugin-registry.js +265 -0
- package/src/dag/dag-engine.js +954 -0
- package/src/dag/dag-node.js +76 -0
- package/src/dag/enhanced-dag-engine.js +822 -0
- package/src/dx/index.js +40 -0
- package/src/dx/integration-templates.js +665 -0
- package/src/dx/performance-profiler.js +968 -0
- package/src/dx/realtime-debugger.js +755 -0
- package/src/dx/visual-pipeline-builder.js +578 -0
- package/src/ecosystem/plugin-analytics-dashboard.js +778 -0
- package/src/ecosystem/plugin-certification.js +580 -0
- package/src/ecosystem/plugin-hub.js +821 -0
- package/src/enterprise/audit-logging.js +967 -0
- package/src/enterprise/data-governance.js +408 -0
- package/src/enterprise/multi-tenancy.js +496 -0
- package/src/enterprise/sso-integration.js +903 -0
- package/src/evaluate/evaluator.js +52 -0
- package/src/evaluate/scoring.js +91 -0
- package/src/index.js +67 -0
- package/src/ingest.js +59 -0
- package/src/loader/csv-loader.js +38 -0
- package/src/loader/directory-loader.js +48 -0
- package/src/loader/html-loader.js +62 -0
- package/src/loader/markdown-loader.js +67 -0
- package/src/mocks/openai-embedder.js +119 -0
- package/src/mocks/openai-llm.js +77 -0
- package/src/mocks/pdf-loader.js +21 -0
- package/src/mocks/pinecone-retriever.js +106 -0
- package/src/observability/audit-logger.js +758 -0
- package/src/observability/dashboard-config.json +675 -0
- package/src/observability/event-logger.js +310 -0
- package/src/observability/metrics.js +691 -0
- package/src/observability/security-monitor.js +830 -0
- package/src/observability/slo-monitor.js +319 -0
- package/src/observability/telemetry.js +686 -0
- package/src/pipeline/pipeline.js +18 -0
- package/src/plugins/sample-embedder.js +53 -0
- package/src/plugins/sample-llm.js +30 -0
- package/src/plugins/sample-loader.js +24 -0
- package/src/plugins/sample-retriever.js +84 -0
- package/src/query.js +117 -0
- package/src/reranker/llm-reranker.js +85 -0
- package/src/scripts/script-utilities.js +36 -0
- package/src/security/plugin-sandbox.js +586 -0
- package/src/security/plugin-signature-verifier.js +414 -0
- package/src/security/validator.js +36 -0
- package/src/utils/ci/diagnostic-reporter.js +57 -0
- package/src/utils/logger.js +211 -0
- package/src/utils/performance-monitor.js +561 -0
- package/src/utils/plugin-scaffolder.js +447 -0
- package/src/utils/retry-policy.js +443 -0
- package/src/utils/retry.js +107 -0
- package/src/utils/safe-expression-evaluator.js +579 -0
- package/src/utils/structured-logger.js +361 -0
- package/src/utils/validate-plugin-contract.js +42 -0
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
/**
|
|
2
|
+
const path = require('path');
|
|
3
|
+
* Instrumented pipeline wrapper with observability features
|
|
4
|
+
* Integrates event logging, tracing, and metrics collection
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
PipelineEventLogger,
|
|
9
|
+
EventTypes,
|
|
10
|
+
EventSeverity,
|
|
11
|
+
} = require('./event-logger.js');
|
|
12
|
+
// eslint-disable-line global-require
|
|
13
|
+
const { pipelineTracer } = require('./tracing.js');
|
|
14
|
+
// eslint-disable-line global-require
|
|
15
|
+
const { pipelineMetrics } = require('./metrics.js');
|
|
16
|
+
// eslint-disable-line global-require
|
|
17
|
+
const { logger } = require('../../utils/structured-logger.js');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Instrumented pipeline wrapper that adds observability to any pipeline
|
|
21
|
+
*/
|
|
22
|
+
class InstrumentedPipeline {
|
|
23
|
+
constructor(pipeline, _options = {}) {
|
|
24
|
+
this.pipeline = pipeline;
|
|
25
|
+
this._options = {
|
|
26
|
+
enableTracing: _options.hasOwnProperty('enableTracing')
|
|
27
|
+
? _options.enableTracing
|
|
28
|
+
: true,
|
|
29
|
+
enableMetrics: _options.enableMetrics !== false,
|
|
30
|
+
enableEventLogging: _options.enableEventLogging !== false,
|
|
31
|
+
verboseLogging: _options.verboseLogging || false,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Create event logger instance
|
|
35
|
+
this.eventLogger = new PipelineEventLogger();
|
|
36
|
+
if (this._options.enableEventLogging) {
|
|
37
|
+
this.eventLogger.startSession();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Set reference in base pipeline for plugin instrumentation
|
|
41
|
+
if (pipeline._instrumentedPipeline !== undefined) {
|
|
42
|
+
pipeline._instrumentedPipeline = this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Start memory monitoring
|
|
46
|
+
if (this._options.enableMetrics) {
|
|
47
|
+
this.startMemoryMonitoring();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Start periodic memory monitoring
|
|
53
|
+
*/
|
|
54
|
+
startMemoryMonitoring() {
|
|
55
|
+
this.memoryInterval = setInterval(() => {
|
|
56
|
+
pipelineMetrics.recordMemoryUsage();
|
|
57
|
+
}, 5000); // Every 5 seconds
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Stop memory monitoring
|
|
62
|
+
*/
|
|
63
|
+
stopMemoryMonitoring() {
|
|
64
|
+
if (this.memoryInterval) {
|
|
65
|
+
clearInterval(this.memoryInterval);
|
|
66
|
+
this.memoryInterval = null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Instrument plugin execution
|
|
72
|
+
* @param {string} pluginType - Type of plugin
|
|
73
|
+
* @param {string} pluginName - Name of plugin
|
|
74
|
+
* @param {Function} pluginFn - Plugin function
|
|
75
|
+
* @param {any} input - Plugin input
|
|
76
|
+
* @returns {Promise<any>} Plugin result
|
|
77
|
+
*/
|
|
78
|
+
async instrumentPlugin(pluginType, pluginName, pluginFn, input) {
|
|
79
|
+
const startTime = Date.now();
|
|
80
|
+
|
|
81
|
+
// Event logging
|
|
82
|
+
if (this._options.enableEventLogging) {
|
|
83
|
+
this.eventLogger.logPluginStart({ pluginType, pluginName, input });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Metrics
|
|
87
|
+
if (this._options.enableMetrics) {
|
|
88
|
+
pipelineMetrics.recordOperationStart('plugin', pluginType, pluginName);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
let result;
|
|
93
|
+
|
|
94
|
+
// Execute plugin with or without tracing
|
|
95
|
+
try {
|
|
96
|
+
if (this._options.enableTracing) {
|
|
97
|
+
result = await pipelineTracer.tracePlugin(
|
|
98
|
+
pluginType,
|
|
99
|
+
pluginName,
|
|
100
|
+
pluginFn,
|
|
101
|
+
input,
|
|
102
|
+
);
|
|
103
|
+
} else {
|
|
104
|
+
result = await pluginFn(input);
|
|
105
|
+
}
|
|
106
|
+
} catch (tracingError) {
|
|
107
|
+
// Check if this is a plugin execution error or tracing error
|
|
108
|
+
if (
|
|
109
|
+
tracingError.message &&
|
|
110
|
+
tracingError.message.includes('service unavailable')
|
|
111
|
+
) {
|
|
112
|
+
// This is a plugin error, not a tracing error - rethrow it
|
|
113
|
+
throw tracingError;
|
|
114
|
+
}
|
|
115
|
+
// Fallback to direct execution if tracing fails
|
|
116
|
+
logger.warn('Tracing failed, falling back to direct execution', {
|
|
117
|
+
error: tracingError.message,
|
|
118
|
+
});
|
|
119
|
+
result = await pluginFn(input);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const duration = Math.max(Date.now() - startTime, 1); // Ensure non-zero duration
|
|
123
|
+
|
|
124
|
+
// Event logging
|
|
125
|
+
if (this._options.enableEventLogging) {
|
|
126
|
+
this.eventLogger.logPluginEnd({
|
|
127
|
+
pluginType,
|
|
128
|
+
pluginName,
|
|
129
|
+
duration,
|
|
130
|
+
result,
|
|
131
|
+
status: 'success',
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Metrics
|
|
136
|
+
if (this._options.enableMetrics) {
|
|
137
|
+
pipelineMetrics.recordOperationEnd(
|
|
138
|
+
'plugin',
|
|
139
|
+
pluginType,
|
|
140
|
+
pluginName,
|
|
141
|
+
duration,
|
|
142
|
+
'success',
|
|
143
|
+
);
|
|
144
|
+
this.recordPluginSpecificMetrics(
|
|
145
|
+
pluginType,
|
|
146
|
+
pluginName,
|
|
147
|
+
duration,
|
|
148
|
+
input,
|
|
149
|
+
result,
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return result;
|
|
154
|
+
} catch (error) {
|
|
155
|
+
const duration = Date.now() - startTime;
|
|
156
|
+
|
|
157
|
+
// Event logging
|
|
158
|
+
if (this._options.enableEventLogging) {
|
|
159
|
+
this.eventLogger.logPluginError({
|
|
160
|
+
pluginType,
|
|
161
|
+
pluginName,
|
|
162
|
+
duration,
|
|
163
|
+
error,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Metrics
|
|
168
|
+
if (this._options.enableMetrics) {
|
|
169
|
+
pipelineMetrics.recordOperationEnd(
|
|
170
|
+
'plugin',
|
|
171
|
+
pluginType,
|
|
172
|
+
pluginName,
|
|
173
|
+
duration,
|
|
174
|
+
'error',
|
|
175
|
+
);
|
|
176
|
+
pipelineMetrics.recordError('plugin', pluginType, pluginName, error);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Record plugin-specific metrics
|
|
185
|
+
* @param {string} pluginType - Plugin _type
|
|
186
|
+
* @param {string} pluginName - Plugin name
|
|
187
|
+
* @param {number} duration - Duration in ms
|
|
188
|
+
* @param {any} input - Plugin input
|
|
189
|
+
* @param {any} result - Plugin result
|
|
190
|
+
*/
|
|
191
|
+
recordPluginSpecificMetrics(pluginType, pluginName, duration, input, result) {
|
|
192
|
+
switch (pluginType) {
|
|
193
|
+
case 'embedder': {
|
|
194
|
+
const tokenCount = this.estimateTokenCount(input);
|
|
195
|
+
const batchSize = Array.isArray(input) ? input.length : 1;
|
|
196
|
+
pipelineMetrics.recordEmbedding(
|
|
197
|
+
pluginName,
|
|
198
|
+
duration,
|
|
199
|
+
tokenCount,
|
|
200
|
+
batchSize,
|
|
201
|
+
);
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
case 'retriever': {
|
|
206
|
+
const resultCount = Array.isArray(result) ? result.length : 1;
|
|
207
|
+
pipelineMetrics.recordRetrieval(pluginName, duration, resultCount);
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
case 'llm': {
|
|
212
|
+
const inputTokens = this.estimateTokenCount(input);
|
|
213
|
+
const outputTokens = this.estimateTokenCount(result);
|
|
214
|
+
const streaming = this.isStreamingResult(result);
|
|
215
|
+
pipelineMetrics.recordLLM(
|
|
216
|
+
pluginName,
|
|
217
|
+
duration,
|
|
218
|
+
inputTokens,
|
|
219
|
+
outputTokens,
|
|
220
|
+
streaming,
|
|
221
|
+
);
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Estimate token count from text
|
|
229
|
+
* @param {any} text - Text to estimate
|
|
230
|
+
* @returns {number} Estimated token count
|
|
231
|
+
*/
|
|
232
|
+
estimateTokenCount(text) {
|
|
233
|
+
if (typeof text === 'string') {
|
|
234
|
+
return Math.ceil(text.length / 4); // Rough approximation
|
|
235
|
+
} else if (Array.isArray(text)) {
|
|
236
|
+
return text.reduce((sum, item) => sum + this.estimateTokenCount(item), 0);
|
|
237
|
+
} else if (text && typeof text === 'object') {
|
|
238
|
+
return this.estimateTokenCount(JSON.stringify(text));
|
|
239
|
+
}
|
|
240
|
+
return 0;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Check if result is from streaming
|
|
245
|
+
* @param {any} result - Result to check
|
|
246
|
+
* @returns {boolean} True if streaming result
|
|
247
|
+
*/
|
|
248
|
+
isStreamingResult(result) {
|
|
249
|
+
return result && typeof result === 'object' && result.streaming === true;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Instrumented ingest method
|
|
254
|
+
* @param {string} docPath - Document path
|
|
255
|
+
* @returns {Promise<void>}
|
|
256
|
+
*/
|
|
257
|
+
async ingest(docPath) {
|
|
258
|
+
if (this._options.enableEventLogging) {
|
|
259
|
+
this.eventLogger.logStageStart('ingest');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const startTime = Date.now();
|
|
263
|
+
|
|
264
|
+
try {
|
|
265
|
+
let result;
|
|
266
|
+
|
|
267
|
+
if (this._options.enableTracing) {
|
|
268
|
+
result = await pipelineTracer.traceStage(
|
|
269
|
+
'ingest',
|
|
270
|
+
async () => {
|
|
271
|
+
return await this.pipeline.ingest(docPath);
|
|
272
|
+
},
|
|
273
|
+
{ docPath },
|
|
274
|
+
);
|
|
275
|
+
} else {
|
|
276
|
+
result = await this.pipeline.ingest(docPath);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const duration = Date.now() - startTime;
|
|
280
|
+
|
|
281
|
+
if (this._options.enableEventLogging) {
|
|
282
|
+
this.eventLogger.logStageEnd('ingest', duration, {
|
|
283
|
+
docPath,
|
|
284
|
+
success: true,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return result;
|
|
289
|
+
} catch (error) {
|
|
290
|
+
const duration = Date.now() - startTime;
|
|
291
|
+
|
|
292
|
+
if (this._options.enableEventLogging) {
|
|
293
|
+
this.eventLogger.logEvent(
|
|
294
|
+
EventTypes.STAGE_ERROR,
|
|
295
|
+
EventSeverity.ERROR,
|
|
296
|
+
{ stage: 'ingest', duration, docPath, error: error.message },
|
|
297
|
+
`Ingest stage failed: ${error.message}`,
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
throw error;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Instrumented query method
|
|
307
|
+
* @param {string} prompt - Query prompt
|
|
308
|
+
* @returns {Promise<string>}
|
|
309
|
+
*/
|
|
310
|
+
async query(prompt) {
|
|
311
|
+
if (this._options.enableEventLogging) {
|
|
312
|
+
this.eventLogger.logStageStart('query');
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const startTime = Date.now();
|
|
316
|
+
|
|
317
|
+
try {
|
|
318
|
+
let result;
|
|
319
|
+
|
|
320
|
+
if (this._options.enableTracing) {
|
|
321
|
+
result = await pipelineTracer.traceStage(
|
|
322
|
+
'query',
|
|
323
|
+
async () => {
|
|
324
|
+
return await this.pipeline.query(prompt);
|
|
325
|
+
},
|
|
326
|
+
{ promptLength: prompt.length },
|
|
327
|
+
);
|
|
328
|
+
} else {
|
|
329
|
+
result = await this.pipeline.query(prompt);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const duration = Date.now() - startTime;
|
|
333
|
+
|
|
334
|
+
if (this._options.enableEventLogging) {
|
|
335
|
+
this.eventLogger.logStageEnd('query', duration, {
|
|
336
|
+
promptLength: prompt.length,
|
|
337
|
+
responseLength:
|
|
338
|
+
typeof result === 'string' ? result.length : result?.length || 0,
|
|
339
|
+
success: true,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return result;
|
|
344
|
+
} catch (error) {
|
|
345
|
+
const duration = Date.now() - startTime;
|
|
346
|
+
|
|
347
|
+
if (this._options.enableEventLogging) {
|
|
348
|
+
this.eventLogger.logEvent(
|
|
349
|
+
EventTypes.STAGE_ERROR,
|
|
350
|
+
EventSeverity.ERROR,
|
|
351
|
+
{
|
|
352
|
+
stage: 'query',
|
|
353
|
+
duration,
|
|
354
|
+
promptLength: prompt.length,
|
|
355
|
+
error: error.message,
|
|
356
|
+
},
|
|
357
|
+
`Query stage failed: ${error.message}`,
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
throw error;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Instrumented streaming query method
|
|
367
|
+
* @param {string} prompt - Query prompt
|
|
368
|
+
* @returns {AsyncGenerator<string>}
|
|
369
|
+
*/
|
|
370
|
+
async *queryStream(prompt) {
|
|
371
|
+
if (this._options.enableEventLogging) {
|
|
372
|
+
this.eventLogger.logStageStart('query_stream');
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const startTime = Date.now();
|
|
376
|
+
let tokenCount = 0;
|
|
377
|
+
|
|
378
|
+
try {
|
|
379
|
+
if (this._options.enableTracing) {
|
|
380
|
+
const span = pipelineTracer.startSpan('pipeline.query_stream');
|
|
381
|
+
span.setAttributes({
|
|
382
|
+
'pipeline.stage': 'query_stream',
|
|
383
|
+
'query.prompt_length': prompt.length,
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
try {
|
|
387
|
+
for await (const token of this.pipeline.queryStream(prompt)) {
|
|
388
|
+
tokenCount++;
|
|
389
|
+
yield token;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
span.setAttributes({
|
|
393
|
+
'query.tokens_generated': tokenCount,
|
|
394
|
+
'query.success': true,
|
|
395
|
+
});
|
|
396
|
+
} finally {
|
|
397
|
+
span.end();
|
|
398
|
+
}
|
|
399
|
+
} else {
|
|
400
|
+
for await (const token of this.pipeline.queryStream(prompt)) {
|
|
401
|
+
tokenCount++;
|
|
402
|
+
yield token;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const duration = Date.now() - startTime;
|
|
407
|
+
|
|
408
|
+
if (this._options.enableEventLogging) {
|
|
409
|
+
this.eventLogger.logStageEnd('query_stream', duration, {
|
|
410
|
+
promptLength: prompt.length,
|
|
411
|
+
tokensGenerated: tokenCount,
|
|
412
|
+
success: true,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
} catch (error) {
|
|
416
|
+
const duration = Date.now() - startTime;
|
|
417
|
+
|
|
418
|
+
if (this._options.enableEventLogging) {
|
|
419
|
+
this.eventLogger.logEvent(
|
|
420
|
+
EventTypes.STAGE_ERROR,
|
|
421
|
+
EventSeverity.ERROR,
|
|
422
|
+
{
|
|
423
|
+
stage: 'query_stream',
|
|
424
|
+
duration,
|
|
425
|
+
promptLength: prompt.length,
|
|
426
|
+
tokensGenerated: tokenCount,
|
|
427
|
+
error: error.message,
|
|
428
|
+
},
|
|
429
|
+
`Streaming query stage failed: ${error.message}`,
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
throw error;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Instrumented streaming ingest method
|
|
439
|
+
* @param {string} docPath - Document path
|
|
440
|
+
* @returns {AsyncGenerator}
|
|
441
|
+
*/
|
|
442
|
+
async *ingestStream(docPath) {
|
|
443
|
+
if (!this.pipeline.ingestStream) {
|
|
444
|
+
throw new Error('Pipeline does not support streaming ingest');
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (this._options.enableEventLogging) {
|
|
448
|
+
this.eventLogger.logStageStart('ingest_stream');
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const startTime = Date.now();
|
|
452
|
+
let chunksProcessed = 0;
|
|
453
|
+
let chunksFailed = 0;
|
|
454
|
+
|
|
455
|
+
try {
|
|
456
|
+
for await (const update of this.pipeline.ingestStream(docPath)) {
|
|
457
|
+
if (update._type === 'chunk_processed') {
|
|
458
|
+
chunksProcessed++;
|
|
459
|
+
} else if (update._type === 'chunk_failed') {
|
|
460
|
+
chunksFailed++;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
yield update;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const duration = Date.now() - startTime;
|
|
467
|
+
|
|
468
|
+
if (this._options.enableEventLogging) {
|
|
469
|
+
this.eventLogger.logStageEnd('ingest_stream', duration, {
|
|
470
|
+
docPath,
|
|
471
|
+
chunksProcessed,
|
|
472
|
+
chunksFailed,
|
|
473
|
+
success: true,
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
} catch (error) {
|
|
477
|
+
const duration = Date.now() - startTime;
|
|
478
|
+
|
|
479
|
+
if (this._options.enableEventLogging) {
|
|
480
|
+
this.eventLogger.logEvent(
|
|
481
|
+
EventTypes.STAGE_ERROR,
|
|
482
|
+
EventSeverity.ERROR,
|
|
483
|
+
{
|
|
484
|
+
stage: 'ingest_stream',
|
|
485
|
+
duration,
|
|
486
|
+
docPath,
|
|
487
|
+
chunksProcessed,
|
|
488
|
+
chunksFailed,
|
|
489
|
+
error: error.message,
|
|
490
|
+
},
|
|
491
|
+
`Streaming ingest stage failed: ${error.message}`,
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
throw error;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Get observability statistics
|
|
501
|
+
* @returns {object} Observability statistics
|
|
502
|
+
*/
|
|
503
|
+
getObservabilityStats() {
|
|
504
|
+
const stats = {
|
|
505
|
+
enabled: this._options,
|
|
506
|
+
session: this.eventLogger.getSessionStats(),
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
if (this._options.enableMetrics) {
|
|
510
|
+
stats.metrics = pipelineMetrics.getSummary();
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (this._options.enableTracing) {
|
|
514
|
+
stats.tracing = pipelineTracer.getTraceStats();
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return stats;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Export observability data
|
|
522
|
+
* @param {object} _options - Export _options
|
|
523
|
+
* @returns {object} Exported data
|
|
524
|
+
*/
|
|
525
|
+
exportObservabilityData(_options = {}) {
|
|
526
|
+
const data = {
|
|
527
|
+
timestamp: new Date().toISOString(),
|
|
528
|
+
sessionId: this.eventLogger.sessionId,
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
if (this._options.enableEventLogging && _options.includeEvents !== false) {
|
|
532
|
+
data.events = this.eventLogger.getEventHistory(
|
|
533
|
+
_options.eventFilters || {},
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
if (this._options.enableMetrics && _options.includeMetrics !== false) {
|
|
538
|
+
data.metrics = pipelineMetrics.exportMetrics();
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (this._options.enableTracing && _options.includeTraces !== false) {
|
|
542
|
+
data.traces = pipelineTracer.exportSpans(_options.traceFilters || {});
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
return data;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Clear all observability data
|
|
550
|
+
*/
|
|
551
|
+
clearObservabilityData() {
|
|
552
|
+
if (this._options.enableEventLogging) {
|
|
553
|
+
this.eventLogger.clearHistory();
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if (this._options.enableMetrics) {
|
|
557
|
+
pipelineMetrics.clearMetrics();
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
if (this._options.enableTracing) {
|
|
561
|
+
pipelineTracer.clearCompletedSpans();
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Cleanup resources
|
|
567
|
+
*/
|
|
568
|
+
cleanup() {
|
|
569
|
+
this.stopMemoryMonitoring();
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Get pipeline configuration with observability settings
|
|
574
|
+
* @returns {object} Pipeline configuration
|
|
575
|
+
*/
|
|
576
|
+
getConfig() {
|
|
577
|
+
const baseConfig = this.pipeline.getConfig ? this.pipeline.getConfig() : {};
|
|
578
|
+
|
|
579
|
+
return {
|
|
580
|
+
...baseConfig,
|
|
581
|
+
observability: {
|
|
582
|
+
enabled: this._options,
|
|
583
|
+
sessionId: this.eventLogger.sessionId,
|
|
584
|
+
capabilities: {
|
|
585
|
+
eventLogging: this._options.enableEventLogging,
|
|
586
|
+
tracing: this._options.enableTracing,
|
|
587
|
+
metrics: this._options.enableMetrics,
|
|
588
|
+
},
|
|
589
|
+
},
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Create instrumented pipeline wrapper
|
|
596
|
+
* @param {object} pipeline - Base pipeline _instance
|
|
597
|
+
* @param {object} _options - Observability _options
|
|
598
|
+
* @returns {InstrumentedPipeline} Instrumented pipeline
|
|
599
|
+
*/
|
|
600
|
+
function createInstrumentedPipeline(_pipeline, options = {}) {
|
|
601
|
+
return new InstrumentedPipeline(_pipeline, options);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Default export
|
|
605
|
+
|
|
606
|
+
module.exports = {
|
|
607
|
+
InstrumentedPipeline,
|
|
608
|
+
createInstrumentedPipeline,
|
|
609
|
+
};
|