jevascript 0.1.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/LICENSE +21 -0
- package/README.md +447 -0
- package/dist/cache.d.ts +18 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +58 -0
- package/dist/cache.js.map +1 -0
- package/dist/collections.d.ts +52 -0
- package/dist/collections.d.ts.map +1 -0
- package/dist/collections.js +206 -0
- package/dist/collections.js.map +1 -0
- package/dist/config.d.ts +57 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +75 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +73 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +251 -0
- package/dist/context.js.map +1 -0
- package/dist/define.d.ts +52 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +59 -0
- package/dist/define.js.map +1 -0
- package/dist/errors.d.ts +28 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +56 -0
- package/dist/errors.js.map +1 -0
- package/dist/evaluate.d.ts +31 -0
- package/dist/evaluate.d.ts.map +1 -0
- package/dist/evaluate.js +142 -0
- package/dist/evaluate.js.map +1 -0
- package/dist/factory.d.ts +6 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +7 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +68 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +3 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +6 -0
- package/dist/internal.js.map +1 -0
- package/dist/outputs.d.ts +40 -0
- package/dist/outputs.d.ts.map +1 -0
- package/dist/outputs.js +20 -0
- package/dist/outputs.js.map +1 -0
- package/dist/providers/jev.d.ts +21 -0
- package/dist/providers/jev.d.ts.map +1 -0
- package/dist/providers/jev.js +175 -0
- package/dist/providers/jev.js.map +1 -0
- package/dist/questions.d.ts +98 -0
- package/dist/questions.d.ts.map +1 -0
- package/dist/questions.js +57 -0
- package/dist/questions.js.map +1 -0
- package/dist/runner.d.ts +52 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +208 -0
- package/dist/runner.js.map +1 -0
- package/dist/schema.d.ts +49 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +30 -0
- package/dist/schema.js.map +1 -0
- package/dist/testing.d.ts +34 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +68 -0
- package/dist/testing.js.map +1 -0
- package/dist/types.d.ts +152 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +29 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { ChoiceOptionSpec, ChoiceQuestion, JsonValue, LevelSpec, SemanticProvider, SemanticQuestion, TruthQuestion } from "./types.ts";
|
|
2
|
+
export interface SharedOptions {
|
|
3
|
+
provider?: SemanticProvider;
|
|
4
|
+
timeoutMs?: number;
|
|
5
|
+
cache?: string | number;
|
|
6
|
+
/** Rounds used to measure confidence. Implied by `minConfidence`. */
|
|
7
|
+
samples?: number;
|
|
8
|
+
minConfidence?: number;
|
|
9
|
+
detailed?: boolean;
|
|
10
|
+
/** Identity of the definition this came from, surfaced in observability. */
|
|
11
|
+
metric?: {
|
|
12
|
+
name: string;
|
|
13
|
+
version?: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface TruthCriteria {
|
|
17
|
+
/** What clearly counts as true. */
|
|
18
|
+
trueWhen?: string | JsonValue;
|
|
19
|
+
/** What clearly does not count, even when it looks close. */
|
|
20
|
+
falseWhen?: string | JsonValue;
|
|
21
|
+
}
|
|
22
|
+
export interface IsOptions extends SharedOptions, TruthCriteria {
|
|
23
|
+
/** Probability above which the answer reads as true. Defaults to 0.5. */
|
|
24
|
+
threshold?: number;
|
|
25
|
+
/** Report probabilities inside the uncertainty band as "unknown". */
|
|
26
|
+
allowUnknown?: boolean;
|
|
27
|
+
uncertaintyBand?: readonly [number, number];
|
|
28
|
+
fallback?: boolean | (() => boolean | Promise<boolean>);
|
|
29
|
+
}
|
|
30
|
+
export interface ScoreOptions extends SharedOptions, TruthCriteria {
|
|
31
|
+
range?: readonly [number, number];
|
|
32
|
+
/**
|
|
33
|
+
* Ordered rubric levels, 2–10 of them, each describing a *situation* rather
|
|
34
|
+
* than a degree. Supplying these switches from a probability-backed score to
|
|
35
|
+
* a rubric-backed one.
|
|
36
|
+
*/
|
|
37
|
+
levels?: readonly (string | LevelSpec)[];
|
|
38
|
+
/** Treat the criterion as a complete proposition instead of framing it. */
|
|
39
|
+
asProposition?: boolean;
|
|
40
|
+
fallback?: number | (() => number | Promise<number>);
|
|
41
|
+
}
|
|
42
|
+
export interface ChooseOptions extends SharedOptions {
|
|
43
|
+
instructions?: string;
|
|
44
|
+
fallback?: string | (() => string | Promise<string>);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Default framing that turns a noun-phrase criterion into a proposition.
|
|
48
|
+
*
|
|
49
|
+
* `score("fraud risk")` on its own is a noun phrase, and the model answers what
|
|
50
|
+
* it is literally asked. Framing it as "This has high fraud risk." gives the
|
|
51
|
+
* probability a well-defined referent. Override for other languages via
|
|
52
|
+
* `configureSemantic({ defaults: { scoreFrame } })`.
|
|
53
|
+
*/
|
|
54
|
+
export declare const DEFAULT_SCORE_FRAME: (criterion: string) => string;
|
|
55
|
+
export interface BuiltQuestion {
|
|
56
|
+
question: SemanticQuestion;
|
|
57
|
+
options: SharedOptions;
|
|
58
|
+
operation: "is" | "score" | "choose";
|
|
59
|
+
range?: readonly [number, number];
|
|
60
|
+
optionKeys?: readonly string[];
|
|
61
|
+
}
|
|
62
|
+
/** A question that has not been bound to a state yet. Used by `batch()`. */
|
|
63
|
+
export interface QuestionSpec<TValue = unknown> {
|
|
64
|
+
readonly __value?: TValue;
|
|
65
|
+
readonly build: (frame: (criterion: string) => string) => BuiltQuestion;
|
|
66
|
+
}
|
|
67
|
+
export declare function buildIs(condition: string | JsonValue, options?: IsOptions): {
|
|
68
|
+
question: TruthQuestion;
|
|
69
|
+
options: IsOptions;
|
|
70
|
+
operation: "is";
|
|
71
|
+
};
|
|
72
|
+
export declare function buildScore(criterion: string, options?: ScoreOptions, frame?: (criterion: string) => string): {
|
|
73
|
+
question: {
|
|
74
|
+
kind: "level";
|
|
75
|
+
instructions: string;
|
|
76
|
+
levels: readonly (string | LevelSpec)[];
|
|
77
|
+
};
|
|
78
|
+
options: ScoreOptions;
|
|
79
|
+
operation: "score";
|
|
80
|
+
range: readonly [number, number];
|
|
81
|
+
} | {
|
|
82
|
+
question: TruthQuestion;
|
|
83
|
+
options: ScoreOptions;
|
|
84
|
+
operation: "score";
|
|
85
|
+
range: readonly [number, number];
|
|
86
|
+
};
|
|
87
|
+
export type ChoiceInput = readonly string[] | Readonly<Record<string, string | ChoiceOptionSpec>>;
|
|
88
|
+
export declare function buildChoose(input: ChoiceInput, options?: ChooseOptions): {
|
|
89
|
+
question: ChoiceQuestion;
|
|
90
|
+
options: ChooseOptions;
|
|
91
|
+
operation: "choose";
|
|
92
|
+
optionKeys: string[];
|
|
93
|
+
};
|
|
94
|
+
export declare function is(condition: string, options?: IsOptions): QuestionSpec<boolean>;
|
|
95
|
+
export declare function score(criterion: string, options?: ScoreOptions): QuestionSpec<number>;
|
|
96
|
+
export declare function choose<const T extends readonly string[]>(options: T, extra?: ChooseOptions): QuestionSpec<T[number]>;
|
|
97
|
+
export declare function choose<const T extends Readonly<Record<string, string | ChoiceOptionSpec>>>(options: T, extra?: ChooseOptions): QuestionSpec<keyof T & string>;
|
|
98
|
+
//# sourceMappingURL=questions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"questions.d.ts","sourceRoot":"","sources":["../src/questions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default framing that turns a noun-phrase criterion into a proposition.
|
|
3
|
+
*
|
|
4
|
+
* `score("fraud risk")` on its own is a noun phrase, and the model answers what
|
|
5
|
+
* it is literally asked. Framing it as "This has high fraud risk." gives the
|
|
6
|
+
* probability a well-defined referent. Override for other languages via
|
|
7
|
+
* `configureSemantic({ defaults: { scoreFrame } })`.
|
|
8
|
+
*/
|
|
9
|
+
export const DEFAULT_SCORE_FRAME = (criterion) => `This has high ${criterion}.`;
|
|
10
|
+
function truthQuestion(instructions, criteria) {
|
|
11
|
+
return {
|
|
12
|
+
kind: "truth",
|
|
13
|
+
instructions,
|
|
14
|
+
...(criteria.trueWhen !== undefined ? { trueWhen: criteria.trueWhen } : {}),
|
|
15
|
+
...(criteria.falseWhen !== undefined ? { falseWhen: criteria.falseWhen } : {}),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function buildIs(condition, options = {}) {
|
|
19
|
+
return { question: truthQuestion(condition, options), options, operation: "is" };
|
|
20
|
+
}
|
|
21
|
+
export function buildScore(criterion, options = {}, frame = DEFAULT_SCORE_FRAME) {
|
|
22
|
+
const range = options.range ?? [0, 100];
|
|
23
|
+
if (options.levels) {
|
|
24
|
+
return {
|
|
25
|
+
question: { kind: "level", instructions: criterion, levels: options.levels },
|
|
26
|
+
options,
|
|
27
|
+
operation: "score",
|
|
28
|
+
range,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const instructions = options.asProposition ? criterion : frame(criterion);
|
|
32
|
+
return { question: truthQuestion(instructions, options), options, operation: "score", range };
|
|
33
|
+
}
|
|
34
|
+
export function buildChoose(input, options = {}) {
|
|
35
|
+
const optionMap = Array.isArray(input)
|
|
36
|
+
? Object.fromEntries(input.map((key) => [key, key]))
|
|
37
|
+
: { ...input };
|
|
38
|
+
const question = {
|
|
39
|
+
kind: "choice",
|
|
40
|
+
instructions: options.instructions ?? "Select the option that best fits the state.",
|
|
41
|
+
options: optionMap,
|
|
42
|
+
};
|
|
43
|
+
return { question, options, operation: "choose", optionKeys: Object.keys(optionMap) };
|
|
44
|
+
}
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Standalone builders, for composing inside `batch()`.
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
export function is(condition, options = {}) {
|
|
49
|
+
return { build: () => buildIs(condition, options) };
|
|
50
|
+
}
|
|
51
|
+
export function score(criterion, options = {}) {
|
|
52
|
+
return { build: (frame) => buildScore(criterion, options, frame) };
|
|
53
|
+
}
|
|
54
|
+
export function choose(options, extra = {}) {
|
|
55
|
+
return { build: () => buildChoose(options, extra) };
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=questions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"questions.js","sourceRoot":"","sources":["../src/questions.ts"],"names":[],"mappings":"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"}
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { parseTtlOrUndefined } from "./internal.ts";
|
|
2
|
+
import type { SemanticCache } from "./cache.ts";
|
|
3
|
+
import type { SemanticConfig } from "./config.ts";
|
|
4
|
+
import type { EvaluationEvent, SemanticAnswer, SemanticProvider, SemanticQuestion, State, Usage } from "./types.ts";
|
|
5
|
+
export interface PlannedQuestion {
|
|
6
|
+
key: string;
|
|
7
|
+
question: SemanticQuestion;
|
|
8
|
+
/** Rounds to run. 1 means a single pass with no measured confidence. */
|
|
9
|
+
samples: number;
|
|
10
|
+
cacheTtlMs?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface RunResult {
|
|
13
|
+
answers: Record<string, SemanticAnswer>;
|
|
14
|
+
/** Per-key confidence measured across sample rounds, when samples > 1. */
|
|
15
|
+
measured: Record<string, number | undefined>;
|
|
16
|
+
cachedKeys: Set<string>;
|
|
17
|
+
usage: Usage;
|
|
18
|
+
latencyMs: number;
|
|
19
|
+
requestCount: number;
|
|
20
|
+
}
|
|
21
|
+
export declare function cacheKeyFor(provider: SemanticProvider, state: State, question: SemanticQuestion, samples: number): string;
|
|
22
|
+
/**
|
|
23
|
+
* Validates a question against what the provider can actually express, so an
|
|
24
|
+
* impossible request fails here rather than as a confusing 4xx.
|
|
25
|
+
*/
|
|
26
|
+
export declare function assertSupported(provider: SemanticProvider, question: SemanticQuestion): void;
|
|
27
|
+
/**
|
|
28
|
+
* Turns observed spread across sample rounds into a 0–1 confidence.
|
|
29
|
+
*
|
|
30
|
+
* A truth answer has no provider-reported confidence: the probability itself
|
|
31
|
+
* carries the uncertainty. Deriving confidence from the probability (e.g.
|
|
32
|
+
* |p-0.5|*2) is wrong for scores, where a mid-range value means "middling",
|
|
33
|
+
* not "unsure". So we measure instead: re-ask and see how much the answer moves.
|
|
34
|
+
*
|
|
35
|
+
* sigma of 0 maps to 1.0, and 0.5 (the widest meaningful spread on [0,1]) to 0.
|
|
36
|
+
*/
|
|
37
|
+
export declare function confidenceFromSpread(samples: readonly number[]): number;
|
|
38
|
+
/**
|
|
39
|
+
* Executes a plan as few provider requests as possible.
|
|
40
|
+
*
|
|
41
|
+
* Round 0 carries every question. Later rounds carry only the questions that
|
|
42
|
+
* asked for more samples, so raising `samples` on one question does not
|
|
43
|
+
* multiply the cost of its neighbours.
|
|
44
|
+
*/
|
|
45
|
+
export declare function runPlan(provider: SemanticProvider, state: State, planned: readonly PlannedQuestion[], options?: {
|
|
46
|
+
timeoutMs?: number;
|
|
47
|
+
signal?: AbortSignal;
|
|
48
|
+
store?: SemanticCache;
|
|
49
|
+
}): Promise<RunResult>;
|
|
50
|
+
export declare function emit(event: EvaluationEvent, config?: SemanticConfig): void;
|
|
51
|
+
export { parseTtlOrUndefined };
|
|
52
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAGjD,OAAO,KAAK,EAGV,eAAe,EAGf,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,EAEL,KAAK,EACN,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IACvC,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IAC5C,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACvB,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB;AAUD,wBAAgB,WAAW,CACzB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,MAAM,GACd,MAAM,CAIR;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CA2B5F;AA2BD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEvE;AA8CD;;;;;;GAMG;AACH,wBAAsB,OAAO,CAC3B,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,SAAS,eAAe,EAAE,EACnC,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,aAAa,CAAA;CAAO,GAChF,OAAO,CAAC,SAAS,CAAC,CAqEpB;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,GAAE,cAA4B,GAAG,IAAI,CAQvF;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAA"}
|
package/dist/runner.js
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { getCacheStore, getConfig, parseTtlOrUndefined } from "./internal.js";
|
|
2
|
+
import { hashKey } from "./cache.js";
|
|
3
|
+
import { UnsupportedByProviderError } from "./errors.js";
|
|
4
|
+
/** Stable stringify so cache keys survive key reordering. */
|
|
5
|
+
function stable(value) {
|
|
6
|
+
if (value === null || typeof value !== "object")
|
|
7
|
+
return JSON.stringify(value) ?? "null";
|
|
8
|
+
if (Array.isArray(value))
|
|
9
|
+
return `[${value.map(stable).join(",")}]`;
|
|
10
|
+
const entries = Object.entries(value).sort(([a], [b]) => (a < b ? -1 : 1));
|
|
11
|
+
return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stable(v)}`).join(",")}}`;
|
|
12
|
+
}
|
|
13
|
+
export function cacheKeyFor(provider, state, question, samples) {
|
|
14
|
+
return hashKey(stable({ p: provider.name, m: provider.model, s: state, q: question, n: samples }));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Validates a question against what the provider can actually express, so an
|
|
18
|
+
* impossible request fails here rather than as a confusing 4xx.
|
|
19
|
+
*/
|
|
20
|
+
export function assertSupported(provider, question) {
|
|
21
|
+
const caps = provider.capabilities;
|
|
22
|
+
if (question.kind === "choice") {
|
|
23
|
+
const count = Object.keys(question.options).length;
|
|
24
|
+
if (count > caps.maxChoiceOptions) {
|
|
25
|
+
throw new UnsupportedByProviderError(provider.name, `a choice over ${count} options`, `The limit is ${caps.maxChoiceOptions}. Narrow the set first, or classify hierarchically.`);
|
|
26
|
+
}
|
|
27
|
+
if (count < 2) {
|
|
28
|
+
throw new UnsupportedByProviderError(provider.name, "a choice over fewer than 2 options", "Add options.");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (question.kind === "level") {
|
|
32
|
+
const count = question.levels.length;
|
|
33
|
+
const [min, max] = caps.levelRange;
|
|
34
|
+
if (count < min || count > max) {
|
|
35
|
+
throw new UnsupportedByProviderError(provider.name, `a rubric with ${count} levels`, `Supported range is ${min}–${max}. Use fewer, well-separated levels, or drop \`levels\` to get a ` +
|
|
36
|
+
"probability-backed score instead.");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function argmax(probabilities) {
|
|
41
|
+
let best = "";
|
|
42
|
+
let bestValue = -Infinity;
|
|
43
|
+
for (const [key, value] of Object.entries(probabilities)) {
|
|
44
|
+
if (value > bestValue) {
|
|
45
|
+
bestValue = value;
|
|
46
|
+
best = key;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return best;
|
|
50
|
+
}
|
|
51
|
+
function mean(values) {
|
|
52
|
+
return values.reduce((a, b) => a + b, 0) / values.length;
|
|
53
|
+
}
|
|
54
|
+
function stdev(values) {
|
|
55
|
+
if (values.length < 2)
|
|
56
|
+
return 0;
|
|
57
|
+
const m = mean(values);
|
|
58
|
+
const variance = values.reduce((a, b) => a + (b - m) ** 2, 0) / (values.length - 1);
|
|
59
|
+
// Identical samples can leave a sub-epsilon residue behind, which would
|
|
60
|
+
// otherwise report a perfectly stable answer as slightly less than certain.
|
|
61
|
+
return variance < 1e-12 ? 0 : Math.sqrt(variance);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Turns observed spread across sample rounds into a 0–1 confidence.
|
|
65
|
+
*
|
|
66
|
+
* A truth answer has no provider-reported confidence: the probability itself
|
|
67
|
+
* carries the uncertainty. Deriving confidence from the probability (e.g.
|
|
68
|
+
* |p-0.5|*2) is wrong for scores, where a mid-range value means "middling",
|
|
69
|
+
* not "unsure". So we measure instead: re-ask and see how much the answer moves.
|
|
70
|
+
*
|
|
71
|
+
* sigma of 0 maps to 1.0, and 0.5 (the widest meaningful spread on [0,1]) to 0.
|
|
72
|
+
*/
|
|
73
|
+
export function confidenceFromSpread(samples) {
|
|
74
|
+
return Math.min(1, Math.max(0, 1 - 2 * stdev(samples)));
|
|
75
|
+
}
|
|
76
|
+
function aggregate(kind, rounds) {
|
|
77
|
+
if (rounds.length === 1)
|
|
78
|
+
return rounds[0];
|
|
79
|
+
if (kind === "truth") {
|
|
80
|
+
const ps = rounds.map((r) => r.probability);
|
|
81
|
+
return { kind: "truth", probability: mean(ps) };
|
|
82
|
+
}
|
|
83
|
+
if (kind === "choice") {
|
|
84
|
+
const all = rounds;
|
|
85
|
+
const keys = Object.keys(all[0].probabilities);
|
|
86
|
+
const averaged = {};
|
|
87
|
+
for (const key of keys)
|
|
88
|
+
averaged[key] = mean(all.map((r) => r.probabilities[key] ?? 0));
|
|
89
|
+
return {
|
|
90
|
+
kind: "choice",
|
|
91
|
+
choice: argmax(averaged),
|
|
92
|
+
probabilities: averaged,
|
|
93
|
+
confidence: mean(all.map((r) => r.confidence)),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const all = rounds;
|
|
97
|
+
const width = all[0].probabilities.length;
|
|
98
|
+
const averaged = [];
|
|
99
|
+
for (let i = 0; i < width; i++)
|
|
100
|
+
averaged.push(mean(all.map((r) => r.probabilities[i] ?? 0)));
|
|
101
|
+
return {
|
|
102
|
+
kind: "level",
|
|
103
|
+
level: mean(all.map((r) => r.level)),
|
|
104
|
+
probabilities: averaged,
|
|
105
|
+
confidence: mean(all.map((r) => r.confidence)),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/** Numeric series a measured confidence can be computed from, per kind. */
|
|
109
|
+
function series(kind, rounds) {
|
|
110
|
+
if (kind === "truth")
|
|
111
|
+
return rounds.map((r) => r.probability);
|
|
112
|
+
if (kind === "level") {
|
|
113
|
+
// Normalise rubric position onto 0–1 so the spread formula stays comparable.
|
|
114
|
+
const all = rounds;
|
|
115
|
+
const width = Math.max(1, all[0].probabilities.length - 1);
|
|
116
|
+
return all.map((r) => r.level / width);
|
|
117
|
+
}
|
|
118
|
+
const all = rounds;
|
|
119
|
+
const winner = argmax(all[0].probabilities);
|
|
120
|
+
return all.map((r) => r.probabilities[winner] ?? 0);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Executes a plan as few provider requests as possible.
|
|
124
|
+
*
|
|
125
|
+
* Round 0 carries every question. Later rounds carry only the questions that
|
|
126
|
+
* asked for more samples, so raising `samples` on one question does not
|
|
127
|
+
* multiply the cost of its neighbours.
|
|
128
|
+
*/
|
|
129
|
+
export async function runPlan(provider, state, planned, options = {}) {
|
|
130
|
+
const started = Date.now();
|
|
131
|
+
const store = options.store ?? getCacheStore();
|
|
132
|
+
const answers = {};
|
|
133
|
+
const measured = {};
|
|
134
|
+
const cachedKeys = new Set();
|
|
135
|
+
const usage = { inputTokens: 0, outputTokens: 0 };
|
|
136
|
+
const live = [];
|
|
137
|
+
for (const item of planned) {
|
|
138
|
+
assertSupported(provider, item.question);
|
|
139
|
+
if (item.cacheTtlMs && item.cacheTtlMs > 0) {
|
|
140
|
+
const hit = await store.get(cacheKeyFor(provider, state, item.question, item.samples));
|
|
141
|
+
if (hit) {
|
|
142
|
+
answers[item.key] = hit;
|
|
143
|
+
cachedKeys.add(item.key);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
live.push(item);
|
|
148
|
+
}
|
|
149
|
+
let requestCount = 0;
|
|
150
|
+
if (live.length > 0) {
|
|
151
|
+
const maxRounds = Math.max(...live.map((q) => q.samples));
|
|
152
|
+
const rounds = {};
|
|
153
|
+
for (const item of live)
|
|
154
|
+
rounds[item.key] = [];
|
|
155
|
+
for (let round = 0; round < maxRounds; round++) {
|
|
156
|
+
const inRound = live.filter((q) => q.samples > round);
|
|
157
|
+
if (inRound.length === 0)
|
|
158
|
+
break;
|
|
159
|
+
const questions = {};
|
|
160
|
+
for (const item of inRound)
|
|
161
|
+
questions[item.key] = item.question;
|
|
162
|
+
const response = await provider.evaluate({
|
|
163
|
+
state,
|
|
164
|
+
questions,
|
|
165
|
+
...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),
|
|
166
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
167
|
+
});
|
|
168
|
+
requestCount++;
|
|
169
|
+
usage.inputTokens += response.usage?.inputTokens ?? 0;
|
|
170
|
+
usage.outputTokens += response.usage?.outputTokens ?? 0;
|
|
171
|
+
for (const item of inRound) {
|
|
172
|
+
const answer = response.answers[item.key];
|
|
173
|
+
if (!answer)
|
|
174
|
+
throw new Error(`Provider "${provider.name}" returned no answer for key "${item.key}".`);
|
|
175
|
+
rounds[item.key].push(answer);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
for (const item of live) {
|
|
179
|
+
const collected = rounds[item.key];
|
|
180
|
+
answers[item.key] = aggregate(item.question.kind, collected);
|
|
181
|
+
measured[item.key] = collected.length > 1 ? confidenceFromSpread(series(item.question.kind, collected)) : undefined;
|
|
182
|
+
if (item.cacheTtlMs && item.cacheTtlMs > 0) {
|
|
183
|
+
await store.set(cacheKeyFor(provider, state, item.question, item.samples), answers[item.key], item.cacheTtlMs);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
answers,
|
|
189
|
+
measured,
|
|
190
|
+
cachedKeys,
|
|
191
|
+
usage,
|
|
192
|
+
latencyMs: Date.now() - started,
|
|
193
|
+
requestCount,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
export function emit(event, config = getConfig()) {
|
|
197
|
+
const hook = config.observability?.onEvaluation;
|
|
198
|
+
if (!hook)
|
|
199
|
+
return;
|
|
200
|
+
try {
|
|
201
|
+
hook(event);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// Observability must never break the call path it observes.
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
export { parseTtlOrUndefined };
|
|
208
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type Runtime } from "./config.ts";
|
|
2
|
+
import type { AnyOutput, OutputValue } from "./outputs.ts";
|
|
3
|
+
import type { SemanticProvider, State } from "./types.ts";
|
|
4
|
+
export interface SchemaDefinition<O extends AnyOutput> {
|
|
5
|
+
name: string;
|
|
6
|
+
/** Bump when the wording changes, so old results stay interpretable. */
|
|
7
|
+
version?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Domain context applied to every field of the schema.
|
|
10
|
+
*
|
|
11
|
+
* This is the closest thing to a system prompt, but it is not one: it is not
|
|
12
|
+
* an instruction the model obeys, it is the frame each question is asked in.
|
|
13
|
+
* Say what the data is and what the words mean in your business. Do not say
|
|
14
|
+
* how to behave — there is no behaviour to steer.
|
|
15
|
+
*/
|
|
16
|
+
instructions: string;
|
|
17
|
+
/**
|
|
18
|
+
* Background merged into the state on every call — a policy, a price list, a
|
|
19
|
+
* tier definition. Kept separate from the input so the two never blur.
|
|
20
|
+
*/
|
|
21
|
+
context?: Record<string, unknown>;
|
|
22
|
+
output: O;
|
|
23
|
+
defaults?: {
|
|
24
|
+
timeoutMs?: number;
|
|
25
|
+
cache?: string | number;
|
|
26
|
+
samples?: number;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export interface SchemaOptions {
|
|
30
|
+
provider?: SemanticProvider;
|
|
31
|
+
timeoutMs?: number;
|
|
32
|
+
cache?: string | number;
|
|
33
|
+
samples?: number;
|
|
34
|
+
}
|
|
35
|
+
export interface Evaluator<O extends AnyOutput> {
|
|
36
|
+
(data: State, options?: SchemaOptions): Promise<OutputValue<O>>;
|
|
37
|
+
readonly name: string;
|
|
38
|
+
readonly version: string | undefined;
|
|
39
|
+
readonly definition: SchemaDefinition<O>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A reusable evaluator: instructions, background and output shape declared
|
|
43
|
+
* once, then applied to data.
|
|
44
|
+
*
|
|
45
|
+
* Every field resolves in a single request, however many there are.
|
|
46
|
+
*/
|
|
47
|
+
export declare function defineSchema<const O extends AnyOutput>(definition: SchemaDefinition<O>): Evaluator<O>;
|
|
48
|
+
export declare function defineSchemaWith<const O extends AnyOutput>(runtime: Runtime, definition: SchemaDefinition<O>): Evaluator<O>;
|
|
49
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,OAAO,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEzD,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,SAAS;IACnD,IAAI,EAAE,MAAM,CAAA;IACZ,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;;;;OAOG;IACH,YAAY,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,MAAM,EAAE,CAAC,CAAA;IACT,QAAQ,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;QACvB,OAAO,CAAC,EAAE,MAAM,CAAA;KACjB,CAAA;CACF;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,gBAAgB,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,SAAS,CAAC,CAAC,SAAS,SAAS;IAC5C,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;CACzC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,SAAS,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAErG;AAED,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,CAAC,SAAS,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAmB3H"}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { evaluateWith } from "./evaluate.js";
|
|
2
|
+
import { globalRuntime } from "./config.js";
|
|
3
|
+
/**
|
|
4
|
+
* A reusable evaluator: instructions, background and output shape declared
|
|
5
|
+
* once, then applied to data.
|
|
6
|
+
*
|
|
7
|
+
* Every field resolves in a single request, however many there are.
|
|
8
|
+
*/
|
|
9
|
+
export function defineSchema(definition) {
|
|
10
|
+
return defineSchemaWith(globalRuntime, definition);
|
|
11
|
+
}
|
|
12
|
+
export function defineSchemaWith(runtime, definition) {
|
|
13
|
+
const call = (data, options = {}) => evaluateWith(runtime, {
|
|
14
|
+
data,
|
|
15
|
+
question: definition.instructions,
|
|
16
|
+
// Background stays in its own labelled field rather than merged, so input
|
|
17
|
+
// can never quietly overwrite the policy it is being judged against.
|
|
18
|
+
...(definition.context ? { context: definition.context } : {}),
|
|
19
|
+
output: definition.output,
|
|
20
|
+
...definition.defaults,
|
|
21
|
+
...options,
|
|
22
|
+
metric: { name: definition.name, ...(definition.version ? { version: definition.version } : {}) },
|
|
23
|
+
});
|
|
24
|
+
const evaluator = call;
|
|
25
|
+
Object.defineProperty(evaluator, "name", { value: definition.name, configurable: true });
|
|
26
|
+
Object.defineProperty(evaluator, "version", { value: definition.version, configurable: true });
|
|
27
|
+
Object.defineProperty(evaluator, "definition", { value: definition, configurable: true });
|
|
28
|
+
return evaluator;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAgB,MAAM,aAAa,CAAA;AA4CzD;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAA4B,UAA+B;IACrF,OAAO,gBAAgB,CAAC,aAAa,EAAE,UAAU,CAAC,CAAA;AACpD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAA4B,OAAgB,EAAE,UAA+B;IAC3G,MAAM,IAAI,GAAG,CAAC,IAAW,EAAE,UAAyB,EAAE,EAA2B,EAAE,CACjF,YAAY,CAAC,OAAO,EAAE;QACpB,IAAI;QACJ,QAAQ,EAAE,UAAU,CAAC,YAAY;QACjC,0EAA0E;QAC1E,qEAAqE;QACrE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,GAAG,UAAU,CAAC,QAAQ;QACtB,GAAG,OAAO;QACV,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;KAClG,CAAC,CAAA;IAEJ,MAAM,SAAS,GAAG,IAAoB,CAAA;IACtC,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAA;IACxF,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,UAAU,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAA;IAC9F,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAA;IACzF,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ProviderCapabilities, SemanticAnswer, SemanticProvider, SemanticQuestion, SemanticRequest } from "./types.ts";
|
|
2
|
+
export interface MockCall {
|
|
3
|
+
state: SemanticRequest["state"];
|
|
4
|
+
questions: Record<string, SemanticQuestion>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* What a stubbed answer may look like.
|
|
8
|
+
*
|
|
9
|
+
* A bare number stands in for a probability (truth) or a rubric position
|
|
10
|
+
* (level); a boolean becomes 0.95/0.05; a string selects a choice option.
|
|
11
|
+
*/
|
|
12
|
+
export type MockValue = number | boolean | string | SemanticAnswer;
|
|
13
|
+
export interface MockProviderOptions {
|
|
14
|
+
capabilities?: Partial<ProviderCapabilities>;
|
|
15
|
+
model?: string;
|
|
16
|
+
/** Answer used when no rule matches. Defaults to 0.5 / the first option. */
|
|
17
|
+
fallback?: MockValue;
|
|
18
|
+
/** Adds jitter to probabilities so sampling-based confidence can be exercised. */
|
|
19
|
+
jitter?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface MockProvider extends SemanticProvider {
|
|
22
|
+
readonly calls: MockCall[];
|
|
23
|
+
/** Number of requests actually issued — the assertion that proves batching. */
|
|
24
|
+
readonly requestCount: number;
|
|
25
|
+
reset(): void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A provider that answers from a lookup table instead of a network call.
|
|
29
|
+
*
|
|
30
|
+
* Keys are matched as substrings of a question's instructions, so a rule like
|
|
31
|
+
* `"urgency"` answers `score("urgency")` regardless of how it was framed.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createMockSemanticProvider(rules?: Record<string, MockValue>, options?: MockProviderOptions): MockProvider;
|
|
34
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAEhB,gBAAgB,EAChB,eAAe,EAChB,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,CAAA;IAC/B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;CAC5C;AAED;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,cAAc,CAAA;AAElE,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAA;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,YAAa,SAAQ,gBAAgB;IACpD,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAA;IAC1B,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,KAAK,IAAI,IAAI,CAAA;CACd;AA8BD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAM,EACrC,OAAO,GAAE,mBAAwB,GAChC,YAAY,CAoCd"}
|
package/dist/testing.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
function instructionsText(question) {
|
|
2
|
+
const raw = question.instructions;
|
|
3
|
+
return typeof raw === "string" ? raw : JSON.stringify(raw);
|
|
4
|
+
}
|
|
5
|
+
function toAnswer(question, value, jitter) {
|
|
6
|
+
if (typeof value === "object")
|
|
7
|
+
return value;
|
|
8
|
+
if (question.kind === "truth") {
|
|
9
|
+
const base = typeof value === "boolean" ? (value ? 0.95 : 0.05) : Number(value);
|
|
10
|
+
const noise = jitter > 0 ? (Math.random() - 0.5) * 2 * jitter : 0;
|
|
11
|
+
return { kind: "truth", probability: Math.min(1, Math.max(0, base + noise)) };
|
|
12
|
+
}
|
|
13
|
+
if (question.kind === "choice") {
|
|
14
|
+
const keys = Object.keys(question.options);
|
|
15
|
+
const picked = typeof value === "string" && keys.includes(value) ? value : keys[0];
|
|
16
|
+
const probabilities = {};
|
|
17
|
+
for (const key of keys)
|
|
18
|
+
probabilities[key] = key === picked ? 1 : 0;
|
|
19
|
+
return { kind: "choice", choice: picked, probabilities, confidence: 1 };
|
|
20
|
+
}
|
|
21
|
+
const width = question.levels.length;
|
|
22
|
+
const level = Math.min(width - 1, Math.max(0, typeof value === "number" ? value : 0));
|
|
23
|
+
const probabilities = Array.from({ length: width }, (_, index) => (index === Math.round(level) ? 1 : 0));
|
|
24
|
+
return { kind: "level", level, probabilities, confidence: 1 };
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A provider that answers from a lookup table instead of a network call.
|
|
28
|
+
*
|
|
29
|
+
* Keys are matched as substrings of a question's instructions, so a rule like
|
|
30
|
+
* `"urgency"` answers `score("urgency")` regardless of how it was framed.
|
|
31
|
+
*/
|
|
32
|
+
export function createMockSemanticProvider(rules = {}, options = {}) {
|
|
33
|
+
const calls = [];
|
|
34
|
+
const jitter = options.jitter ?? 0;
|
|
35
|
+
const provider = {
|
|
36
|
+
name: "mock",
|
|
37
|
+
model: options.model ?? "mock-1",
|
|
38
|
+
capabilities: {
|
|
39
|
+
maxChoiceOptions: 255,
|
|
40
|
+
levelRange: [2, 10],
|
|
41
|
+
generatesText: false,
|
|
42
|
+
batching: true,
|
|
43
|
+
...options.capabilities,
|
|
44
|
+
},
|
|
45
|
+
get calls() {
|
|
46
|
+
return calls;
|
|
47
|
+
},
|
|
48
|
+
get requestCount() {
|
|
49
|
+
return calls.length;
|
|
50
|
+
},
|
|
51
|
+
reset() {
|
|
52
|
+
calls.length = 0;
|
|
53
|
+
},
|
|
54
|
+
async evaluate(request) {
|
|
55
|
+
calls.push({ state: request.state, questions: { ...request.questions } });
|
|
56
|
+
const answers = {};
|
|
57
|
+
for (const [key, question] of Object.entries(request.questions)) {
|
|
58
|
+
const text = instructionsText(question).toLowerCase();
|
|
59
|
+
const match = Object.entries(rules).find(([needle]) => text.includes(needle.toLowerCase()));
|
|
60
|
+
const value = match ? match[1] : (options.fallback ?? 0.5);
|
|
61
|
+
answers[key] = toAnswer(question, value, jitter);
|
|
62
|
+
}
|
|
63
|
+
return { answers, model: provider.model, usage: { inputTokens: 0, outputTokens: 0 } };
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
return provider;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=testing.js.map
|