@devilsdev/rag-pipeline-utils 2.6.1 → 2.7.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/BENCHMARKS.md +7 -1
- package/CHANGELOG.md +135 -0
- package/README.md +37 -24
- package/dist/index.cjs +4164 -1825
- package/dist/index.d.ts +265 -256
- package/dist/index.mjs +1 -1
- package/dist/types/cache/memory-cache.d.ts +4 -1
- package/dist/types/cache/redis-cache.d.ts +4 -1
- package/dist/types/cli/services/instrument.d.ts +14 -0
- package/dist/types/cli/services/rag-service.d.ts +140 -0
- package/dist/types/cli/shared/config-context.d.ts +9 -0
- package/dist/types/config/component-factory.d.ts +57 -0
- package/dist/types/config/enhanced-ragrc-schema.d.ts +648 -0
- package/dist/types/config/load-config.d.ts +18 -0
- package/dist/types/config/normalize-config.d.ts +9 -0
- package/dist/types/core/observability/event-logger.d.ts +211 -0
- package/dist/types/core/observability/metrics.d.ts +585 -0
- package/dist/types/core/performance/parallel-processor.d.ts +92 -0
- package/dist/types/core/plugin-registry.d.ts +5 -0
- package/dist/types/dag/core/execution-scheduler.d.ts +3 -1
- package/dist/types/dag/dag-engine.d.ts +15 -2
- package/dist/types/dev/dev-server.d.ts +136 -0
- package/dist/types/dev/hot-reload.d.ts +226 -0
- package/dist/types/ecosystem/plugin-analytics-dashboard.d.ts +141 -0
- package/dist/types/ecosystem/plugin-hub.d.ts +161 -0
- package/dist/types/ecosystem/plugin-installer.d.ts +40 -0
- package/dist/types/ecosystem/plugin-probe.d.ts +21 -0
- package/dist/types/ecosystem/plugin-scanner.d.ts +30 -0
- package/dist/types/ecosystem/tar-extract.d.ts +24 -0
- package/dist/types/enterprise/audit-logging.d.ts +217 -0
- package/dist/types/evaluate/compare.d.ts +140 -0
- package/dist/types/evaluate/dataset.d.ts +43 -0
- package/dist/types/evaluate/evaluator.d.ts +14 -0
- package/dist/types/evaluate/report.d.ts +56 -0
- package/dist/types/evaluate/synthetic.d.ts +64 -0
- package/dist/types/loader/csv-loader.d.ts +10 -0
- package/dist/types/loader/document-reader.d.ts +18 -0
- package/dist/types/loader/html-loader.d.ts +21 -0
- package/dist/types/loader/markdown-loader.d.ts +21 -0
- package/dist/types/retrieval/bm25-search.d.ts +4 -0
- package/dist/types/retrieval/file-vector-store.d.ts +4 -1
- package/dist/types/retrieval/hybrid-retriever.d.ts +4 -0
- package/dist/types/retrieval/pgvector-retriever.d.ts +123 -0
- package/dist/types/retrieval/qdrant-retriever.d.ts +106 -0
- package/dist/types/security/validator.d.ts +11 -1
- package/dist/types/testing.d.ts +2 -0
- package/dist/types/utils/batch-processor.d.ts +205 -0
- package/dist/types/utils/connection-pool.d.ts +158 -0
- package/dist/types/utils/error-formatter.d.ts +312 -0
- package/dist/types/utils/logger.d.ts +29 -4
- package/dist/types/utils/rate-limiter.d.ts +13 -8
- package/dist/types/utils/retry.d.ts +10 -0
- package/package.json +13 -3
- package/src/cache/memory-cache.js +4 -1
- package/src/cache/redis-cache.js +4 -1
- package/src/cli/enhanced-cli-commands.js +79 -0
- package/src/cli/handlers/ai-handler.js +2 -2
- package/src/cli/handlers/eval-handler.js +201 -0
- package/src/cli/handlers/generate-handler.js +103 -0
- package/src/cli/services/benchmark.js +2 -2
- package/src/cli/services/rag-service.js +59 -10
- package/src/cli/shared/cli-utils.js +40 -1
- package/src/config/component-factory.js +32 -0
- package/src/connectors/local-embedder.js +20 -13
- package/src/core/observability/event-logger.js +135 -1
- package/src/core/observability/metrics.js +223 -5
- package/src/core/performance/parallel-processor.js +2 -0
- package/src/core/plugin-registry.js +5 -1
- package/src/dag/core/execution-scheduler.js +2 -0
- package/src/dag/dag-engine.js +13 -0
- package/src/dev/dev-server.js +6 -0
- package/src/ecosystem/plugin-hub.js +4 -0
- package/src/enterprise/audit-logging.js +5 -0
- package/src/evaluate/compare.js +395 -0
- package/src/evaluate/dataset.js +207 -0
- package/src/evaluate/report.js +350 -0
- package/src/evaluate/synthetic.js +246 -0
- package/src/index.js +17 -0
- package/src/retrieval/bm25-search.js +4 -0
- package/src/retrieval/file-vector-store.js +4 -1
- package/src/retrieval/hybrid-retriever.js +4 -0
- package/src/retrieval/pgvector-retriever.js +420 -0
- package/src/retrieval/qdrant-retriever.js +361 -0
- package/src/security/validator.js +8 -0
- package/src/testing.js +2 -0
- package/src/utils/batch-processor.js +7 -3
- package/src/utils/error-formatter.js +48 -20
- package/src/utils/logger.js +31 -1
- package/src/utils/rate-limiter.js +9 -4
- package/src/utils/retry.js +10 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {object} params
|
|
3
|
+
* @param {string} params.source - Registry id, path, .tgz, .js or "npm:<spec>"
|
|
4
|
+
* @param {string} params.configPath - .ragrc.json to register the plugin in
|
|
5
|
+
* @param {string} [params.stage] - Overrides package.json "ragPipeline.stage"
|
|
6
|
+
* @param {string} [params.name] - Overrides package.json "ragPipeline.name"
|
|
7
|
+
* @param {boolean} [params.force] - Replace an installed plugin with the same stage/name
|
|
8
|
+
* @param {boolean} [params.allowRisky] - Install despite high-risk scan findings
|
|
9
|
+
* @param {object} [params.hub] - PluginHub, required for registry ids
|
|
10
|
+
* @param {string} [params.version] - Registry version (default "latest")
|
|
11
|
+
* @param {function} [params.onProgress] - Called with a stage label
|
|
12
|
+
* @returns {Promise<object>} Installation summary
|
|
13
|
+
*/
|
|
14
|
+
export function installPlugin(params: {
|
|
15
|
+
source: string;
|
|
16
|
+
configPath: string;
|
|
17
|
+
stage?: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
force?: boolean;
|
|
20
|
+
allowRisky?: boolean;
|
|
21
|
+
hub?: object;
|
|
22
|
+
version?: string;
|
|
23
|
+
onProgress?: Function;
|
|
24
|
+
}): Promise<object>;
|
|
25
|
+
/**
|
|
26
|
+
* Plugins registered under `plugins` in a config, with the installed
|
|
27
|
+
* package's version when it lives in .rag/plugins.
|
|
28
|
+
*
|
|
29
|
+
* @param {string} configPath
|
|
30
|
+
* @returns {Array<{stage: string, name: string, entry: string, version: string|null, installed: boolean, inPipeline: boolean, exists: boolean}>}
|
|
31
|
+
*/
|
|
32
|
+
export function listInstalledPlugins(configPath: string): Array<{
|
|
33
|
+
stage: string;
|
|
34
|
+
name: string;
|
|
35
|
+
entry: string;
|
|
36
|
+
version: string | null;
|
|
37
|
+
installed: boolean;
|
|
38
|
+
inPipeline: boolean;
|
|
39
|
+
exists: boolean;
|
|
40
|
+
}>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string} modulePath - Plugin entry file
|
|
3
|
+
* @param {string} stage - loader | embedder | retriever | llm | reranker
|
|
4
|
+
* @param {{timeoutMs?: number}} [options]
|
|
5
|
+
* @returns {Promise<{ok: boolean, missing: string[], methods: string[], error?: string}>}
|
|
6
|
+
*/
|
|
7
|
+
export function probeContract(modulePath: string, stage: string, options?: {
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
}): Promise<{
|
|
10
|
+
ok: boolean;
|
|
11
|
+
missing: string[];
|
|
12
|
+
methods: string[];
|
|
13
|
+
error?: string;
|
|
14
|
+
}>;
|
|
15
|
+
export namespace STAGE_METHODS {
|
|
16
|
+
let loader: string[];
|
|
17
|
+
let embedder: string[];
|
|
18
|
+
let retriever: string[];
|
|
19
|
+
let llm: string[];
|
|
20
|
+
let reranker: string[];
|
|
21
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string} pluginPath - Plugin directory or single .js file
|
|
3
|
+
* @returns {{
|
|
4
|
+
* findings: Array<{severity: string, rule: string, message: string, file: string, line?: number}>,
|
|
5
|
+
* counts: {high: number, medium: number, low: number},
|
|
6
|
+
* filesScanned: number
|
|
7
|
+
* }}
|
|
8
|
+
*/
|
|
9
|
+
export function scanPlugin(pluginPath: string): {
|
|
10
|
+
findings: Array<{
|
|
11
|
+
severity: string;
|
|
12
|
+
rule: string;
|
|
13
|
+
message: string;
|
|
14
|
+
file: string;
|
|
15
|
+
line?: number;
|
|
16
|
+
}>;
|
|
17
|
+
counts: {
|
|
18
|
+
high: number;
|
|
19
|
+
medium: number;
|
|
20
|
+
low: number;
|
|
21
|
+
};
|
|
22
|
+
filesScanned: number;
|
|
23
|
+
};
|
|
24
|
+
/** severity: high blocks installation unless explicitly allowed */
|
|
25
|
+
export const RULES: {
|
|
26
|
+
id: string;
|
|
27
|
+
severity: string;
|
|
28
|
+
pattern: RegExp;
|
|
29
|
+
message: string;
|
|
30
|
+
}[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract a gzipped tarball into destDir.
|
|
3
|
+
*
|
|
4
|
+
* @param {Buffer} archive - .tgz contents
|
|
5
|
+
* @param {string} destDir - Target directory (created if missing)
|
|
6
|
+
* @param {object} [options]
|
|
7
|
+
* @param {number} [options.strip=0] - Leading path components to drop (npm packs use "package/")
|
|
8
|
+
* @param {number} [options.maxBytes=50MB] - Refuse archives that expand beyond this
|
|
9
|
+
* @returns {{files: string[], skipped: string[]}}
|
|
10
|
+
*/
|
|
11
|
+
export function extractTarGz(archive: Buffer, destDir: string, options?: {
|
|
12
|
+
strip?: number;
|
|
13
|
+
maxBytes?: number;
|
|
14
|
+
}): {
|
|
15
|
+
files: string[];
|
|
16
|
+
skipped: string[];
|
|
17
|
+
};
|
|
18
|
+
/** Separator-agnostic "child is root or inside it" (paths already resolved). */
|
|
19
|
+
export function isWithin(root: any, child: any): any;
|
|
20
|
+
/**
|
|
21
|
+
* Path of `child` relative to `root` with "/" separators, or null when it is
|
|
22
|
+
* not inside root. Separator-agnostic like isWithin.
|
|
23
|
+
*/
|
|
24
|
+
export function relativeWithin(root: any, child: any): any;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Records authentication, data access, data change and other audit events
|
|
3
|
+
* in hash-chained logs, with querying, compliance reports and an integrity
|
|
4
|
+
* check.
|
|
5
|
+
*/
|
|
6
|
+
export class AuditLogger extends EventEmitter<[never]> {
|
|
7
|
+
constructor(_options?: {});
|
|
8
|
+
_config: {
|
|
9
|
+
logDir: any;
|
|
10
|
+
retention: {
|
|
11
|
+
days: any;
|
|
12
|
+
maxSizeMB: any;
|
|
13
|
+
compressionEnabled: boolean;
|
|
14
|
+
};
|
|
15
|
+
compliance: {
|
|
16
|
+
standards: any;
|
|
17
|
+
immutable: boolean;
|
|
18
|
+
encryption: boolean;
|
|
19
|
+
digitalSigning: boolean;
|
|
20
|
+
};
|
|
21
|
+
realtime: {
|
|
22
|
+
enabled: boolean;
|
|
23
|
+
batchSize: any;
|
|
24
|
+
flushInterval: any;
|
|
25
|
+
webhookUrl: any;
|
|
26
|
+
};
|
|
27
|
+
categories: {
|
|
28
|
+
authentication: {
|
|
29
|
+
level: string;
|
|
30
|
+
retention: number;
|
|
31
|
+
};
|
|
32
|
+
authorization: {
|
|
33
|
+
level: string;
|
|
34
|
+
retention: number;
|
|
35
|
+
};
|
|
36
|
+
dataAccess: {
|
|
37
|
+
level: string;
|
|
38
|
+
retention: number;
|
|
39
|
+
};
|
|
40
|
+
dataModification: {
|
|
41
|
+
level: string;
|
|
42
|
+
retention: number;
|
|
43
|
+
};
|
|
44
|
+
systemChanges: {
|
|
45
|
+
level: string;
|
|
46
|
+
retention: number;
|
|
47
|
+
};
|
|
48
|
+
userActivity: {
|
|
49
|
+
level: string;
|
|
50
|
+
retention: number;
|
|
51
|
+
};
|
|
52
|
+
apiAccess: {
|
|
53
|
+
level: string;
|
|
54
|
+
retention: number;
|
|
55
|
+
};
|
|
56
|
+
pluginActivity: {
|
|
57
|
+
level: string;
|
|
58
|
+
retention: number;
|
|
59
|
+
};
|
|
60
|
+
complianceEvents: {
|
|
61
|
+
level: string;
|
|
62
|
+
retention: number;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
logBuffer: any[];
|
|
67
|
+
encryptionKey: string | Buffer<ArrayBufferLike>;
|
|
68
|
+
signingKey: any;
|
|
69
|
+
sequenceNumber: number;
|
|
70
|
+
/**
|
|
71
|
+
* Initialize audit logging system
|
|
72
|
+
*/
|
|
73
|
+
_initializeAuditSystem(): Promise<void>;
|
|
74
|
+
flushTimer: NodeJS.Timeout;
|
|
75
|
+
/**
|
|
76
|
+
* Log authentication events
|
|
77
|
+
*/
|
|
78
|
+
logAuthentication(event: any): Promise<any>;
|
|
79
|
+
/**
|
|
80
|
+
* Log authorization events
|
|
81
|
+
*/
|
|
82
|
+
logAuthorization(event: any): Promise<any>;
|
|
83
|
+
/**
|
|
84
|
+
* Log data access events
|
|
85
|
+
*/
|
|
86
|
+
logDataAccess(event: any): Promise<any>;
|
|
87
|
+
/**
|
|
88
|
+
* Log data modification events
|
|
89
|
+
*/
|
|
90
|
+
logDataModification(event: any): Promise<any>;
|
|
91
|
+
/**
|
|
92
|
+
* Log system configuration changes
|
|
93
|
+
*/
|
|
94
|
+
logSystemChanges(event: any): Promise<any>;
|
|
95
|
+
/**
|
|
96
|
+
* Log API access events
|
|
97
|
+
*/
|
|
98
|
+
logAPIAccess(event: any): Promise<any>;
|
|
99
|
+
/**
|
|
100
|
+
* Log compliance events
|
|
101
|
+
*/
|
|
102
|
+
logComplianceEvent(event: any): Promise<any>;
|
|
103
|
+
/**
|
|
104
|
+
* Write audit log with integrity protection
|
|
105
|
+
*/
|
|
106
|
+
_writeAuditLog(auditEvent: any): Promise<any>;
|
|
107
|
+
/**
|
|
108
|
+
* Flush logs to persistent storage
|
|
109
|
+
*/
|
|
110
|
+
_flushLogs(): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Query audit logs
|
|
113
|
+
*/
|
|
114
|
+
queryLogs(query: any): Promise<{
|
|
115
|
+
results: any[];
|
|
116
|
+
total: number;
|
|
117
|
+
hasMore: boolean;
|
|
118
|
+
}>;
|
|
119
|
+
/**
|
|
120
|
+
* Generate compliance report
|
|
121
|
+
*/
|
|
122
|
+
generateComplianceReport(_options: any): Promise<{
|
|
123
|
+
metadata: {
|
|
124
|
+
_tenantId: any;
|
|
125
|
+
standard: any;
|
|
126
|
+
period: {
|
|
127
|
+
startDate: any;
|
|
128
|
+
endDate: any;
|
|
129
|
+
};
|
|
130
|
+
generatedAt: string;
|
|
131
|
+
totalEvents: number;
|
|
132
|
+
};
|
|
133
|
+
summary: {
|
|
134
|
+
authenticationEvents: number;
|
|
135
|
+
authorizationEvents: number;
|
|
136
|
+
dataAccessEvents: number;
|
|
137
|
+
dataModificationEvents: number;
|
|
138
|
+
systemChangeEvents: number;
|
|
139
|
+
complianceEvents: number;
|
|
140
|
+
criticalEvents: number;
|
|
141
|
+
failedEvents: number;
|
|
142
|
+
};
|
|
143
|
+
compliance: {
|
|
144
|
+
requirements: any[];
|
|
145
|
+
violations: any[];
|
|
146
|
+
recommendations: any[];
|
|
147
|
+
};
|
|
148
|
+
evidence: any[];
|
|
149
|
+
}>;
|
|
150
|
+
/**
|
|
151
|
+
* Verify log integrity
|
|
152
|
+
*/
|
|
153
|
+
verifyIntegrity(_options?: {}): Promise<{
|
|
154
|
+
verified: boolean;
|
|
155
|
+
totalLogs: number;
|
|
156
|
+
verifiedLogs: number;
|
|
157
|
+
tamperedLogs: any[];
|
|
158
|
+
missingLogs: any[];
|
|
159
|
+
integrityBreaks: any[];
|
|
160
|
+
}>;
|
|
161
|
+
_calculateIntegrityHash(auditEvent: any): Promise<string>;
|
|
162
|
+
_encryptSensitiveFields(auditEvent: any): Promise<any>;
|
|
163
|
+
_decryptAuditEvent(auditEvent: any): Promise<any>;
|
|
164
|
+
_calculateSeverity(_category: any, _action: any, result: any): any;
|
|
165
|
+
_sanitizeQuery(query: any): any;
|
|
166
|
+
_sanitizeValue(value: any): any;
|
|
167
|
+
_sanitizeParameters(params: any): any;
|
|
168
|
+
_hashApiKey(apiKey: any): string;
|
|
169
|
+
/**
|
|
170
|
+
* Resolve the field-encryption key.
|
|
171
|
+
*
|
|
172
|
+
* Order: the `encryptionKey` option, then the RAG_AUDIT_ENCRYPTION_KEY
|
|
173
|
+
* environment variable (used as a passphrase, like a string option). A
|
|
174
|
+
* random per-process key is never generated: records written with it
|
|
175
|
+
* could not be decrypted after a restart.
|
|
176
|
+
*
|
|
177
|
+
* If encryption is enabled but no key is configured, encryption is
|
|
178
|
+
* disabled for this instance with a loud warning (an `encryption_disabled`
|
|
179
|
+
* event is also emitted on the next tick). Pass `requireEncryption: true`
|
|
180
|
+
* to throw instead.
|
|
181
|
+
*
|
|
182
|
+
* @param {Object} _options - Constructor options
|
|
183
|
+
* @returns {Buffer|string|null} Key material, or null when unavailable
|
|
184
|
+
* @private
|
|
185
|
+
*/
|
|
186
|
+
private _resolveEncryptionKey;
|
|
187
|
+
/**
|
|
188
|
+
* AES-256 needs exactly 32 key bytes. A 32-byte Buffer is used as-is; any
|
|
189
|
+
* other key (e.g. a passphrase string) is reduced with SHA-256.
|
|
190
|
+
*/
|
|
191
|
+
_getCipherKey(): Buffer<ArrayBufferLike>;
|
|
192
|
+
_createDecipher(encryptedField: any): crypto.DecipherGCM;
|
|
193
|
+
_generateSigningKey(): Buffer<ArrayBufferLike>;
|
|
194
|
+
_initializeIntegrityChain(): Promise<void>;
|
|
195
|
+
_updateIntegrityChain(logs: any): Promise<void>;
|
|
196
|
+
_signAuditEvent(auditEvent: any): Promise<string>;
|
|
197
|
+
_verifySignature(auditEvent: any): Promise<boolean>;
|
|
198
|
+
_getLogFilesInRange(startDate: any, endDate: any): Promise<string[]>;
|
|
199
|
+
_readLogFile(filepath: any): Promise<any[]>;
|
|
200
|
+
_matchesQuery(log: any, query: any): boolean;
|
|
201
|
+
_checkCompliance(log: any, standard: any): {
|
|
202
|
+
requirement: any;
|
|
203
|
+
violation: boolean;
|
|
204
|
+
evidence: any;
|
|
205
|
+
};
|
|
206
|
+
_sendToWebhook(logs: any): Promise<void>;
|
|
207
|
+
/**
|
|
208
|
+
* Cleanup old logs based on retention policy
|
|
209
|
+
*/
|
|
210
|
+
cleanupOldLogs(): Promise<{
|
|
211
|
+
filesRemoved: number;
|
|
212
|
+
bytesFreed: number;
|
|
213
|
+
errors: any[];
|
|
214
|
+
}>;
|
|
215
|
+
}
|
|
216
|
+
import { EventEmitter } from "events";
|
|
217
|
+
import crypto = require("crypto");
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs every case of a dataset through a pipeline and scores it.
|
|
3
|
+
*
|
|
4
|
+
* Each case runs with citations and evaluation on, and its expected answer
|
|
5
|
+
* as the reference. A case that fails is recorded with its error, not
|
|
6
|
+
* thrown. Throws a DatasetError (`code: 'RAG_INVALID_DATASET'`, `errors`
|
|
7
|
+
* from validateDataset) when the dataset is invalid.
|
|
8
|
+
*
|
|
9
|
+
* @param {Array<Object>|{cases: Array<Object>}} dataset - See validateDataset
|
|
10
|
+
* @param {{ run: Function }} pipeline - A createRagPipeline() pipeline
|
|
11
|
+
* @param {Object} [options]
|
|
12
|
+
* @param {number} [options.concurrency=1] - Cases run at the same time
|
|
13
|
+
* @param {number} [options.timeout] - Per-case timeout in milliseconds
|
|
14
|
+
* @param {AbortSignal} [options.signal] - Stops the run; unstarted cases are not run
|
|
15
|
+
* @param {Object} [options.runOptions] - Extra `run()` options for every case
|
|
16
|
+
* @param {(caseResult: Object, index: number) => void} [options.onCase] - Called as each case finishes
|
|
17
|
+
* @returns {Promise<{
|
|
18
|
+
* version: number,
|
|
19
|
+
* libraryVersion: string,
|
|
20
|
+
* createdAt: string,
|
|
21
|
+
* summary: { cases: number, succeeded: number, failed: number, metrics: Object<string, { mean: number, count: number }> },
|
|
22
|
+
* cases: Array<{ id: string, prompt: string, success: boolean, error?: string, answer: string|null, retrievedIds: string[], scores: Object<string, number>, durationMs: number }>
|
|
23
|
+
* }>} A JSON-serialisable report
|
|
24
|
+
*/
|
|
25
|
+
export function runEvaluation(dataset: Array<any> | {
|
|
26
|
+
cases: Array<any>;
|
|
27
|
+
}, pipeline: {
|
|
28
|
+
run: Function;
|
|
29
|
+
}, options?: {
|
|
30
|
+
concurrency?: number;
|
|
31
|
+
timeout?: number;
|
|
32
|
+
signal?: AbortSignal;
|
|
33
|
+
runOptions?: any;
|
|
34
|
+
onCase?: (caseResult: any, index: number) => void;
|
|
35
|
+
}): Promise<{
|
|
36
|
+
version: number;
|
|
37
|
+
libraryVersion: string;
|
|
38
|
+
createdAt: string;
|
|
39
|
+
summary: {
|
|
40
|
+
cases: number;
|
|
41
|
+
succeeded: number;
|
|
42
|
+
failed: number;
|
|
43
|
+
metrics: {
|
|
44
|
+
[x: string]: {
|
|
45
|
+
mean: number;
|
|
46
|
+
count: number;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
cases: Array<{
|
|
51
|
+
id: string;
|
|
52
|
+
prompt: string;
|
|
53
|
+
success: boolean;
|
|
54
|
+
error?: string;
|
|
55
|
+
answer: string | null;
|
|
56
|
+
retrievedIds: string[];
|
|
57
|
+
scores: {
|
|
58
|
+
[x: string]: number;
|
|
59
|
+
};
|
|
60
|
+
durationMs: number;
|
|
61
|
+
}>;
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* Compares two configurations on the same dataset and reports what got
|
|
65
|
+
* worse. Each side is a pipeline (run now) or a saved runEvaluation()
|
|
66
|
+
* report, so CI can compare against the base branch's saved report.
|
|
67
|
+
*
|
|
68
|
+
* A metric has regressed when its mean drops by more than `tolerance`.
|
|
69
|
+
* A case has regressed when it now fails, or a metric drops by more than
|
|
70
|
+
* `caseTolerance`; those cases are listed but don't set `regressed` on
|
|
71
|
+
* their own, except failures. Scores from LLM answers vary between runs,
|
|
72
|
+
* so keep the tolerances above the noise you see on repeated runs.
|
|
73
|
+
*
|
|
74
|
+
* @param {Array<Object>|{cases: Array<Object>}|null} dataset - Needed when either side is a pipeline
|
|
75
|
+
* @param {Object} options
|
|
76
|
+
* @param {Object} options.baseline - Pipeline or report
|
|
77
|
+
* @param {Object} options.candidate - Pipeline or report
|
|
78
|
+
* @param {number} [options.tolerance=0.02] - Allowed drop in a metric's mean
|
|
79
|
+
* @param {number} [options.caseTolerance=0.1] - Drop in one case's metric that lists the case
|
|
80
|
+
* @param {string[]} [options.metrics] - Metrics to compare (default: all both runs have)
|
|
81
|
+
* @param {Object} [options.runOptions] - Options for runEvaluation when a side is a pipeline
|
|
82
|
+
* @returns {Promise<{
|
|
83
|
+
* regressed: boolean,
|
|
84
|
+
* metrics: Object<string, { baseline: number, candidate: number, delta: number, regressed: boolean }>,
|
|
85
|
+
* regressions: Array<{ id: string, prompt: string, reason: string, metric?: string, baseline?: number, candidate?: number, delta?: number }>,
|
|
86
|
+
* improvements: Array<{ id: string, prompt: string, reason: string, metric?: string, baseline?: number, candidate?: number, delta?: number }>,
|
|
87
|
+
* warnings: string[],
|
|
88
|
+
* baseline: Object,
|
|
89
|
+
* candidate: Object
|
|
90
|
+
* }>}
|
|
91
|
+
*/
|
|
92
|
+
export function compareConfigurations(dataset: Array<any> | {
|
|
93
|
+
cases: Array<any>;
|
|
94
|
+
} | null, options?: {
|
|
95
|
+
baseline: any;
|
|
96
|
+
candidate: any;
|
|
97
|
+
tolerance?: number;
|
|
98
|
+
caseTolerance?: number;
|
|
99
|
+
metrics?: string[];
|
|
100
|
+
runOptions?: any;
|
|
101
|
+
}): Promise<{
|
|
102
|
+
regressed: boolean;
|
|
103
|
+
metrics: {
|
|
104
|
+
[x: string]: {
|
|
105
|
+
baseline: number;
|
|
106
|
+
candidate: number;
|
|
107
|
+
delta: number;
|
|
108
|
+
regressed: boolean;
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
regressions: Array<{
|
|
112
|
+
id: string;
|
|
113
|
+
prompt: string;
|
|
114
|
+
reason: string;
|
|
115
|
+
metric?: string;
|
|
116
|
+
baseline?: number;
|
|
117
|
+
candidate?: number;
|
|
118
|
+
delta?: number;
|
|
119
|
+
}>;
|
|
120
|
+
improvements: Array<{
|
|
121
|
+
id: string;
|
|
122
|
+
prompt: string;
|
|
123
|
+
reason: string;
|
|
124
|
+
metric?: string;
|
|
125
|
+
baseline?: number;
|
|
126
|
+
candidate?: number;
|
|
127
|
+
delta?: number;
|
|
128
|
+
}>;
|
|
129
|
+
warnings: string[];
|
|
130
|
+
baseline: any;
|
|
131
|
+
candidate: any;
|
|
132
|
+
}>;
|
|
133
|
+
export class DatasetError extends Error {
|
|
134
|
+
constructor(errors: any);
|
|
135
|
+
code: string;
|
|
136
|
+
errors: any;
|
|
137
|
+
}
|
|
138
|
+
/** Metrics a report can hold; higher is better for all of them. */
|
|
139
|
+
declare const METRICS: string[];
|
|
140
|
+
export { METRICS as EVALUATION_METRICS };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks an evaluation dataset before anything runs. It never throws: every
|
|
3
|
+
* problem is reported, with the case it is in.
|
|
4
|
+
*
|
|
5
|
+
* @param {Array<Object>|{cases: Array<Object>}} dataset - Cases, or an object with `cases`
|
|
6
|
+
* @param {Object} [options]
|
|
7
|
+
* @param {boolean} [options.requireExpected=false] - Every case needs `expected`
|
|
8
|
+
* @param {boolean} [options.requireSourceIds=false] - Every case needs `sourceIds`
|
|
9
|
+
* @returns {{
|
|
10
|
+
* valid: boolean,
|
|
11
|
+
* errors: Array<{ index: number|null, id: string|null, field: string|null, message: string }>,
|
|
12
|
+
* warnings: Array<{ index: number|null, id: string|null, field: string|null, message: string }>,
|
|
13
|
+
* cases: Array<{ id: string, prompt: string, expected?: string, sourceIds?: string[], tags?: string[] }>
|
|
14
|
+
* }} `cases` holds the normalised cases (aliases resolved, ids filled in)
|
|
15
|
+
* when `valid` is true, and is empty otherwise
|
|
16
|
+
*/
|
|
17
|
+
export function validateDataset(dataset: Array<any> | {
|
|
18
|
+
cases: Array<any>;
|
|
19
|
+
}, options?: {
|
|
20
|
+
requireExpected?: boolean;
|
|
21
|
+
requireSourceIds?: boolean;
|
|
22
|
+
}): {
|
|
23
|
+
valid: boolean;
|
|
24
|
+
errors: Array<{
|
|
25
|
+
index: number | null;
|
|
26
|
+
id: string | null;
|
|
27
|
+
field: string | null;
|
|
28
|
+
message: string;
|
|
29
|
+
}>;
|
|
30
|
+
warnings: Array<{
|
|
31
|
+
index: number | null;
|
|
32
|
+
id: string | null;
|
|
33
|
+
field: string | null;
|
|
34
|
+
message: string;
|
|
35
|
+
}>;
|
|
36
|
+
cases: Array<{
|
|
37
|
+
id: string;
|
|
38
|
+
prompt: string;
|
|
39
|
+
expected?: string;
|
|
40
|
+
sourceIds?: string[];
|
|
41
|
+
tags?: string[];
|
|
42
|
+
}>;
|
|
43
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evaluate a list of prompt/answer pairs using the RAG pipeline and compute scores
|
|
3
|
+
* @param {string} datasetPath - Path to JSON file with { prompt, expected }[]
|
|
4
|
+
* @param {object} _config - RAG plugin _config (loader optional)
|
|
5
|
+
* @returns {Promise<Array<{ prompt: string, expected: string, actual: string, success: boolean, scores: object }>>}
|
|
6
|
+
*/
|
|
7
|
+
export function evaluateRagDataset(_datasetPath: any, _config: object): Promise<Array<{
|
|
8
|
+
prompt: string;
|
|
9
|
+
expected: string;
|
|
10
|
+
actual: string;
|
|
11
|
+
success: boolean;
|
|
12
|
+
scores: object;
|
|
13
|
+
}>>;
|
|
14
|
+
export function normalizeText(txt: any): any;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decides whether a run passes: no case failed, every metric in `min` is at
|
|
3
|
+
* or above its minimum, and the comparison (if any) found no regression.
|
|
4
|
+
*
|
|
5
|
+
* @param {Object} input
|
|
6
|
+
* @param {Object} input.report - A runEvaluation() report
|
|
7
|
+
* @param {Object} [input.comparison] - A compareConfigurations() result
|
|
8
|
+
* @param {Object<string, number>} [input.min] - Minimum mean per metric, e.g. `{ faithfulness: 0.8 }`
|
|
9
|
+
* @returns {{
|
|
10
|
+
* passed: boolean,
|
|
11
|
+
* reasons: string[],
|
|
12
|
+
* thresholds: Array<{ metric: string, min: number, actual: number|null, passed: boolean }>
|
|
13
|
+
* }}
|
|
14
|
+
*/
|
|
15
|
+
export function evaluationVerdict({ report, comparison, min }?: {
|
|
16
|
+
report: any;
|
|
17
|
+
comparison?: any;
|
|
18
|
+
min?: {
|
|
19
|
+
[x: string]: number;
|
|
20
|
+
};
|
|
21
|
+
}): {
|
|
22
|
+
passed: boolean;
|
|
23
|
+
reasons: string[];
|
|
24
|
+
thresholds: Array<{
|
|
25
|
+
metric: string;
|
|
26
|
+
min: number;
|
|
27
|
+
actual: number | null;
|
|
28
|
+
passed: boolean;
|
|
29
|
+
}>;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Renders an evaluation run, and its comparison with a baseline if given,
|
|
33
|
+
* as Markdown (for a pull request comment) or a standalone HTML page.
|
|
34
|
+
*
|
|
35
|
+
* @param {Object} input
|
|
36
|
+
* @param {Object} input.report - A runEvaluation() report
|
|
37
|
+
* @param {Object} [input.comparison] - A compareConfigurations() result
|
|
38
|
+
* @param {Object<string, number>} [input.min] - Minimum mean per metric
|
|
39
|
+
* @param {Object} [options]
|
|
40
|
+
* @param {'markdown'|'html'} [options.format='markdown']
|
|
41
|
+
* @param {string} [options.title='RAG evaluation']
|
|
42
|
+
* @returns {string}
|
|
43
|
+
*/
|
|
44
|
+
export function renderEvaluationReport(input: {
|
|
45
|
+
report: any;
|
|
46
|
+
comparison?: any;
|
|
47
|
+
min?: {
|
|
48
|
+
[x: string]: number;
|
|
49
|
+
};
|
|
50
|
+
}, options?: {
|
|
51
|
+
format?: "markdown" | "html";
|
|
52
|
+
title?: string;
|
|
53
|
+
}): string;
|
|
54
|
+
/** Marks the comment so the Action can find and update it. */
|
|
55
|
+
declare const MARKER: "<!-- rag-eval-report -->";
|
|
56
|
+
export { MARKER as REPORT_MARKER };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates question and answer pairs from documents with an LLM.
|
|
3
|
+
*
|
|
4
|
+
* Each document gets its own request, with that document as the only
|
|
5
|
+
* context, so every case knows its source. Generated answers are checked
|
|
6
|
+
* against the document with computeFaithfulness, and pairs whose answer the
|
|
7
|
+
* document doesn't support, malformed pairs and repeated questions are
|
|
8
|
+
* dropped and listed in `skipped`.
|
|
9
|
+
*
|
|
10
|
+
* @param {Array<{id?: string, content: string, metadata?: Object}|string>} documents - The corpus, e.g. the chunks you index
|
|
11
|
+
* @param {Object} options
|
|
12
|
+
* @param {{ generate: Function }} options.llm - Any llm stage: `generate(query, docs, options)` returning a string
|
|
13
|
+
* @param {number} [options.count=20] - Cases to generate at most
|
|
14
|
+
* @param {number} [options.perDocument=1] - Questions to ask per document
|
|
15
|
+
* @param {number} [options.minFaithfulness=1] - Share of an answer's sentences the document must support
|
|
16
|
+
* @param {number} [options.minLength=80] - Documents shorter than this many characters are skipped
|
|
17
|
+
* @param {string} [options.prompt] - Replaces the instruction; `{count}` is replaced by perDocument
|
|
18
|
+
* @param {number} [options.concurrency=1] - Documents processed at the same time
|
|
19
|
+
* @param {Object} [options.generateOptions] - Extra options for every `llm.generate()` call, e.g. `{ temperature: 0.7 }`
|
|
20
|
+
* @param {AbortSignal} [options.signal]
|
|
21
|
+
* @param {(testCase: Object) => void} [options.onCase] - Called for each case kept
|
|
22
|
+
* @returns {Promise<{
|
|
23
|
+
* cases: Array<{ id: string, prompt: string, expected: string, sourceIds: string[], tags: string[], reviewed: boolean }>,
|
|
24
|
+
* skipped: Array<{ sourceId: string, reason: string, question?: string }>
|
|
25
|
+
* }>} A dataset (`{ cases }`) plus what was dropped and why
|
|
26
|
+
*/
|
|
27
|
+
export function generateSyntheticDataset(documents: Array<{
|
|
28
|
+
id?: string;
|
|
29
|
+
content: string;
|
|
30
|
+
metadata?: any;
|
|
31
|
+
} | string>, options?: {
|
|
32
|
+
llm: {
|
|
33
|
+
generate: Function;
|
|
34
|
+
};
|
|
35
|
+
count?: number;
|
|
36
|
+
perDocument?: number;
|
|
37
|
+
minFaithfulness?: number;
|
|
38
|
+
minLength?: number;
|
|
39
|
+
prompt?: string;
|
|
40
|
+
concurrency?: number;
|
|
41
|
+
generateOptions?: any;
|
|
42
|
+
signal?: AbortSignal;
|
|
43
|
+
onCase?: (testCase: any) => void;
|
|
44
|
+
}): Promise<{
|
|
45
|
+
cases: Array<{
|
|
46
|
+
id: string;
|
|
47
|
+
prompt: string;
|
|
48
|
+
expected: string;
|
|
49
|
+
sourceIds: string[];
|
|
50
|
+
tags: string[];
|
|
51
|
+
reviewed: boolean;
|
|
52
|
+
}>;
|
|
53
|
+
skipped: Array<{
|
|
54
|
+
sourceId: string;
|
|
55
|
+
reason: string;
|
|
56
|
+
question?: string;
|
|
57
|
+
}>;
|
|
58
|
+
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Pulls the JSON array of pairs out of a model reply. Accepts a bare array,
|
|
61
|
+
* one inside a ```json fence, or one surrounded by prose; returns null when
|
|
62
|
+
* there is none.
|
|
63
|
+
*/
|
|
64
|
+
export function parsePairs(reply: any): any;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read a file or every supported file under a directory and return its
|
|
3
|
+
* chunks together with the file they came from. Unlike DirectoryLoader this
|
|
4
|
+
* keeps the source path, which ingestion needs for stable chunk ids,
|
|
5
|
+
* re-ingestion and citations.
|
|
6
|
+
*
|
|
7
|
+
* @param {string} inputPath - File or directory
|
|
8
|
+
* @param {object} [options]
|
|
9
|
+
* @param {string} [options.baseDir=process.cwd()] - Sources are reported relative to this
|
|
10
|
+
* @returns {Promise<Array<{source: string, chunks: string[]}>>}
|
|
11
|
+
*/
|
|
12
|
+
export function readDocuments(inputPath: string, options?: {
|
|
13
|
+
baseDir?: string;
|
|
14
|
+
}): Promise<Array<{
|
|
15
|
+
source: string;
|
|
16
|
+
chunks: string[];
|
|
17
|
+
}>>;
|
|
18
|
+
export const SUPPORTED_EXTENSIONS: string[];
|