veryfront 0.1.871 → 0.1.873
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/esm/cli/commands/eval/command-help.d.ts +3 -0
- package/esm/cli/commands/eval/command-help.d.ts.map +1 -0
- package/esm/cli/commands/eval/command-help.js +42 -0
- package/esm/cli/commands/eval/command.d.ts +21 -0
- package/esm/cli/commands/eval/command.d.ts.map +1 -0
- package/esm/cli/commands/eval/command.js +289 -0
- package/esm/cli/commands/eval/handler.d.ts +26 -0
- package/esm/cli/commands/eval/handler.d.ts.map +1 -0
- package/esm/cli/commands/eval/handler.js +28 -0
- package/esm/cli/help/command-definitions.d.ts.map +1 -1
- package/esm/cli/help/command-definitions.js +2 -0
- package/esm/cli/router.d.ts.map +1 -1
- package/esm/cli/router.js +2 -0
- package/esm/deno.d.ts +5 -2
- package/esm/deno.js +7 -4
- package/esm/src/agent/runtime/client-profile.d.ts.map +1 -1
- package/esm/src/agent/runtime/client-profile.js +10 -1
- package/esm/src/chat/ag-ui.d.ts.map +1 -1
- package/esm/src/chat/protocol.d.ts.map +1 -1
- package/esm/src/chat/protocol.js +0 -1
- package/esm/src/config/schemas/config.schema.d.ts +12 -0
- package/esm/src/config/schemas/config.schema.d.ts.map +1 -1
- package/esm/src/config/schemas/config.schema.js +12 -0
- package/esm/src/discovery/discovery-engine.d.ts.map +1 -1
- package/esm/src/discovery/discovery-engine.js +6 -1
- package/esm/src/discovery/handlers/eval-handler.d.ts +7 -0
- package/esm/src/discovery/handlers/eval-handler.d.ts.map +1 -0
- package/esm/src/discovery/handlers/eval-handler.js +16 -0
- package/esm/src/discovery/handlers/index.d.ts +1 -0
- package/esm/src/discovery/handlers/index.d.ts.map +1 -1
- package/esm/src/discovery/handlers/index.js +1 -0
- package/esm/src/discovery/import-rewriter.d.ts +1 -1
- package/esm/src/discovery/import-rewriter.d.ts.map +1 -1
- package/esm/src/discovery/import-rewriter.js +1 -0
- package/esm/src/discovery/project-discovery-config.d.ts +2 -0
- package/esm/src/discovery/project-discovery-config.d.ts.map +1 -1
- package/esm/src/discovery/project-discovery-config.js +2 -0
- package/esm/src/discovery/transpiler.d.ts.map +1 -1
- package/esm/src/discovery/transpiler.js +2 -0
- package/esm/src/discovery/types.d.ts +3 -0
- package/esm/src/discovery/types.d.ts.map +1 -1
- package/esm/src/eval/datasets.d.ts +8 -0
- package/esm/src/eval/datasets.d.ts.map +1 -0
- package/esm/src/eval/datasets.js +66 -0
- package/esm/src/eval/discovery.d.ts +43 -0
- package/esm/src/eval/discovery.d.ts.map +1 -0
- package/esm/src/eval/discovery.js +123 -0
- package/esm/src/eval/expect.d.ts +16 -0
- package/esm/src/eval/expect.d.ts.map +1 -0
- package/esm/src/eval/expect.js +62 -0
- package/esm/src/eval/factory.d.ts +6 -0
- package/esm/src/eval/factory.d.ts.map +1 -0
- package/esm/src/eval/factory.js +50 -0
- package/esm/src/eval/index.d.ts +33 -0
- package/esm/src/eval/index.d.ts.map +1 -0
- package/esm/src/eval/index.js +29 -0
- package/esm/src/eval/metrics.d.ts +55 -0
- package/esm/src/eval/metrics.d.ts.map +1 -0
- package/esm/src/eval/metrics.js +223 -0
- package/esm/src/eval/report.d.ts +12 -0
- package/esm/src/eval/report.d.ts.map +1 -0
- package/esm/src/eval/report.js +64 -0
- package/esm/src/eval/runner.d.ts +4 -0
- package/esm/src/eval/runner.d.ts.map +1 -0
- package/esm/src/eval/runner.js +101 -0
- package/esm/src/eval/studio.d.ts +177 -0
- package/esm/src/eval/studio.d.ts.map +1 -0
- package/esm/src/eval/studio.js +176 -0
- package/esm/src/eval/types.d.ts +221 -0
- package/esm/src/eval/types.d.ts.map +1 -0
- package/esm/src/eval/types.js +6 -0
- package/esm/src/eval/validation.d.ts +4 -0
- package/esm/src/eval/validation.d.ts.map +1 -0
- package/esm/src/eval/validation.js +41 -0
- package/esm/src/runs/index.d.ts +1 -1
- package/esm/src/runs/index.js +1 -1
- package/esm/src/runs/schemas.d.ts +9 -9
- package/esm/src/runs/schemas.d.ts.map +1 -1
- package/esm/src/runs/schemas.js +1 -1
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +12 -4
- package/esm/src/agent/testing/agent-tester.d.ts +0 -53
- package/esm/src/agent/testing/agent-tester.d.ts.map +0 -1
- package/esm/src/agent/testing/agent-tester.js +0 -132
- package/esm/src/agent/testing/durable-run-canaries/cli-runner.d.ts +0 -21
- package/esm/src/agent/testing/durable-run-canaries/cli-runner.d.ts.map +0 -1
- package/esm/src/agent/testing/durable-run-canaries/cli-runner.js +0 -66
- package/esm/src/agent/testing/durable-run-canaries/environment.d.ts +0 -14
- package/esm/src/agent/testing/durable-run-canaries/environment.d.ts.map +0 -1
- package/esm/src/agent/testing/durable-run-canaries/environment.js +0 -15
- package/esm/src/agent/testing/durable-run-canaries/index.d.ts +0 -5
- package/esm/src/agent/testing/durable-run-canaries/index.d.ts.map +0 -1
- package/esm/src/agent/testing/durable-run-canaries/index.js +0 -4
- package/esm/src/agent/testing/durable-run-canaries/runner.d.ts +0 -118
- package/esm/src/agent/testing/durable-run-canaries/runner.d.ts.map +0 -1
- package/esm/src/agent/testing/durable-run-canaries/runner.js +0 -391
- package/esm/src/agent/testing/durable-run-canaries/validation.d.ts +0 -12
- package/esm/src/agent/testing/durable-run-canaries/validation.d.ts.map +0 -1
- package/esm/src/agent/testing/durable-run-canaries/validation.js +0 -71
- package/esm/src/agent/testing/index.d.ts +0 -10
- package/esm/src/agent/testing/index.d.ts.map +0 -1
- package/esm/src/agent/testing/index.js +0 -9
- package/esm/src/agent/testing/live-evals/api-client.d.ts +0 -102
- package/esm/src/agent/testing/live-evals/api-client.d.ts.map +0 -1
- package/esm/src/agent/testing/live-evals/api-client.js +0 -313
- package/esm/src/agent/testing/live-evals/cli-runner.d.ts +0 -40
- package/esm/src/agent/testing/live-evals/cli-runner.d.ts.map +0 -1
- package/esm/src/agent/testing/live-evals/cli-runner.js +0 -144
- package/esm/src/agent/testing/live-evals/environment.d.ts +0 -15
- package/esm/src/agent/testing/live-evals/environment.d.ts.map +0 -1
- package/esm/src/agent/testing/live-evals/environment.js +0 -20
- package/esm/src/agent/testing/live-evals/formatting.d.ts +0 -15
- package/esm/src/agent/testing/live-evals/formatting.d.ts.map +0 -1
- package/esm/src/agent/testing/live-evals/formatting.js +0 -75
- package/esm/src/agent/testing/live-evals/index.d.ts +0 -12
- package/esm/src/agent/testing/live-evals/index.d.ts.map +0 -1
- package/esm/src/agent/testing/live-evals/index.js +0 -11
- package/esm/src/agent/testing/live-evals/metadata.d.ts +0 -34
- package/esm/src/agent/testing/live-evals/metadata.d.ts.map +0 -1
- package/esm/src/agent/testing/live-evals/metadata.js +0 -116
- package/esm/src/agent/testing/live-evals/performance.d.ts +0 -19
- package/esm/src/agent/testing/live-evals/performance.d.ts.map +0 -1
- package/esm/src/agent/testing/live-evals/performance.js +0 -22
- package/esm/src/agent/testing/live-evals/preflight.d.ts +0 -12
- package/esm/src/agent/testing/live-evals/preflight.d.ts.map +0 -1
- package/esm/src/agent/testing/live-evals/preflight.js +0 -27
- package/esm/src/agent/testing/live-evals/report.d.ts +0 -55
- package/esm/src/agent/testing/live-evals/report.d.ts.map +0 -1
- package/esm/src/agent/testing/live-evals/report.js +0 -79
- package/esm/src/agent/testing/live-evals/request.d.ts +0 -31
- package/esm/src/agent/testing/live-evals/request.d.ts.map +0 -1
- package/esm/src/agent/testing/live-evals/request.js +0 -48
- package/esm/src/agent/testing/live-evals/result.d.ts +0 -56
- package/esm/src/agent/testing/live-evals/result.d.ts.map +0 -1
- package/esm/src/agent/testing/live-evals/result.js +0 -36
- package/esm/src/agent/testing/live-evals/runner.d.ts +0 -135
- package/esm/src/agent/testing/live-evals/runner.d.ts.map +0 -1
- package/esm/src/agent/testing/live-evals/runner.js +0 -396
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { getOutputText } from "./metrics.js";
|
|
2
|
+
function createExpectation(checks, base) {
|
|
3
|
+
function record(severity, threshold) {
|
|
4
|
+
const check = {
|
|
5
|
+
...base,
|
|
6
|
+
severity,
|
|
7
|
+
...(threshold ? { evidence: { ...(base.evidence ?? {}), threshold } } : {}),
|
|
8
|
+
};
|
|
9
|
+
checks.push(check);
|
|
10
|
+
return check;
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
gate: (threshold) => record("gate", threshold),
|
|
14
|
+
soft: (threshold) => record("soft", threshold),
|
|
15
|
+
budget: (threshold) => record("budget", threshold),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function createEvalExpect(record, checks) {
|
|
19
|
+
return {
|
|
20
|
+
completed() {
|
|
21
|
+
return createExpectation(checks, {
|
|
22
|
+
name: "expect.completed",
|
|
23
|
+
family: "check",
|
|
24
|
+
score: record.completed ? 1 : 0,
|
|
25
|
+
pass: record.completed,
|
|
26
|
+
...(record.error ? { explanation: record.error } : {}),
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
outputContains(text) {
|
|
30
|
+
const output = getOutputText(record.output);
|
|
31
|
+
const pass = output.includes(text);
|
|
32
|
+
return createExpectation(checks, {
|
|
33
|
+
name: "expect.outputContains",
|
|
34
|
+
family: "check",
|
|
35
|
+
score: pass ? 1 : 0,
|
|
36
|
+
pass,
|
|
37
|
+
evidence: { text },
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
noFailedTools() {
|
|
41
|
+
const failedTools = record.trace.toolCalls
|
|
42
|
+
.filter((tool) => tool.status === "error" || typeof tool.error === "string")
|
|
43
|
+
.map((tool) => tool.name);
|
|
44
|
+
return createExpectation(checks, {
|
|
45
|
+
name: "expect.noFailedTools",
|
|
46
|
+
family: "check",
|
|
47
|
+
score: failedTools.length === 0 ? 1 : 0,
|
|
48
|
+
pass: failedTools.length === 0,
|
|
49
|
+
...(failedTools.length > 0 ? { evidence: { failedTools } } : {}),
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export function createEvalCheckContext(input) {
|
|
55
|
+
return {
|
|
56
|
+
definition: input.definition,
|
|
57
|
+
example: input.example,
|
|
58
|
+
repetition: input.repetition,
|
|
59
|
+
record: input.record,
|
|
60
|
+
expect: createEvalExpect(input.record, input.checks),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { EvalAgentInput, EvalDefinition } from "./types.js";
|
|
2
|
+
/** Define a V1 eval that targets a Veryfront agent. */
|
|
3
|
+
export declare function evalAgent(input: EvalAgentInput): EvalDefinition;
|
|
4
|
+
/** Check whether a value is a normalized eval definition. */
|
|
5
|
+
export declare function isEvalDefinition(value: unknown): value is EvalDefinition;
|
|
6
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/src/eval/factory.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAe,cAAc,EAAoB,MAAM,YAAY,CAAC;AAwBhG,uDAAuD;AACvD,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAmB/D;AAED,6DAA6D;AAC7D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CASxE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { datasets } from "./datasets.js";
|
|
2
|
+
import { createEvalValidationError } from "./validation.js";
|
|
3
|
+
function isEvalDataset(value) {
|
|
4
|
+
return !!value &&
|
|
5
|
+
typeof value === "object" &&
|
|
6
|
+
typeof value.kind === "string" &&
|
|
7
|
+
typeof value.load === "function";
|
|
8
|
+
}
|
|
9
|
+
function normalizeDataset(dataset) {
|
|
10
|
+
return isEvalDataset(dataset) ? dataset : datasets.inline(dataset);
|
|
11
|
+
}
|
|
12
|
+
function normalizeRepetitions(repetitions) {
|
|
13
|
+
const value = repetitions ?? 1;
|
|
14
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
15
|
+
throw createEvalValidationError("Eval repetitions must be an integer greater than or equal to 1");
|
|
16
|
+
}
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
/** Define a V1 eval that targets a Veryfront agent. */
|
|
20
|
+
export function evalAgent(input) {
|
|
21
|
+
if (typeof input.target !== "string" || input.target.trim() === "") {
|
|
22
|
+
throw createEvalValidationError("Eval target must be a non-empty string");
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
kind: "eval",
|
|
26
|
+
targetKind: "agent",
|
|
27
|
+
id: input.id ?? "",
|
|
28
|
+
name: input.name ?? input.id ?? input.target,
|
|
29
|
+
...(input.description ? { description: input.description } : {}),
|
|
30
|
+
target: input.target,
|
|
31
|
+
dataset: normalizeDataset(input.dataset),
|
|
32
|
+
metrics: input.metrics ?? [],
|
|
33
|
+
repetitions: normalizeRepetitions(input.repetitions),
|
|
34
|
+
tags: input.tags ?? [],
|
|
35
|
+
metadata: input.metadata ?? {},
|
|
36
|
+
...(input.check ? { check: input.check } : {}),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** Check whether a value is a normalized eval definition. */
|
|
40
|
+
export function isEvalDefinition(value) {
|
|
41
|
+
if (!value || typeof value !== "object")
|
|
42
|
+
return false;
|
|
43
|
+
const candidate = value;
|
|
44
|
+
return candidate.kind === "eval" &&
|
|
45
|
+
candidate.targetKind === "agent" &&
|
|
46
|
+
typeof candidate.target === "string" &&
|
|
47
|
+
isEvalDataset(candidate.dataset) &&
|
|
48
|
+
Array.isArray(candidate.metrics) &&
|
|
49
|
+
typeof candidate.repetitions === "number";
|
|
50
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* First-class eval primitives for agent quality checks.
|
|
3
|
+
*
|
|
4
|
+
* @module eval
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { datasets, evalAgent, metrics } from "veryfront/eval";
|
|
9
|
+
*
|
|
10
|
+
* export default evalAgent({
|
|
11
|
+
* target: "agent:researcher",
|
|
12
|
+
* dataset: datasets.inline([
|
|
13
|
+
* { id: "q1", input: "Capital of France?", reference: "Paris" },
|
|
14
|
+
* ]),
|
|
15
|
+
* metrics: [
|
|
16
|
+
* metrics.answer.contains({ text: "Paris" }).gate(),
|
|
17
|
+
* metrics.agent.noFailedTools().gate(),
|
|
18
|
+
* ],
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import "../../_dnt.polyfills.js";
|
|
23
|
+
export { datasets } from "./datasets.js";
|
|
24
|
+
export { evalAgent, isEvalDefinition } from "./factory.js";
|
|
25
|
+
export { metrics } from "./metrics.js";
|
|
26
|
+
export { createEvalReport, summarizeEvalRecords } from "./report.js";
|
|
27
|
+
export { runEval } from "./runner.js";
|
|
28
|
+
export { deriveEvalId, discoverEvals, findEvalById } from "./discovery.js";
|
|
29
|
+
export { createEvalSourceDocument, getEvalEditableFieldSchema, getEvalRunSchema, getEvalSourceDocumentSchema, getEvalSourcePatchSchema, getEvalSourceReferenceSchema, getEvalStudioCapabilitySchema, } from "./studio.js";
|
|
30
|
+
export type { DiscoveredEval, EvalDiscoveryOptions, EvalDiscoveryResult } from "./discovery.js";
|
|
31
|
+
export type { EvalAgentAdapter, EvalAgentAdapterContext, EvalAgentAdapterResult, EvalAgentInput, EvalCheckContext, EvalDataset, EvalDatasetLoadContext, EvalDefinition, EvalExample, EvalExampleInput, EvalExpect, EvalExpectation, EvalMetric, EvalMetricContext, EvalMetricFamily, EvalMetricResult, EvalMetricSummary, EvalMetricThreshold, EvalRecord, EvalReport, EvalReportSummary, EvalSeverity, EvalSource, EvalTargetKind, EvalToolCall, EvalTrace, EvalUsage, RunEvalOptions, } from "./types.js";
|
|
32
|
+
export type { CreateEvalSourceDocumentOptions, EvalEditableField, EvalRun, EvalSourceDocument, EvalSourcePatch, EvalSourceReference, EvalStudioCapability, } from "./studio.js";
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/eval/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,yBAAyB,CAAC;AAGjC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,gBAAgB,EAChB,2BAA2B,EAC3B,wBAAwB,EACxB,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAChG,YAAY,EACV,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,sBAAsB,EACtB,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,cAAc,EACd,YAAY,EACZ,SAAS,EACT,SAAS,EACT,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,+BAA+B,EAC/B,iBAAiB,EACjB,OAAO,EACP,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* First-class eval primitives for agent quality checks.
|
|
3
|
+
*
|
|
4
|
+
* @module eval
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { datasets, evalAgent, metrics } from "veryfront/eval";
|
|
9
|
+
*
|
|
10
|
+
* export default evalAgent({
|
|
11
|
+
* target: "agent:researcher",
|
|
12
|
+
* dataset: datasets.inline([
|
|
13
|
+
* { id: "q1", input: "Capital of France?", reference: "Paris" },
|
|
14
|
+
* ]),
|
|
15
|
+
* metrics: [
|
|
16
|
+
* metrics.answer.contains({ text: "Paris" }).gate(),
|
|
17
|
+
* metrics.agent.noFailedTools().gate(),
|
|
18
|
+
* ],
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import "../../_dnt.polyfills.js";
|
|
23
|
+
export { datasets } from "./datasets.js";
|
|
24
|
+
export { evalAgent, isEvalDefinition } from "./factory.js";
|
|
25
|
+
export { metrics } from "./metrics.js";
|
|
26
|
+
export { createEvalReport, summarizeEvalRecords } from "./report.js";
|
|
27
|
+
export { runEval } from "./runner.js";
|
|
28
|
+
export { deriveEvalId, discoverEvals, findEvalById } from "./discovery.js";
|
|
29
|
+
export { createEvalSourceDocument, getEvalEditableFieldSchema, getEvalRunSchema, getEvalSourceDocumentSchema, getEvalSourcePatchSchema, getEvalSourceReferenceSchema, getEvalStudioCapabilitySchema, } from "./studio.js";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { EvalMetric } from "./types.js";
|
|
2
|
+
type JudgeRubricInput = {
|
|
3
|
+
rubric: string;
|
|
4
|
+
judge?: (input: {
|
|
5
|
+
rubric: string;
|
|
6
|
+
input: unknown;
|
|
7
|
+
output: Record<string, unknown>;
|
|
8
|
+
reference?: unknown;
|
|
9
|
+
metadata: Record<string, unknown>;
|
|
10
|
+
}) => Promise<{
|
|
11
|
+
score: number;
|
|
12
|
+
pass?: boolean;
|
|
13
|
+
explanation?: string;
|
|
14
|
+
}>;
|
|
15
|
+
};
|
|
16
|
+
declare function getOutputText(output: unknown): string;
|
|
17
|
+
declare function stableStringify(value: unknown): string;
|
|
18
|
+
/** Metric factories for deterministic answers, agent behavior, operations, and judges. */
|
|
19
|
+
export declare const metrics: {
|
|
20
|
+
readonly answer: {
|
|
21
|
+
readonly exactMatch: () => EvalMetric;
|
|
22
|
+
readonly contains: (options: {
|
|
23
|
+
text: string;
|
|
24
|
+
caseSensitive?: boolean;
|
|
25
|
+
}) => EvalMetric;
|
|
26
|
+
readonly regex: (options: {
|
|
27
|
+
pattern: string;
|
|
28
|
+
flags?: string;
|
|
29
|
+
}) => EvalMetric;
|
|
30
|
+
readonly jsonMatch: (options: {
|
|
31
|
+
expected?: unknown;
|
|
32
|
+
}) => EvalMetric;
|
|
33
|
+
};
|
|
34
|
+
readonly agent: {
|
|
35
|
+
readonly noFailedTools: () => EvalMetric;
|
|
36
|
+
};
|
|
37
|
+
readonly ops: {
|
|
38
|
+
readonly latency: (options: {
|
|
39
|
+
maxMs: number;
|
|
40
|
+
}) => EvalMetric;
|
|
41
|
+
readonly tokens: (options: {
|
|
42
|
+
maxTotal?: number;
|
|
43
|
+
maxInput?: number;
|
|
44
|
+
maxOutput?: number;
|
|
45
|
+
}) => EvalMetric;
|
|
46
|
+
readonly cost: (options: {
|
|
47
|
+
maxUsd: number;
|
|
48
|
+
}) => EvalMetric;
|
|
49
|
+
};
|
|
50
|
+
readonly judge: {
|
|
51
|
+
readonly rubric: (options: JudgeRubricInput) => EvalMetric;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
export { getOutputText, stableStringify };
|
|
55
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/src/eval/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EAMX,MAAM,YAAY,CAAC;AAIpB,KAAK,gBAAgB,GAAG;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE;QACd,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,OAAO,CAAC;QACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxE,CAAC;AAEF,iBAAS,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAQ9C;AASD,iBAAS,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAE/C;AA2FD,0FAA0F;AAC1F,eAAO,MAAM,OAAO;;mCAEF,UAAU;qCAON;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,aAAa,CAAC,EAAE,OAAO,CAAA;SAAE,KAAG,UAAU;kCAWzD;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,KAAG,UAAU;sCAY5C;YAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;SAAE,KAAG,UAAU;;;sCAWrC,UAAU;;;oCAgBV;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,KAAG,UAAU;mCAc/B;YAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE,KAAG,UAAU;iCAoB3E;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,KAAG,UAAU;;;mCAiB7B,gBAAgB,KAAG,UAAU;;CAmCvC,CAAC;AAEX,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
function getOutputText(output) {
|
|
2
|
+
if (typeof output === "string")
|
|
3
|
+
return output;
|
|
4
|
+
if (output && typeof output === "object") {
|
|
5
|
+
const record = output;
|
|
6
|
+
if (typeof record.text === "string")
|
|
7
|
+
return record.text;
|
|
8
|
+
if (typeof record.output === "string")
|
|
9
|
+
return record.output;
|
|
10
|
+
}
|
|
11
|
+
return stableStringify(output);
|
|
12
|
+
}
|
|
13
|
+
function getOutputJson(output) {
|
|
14
|
+
if (output && typeof output === "object" && "json" in output) {
|
|
15
|
+
return output.json;
|
|
16
|
+
}
|
|
17
|
+
return output;
|
|
18
|
+
}
|
|
19
|
+
function stableStringify(value) {
|
|
20
|
+
return JSON.stringify(sortJsonValue(value));
|
|
21
|
+
}
|
|
22
|
+
function sortJsonValue(value) {
|
|
23
|
+
if (Array.isArray(value))
|
|
24
|
+
return value.map(sortJsonValue);
|
|
25
|
+
if (!value || typeof value !== "object")
|
|
26
|
+
return value;
|
|
27
|
+
const sorted = {};
|
|
28
|
+
for (const key of Object.keys(value).sort()) {
|
|
29
|
+
sorted[key] = sortJsonValue(value[key]);
|
|
30
|
+
}
|
|
31
|
+
return sorted;
|
|
32
|
+
}
|
|
33
|
+
function withSeverity(metric, severity, threshold) {
|
|
34
|
+
const base = { ...metric, severity, ...(threshold ? { threshold } : {}) };
|
|
35
|
+
return {
|
|
36
|
+
...base,
|
|
37
|
+
async evaluate(record, context) {
|
|
38
|
+
const result = await metric.evaluate(record, context);
|
|
39
|
+
const next = {
|
|
40
|
+
...result,
|
|
41
|
+
name: metric.name,
|
|
42
|
+
family: metric.family,
|
|
43
|
+
severity,
|
|
44
|
+
};
|
|
45
|
+
if (!threshold || result.skipped || typeof next.score !== "number") {
|
|
46
|
+
return next;
|
|
47
|
+
}
|
|
48
|
+
const minPass = threshold.min === undefined || next.score >= threshold.min;
|
|
49
|
+
const maxPass = threshold.max === undefined || next.score <= threshold.max;
|
|
50
|
+
const thresholdPass = minPass && maxPass;
|
|
51
|
+
return {
|
|
52
|
+
...next,
|
|
53
|
+
pass: next.pass === undefined ? thresholdPass : next.pass && thresholdPass,
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
gate(nextThreshold) {
|
|
57
|
+
return withSeverity(base, "gate", nextThreshold ?? threshold);
|
|
58
|
+
},
|
|
59
|
+
soft(nextThreshold) {
|
|
60
|
+
return withSeverity(base, "soft", nextThreshold ?? threshold);
|
|
61
|
+
},
|
|
62
|
+
budget(nextThreshold) {
|
|
63
|
+
return withSeverity(base, "budget", nextThreshold ?? threshold);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function createMetric(name, family, evaluator, config) {
|
|
68
|
+
const metric = {
|
|
69
|
+
name,
|
|
70
|
+
family,
|
|
71
|
+
severity: "gate",
|
|
72
|
+
...(config ? { config } : {}),
|
|
73
|
+
async evaluate(record) {
|
|
74
|
+
const result = await evaluator(record);
|
|
75
|
+
return {
|
|
76
|
+
...result,
|
|
77
|
+
name,
|
|
78
|
+
family,
|
|
79
|
+
severity: "gate",
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
return withSeverity(metric, "gate");
|
|
84
|
+
}
|
|
85
|
+
function scoreResult(name, family, severity, pass, score = pass ? 1 : 0) {
|
|
86
|
+
return { name, family, severity, score, pass };
|
|
87
|
+
}
|
|
88
|
+
function isToolFailed(toolCall) {
|
|
89
|
+
return toolCall.status === "error" || typeof toolCall.error === "string";
|
|
90
|
+
}
|
|
91
|
+
/** Metric factories for deterministic answers, agent behavior, operations, and judges. */
|
|
92
|
+
export const metrics = {
|
|
93
|
+
answer: {
|
|
94
|
+
exactMatch() {
|
|
95
|
+
return createMetric("answer.exactMatch", "answer", (record) => {
|
|
96
|
+
const pass = getOutputText(record.output) === getOutputText(record.reference);
|
|
97
|
+
return scoreResult("answer.exactMatch", "answer", "gate", pass);
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
contains(options) {
|
|
101
|
+
return createMetric("answer.contains", "answer", (record) => {
|
|
102
|
+
const actual = getOutputText(record.output);
|
|
103
|
+
const expected = options.text;
|
|
104
|
+
const pass = options.caseSensitive
|
|
105
|
+
? actual.includes(expected)
|
|
106
|
+
: actual.toLowerCase().includes(expected.toLowerCase());
|
|
107
|
+
return scoreResult("answer.contains", "answer", "gate", pass);
|
|
108
|
+
}, options);
|
|
109
|
+
},
|
|
110
|
+
regex(options) {
|
|
111
|
+
return createMetric("answer.regex", "answer", (record) => {
|
|
112
|
+
const pattern = new RegExp(options.pattern, options.flags);
|
|
113
|
+
return scoreResult("answer.regex", "answer", "gate", pattern.test(getOutputText(record.output)));
|
|
114
|
+
}, options);
|
|
115
|
+
},
|
|
116
|
+
jsonMatch(options) {
|
|
117
|
+
return createMetric("answer.jsonMatch", "answer", (record) => {
|
|
118
|
+
const expected = Object.hasOwn(options, "expected") ? options.expected : record.reference;
|
|
119
|
+
const actual = getOutputJson(record.output);
|
|
120
|
+
const pass = stableStringify(actual) === stableStringify(expected);
|
|
121
|
+
return scoreResult("answer.jsonMatch", "answer", "gate", pass);
|
|
122
|
+
}, options);
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
agent: {
|
|
126
|
+
noFailedTools() {
|
|
127
|
+
return createMetric("agent.noFailedTools", "agent", (record) => {
|
|
128
|
+
const failedTools = record.trace.toolCalls.filter(isToolFailed).map((tool) => tool.name);
|
|
129
|
+
return {
|
|
130
|
+
name: "agent.noFailedTools",
|
|
131
|
+
family: "agent",
|
|
132
|
+
severity: "gate",
|
|
133
|
+
score: failedTools.length === 0 ? 1 : 0,
|
|
134
|
+
pass: failedTools.length === 0,
|
|
135
|
+
...(failedTools.length > 0 ? { evidence: { failedTools } } : {}),
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
ops: {
|
|
141
|
+
latency(options) {
|
|
142
|
+
return createMetric("ops.latency", "ops", (record) => {
|
|
143
|
+
const pass = record.durationMs <= options.maxMs;
|
|
144
|
+
return {
|
|
145
|
+
name: "ops.latency",
|
|
146
|
+
family: "ops",
|
|
147
|
+
severity: "budget",
|
|
148
|
+
score: pass ? 1 : 0,
|
|
149
|
+
pass,
|
|
150
|
+
evidence: { durationMs: record.durationMs, maxMs: options.maxMs },
|
|
151
|
+
};
|
|
152
|
+
}, options);
|
|
153
|
+
},
|
|
154
|
+
tokens(options) {
|
|
155
|
+
return createMetric("ops.tokens", "ops", (record) => {
|
|
156
|
+
const inputOk = options.maxInput === undefined ||
|
|
157
|
+
(record.usage.inputTokens ?? 0) <= options.maxInput;
|
|
158
|
+
const outputOk = options.maxOutput === undefined ||
|
|
159
|
+
(record.usage.outputTokens ?? 0) <= options.maxOutput;
|
|
160
|
+
const totalOk = options.maxTotal === undefined ||
|
|
161
|
+
(record.usage.totalTokens ?? 0) <= options.maxTotal;
|
|
162
|
+
const pass = inputOk && outputOk && totalOk;
|
|
163
|
+
return {
|
|
164
|
+
name: "ops.tokens",
|
|
165
|
+
family: "ops",
|
|
166
|
+
severity: "budget",
|
|
167
|
+
score: pass ? 1 : 0,
|
|
168
|
+
pass,
|
|
169
|
+
evidence: { usage: record.usage, limits: options },
|
|
170
|
+
};
|
|
171
|
+
}, options);
|
|
172
|
+
},
|
|
173
|
+
cost(options) {
|
|
174
|
+
return createMetric("ops.cost", "ops", (record) => {
|
|
175
|
+
const costUsd = record.usage.costUsd ?? 0;
|
|
176
|
+
const pass = costUsd <= options.maxUsd;
|
|
177
|
+
return {
|
|
178
|
+
name: "ops.cost",
|
|
179
|
+
family: "ops",
|
|
180
|
+
severity: "budget",
|
|
181
|
+
score: pass ? 1 : 0,
|
|
182
|
+
pass,
|
|
183
|
+
evidence: { costUsd, maxUsd: options.maxUsd },
|
|
184
|
+
};
|
|
185
|
+
}, options);
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
judge: {
|
|
189
|
+
rubric(options) {
|
|
190
|
+
return createMetric("judge.rubric", "judge", async (record) => {
|
|
191
|
+
if (!options.judge) {
|
|
192
|
+
return {
|
|
193
|
+
name: "judge.rubric",
|
|
194
|
+
family: "judge",
|
|
195
|
+
severity: "gate",
|
|
196
|
+
skipped: true,
|
|
197
|
+
explanation: "No judge function was provided.",
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
const output = record.output && typeof record.output === "object"
|
|
201
|
+
? record.output
|
|
202
|
+
: { text: getOutputText(record.output) };
|
|
203
|
+
const judged = await options.judge({
|
|
204
|
+
rubric: options.rubric,
|
|
205
|
+
input: record.input,
|
|
206
|
+
output,
|
|
207
|
+
reference: record.reference,
|
|
208
|
+
metadata: record.metadata,
|
|
209
|
+
});
|
|
210
|
+
const min = 0;
|
|
211
|
+
return {
|
|
212
|
+
name: "judge.rubric",
|
|
213
|
+
family: "judge",
|
|
214
|
+
severity: "gate",
|
|
215
|
+
score: judged.score,
|
|
216
|
+
pass: judged.pass ?? judged.score > min,
|
|
217
|
+
...(judged.explanation ? { explanation: judged.explanation } : {}),
|
|
218
|
+
};
|
|
219
|
+
}, { rubric: options.rubric });
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
export { getOutputText, stableStringify };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { EvalDefinition, EvalRecord, EvalReport, EvalReportSummary } from "./types.js";
|
|
2
|
+
/** Summarize eval records into pass/fail and metric aggregates. */
|
|
3
|
+
export declare function summarizeEvalRecords(records: EvalRecord[]): EvalReportSummary;
|
|
4
|
+
/** Create a JSON-serializable eval report from executed records. */
|
|
5
|
+
export declare function createEvalReport(input: {
|
|
6
|
+
definition: EvalDefinition;
|
|
7
|
+
records: EvalRecord[];
|
|
8
|
+
runId: string;
|
|
9
|
+
startedAt: Date;
|
|
10
|
+
endedAt: Date;
|
|
11
|
+
}): EvalReport;
|
|
12
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/src/eval/report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EAGd,UAAU,EACV,UAAU,EACV,iBAAiB,EAClB,MAAM,YAAY,CAAC;AA6CpB,mEAAmE;AACnE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,iBAAiB,CAU7E;AAED,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC;CACf,GAAG,UAAU,CAYb"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
function isBlockingFailure(result) {
|
|
2
|
+
return !result.skipped && result.pass === false &&
|
|
3
|
+
(result.severity === "gate" || result.severity === "budget");
|
|
4
|
+
}
|
|
5
|
+
function recordPassed(record) {
|
|
6
|
+
const results = [...(record.metrics ?? []), ...(record.checks ?? [])];
|
|
7
|
+
return results.every((result) => !isBlockingFailure(result));
|
|
8
|
+
}
|
|
9
|
+
function summarizeMetricResults(records) {
|
|
10
|
+
const summaries = new Map();
|
|
11
|
+
for (const record of records) {
|
|
12
|
+
for (const result of [...(record.metrics ?? []), ...(record.checks ?? [])]) {
|
|
13
|
+
const key = `${result.name}:${result.family}:${result.severity}`;
|
|
14
|
+
const summary = summaries.get(key) ?? {
|
|
15
|
+
name: result.name,
|
|
16
|
+
family: result.family,
|
|
17
|
+
severity: result.severity,
|
|
18
|
+
passed: 0,
|
|
19
|
+
failed: 0,
|
|
20
|
+
skipped: 0,
|
|
21
|
+
passRate: 0,
|
|
22
|
+
};
|
|
23
|
+
if (result.skipped) {
|
|
24
|
+
summary.skipped += 1;
|
|
25
|
+
}
|
|
26
|
+
else if (result.pass === false) {
|
|
27
|
+
summary.failed += 1;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
summary.passed += 1;
|
|
31
|
+
}
|
|
32
|
+
const denominator = summary.passed + summary.failed;
|
|
33
|
+
summary.passRate = denominator === 0 ? 1 : summary.passed / denominator;
|
|
34
|
+
summaries.set(key, summary);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return [...summaries.values()];
|
|
38
|
+
}
|
|
39
|
+
/** Summarize eval records into pass/fail and metric aggregates. */
|
|
40
|
+
export function summarizeEvalRecords(records) {
|
|
41
|
+
const passed = records.filter(recordPassed).length;
|
|
42
|
+
const failed = records.length - passed;
|
|
43
|
+
return {
|
|
44
|
+
records: records.length,
|
|
45
|
+
passed,
|
|
46
|
+
failed,
|
|
47
|
+
passRate: records.length === 0 ? 1 : passed / records.length,
|
|
48
|
+
metrics: summarizeMetricResults(records),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** Create a JSON-serializable eval report from executed records. */
|
|
52
|
+
export function createEvalReport(input) {
|
|
53
|
+
return {
|
|
54
|
+
kind: "eval-report",
|
|
55
|
+
runId: input.runId,
|
|
56
|
+
definitionId: input.definition.id,
|
|
57
|
+
targetKind: input.definition.targetKind,
|
|
58
|
+
target: input.definition.target,
|
|
59
|
+
startedAt: input.startedAt.toISOString(),
|
|
60
|
+
endedAt: input.endedAt.toISOString(),
|
|
61
|
+
summary: summarizeEvalRecords(input.records),
|
|
62
|
+
records: input.records,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { EvalDefinition, RunEvalOptions } from "./types.js";
|
|
2
|
+
/** Execute an eval locally with injected target adapters. */
|
|
3
|
+
export declare function runEval(definition: EvalDefinition, options: RunEvalOptions): Promise<import("./types.js").EvalReport>;
|
|
4
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/src/eval/runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,cAAc,EAKd,cAAc,EACf,MAAM,YAAY,CAAC;AAkGpB,6DAA6D;AAC7D,wBAAsB,OAAO,CAC3B,UAAU,EAAE,cAAc,EAC1B,OAAO,EAAE,cAAc,4CAqBxB"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
2
|
+
import { createEvalCheckContext } from "./expect.js";
|
|
3
|
+
import { createEvalReport } from "./report.js";
|
|
4
|
+
function createRunId(now) {
|
|
5
|
+
return `evalrun_${now.toISOString().replace(/[-:.]/g, "").replace("T", "_").replace("Z", "")}`;
|
|
6
|
+
}
|
|
7
|
+
function normalizeTrace(trace) {
|
|
8
|
+
return {
|
|
9
|
+
events: trace?.events ?? [],
|
|
10
|
+
toolCalls: trace?.toolCalls ?? [],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function normalizeUsage(usage) {
|
|
14
|
+
return usage ?? {};
|
|
15
|
+
}
|
|
16
|
+
function normalizeAdapterResult(result) {
|
|
17
|
+
return typeof result === "string" ? { text: result } : result;
|
|
18
|
+
}
|
|
19
|
+
function normalizeOutput(result) {
|
|
20
|
+
if (Object.hasOwn(result, "output"))
|
|
21
|
+
return result.output;
|
|
22
|
+
if (Object.hasOwn(result, "json"))
|
|
23
|
+
return { json: result.json };
|
|
24
|
+
if (Object.hasOwn(result, "text"))
|
|
25
|
+
return { text: result.text };
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
function isBlockingFailure(record) {
|
|
29
|
+
return [...(record.metrics ?? []), ...(record.checks ?? [])].some((result) => !result.skipped && result.pass === false &&
|
|
30
|
+
(result.severity === "gate" || result.severity === "budget"));
|
|
31
|
+
}
|
|
32
|
+
async function runRecord(definition, options, example, repetition) {
|
|
33
|
+
const started = Date.now();
|
|
34
|
+
let result;
|
|
35
|
+
try {
|
|
36
|
+
result = normalizeAdapterResult(await options.adapters.agent({ definition, example, repetition }));
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
result = {
|
|
40
|
+
text: "",
|
|
41
|
+
completed: false,
|
|
42
|
+
error: error instanceof Error ? error.message : String(error),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const output = normalizeOutput(result);
|
|
46
|
+
const record = {
|
|
47
|
+
id: `${example.id}:${repetition}`,
|
|
48
|
+
evalId: definition.id,
|
|
49
|
+
exampleId: example.id,
|
|
50
|
+
repetition,
|
|
51
|
+
input: example.input,
|
|
52
|
+
output,
|
|
53
|
+
...(Object.hasOwn(example, "reference") ? { reference: example.reference } : {}),
|
|
54
|
+
metadata: example.metadata ?? {},
|
|
55
|
+
trace: normalizeTrace(result.trace),
|
|
56
|
+
usage: normalizeUsage(result.usage),
|
|
57
|
+
durationMs: result.durationMs ?? Date.now() - started,
|
|
58
|
+
completed: result.completed ?? !result.error,
|
|
59
|
+
...(result.error ? { error: result.error } : {}),
|
|
60
|
+
};
|
|
61
|
+
const metricResults = [];
|
|
62
|
+
for (const metric of definition.metrics) {
|
|
63
|
+
metricResults.push(await metric.evaluate(record));
|
|
64
|
+
}
|
|
65
|
+
record.metrics = metricResults;
|
|
66
|
+
const checks = [];
|
|
67
|
+
if (definition.check) {
|
|
68
|
+
await definition.check(createEvalCheckContext({
|
|
69
|
+
definition,
|
|
70
|
+
example,
|
|
71
|
+
repetition,
|
|
72
|
+
record,
|
|
73
|
+
checks,
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
record.checks = checks;
|
|
77
|
+
if (isBlockingFailure(record)) {
|
|
78
|
+
record.completed = record.completed && true;
|
|
79
|
+
}
|
|
80
|
+
return record;
|
|
81
|
+
}
|
|
82
|
+
/** Execute an eval locally with injected target adapters. */
|
|
83
|
+
export async function runEval(definition, options) {
|
|
84
|
+
const startedAt = options.now?.() ?? new Date();
|
|
85
|
+
const baseDir = options.baseDir ?? dntShim.Deno.cwd();
|
|
86
|
+
const examples = await definition.dataset.load({ baseDir });
|
|
87
|
+
const records = [];
|
|
88
|
+
for (const example of examples) {
|
|
89
|
+
for (let repetition = 1; repetition <= definition.repetitions; repetition += 1) {
|
|
90
|
+
records.push(await runRecord(definition, options, example, repetition));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const endedAt = options.now?.() ?? new Date();
|
|
94
|
+
return createEvalReport({
|
|
95
|
+
definition,
|
|
96
|
+
records,
|
|
97
|
+
runId: options.runId ?? createRunId(startedAt),
|
|
98
|
+
startedAt,
|
|
99
|
+
endedAt,
|
|
100
|
+
});
|
|
101
|
+
}
|