@trazum/core 1.50.7 → 1.50.8
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/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/quality-gate.d.ts +134 -0
- package/dist/quality-gate.d.ts.map +1 -0
- package/dist/quality-gate.js +185 -0
- package/dist/quality-gate.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +8 -0
- package/src/quality-gate.ts +253 -0
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export { verifyPlan } from './verify.js';
|
|
|
20
20
|
export { buildHistory, storedReportFrom, MIN_RUN } from './history.js';
|
|
21
21
|
export { outcomeReport, judgeOutcome, OUTCOME_UNLOCKS } from './outcome.js';
|
|
22
22
|
export { runExperiment } from './experiment.js';
|
|
23
|
+
export { qualityGate, MIN_OUTCOMES_EACH_SIDE, MAX_MODEL_MIX_DRIFT, MAX_VOLUME_RATIO, MAX_COVERAGE_DRIFT, } from './quality-gate.js';
|
|
24
|
+
export type { Confounder, GateSide, GateUnknown, GateVerdict, QualityGate } from './quality-gate.js';
|
|
23
25
|
export type { ArmResult, ExperimentArm, ExperimentDeclaration, ExperimentResult, Marginal, NotSeparableReason, Separation, } from './experiment.js';
|
|
24
26
|
export { ladderArithmetic, ladderPosition, validateLadder, MIN_CALLS_FOR_LADDER, BREAK_EVEN_BAND, } from './ladder.js';
|
|
25
27
|
export type { LadderArithmetic, LadderPolicy, LadderPosition, LadderProblem, LadderUnknown, LadderVerdict, } from './ladder.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -23,6 +23,7 @@ export { verifyPlan } from './verify.js';
|
|
|
23
23
|
export { buildHistory, storedReportFrom, MIN_RUN } from './history.js';
|
|
24
24
|
export { outcomeReport, judgeOutcome, OUTCOME_UNLOCKS } from './outcome.js';
|
|
25
25
|
export { runExperiment } from './experiment.js';
|
|
26
|
+
export { qualityGate, MIN_OUTCOMES_EACH_SIDE, MAX_MODEL_MIX_DRIFT, MAX_VOLUME_RATIO, MAX_COVERAGE_DRIFT, } from './quality-gate.js';
|
|
26
27
|
export { ladderArithmetic, ladderPosition, validateLadder, MIN_CALLS_FOR_LADDER, BREAK_EVEN_BAND, } from './ladder.js';
|
|
27
28
|
export { perOutcome, rankPerOutcome, MIN_OUTCOMES_FOR_RATE, MIN_COVERAGE_FOR_RATE, } from './per-outcome.js';
|
|
28
29
|
export { gatewayDecision, usageFromResponse, FAILURE_POLICIES } from './gateway.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC/F,OAAO,EACL,UAAU,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,QAAQ,GACT,MAAM,YAAY,CAAC;AAWpB,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAClF,gFAAgF;AAChF,4EAA4E;AAC5E,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEtF,2EAA2E;AAC3E,+EAA+E;AAC/E,8EAA8E;AAC9E,0EAA0E;AAC1E,yCAAyC;AACzC,4EAA4E;AAC5E,qDAAqD;AACrD,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,6BAA6B,EAC7B,YAAY,GACb,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACpG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAG3F,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The failure that actually matters, and the four ways of getting it wrong.
|
|
3
|
+
*
|
|
4
|
+
* CI has been able to fail a build for tokens since 1.4 and for dollars since
|
|
5
|
+
* 1.21. A prompt edit that quietly made the product worse has never been
|
|
6
|
+
* gateable — which means every cost saving this tool has ever recommended went
|
|
7
|
+
* into a repository with its most important consequence unmeasured.
|
|
8
|
+
*
|
|
9
|
+
* ## This is a before-and-after, not an experiment
|
|
10
|
+
*
|
|
11
|
+
* Worth saying in the first paragraph, because the arithmetic is the same as
|
|
12
|
+
* `experiment`'s and the epistemics are not. An experiment splits traffic
|
|
13
|
+
* randomly, so the two arms differ only in the thing under test. A
|
|
14
|
+
* before-and-after splits it by **time**, and everything else that changed at
|
|
15
|
+
* the same time is in the difference too.
|
|
16
|
+
*
|
|
17
|
+
* So this module spends most of its code looking for reasons *not* to blame the
|
|
18
|
+
* prompt, and it reports `cannot-tell` far more readily than a randomised
|
|
19
|
+
* comparison would. That is not timidity. A gate that blames the prompt because
|
|
20
|
+
* the prompt is the thing it can see will be switched off within a month, and a
|
|
21
|
+
* switched-off gate catches nothing at all.
|
|
22
|
+
*
|
|
23
|
+
* ## The three confounders it can actually see
|
|
24
|
+
*
|
|
25
|
+
* **The model moved.** If the mix of models shifted across the boundary, the
|
|
26
|
+
* prompt is not the only variable, and the drop may be entirely somebody else's
|
|
27
|
+
* migration.
|
|
28
|
+
*
|
|
29
|
+
* **The volume moved.** A workload whose traffic tripled is usually a workload
|
|
30
|
+
* whose *population* changed — a new surface, a new customer, a marketing
|
|
31
|
+
* campaign — and the questions being asked are not the questions from before.
|
|
32
|
+
*
|
|
33
|
+
* **The coverage moved.** The subtle one, and the one nobody thinks of: if the
|
|
34
|
+
* share of calls recording an outcome changed, the two rates describe different
|
|
35
|
+
* populations. A team that started instrumenting its hard cases will see its
|
|
36
|
+
* measured rate fall without anything getting worse.
|
|
37
|
+
*
|
|
38
|
+
* Any of them present, and the verdict is `cannot-tell` with the confounder
|
|
39
|
+
* **named**. Not a hedge attached to a blame — a refusal to blame.
|
|
40
|
+
*
|
|
41
|
+
* ## What it cannot see, and says so
|
|
42
|
+
*
|
|
43
|
+
* Everything else deployed that day. This module has one label's numbers and no
|
|
44
|
+
* knowledge of the world, and it never pretends otherwise: a `dropped` verdict
|
|
45
|
+
* is a statement that the rate fell and the three things it can check did not
|
|
46
|
+
* move, which is a smaller claim than "the prompt did it" and is the largest
|
|
47
|
+
* claim the evidence supports.
|
|
48
|
+
*/
|
|
49
|
+
import type { ArmResult, ExperimentArm } from './experiment.js';
|
|
50
|
+
import type { OutcomeVocabulary } from './outcome.js';
|
|
51
|
+
/**
|
|
52
|
+
* Outcomes each side of the change needs before a verdict is offered.
|
|
53
|
+
*
|
|
54
|
+
* A hundred rather than the ten used for a rate elsewhere, because this one
|
|
55
|
+
* fails builds. The cost of a wrong `dropped` is somebody reverting a good
|
|
56
|
+
* change and losing the saving; the cost of a wrong `cannot-tell` is waiting a
|
|
57
|
+
* day. Those are not symmetric and the threshold is not either.
|
|
58
|
+
*/
|
|
59
|
+
export declare const MIN_OUTCOMES_EACH_SIDE = 100;
|
|
60
|
+
/** How far the model mix may move before the comparison stops being about the prompt. */
|
|
61
|
+
export declare const MAX_MODEL_MIX_DRIFT = 0.1;
|
|
62
|
+
/**
|
|
63
|
+
* How far the call volume may move, as a ratio.
|
|
64
|
+
*
|
|
65
|
+
* Half again, either way. Ordinary week-to-week traffic moves less than that;
|
|
66
|
+
* a workload that doubled is usually a workload whose population changed.
|
|
67
|
+
*/
|
|
68
|
+
export declare const MAX_VOLUME_RATIO = 1.5;
|
|
69
|
+
/** How far outcome coverage may move before the two rates describe different populations. */
|
|
70
|
+
export declare const MAX_COVERAGE_DRIFT = 0.1;
|
|
71
|
+
export type Confounder = {
|
|
72
|
+
kind: 'model-mix-moved';
|
|
73
|
+
drift: number;
|
|
74
|
+
model: string;
|
|
75
|
+
} | {
|
|
76
|
+
kind: 'volume-moved';
|
|
77
|
+
beforeCalls: number;
|
|
78
|
+
afterCalls: number;
|
|
79
|
+
ratio: number;
|
|
80
|
+
} | {
|
|
81
|
+
kind: 'coverage-moved';
|
|
82
|
+
before: number;
|
|
83
|
+
after: number;
|
|
84
|
+
};
|
|
85
|
+
export type GateVerdict = 'held' | 'dropped' | 'cannot-tell';
|
|
86
|
+
export type GateUnknown = 'too-few-before' | 'too-few-after' | 'confounded' | 'no-vocabulary' | 'not-separable';
|
|
87
|
+
/** One side of the boundary, as the caller measured it. */
|
|
88
|
+
export interface GateSide {
|
|
89
|
+
arm: ExperimentArm;
|
|
90
|
+
/** Every call in the window, outcome or not — the coverage denominator. */
|
|
91
|
+
calls: number;
|
|
92
|
+
/** Spend per model, for the mix comparison. */
|
|
93
|
+
usdByModel: Array<{
|
|
94
|
+
model: string;
|
|
95
|
+
usd: number;
|
|
96
|
+
}>;
|
|
97
|
+
}
|
|
98
|
+
export interface QualityGate {
|
|
99
|
+
verdict: GateVerdict;
|
|
100
|
+
/** Why, when the verdict is `cannot-tell`. A refusal never arrives bare. */
|
|
101
|
+
unknown: GateUnknown | null;
|
|
102
|
+
before: ArmResult;
|
|
103
|
+
after: ArmResult;
|
|
104
|
+
/** The 95% interval on (after − before), or null. */
|
|
105
|
+
difference: {
|
|
106
|
+
point: number;
|
|
107
|
+
low: number;
|
|
108
|
+
high: number;
|
|
109
|
+
} | null;
|
|
110
|
+
/**
|
|
111
|
+
* Everything found that means the prompt is not the only variable.
|
|
112
|
+
*
|
|
113
|
+
* Non-empty forces `cannot-tell`. Reported even on a `held` verdict, because
|
|
114
|
+
* a rate that held while the model changed underneath is not evidence that
|
|
115
|
+
* the prompt is fine either.
|
|
116
|
+
*/
|
|
117
|
+
confounders: Confounder[];
|
|
118
|
+
/**
|
|
119
|
+
* The cost half — measured, and kept beside the quality half rather than
|
|
120
|
+
* merged with it. The sentence teams argue about needs both.
|
|
121
|
+
*/
|
|
122
|
+
cost: {
|
|
123
|
+
beforeUsdPerCall: number;
|
|
124
|
+
afterUsdPerCall: number;
|
|
125
|
+
deltaUsdPerCall: number;
|
|
126
|
+
} | null;
|
|
127
|
+
/** Outcomes behind the comparison, so the claim carries its own sample size. */
|
|
128
|
+
outcomes: {
|
|
129
|
+
before: number;
|
|
130
|
+
after: number;
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
export declare function qualityGate(before: GateSide, after: GateSide, vocabulary: OutcomeVocabulary | null): QualityGate;
|
|
134
|
+
//# sourceMappingURL=quality-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-gate.d.ts","sourceRoot":"","sources":["../src/quality-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC,6FAA6F;AAC7F,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChF;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;AAE7D,MAAM,MAAM,WAAW,GACnB,gBAAgB,GAChB,eAAe,GACf,YAAY,GACZ,eAAe,GACf,eAAe,CAAC;AAEpB,2DAA2D;AAC3D,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,aAAa,CAAC;IACnB,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,UAAU,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,WAAW,CAAC;IACrB,4EAA4E;IAC5E,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,qDAAqD;IACrD,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAChE;;;;;;OAMG;IACH,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B;;;OAGG;IACH,IAAI,EAAE;QAAE,gBAAgB,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5F,gFAAgF;IAChF,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAwBD,wBAAgB,WAAW,CACzB,MAAM,EAAE,QAAQ,EAChB,KAAK,EAAE,QAAQ,EACf,UAAU,EAAE,iBAAiB,GAAG,IAAI,GACnC,WAAW,CAqGb"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The failure that actually matters, and the four ways of getting it wrong.
|
|
3
|
+
*
|
|
4
|
+
* CI has been able to fail a build for tokens since 1.4 and for dollars since
|
|
5
|
+
* 1.21. A prompt edit that quietly made the product worse has never been
|
|
6
|
+
* gateable — which means every cost saving this tool has ever recommended went
|
|
7
|
+
* into a repository with its most important consequence unmeasured.
|
|
8
|
+
*
|
|
9
|
+
* ## This is a before-and-after, not an experiment
|
|
10
|
+
*
|
|
11
|
+
* Worth saying in the first paragraph, because the arithmetic is the same as
|
|
12
|
+
* `experiment`'s and the epistemics are not. An experiment splits traffic
|
|
13
|
+
* randomly, so the two arms differ only in the thing under test. A
|
|
14
|
+
* before-and-after splits it by **time**, and everything else that changed at
|
|
15
|
+
* the same time is in the difference too.
|
|
16
|
+
*
|
|
17
|
+
* So this module spends most of its code looking for reasons *not* to blame the
|
|
18
|
+
* prompt, and it reports `cannot-tell` far more readily than a randomised
|
|
19
|
+
* comparison would. That is not timidity. A gate that blames the prompt because
|
|
20
|
+
* the prompt is the thing it can see will be switched off within a month, and a
|
|
21
|
+
* switched-off gate catches nothing at all.
|
|
22
|
+
*
|
|
23
|
+
* ## The three confounders it can actually see
|
|
24
|
+
*
|
|
25
|
+
* **The model moved.** If the mix of models shifted across the boundary, the
|
|
26
|
+
* prompt is not the only variable, and the drop may be entirely somebody else's
|
|
27
|
+
* migration.
|
|
28
|
+
*
|
|
29
|
+
* **The volume moved.** A workload whose traffic tripled is usually a workload
|
|
30
|
+
* whose *population* changed — a new surface, a new customer, a marketing
|
|
31
|
+
* campaign — and the questions being asked are not the questions from before.
|
|
32
|
+
*
|
|
33
|
+
* **The coverage moved.** The subtle one, and the one nobody thinks of: if the
|
|
34
|
+
* share of calls recording an outcome changed, the two rates describe different
|
|
35
|
+
* populations. A team that started instrumenting its hard cases will see its
|
|
36
|
+
* measured rate fall without anything getting worse.
|
|
37
|
+
*
|
|
38
|
+
* Any of them present, and the verdict is `cannot-tell` with the confounder
|
|
39
|
+
* **named**. Not a hedge attached to a blame — a refusal to blame.
|
|
40
|
+
*
|
|
41
|
+
* ## What it cannot see, and says so
|
|
42
|
+
*
|
|
43
|
+
* Everything else deployed that day. This module has one label's numbers and no
|
|
44
|
+
* knowledge of the world, and it never pretends otherwise: a `dropped` verdict
|
|
45
|
+
* is a statement that the rate fell and the three things it can check did not
|
|
46
|
+
* move, which is a smaller claim than "the prompt did it" and is the largest
|
|
47
|
+
* claim the evidence supports.
|
|
48
|
+
*/
|
|
49
|
+
import { runExperiment } from './experiment.js';
|
|
50
|
+
/**
|
|
51
|
+
* Outcomes each side of the change needs before a verdict is offered.
|
|
52
|
+
*
|
|
53
|
+
* A hundred rather than the ten used for a rate elsewhere, because this one
|
|
54
|
+
* fails builds. The cost of a wrong `dropped` is somebody reverting a good
|
|
55
|
+
* change and losing the saving; the cost of a wrong `cannot-tell` is waiting a
|
|
56
|
+
* day. Those are not symmetric and the threshold is not either.
|
|
57
|
+
*/
|
|
58
|
+
export const MIN_OUTCOMES_EACH_SIDE = 100;
|
|
59
|
+
/** How far the model mix may move before the comparison stops being about the prompt. */
|
|
60
|
+
export const MAX_MODEL_MIX_DRIFT = 0.1;
|
|
61
|
+
/**
|
|
62
|
+
* How far the call volume may move, as a ratio.
|
|
63
|
+
*
|
|
64
|
+
* Half again, either way. Ordinary week-to-week traffic moves less than that;
|
|
65
|
+
* a workload that doubled is usually a workload whose population changed.
|
|
66
|
+
*/
|
|
67
|
+
export const MAX_VOLUME_RATIO = 1.5;
|
|
68
|
+
/** How far outcome coverage may move before the two rates describe different populations. */
|
|
69
|
+
export const MAX_COVERAGE_DRIFT = 0.1;
|
|
70
|
+
function mixDrift(before, after) {
|
|
71
|
+
const share = (rows) => {
|
|
72
|
+
const total = rows.reduce((sum, row) => sum + row.usd, 0);
|
|
73
|
+
const out = new Map();
|
|
74
|
+
if (total <= 0)
|
|
75
|
+
return out;
|
|
76
|
+
for (const row of rows)
|
|
77
|
+
out.set(row.model, (out.get(row.model) ?? 0) + row.usd / total);
|
|
78
|
+
return out;
|
|
79
|
+
};
|
|
80
|
+
const a = share(before);
|
|
81
|
+
const b = share(after);
|
|
82
|
+
let worst = null;
|
|
83
|
+
for (const model of new Set([...a.keys(), ...b.keys()])) {
|
|
84
|
+
const drift = Math.abs((b.get(model) ?? 0) - (a.get(model) ?? 0));
|
|
85
|
+
if (worst === null || drift > worst.drift)
|
|
86
|
+
worst = { model, drift };
|
|
87
|
+
}
|
|
88
|
+
if (worst === null || worst.drift <= MAX_MODEL_MIX_DRIFT)
|
|
89
|
+
return null;
|
|
90
|
+
return { kind: 'model-mix-moved', drift: worst.drift, model: worst.model };
|
|
91
|
+
}
|
|
92
|
+
export function qualityGate(before, after, vocabulary) {
|
|
93
|
+
/**
|
|
94
|
+
* The statistics are `experiment`'s, deliberately.
|
|
95
|
+
*
|
|
96
|
+
* One implementation of a two-proportion comparison, so a gate and a
|
|
97
|
+
* deliberate experiment can never disagree about the same two numbers — the
|
|
98
|
+
* failure mode where a team runs both and gets two answers, then trusts
|
|
99
|
+
* whichever one they liked.
|
|
100
|
+
*/
|
|
101
|
+
const stats = runExperiment({ arms: ['before', 'after'], minOutcomesPerArm: MIN_OUTCOMES_EACH_SIDE }, { a: { ...after.arm, name: 'after' }, b: { ...before.arm, name: 'before' } }, vocabulary);
|
|
102
|
+
const outcomes = { before: stats.b.recorded, after: stats.a.recorded };
|
|
103
|
+
const cost = before.calls > 0 && after.calls > 0
|
|
104
|
+
? {
|
|
105
|
+
beforeUsdPerCall: before.arm.totalUsd / before.calls,
|
|
106
|
+
afterUsdPerCall: after.arm.totalUsd / after.calls,
|
|
107
|
+
deltaUsdPerCall: after.arm.totalUsd / after.calls - before.arm.totalUsd / before.calls,
|
|
108
|
+
}
|
|
109
|
+
: null;
|
|
110
|
+
const confounders = [];
|
|
111
|
+
const mix = mixDrift(before.usdByModel, after.usdByModel);
|
|
112
|
+
if (mix !== null)
|
|
113
|
+
confounders.push(mix);
|
|
114
|
+
if (before.calls > 0 && after.calls > 0) {
|
|
115
|
+
const ratio = after.calls / before.calls;
|
|
116
|
+
if (ratio > MAX_VOLUME_RATIO || ratio < 1 / MAX_VOLUME_RATIO) {
|
|
117
|
+
confounders.push({
|
|
118
|
+
kind: 'volume-moved',
|
|
119
|
+
beforeCalls: before.calls,
|
|
120
|
+
afterCalls: after.calls,
|
|
121
|
+
ratio,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Coverage, the one nobody thinks of.
|
|
126
|
+
*
|
|
127
|
+
* A team that starts instrumenting its hard cases sees its measured rate
|
|
128
|
+
* fall without anything having got worse. Comparing two rates over
|
|
129
|
+
* differently-selected populations is the most convincing wrong answer
|
|
130
|
+
* this module could produce.
|
|
131
|
+
*/
|
|
132
|
+
const coverageBefore = outcomes.before / before.calls;
|
|
133
|
+
const coverageAfter = outcomes.after / after.calls;
|
|
134
|
+
if (Math.abs(coverageAfter - coverageBefore) > MAX_COVERAGE_DRIFT) {
|
|
135
|
+
confounders.push({ kind: 'coverage-moved', before: coverageBefore, after: coverageAfter });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const shell = {
|
|
139
|
+
before: stats.b,
|
|
140
|
+
after: stats.a,
|
|
141
|
+
difference: stats.difference,
|
|
142
|
+
confounders,
|
|
143
|
+
cost,
|
|
144
|
+
outcomes,
|
|
145
|
+
};
|
|
146
|
+
if (vocabulary === null || vocabulary.success.length === 0) {
|
|
147
|
+
return { ...shell, verdict: 'cannot-tell', unknown: 'no-vocabulary' };
|
|
148
|
+
}
|
|
149
|
+
if (outcomes.before < MIN_OUTCOMES_EACH_SIDE) {
|
|
150
|
+
return { ...shell, verdict: 'cannot-tell', unknown: 'too-few-before' };
|
|
151
|
+
}
|
|
152
|
+
if (outcomes.after < MIN_OUTCOMES_EACH_SIDE) {
|
|
153
|
+
return { ...shell, verdict: 'cannot-tell', unknown: 'too-few-after' };
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* A confounder outranks the statistics.
|
|
157
|
+
*
|
|
158
|
+
* Checked after the sample sizes and before the verdict, so a build is never
|
|
159
|
+
* failed on a difference that something else could equally explain. A gate
|
|
160
|
+
* that blames the prompt because the prompt is the thing it can see gets
|
|
161
|
+
* switched off within a month, and a switched-off gate catches nothing.
|
|
162
|
+
*/
|
|
163
|
+
if (confounders.length > 0) {
|
|
164
|
+
return { ...shell, verdict: 'cannot-tell', unknown: 'confounded' };
|
|
165
|
+
}
|
|
166
|
+
if (stats.separation === 'not-separable') {
|
|
167
|
+
/**
|
|
168
|
+
* Not separable is `cannot-tell`, never `held`.
|
|
169
|
+
*
|
|
170
|
+
* "The rate did not measurably fall" and "the rate held" are different
|
|
171
|
+
* claims, and a gate that spells them the same way passes a real
|
|
172
|
+
* regression it merely lacked the power to see. `verify` has held this
|
|
173
|
+
* line since 1.39 and it matters more here, because this one is wired to
|
|
174
|
+
* an exit code.
|
|
175
|
+
*/
|
|
176
|
+
return { ...shell, verdict: 'cannot-tell', unknown: 'not-separable' };
|
|
177
|
+
}
|
|
178
|
+
// `a` is the *after* arm, so `a-wins` means the rate went up.
|
|
179
|
+
return {
|
|
180
|
+
...shell,
|
|
181
|
+
verdict: stats.separation === 'a-wins' ? 'held' : 'dropped',
|
|
182
|
+
unknown: null,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=quality-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-gate.js","sourceRoot":"","sources":["../src/quality-gate.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trazum/core",
|
|
3
|
-
"version": "1.50.
|
|
3
|
+
"version": "1.50.8",
|
|
4
4
|
"description": "Trazum core: priced advisories for LLM prompts (caching, model tier, batching, schemas), plus deterministic trimming, token counting and pricing.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "David Mu\u00f1oz Rey",
|
package/src/index.ts
CHANGED
|
@@ -51,6 +51,14 @@ export { verifyPlan } from './verify.js';
|
|
|
51
51
|
export { buildHistory, storedReportFrom, MIN_RUN } from './history.js';
|
|
52
52
|
export { outcomeReport, judgeOutcome, OUTCOME_UNLOCKS } from './outcome.js';
|
|
53
53
|
export { runExperiment } from './experiment.js';
|
|
54
|
+
export {
|
|
55
|
+
qualityGate,
|
|
56
|
+
MIN_OUTCOMES_EACH_SIDE,
|
|
57
|
+
MAX_MODEL_MIX_DRIFT,
|
|
58
|
+
MAX_VOLUME_RATIO,
|
|
59
|
+
MAX_COVERAGE_DRIFT,
|
|
60
|
+
} from './quality-gate.js';
|
|
61
|
+
export type { Confounder, GateSide, GateUnknown, GateVerdict, QualityGate } from './quality-gate.js';
|
|
54
62
|
export type {
|
|
55
63
|
ArmResult,
|
|
56
64
|
ExperimentArm,
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The failure that actually matters, and the four ways of getting it wrong.
|
|
3
|
+
*
|
|
4
|
+
* CI has been able to fail a build for tokens since 1.4 and for dollars since
|
|
5
|
+
* 1.21. A prompt edit that quietly made the product worse has never been
|
|
6
|
+
* gateable — which means every cost saving this tool has ever recommended went
|
|
7
|
+
* into a repository with its most important consequence unmeasured.
|
|
8
|
+
*
|
|
9
|
+
* ## This is a before-and-after, not an experiment
|
|
10
|
+
*
|
|
11
|
+
* Worth saying in the first paragraph, because the arithmetic is the same as
|
|
12
|
+
* `experiment`'s and the epistemics are not. An experiment splits traffic
|
|
13
|
+
* randomly, so the two arms differ only in the thing under test. A
|
|
14
|
+
* before-and-after splits it by **time**, and everything else that changed at
|
|
15
|
+
* the same time is in the difference too.
|
|
16
|
+
*
|
|
17
|
+
* So this module spends most of its code looking for reasons *not* to blame the
|
|
18
|
+
* prompt, and it reports `cannot-tell` far more readily than a randomised
|
|
19
|
+
* comparison would. That is not timidity. A gate that blames the prompt because
|
|
20
|
+
* the prompt is the thing it can see will be switched off within a month, and a
|
|
21
|
+
* switched-off gate catches nothing at all.
|
|
22
|
+
*
|
|
23
|
+
* ## The three confounders it can actually see
|
|
24
|
+
*
|
|
25
|
+
* **The model moved.** If the mix of models shifted across the boundary, the
|
|
26
|
+
* prompt is not the only variable, and the drop may be entirely somebody else's
|
|
27
|
+
* migration.
|
|
28
|
+
*
|
|
29
|
+
* **The volume moved.** A workload whose traffic tripled is usually a workload
|
|
30
|
+
* whose *population* changed — a new surface, a new customer, a marketing
|
|
31
|
+
* campaign — and the questions being asked are not the questions from before.
|
|
32
|
+
*
|
|
33
|
+
* **The coverage moved.** The subtle one, and the one nobody thinks of: if the
|
|
34
|
+
* share of calls recording an outcome changed, the two rates describe different
|
|
35
|
+
* populations. A team that started instrumenting its hard cases will see its
|
|
36
|
+
* measured rate fall without anything getting worse.
|
|
37
|
+
*
|
|
38
|
+
* Any of them present, and the verdict is `cannot-tell` with the confounder
|
|
39
|
+
* **named**. Not a hedge attached to a blame — a refusal to blame.
|
|
40
|
+
*
|
|
41
|
+
* ## What it cannot see, and says so
|
|
42
|
+
*
|
|
43
|
+
* Everything else deployed that day. This module has one label's numbers and no
|
|
44
|
+
* knowledge of the world, and it never pretends otherwise: a `dropped` verdict
|
|
45
|
+
* is a statement that the rate fell and the three things it can check did not
|
|
46
|
+
* move, which is a smaller claim than "the prompt did it" and is the largest
|
|
47
|
+
* claim the evidence supports.
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
import { runExperiment } from './experiment.js';
|
|
51
|
+
import type { ArmResult, ExperimentArm } from './experiment.js';
|
|
52
|
+
import type { OutcomeVocabulary } from './outcome.js';
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Outcomes each side of the change needs before a verdict is offered.
|
|
56
|
+
*
|
|
57
|
+
* A hundred rather than the ten used for a rate elsewhere, because this one
|
|
58
|
+
* fails builds. The cost of a wrong `dropped` is somebody reverting a good
|
|
59
|
+
* change and losing the saving; the cost of a wrong `cannot-tell` is waiting a
|
|
60
|
+
* day. Those are not symmetric and the threshold is not either.
|
|
61
|
+
*/
|
|
62
|
+
export const MIN_OUTCOMES_EACH_SIDE = 100;
|
|
63
|
+
|
|
64
|
+
/** How far the model mix may move before the comparison stops being about the prompt. */
|
|
65
|
+
export const MAX_MODEL_MIX_DRIFT = 0.1;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* How far the call volume may move, as a ratio.
|
|
69
|
+
*
|
|
70
|
+
* Half again, either way. Ordinary week-to-week traffic moves less than that;
|
|
71
|
+
* a workload that doubled is usually a workload whose population changed.
|
|
72
|
+
*/
|
|
73
|
+
export const MAX_VOLUME_RATIO = 1.5;
|
|
74
|
+
|
|
75
|
+
/** How far outcome coverage may move before the two rates describe different populations. */
|
|
76
|
+
export const MAX_COVERAGE_DRIFT = 0.1;
|
|
77
|
+
|
|
78
|
+
export type Confounder =
|
|
79
|
+
| { kind: 'model-mix-moved'; drift: number; model: string }
|
|
80
|
+
| { kind: 'volume-moved'; beforeCalls: number; afterCalls: number; ratio: number }
|
|
81
|
+
| { kind: 'coverage-moved'; before: number; after: number };
|
|
82
|
+
|
|
83
|
+
export type GateVerdict = 'held' | 'dropped' | 'cannot-tell';
|
|
84
|
+
|
|
85
|
+
export type GateUnknown =
|
|
86
|
+
| 'too-few-before'
|
|
87
|
+
| 'too-few-after'
|
|
88
|
+
| 'confounded'
|
|
89
|
+
| 'no-vocabulary'
|
|
90
|
+
| 'not-separable';
|
|
91
|
+
|
|
92
|
+
/** One side of the boundary, as the caller measured it. */
|
|
93
|
+
export interface GateSide {
|
|
94
|
+
arm: ExperimentArm;
|
|
95
|
+
/** Every call in the window, outcome or not — the coverage denominator. */
|
|
96
|
+
calls: number;
|
|
97
|
+
/** Spend per model, for the mix comparison. */
|
|
98
|
+
usdByModel: Array<{ model: string; usd: number }>;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface QualityGate {
|
|
102
|
+
verdict: GateVerdict;
|
|
103
|
+
/** Why, when the verdict is `cannot-tell`. A refusal never arrives bare. */
|
|
104
|
+
unknown: GateUnknown | null;
|
|
105
|
+
before: ArmResult;
|
|
106
|
+
after: ArmResult;
|
|
107
|
+
/** The 95% interval on (after − before), or null. */
|
|
108
|
+
difference: { point: number; low: number; high: number } | null;
|
|
109
|
+
/**
|
|
110
|
+
* Everything found that means the prompt is not the only variable.
|
|
111
|
+
*
|
|
112
|
+
* Non-empty forces `cannot-tell`. Reported even on a `held` verdict, because
|
|
113
|
+
* a rate that held while the model changed underneath is not evidence that
|
|
114
|
+
* the prompt is fine either.
|
|
115
|
+
*/
|
|
116
|
+
confounders: Confounder[];
|
|
117
|
+
/**
|
|
118
|
+
* The cost half — measured, and kept beside the quality half rather than
|
|
119
|
+
* merged with it. The sentence teams argue about needs both.
|
|
120
|
+
*/
|
|
121
|
+
cost: { beforeUsdPerCall: number; afterUsdPerCall: number; deltaUsdPerCall: number } | null;
|
|
122
|
+
/** Outcomes behind the comparison, so the claim carries its own sample size. */
|
|
123
|
+
outcomes: { before: number; after: number };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function mixDrift(
|
|
127
|
+
before: Array<{ model: string; usd: number }>,
|
|
128
|
+
after: Array<{ model: string; usd: number }>,
|
|
129
|
+
): Confounder | null {
|
|
130
|
+
const share = (rows: Array<{ model: string; usd: number }>): Map<string, number> => {
|
|
131
|
+
const total = rows.reduce((sum, row) => sum + row.usd, 0);
|
|
132
|
+
const out = new Map<string, number>();
|
|
133
|
+
if (total <= 0) return out;
|
|
134
|
+
for (const row of rows) out.set(row.model, (out.get(row.model) ?? 0) + row.usd / total);
|
|
135
|
+
return out;
|
|
136
|
+
};
|
|
137
|
+
const a = share(before);
|
|
138
|
+
const b = share(after);
|
|
139
|
+
let worst: { model: string; drift: number } | null = null;
|
|
140
|
+
for (const model of new Set([...a.keys(), ...b.keys()])) {
|
|
141
|
+
const drift = Math.abs((b.get(model) ?? 0) - (a.get(model) ?? 0));
|
|
142
|
+
if (worst === null || drift > worst.drift) worst = { model, drift };
|
|
143
|
+
}
|
|
144
|
+
if (worst === null || worst.drift <= MAX_MODEL_MIX_DRIFT) return null;
|
|
145
|
+
return { kind: 'model-mix-moved', drift: worst.drift, model: worst.model };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function qualityGate(
|
|
149
|
+
before: GateSide,
|
|
150
|
+
after: GateSide,
|
|
151
|
+
vocabulary: OutcomeVocabulary | null,
|
|
152
|
+
): QualityGate {
|
|
153
|
+
/**
|
|
154
|
+
* The statistics are `experiment`'s, deliberately.
|
|
155
|
+
*
|
|
156
|
+
* One implementation of a two-proportion comparison, so a gate and a
|
|
157
|
+
* deliberate experiment can never disagree about the same two numbers — the
|
|
158
|
+
* failure mode where a team runs both and gets two answers, then trusts
|
|
159
|
+
* whichever one they liked.
|
|
160
|
+
*/
|
|
161
|
+
const stats = runExperiment(
|
|
162
|
+
{ arms: ['before', 'after'], minOutcomesPerArm: MIN_OUTCOMES_EACH_SIDE },
|
|
163
|
+
{ a: { ...after.arm, name: 'after' }, b: { ...before.arm, name: 'before' } },
|
|
164
|
+
vocabulary,
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
const outcomes = { before: stats.b.recorded, after: stats.a.recorded };
|
|
168
|
+
const cost =
|
|
169
|
+
before.calls > 0 && after.calls > 0
|
|
170
|
+
? {
|
|
171
|
+
beforeUsdPerCall: before.arm.totalUsd / before.calls,
|
|
172
|
+
afterUsdPerCall: after.arm.totalUsd / after.calls,
|
|
173
|
+
deltaUsdPerCall: after.arm.totalUsd / after.calls - before.arm.totalUsd / before.calls,
|
|
174
|
+
}
|
|
175
|
+
: null;
|
|
176
|
+
|
|
177
|
+
const confounders: Confounder[] = [];
|
|
178
|
+
const mix = mixDrift(before.usdByModel, after.usdByModel);
|
|
179
|
+
if (mix !== null) confounders.push(mix);
|
|
180
|
+
|
|
181
|
+
if (before.calls > 0 && after.calls > 0) {
|
|
182
|
+
const ratio = after.calls / before.calls;
|
|
183
|
+
if (ratio > MAX_VOLUME_RATIO || ratio < 1 / MAX_VOLUME_RATIO) {
|
|
184
|
+
confounders.push({
|
|
185
|
+
kind: 'volume-moved',
|
|
186
|
+
beforeCalls: before.calls,
|
|
187
|
+
afterCalls: after.calls,
|
|
188
|
+
ratio,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Coverage, the one nobody thinks of.
|
|
193
|
+
*
|
|
194
|
+
* A team that starts instrumenting its hard cases sees its measured rate
|
|
195
|
+
* fall without anything having got worse. Comparing two rates over
|
|
196
|
+
* differently-selected populations is the most convincing wrong answer
|
|
197
|
+
* this module could produce.
|
|
198
|
+
*/
|
|
199
|
+
const coverageBefore = outcomes.before / before.calls;
|
|
200
|
+
const coverageAfter = outcomes.after / after.calls;
|
|
201
|
+
if (Math.abs(coverageAfter - coverageBefore) > MAX_COVERAGE_DRIFT) {
|
|
202
|
+
confounders.push({ kind: 'coverage-moved', before: coverageBefore, after: coverageAfter });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const shell = {
|
|
207
|
+
before: stats.b,
|
|
208
|
+
after: stats.a,
|
|
209
|
+
difference: stats.difference,
|
|
210
|
+
confounders,
|
|
211
|
+
cost,
|
|
212
|
+
outcomes,
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
if (vocabulary === null || vocabulary.success.length === 0) {
|
|
216
|
+
return { ...shell, verdict: 'cannot-tell', unknown: 'no-vocabulary' };
|
|
217
|
+
}
|
|
218
|
+
if (outcomes.before < MIN_OUTCOMES_EACH_SIDE) {
|
|
219
|
+
return { ...shell, verdict: 'cannot-tell', unknown: 'too-few-before' };
|
|
220
|
+
}
|
|
221
|
+
if (outcomes.after < MIN_OUTCOMES_EACH_SIDE) {
|
|
222
|
+
return { ...shell, verdict: 'cannot-tell', unknown: 'too-few-after' };
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* A confounder outranks the statistics.
|
|
226
|
+
*
|
|
227
|
+
* Checked after the sample sizes and before the verdict, so a build is never
|
|
228
|
+
* failed on a difference that something else could equally explain. A gate
|
|
229
|
+
* that blames the prompt because the prompt is the thing it can see gets
|
|
230
|
+
* switched off within a month, and a switched-off gate catches nothing.
|
|
231
|
+
*/
|
|
232
|
+
if (confounders.length > 0) {
|
|
233
|
+
return { ...shell, verdict: 'cannot-tell', unknown: 'confounded' };
|
|
234
|
+
}
|
|
235
|
+
if (stats.separation === 'not-separable') {
|
|
236
|
+
/**
|
|
237
|
+
* Not separable is `cannot-tell`, never `held`.
|
|
238
|
+
*
|
|
239
|
+
* "The rate did not measurably fall" and "the rate held" are different
|
|
240
|
+
* claims, and a gate that spells them the same way passes a real
|
|
241
|
+
* regression it merely lacked the power to see. `verify` has held this
|
|
242
|
+
* line since 1.39 and it matters more here, because this one is wired to
|
|
243
|
+
* an exit code.
|
|
244
|
+
*/
|
|
245
|
+
return { ...shell, verdict: 'cannot-tell', unknown: 'not-separable' };
|
|
246
|
+
}
|
|
247
|
+
// `a` is the *after* arm, so `a-wins` means the rate went up.
|
|
248
|
+
return {
|
|
249
|
+
...shell,
|
|
250
|
+
verdict: stats.separation === 'a-wins' ? 'held' : 'dropped',
|
|
251
|
+
unknown: null,
|
|
252
|
+
};
|
|
253
|
+
}
|