@devilsdev/rag-pipeline-utils 2.1.12 → 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 +292 -32
- 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,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model Training Orchestrator
|
|
3
|
+
* Provides model training coordination and job management
|
|
4
|
+
* Extracted from ai/index.js per CLAUDE.md decomposition requirements
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
"use strict";
|
|
8
|
+
|
|
9
|
+
// Import the existing model training implementation
|
|
10
|
+
const modelTraining = require("./model-training");
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* ModelTrainingOrchestrator class
|
|
14
|
+
* Coordinates and manages model training jobs across tenants
|
|
15
|
+
*/
|
|
16
|
+
class ModelTrainingOrchestrator {
|
|
17
|
+
constructor() {
|
|
18
|
+
this.jobs = new Map();
|
|
19
|
+
this.optimizations = new Map();
|
|
20
|
+
this.deployments = new Map();
|
|
21
|
+
this.jobCounter = 0;
|
|
22
|
+
this.optCounter = 0;
|
|
23
|
+
this.deployCounter = 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Create a training job
|
|
28
|
+
* @param {string} tenantId - Tenant identifier
|
|
29
|
+
* @param {object} trainingConfig - Training configuration
|
|
30
|
+
* @returns {Promise<string>} Job ID
|
|
31
|
+
*/
|
|
32
|
+
async createTrainingJob(tenantId, trainingConfig) {
|
|
33
|
+
return await modelTraining.createTrainingJob(tenantId, trainingConfig);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get training job status
|
|
38
|
+
* @param {string} jobId - Job identifier
|
|
39
|
+
* @returns {Promise<object>} Job status
|
|
40
|
+
*/
|
|
41
|
+
async getJobStatus(jobId) {
|
|
42
|
+
return await modelTraining.getJobStatus(jobId);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Optimize model configuration
|
|
47
|
+
* @param {object} modelConfig - Model configuration
|
|
48
|
+
* @returns {Promise<object>} Optimized configuration
|
|
49
|
+
*/
|
|
50
|
+
async optimizeModel(modelConfig) {
|
|
51
|
+
return await modelTraining.optimizeModel(modelConfig);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Deploy trained model
|
|
56
|
+
* @param {string} jobId - Training job identifier
|
|
57
|
+
* @param {object} deployConfig - Deployment configuration
|
|
58
|
+
* @returns {Promise<string>} Deployment ID
|
|
59
|
+
*/
|
|
60
|
+
async deployModel(jobId, deployConfig) {
|
|
61
|
+
return await modelTraining.deployModel(jobId, deployConfig);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Create and export singleton instance
|
|
66
|
+
const orchestrator = new ModelTrainingOrchestrator();
|
|
67
|
+
|
|
68
|
+
module.exports = orchestrator;
|
|
69
|
+
module.exports.ModelTrainingOrchestrator = ModelTrainingOrchestrator;
|
|
70
|
+
module.exports.default = module.exports;
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive Retrieval Engine - Extracted from monolithic AI module
|
|
3
|
+
* Handles personalized content retrieval and user profile management
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { EventEmitter } = require("events");
|
|
7
|
+
const crypto = require("crypto");
|
|
8
|
+
|
|
9
|
+
class AdaptiveRetrievalEngine extends EventEmitter {
|
|
10
|
+
constructor(options = {}) {
|
|
11
|
+
super();
|
|
12
|
+
this.config = {
|
|
13
|
+
learning: {
|
|
14
|
+
algorithm: options.algorithm || "contextual_bandit",
|
|
15
|
+
explorationRate: options.explorationRate || 0.1,
|
|
16
|
+
learningRate: options.learningRate || 0.01,
|
|
17
|
+
},
|
|
18
|
+
...options,
|
|
19
|
+
};
|
|
20
|
+
this.userProfiles = new Map();
|
|
21
|
+
this.queryHistory = new Map();
|
|
22
|
+
this.feedbackHistory = [];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async initializeUserProfile(userId, preferences = {}) {
|
|
26
|
+
const profile = {
|
|
27
|
+
userId,
|
|
28
|
+
interests: preferences.interests || [],
|
|
29
|
+
preferences: preferences,
|
|
30
|
+
expertise: preferences.expertise || "beginner",
|
|
31
|
+
createdAt: Date.now(),
|
|
32
|
+
interactions: 0,
|
|
33
|
+
personalizedRankings: new Map(),
|
|
34
|
+
learningHistory: [],
|
|
35
|
+
adaptationWeights: {
|
|
36
|
+
contentSimilarity: 0.4,
|
|
37
|
+
userPreference: 0.3,
|
|
38
|
+
contextualRelevance: 0.2,
|
|
39
|
+
temporalDecay: 0.1,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
this.userProfiles.set(userId, profile);
|
|
44
|
+
this.emit("userProfileInitialized", { userId, profile });
|
|
45
|
+
return profile;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async getUserProfile(userId) {
|
|
49
|
+
const profile = this.userProfiles.get(userId);
|
|
50
|
+
if (!profile) {
|
|
51
|
+
throw new Error(`User profile not found for ${userId}`);
|
|
52
|
+
}
|
|
53
|
+
return profile;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async adaptiveRetrieve(userId, query, options = {}) {
|
|
57
|
+
const profile = this.userProfiles.get(userId);
|
|
58
|
+
if (!profile) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
`User profile not found for ${userId}. Please initialize profile first.`,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const maxResults = options.maxResults || 10;
|
|
65
|
+
|
|
66
|
+
// Simulate document retrieval with adaptive ranking
|
|
67
|
+
const baseDocuments = Array.from({ length: maxResults }, (_, i) => ({
|
|
68
|
+
id: `doc_${i + 1}`,
|
|
69
|
+
title: `Document ${i + 1} about ${query}`,
|
|
70
|
+
content: `Content related to ${query} with relevance score`,
|
|
71
|
+
baseScore: 0.9 - i * 0.1,
|
|
72
|
+
metadata: {
|
|
73
|
+
source: "knowledge_base",
|
|
74
|
+
timestamp: Date.now() - Math.random() * 86400000,
|
|
75
|
+
tags: profile.interests.slice(0, 2),
|
|
76
|
+
},
|
|
77
|
+
}));
|
|
78
|
+
|
|
79
|
+
// Apply adaptive ranking based on user profile
|
|
80
|
+
const adaptedDocuments = baseDocuments
|
|
81
|
+
.map((doc) => {
|
|
82
|
+
const adaptiveScore = this._calculateAdaptiveScore(doc, profile, query);
|
|
83
|
+
return {
|
|
84
|
+
...doc,
|
|
85
|
+
adaptiveScore,
|
|
86
|
+
finalScore: doc.baseScore * 0.6 + adaptiveScore * 0.4,
|
|
87
|
+
adaptationFactors: {
|
|
88
|
+
userInterests: profile.interests.some((interest) =>
|
|
89
|
+
doc.title.toLowerCase().includes(interest.toLowerCase()),
|
|
90
|
+
)
|
|
91
|
+
? 0.2
|
|
92
|
+
: 0,
|
|
93
|
+
expertise: profile.expertise === "advanced" ? 0.1 : 0,
|
|
94
|
+
historicalPreference: Math.random() * 0.1,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
})
|
|
98
|
+
.sort((a, b) => b.finalScore - a.finalScore);
|
|
99
|
+
|
|
100
|
+
const result = {
|
|
101
|
+
documents: adaptedDocuments,
|
|
102
|
+
adaptationMetadata: {
|
|
103
|
+
userId,
|
|
104
|
+
query,
|
|
105
|
+
adaptationStrategy: this.config.learning.algorithm,
|
|
106
|
+
profileFactors: {
|
|
107
|
+
interests: profile.interests,
|
|
108
|
+
expertise: profile.expertise,
|
|
109
|
+
interactionCount: profile.interactions,
|
|
110
|
+
},
|
|
111
|
+
retrievalTimestamp: Date.now(),
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// Update interaction count
|
|
116
|
+
profile.interactions++;
|
|
117
|
+
|
|
118
|
+
this.emit("adaptiveRetrievalCompleted", {
|
|
119
|
+
userId,
|
|
120
|
+
query,
|
|
121
|
+
resultsCount: adaptedDocuments.length,
|
|
122
|
+
adaptationApplied: true,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async processFeedback(userId, feedback) {
|
|
129
|
+
const profile = this.userProfiles.get(userId);
|
|
130
|
+
if (!profile) {
|
|
131
|
+
throw new Error(`User profile not found for ${userId}`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Store feedback in learning history
|
|
135
|
+
const feedbackEntry = {
|
|
136
|
+
id: crypto.randomUUID(),
|
|
137
|
+
timestamp: Date.now(),
|
|
138
|
+
query: feedback.query,
|
|
139
|
+
results: feedback.results,
|
|
140
|
+
ratings: feedback.ratings || [],
|
|
141
|
+
clickedResults: feedback.clickedResults || [],
|
|
142
|
+
dwellTime: feedback.dwellTime || [],
|
|
143
|
+
feedbackType: "explicit",
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
profile.learningHistory.push(feedbackEntry);
|
|
147
|
+
|
|
148
|
+
// Initialize preferences.queryPatterns if not exists
|
|
149
|
+
if (!profile.preferences.queryPatterns) {
|
|
150
|
+
profile.preferences.queryPatterns = [];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Update query patterns based on feedback
|
|
154
|
+
if (feedback.query) {
|
|
155
|
+
const existingPattern = profile.preferences.queryPatterns.find(
|
|
156
|
+
(p) => p.query === feedback.query,
|
|
157
|
+
);
|
|
158
|
+
if (existingPattern) {
|
|
159
|
+
existingPattern.frequency++;
|
|
160
|
+
existingPattern.lastUsed = Date.now();
|
|
161
|
+
if (feedback.ratings && feedback.ratings.length > 0) {
|
|
162
|
+
const avgRating =
|
|
163
|
+
feedback.ratings.reduce((sum, rating) => sum + rating, 0) /
|
|
164
|
+
feedback.ratings.length;
|
|
165
|
+
existingPattern.avgRating =
|
|
166
|
+
(existingPattern.avgRating + avgRating) / 2;
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
const avgRating =
|
|
170
|
+
feedback.ratings && feedback.ratings.length > 0
|
|
171
|
+
? feedback.ratings.reduce((sum, rating) => sum + rating, 0) /
|
|
172
|
+
feedback.ratings.length
|
|
173
|
+
: 3;
|
|
174
|
+
profile.preferences.queryPatterns.push({
|
|
175
|
+
query: feedback.query,
|
|
176
|
+
frequency: 1,
|
|
177
|
+
avgRating,
|
|
178
|
+
lastUsed: Date.now(),
|
|
179
|
+
category: this._categorizeQuery(feedback.query),
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Update user preferences based on feedback
|
|
185
|
+
if (feedback.ratings && feedback.ratings.length > 0) {
|
|
186
|
+
const avgRating =
|
|
187
|
+
feedback.ratings.reduce((sum, rating) => sum + rating, 0) /
|
|
188
|
+
feedback.ratings.length;
|
|
189
|
+
|
|
190
|
+
// Extract topics from highly rated results
|
|
191
|
+
if (avgRating >= 4) {
|
|
192
|
+
feedback.results.forEach((result, index) => {
|
|
193
|
+
if (feedback.ratings[index] >= 4) {
|
|
194
|
+
// Extract keywords and add to interests if not already present
|
|
195
|
+
const keywords = result.title.toLowerCase().split(" ");
|
|
196
|
+
keywords.forEach((keyword) => {
|
|
197
|
+
if (keyword.length > 3 && !profile.interests.includes(keyword)) {
|
|
198
|
+
profile.interests.push(keyword);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Update adaptation weights based on feedback patterns
|
|
207
|
+
this._updateAdaptationWeights(profile, feedbackEntry);
|
|
208
|
+
|
|
209
|
+
this.emit("feedbackProcessed", {
|
|
210
|
+
userId,
|
|
211
|
+
feedbackId: feedbackEntry.id,
|
|
212
|
+
learningHistorySize: profile.learningHistory.length,
|
|
213
|
+
updatedInterests: profile.interests,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
processed: true,
|
|
218
|
+
feedbackId: feedbackEntry.id,
|
|
219
|
+
profileUpdated: true,
|
|
220
|
+
newInterestsCount: profile.interests.length,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async generatePersonalizedRankings(userId, results, context = {}) {
|
|
225
|
+
const profile = this.userProfiles.get(userId);
|
|
226
|
+
if (!profile) {
|
|
227
|
+
throw new Error(`User profile not found for ${userId}`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Simulate personalized ranking based on user interests
|
|
231
|
+
const rankedResults = results
|
|
232
|
+
.map((result) => ({
|
|
233
|
+
...result,
|
|
234
|
+
personalizedScore: Math.random() * 0.5 + 0.5,
|
|
235
|
+
relevanceFactors: profile.interests.slice(0, 2),
|
|
236
|
+
}))
|
|
237
|
+
.sort((a, b) => b.personalizedScore - a.personalizedScore);
|
|
238
|
+
|
|
239
|
+
this.emit("personalizedRankingsGenerated", {
|
|
240
|
+
userId,
|
|
241
|
+
resultsCount: rankedResults.length,
|
|
242
|
+
});
|
|
243
|
+
return rankedResults;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async personalizeRanking(userId, documents, context = {}) {
|
|
247
|
+
const profile = this.userProfiles.get(userId);
|
|
248
|
+
if (!profile) {
|
|
249
|
+
throw new Error(`User profile not found for ${userId}`);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Apply personalized ranking to documents
|
|
253
|
+
const personalizedResults = documents
|
|
254
|
+
.map((doc) => {
|
|
255
|
+
let personalizedScore = doc.score || 0.5;
|
|
256
|
+
const rankingFactors = {
|
|
257
|
+
contentRelevance: 0,
|
|
258
|
+
userInterests: 0,
|
|
259
|
+
historicalPreference: 0,
|
|
260
|
+
contextualMatch: 0,
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
// Boost score based on user interests
|
|
264
|
+
if (profile.interests && profile.interests.length > 0) {
|
|
265
|
+
const interestMatch = profile.interests.some((interest) =>
|
|
266
|
+
doc.content.toLowerCase().includes(interest.toLowerCase()),
|
|
267
|
+
);
|
|
268
|
+
if (interestMatch) {
|
|
269
|
+
rankingFactors.userInterests = 0.2;
|
|
270
|
+
personalizedScore += 0.2;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Apply historical preferences
|
|
275
|
+
if (profile.learningHistory && profile.learningHistory.length > 0) {
|
|
276
|
+
rankingFactors.historicalPreference = Math.random() * 0.1;
|
|
277
|
+
personalizedScore += rankingFactors.historicalPreference;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Contextual matching with query
|
|
281
|
+
if (context.query) {
|
|
282
|
+
const queryWords = context.query.toLowerCase().split(" ");
|
|
283
|
+
const contentWords = doc.content.toLowerCase().split(" ");
|
|
284
|
+
const overlap = queryWords.filter((word) =>
|
|
285
|
+
contentWords.includes(word),
|
|
286
|
+
).length;
|
|
287
|
+
rankingFactors.contextualMatch = (overlap / queryWords.length) * 0.15;
|
|
288
|
+
personalizedScore += rankingFactors.contextualMatch;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
rankingFactors.contentRelevance = doc.score || 0.5;
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
...doc,
|
|
295
|
+
personalizedScore: Math.min(personalizedScore, 1.0),
|
|
296
|
+
rankingFactors,
|
|
297
|
+
};
|
|
298
|
+
})
|
|
299
|
+
.sort((a, b) => b.personalizedScore - a.personalizedScore);
|
|
300
|
+
|
|
301
|
+
this.emit("personalizedRankingCompleted", {
|
|
302
|
+
userId,
|
|
303
|
+
documentsCount: documents.length,
|
|
304
|
+
query: context.query,
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
return personalizedResults;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async optimizeRetrieval(query, context = {}) {
|
|
311
|
+
const optimizedQuery = `optimized: ${query}`;
|
|
312
|
+
const retrievalStrategy = "adaptive";
|
|
313
|
+
|
|
314
|
+
this.emit("retrievalOptimized", {
|
|
315
|
+
originalQuery: query,
|
|
316
|
+
optimizedQuery,
|
|
317
|
+
strategy: retrievalStrategy,
|
|
318
|
+
context,
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
return {
|
|
322
|
+
query: optimizedQuery,
|
|
323
|
+
strategy: retrievalStrategy,
|
|
324
|
+
confidence: Math.random() * 0.3 + 0.7,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
_categorizeQuery(query) {
|
|
329
|
+
const lowerQuery = query.toLowerCase();
|
|
330
|
+
if (lowerQuery.includes("machine learning") || lowerQuery.includes("ml"))
|
|
331
|
+
return "machine_learning";
|
|
332
|
+
if (lowerQuery.includes("deep learning") || lowerQuery.includes("neural"))
|
|
333
|
+
return "deep_learning";
|
|
334
|
+
if (
|
|
335
|
+
lowerQuery.includes("ai") ||
|
|
336
|
+
lowerQuery.includes("artificial intelligence")
|
|
337
|
+
)
|
|
338
|
+
return "artificial_intelligence";
|
|
339
|
+
if (lowerQuery.includes("data") || lowerQuery.includes("analytics"))
|
|
340
|
+
return "data_science";
|
|
341
|
+
return "general";
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
_calculateAdaptiveScore(document, profile, query) {
|
|
345
|
+
let score = 0;
|
|
346
|
+
|
|
347
|
+
// Interest matching
|
|
348
|
+
const interestMatch = profile.interests.some(
|
|
349
|
+
(interest) =>
|
|
350
|
+
document.title.toLowerCase().includes(interest.toLowerCase()) ||
|
|
351
|
+
document.content.toLowerCase().includes(interest.toLowerCase()),
|
|
352
|
+
);
|
|
353
|
+
if (interestMatch) score += 0.3;
|
|
354
|
+
|
|
355
|
+
// Expertise level matching
|
|
356
|
+
if (
|
|
357
|
+
profile.expertise === "advanced" &&
|
|
358
|
+
document.metadata.tags.includes("advanced")
|
|
359
|
+
) {
|
|
360
|
+
score += 0.2;
|
|
361
|
+
} else if (
|
|
362
|
+
profile.expertise === "beginner" &&
|
|
363
|
+
document.metadata.tags.includes("basic")
|
|
364
|
+
) {
|
|
365
|
+
score += 0.2;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Historical preference (simplified)
|
|
369
|
+
score += Math.random() * 0.2;
|
|
370
|
+
|
|
371
|
+
return Math.min(score, 1.0);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
_updateAdaptationWeights(profile, feedbackEntry) {
|
|
375
|
+
// Simple learning rate adjustment based on feedback quality
|
|
376
|
+
const avgRating =
|
|
377
|
+
feedbackEntry.ratings.length > 0
|
|
378
|
+
? feedbackEntry.ratings.reduce((sum, r) => sum + r, 0) /
|
|
379
|
+
feedbackEntry.ratings.length
|
|
380
|
+
: 3;
|
|
381
|
+
|
|
382
|
+
if (avgRating >= 4) {
|
|
383
|
+
// Positive feedback - slightly increase user preference weight
|
|
384
|
+
profile.adaptationWeights.userPreference = Math.min(
|
|
385
|
+
0.5,
|
|
386
|
+
profile.adaptationWeights.userPreference + 0.01,
|
|
387
|
+
);
|
|
388
|
+
} else if (avgRating <= 2) {
|
|
389
|
+
// Negative feedback - increase content similarity weight
|
|
390
|
+
profile.adaptationWeights.contentSimilarity = Math.min(
|
|
391
|
+
0.6,
|
|
392
|
+
profile.adaptationWeights.contentSimilarity + 0.01,
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
module.exports = { AdaptiveRetrievalEngine };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive Retrieval Engine
|
|
3
|
+
* Provides intelligent document retrieval with adaptive algorithms
|
|
4
|
+
* Extracted from ai/index.js per CLAUDE.md decomposition requirements
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
"use strict";
|
|
8
|
+
|
|
9
|
+
// Import the existing adaptive retrieval implementation
|
|
10
|
+
const adaptiveRetrieval = require("./adaptive-retrieval");
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* AdaptiveRetrievalEngine class
|
|
14
|
+
* Manages intelligent document retrieval with performance optimization
|
|
15
|
+
*/
|
|
16
|
+
class AdaptiveRetrievalEngine {
|
|
17
|
+
constructor() {
|
|
18
|
+
this.algorithms = new Map();
|
|
19
|
+
this.performanceMetrics = new Map();
|
|
20
|
+
this.adaptationThreshold = 0.1;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Process retrieval query with adaptive algorithms
|
|
25
|
+
* @param {string} tenantId - Tenant identifier
|
|
26
|
+
* @param {string} query - Search query
|
|
27
|
+
* @param {object} options - Retrieval options
|
|
28
|
+
* @returns {Promise<object>} Retrieval results
|
|
29
|
+
*/
|
|
30
|
+
async retrieveDocuments(tenantId, query, options = {}) {
|
|
31
|
+
return await adaptiveRetrieval.retrieveDocuments(tenantId, query, options);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Optimize retrieval algorithm based on performance data
|
|
36
|
+
* @param {string} tenantId - Tenant identifier
|
|
37
|
+
* @param {object} performanceData - Performance metrics
|
|
38
|
+
* @returns {Promise<object>} Optimization results
|
|
39
|
+
*/
|
|
40
|
+
async optimizeRetrieval(tenantId, performanceData) {
|
|
41
|
+
return await adaptiveRetrieval.optimizeRetrieval(tenantId, performanceData);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get current algorithm configuration
|
|
46
|
+
* @param {string} tenantId - Tenant identifier
|
|
47
|
+
* @returns {Promise<object>} Current algorithm configuration
|
|
48
|
+
*/
|
|
49
|
+
async getAlgorithmConfig(tenantId) {
|
|
50
|
+
return await adaptiveRetrieval.getAlgorithmConfig(tenantId);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Update retrieval strategy
|
|
55
|
+
* @param {string} tenantId - Tenant identifier
|
|
56
|
+
* @param {string} strategy - New retrieval strategy
|
|
57
|
+
* @returns {Promise<boolean>} Success status
|
|
58
|
+
*/
|
|
59
|
+
async updateStrategy(tenantId, strategy) {
|
|
60
|
+
return await adaptiveRetrieval.updateStrategy(tenantId, strategy);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Create and export singleton instance
|
|
65
|
+
const engine = new AdaptiveRetrievalEngine();
|
|
66
|
+
|
|
67
|
+
module.exports = engine;
|
|
68
|
+
module.exports.AdaptiveRetrievalEngine = AdaptiveRetrievalEngine;
|
|
69
|
+
module.exports.default = module.exports;
|