@trazum/core 1.31.0 → 1.32.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/dist/reprice.d.ts +39 -0
- package/dist/reprice.d.ts.map +1 -1
- package/dist/reprice.js +43 -0
- package/dist/reprice.js.map +1 -1
- package/package.json +1 -1
- package/src/reprice.ts +91 -0
package/dist/reprice.d.ts
CHANGED
|
@@ -71,6 +71,26 @@ export interface RepricedSlice {
|
|
|
71
71
|
deltaUsd: number;
|
|
72
72
|
/** The slice's largest single call, cache reads and writes included. */
|
|
73
73
|
maxCallInputTokens: number;
|
|
74
|
+
/**
|
|
75
|
+
* Present when the slice's cache traffic could not exist on the target.
|
|
76
|
+
*
|
|
77
|
+
* A cache entry only forms above the model's minimum prompt size, and when
|
|
78
|
+
* even this slice's largest call sits under the target's minimum, none of
|
|
79
|
+
* its calls could create one — so `targetUsd`, which grants the cache
|
|
80
|
+
* traffic the target's discounted rates, is priced on entries the target
|
|
81
|
+
* would refuse to create. That error flatters the move, which is exactly
|
|
82
|
+
* the direction this repository refuses. `noCacheUsd` is the same tokens
|
|
83
|
+
* with every cache token at the full input rate: the figure the target
|
|
84
|
+
* would actually bill if the entries cannot form. The truth sits at
|
|
85
|
+
* `noCacheUsd` (no entries) — not between the two by interpolation.
|
|
86
|
+
*
|
|
87
|
+
* Null when the slice has no cache traffic, or when its calls clear the
|
|
88
|
+
* target's minimum — where the standard figure stands unqualified.
|
|
89
|
+
*/
|
|
90
|
+
cacheBeyondTarget: {
|
|
91
|
+
minTokens: number;
|
|
92
|
+
noCacheUsd: number;
|
|
93
|
+
} | null;
|
|
74
94
|
}
|
|
75
95
|
/** A slice holding a call the target model could not have accepted. */
|
|
76
96
|
export interface OverContextSlice {
|
|
@@ -120,6 +140,25 @@ export interface RepriceReport {
|
|
|
120
140
|
*/
|
|
121
141
|
unpricedModels: string[];
|
|
122
142
|
unpricedCalls: number;
|
|
143
|
+
/**
|
|
144
|
+
* The moved bill with the target's Batch API on top, over the same movable
|
|
145
|
+
* slices — or null when the target sells no batch discount, which is a
|
|
146
|
+
* different statement from a $0 saving.
|
|
147
|
+
*
|
|
148
|
+
* The other half of "priced whole": routing and batching combine by
|
|
149
|
+
* discounting the *target's* rates, not by adding two savings — the same
|
|
150
|
+
* never-summed rule the levers learned when $12.60 plus $10.50 exceeded
|
|
151
|
+
* the $21.00 slice they came from. The discount covers input and output,
|
|
152
|
+
* cache traffic priced unchanged, matching the levers' convention exactly
|
|
153
|
+
* so the two surfaces cannot disagree about what batching is worth.
|
|
154
|
+
*
|
|
155
|
+
* Whether these calls can wait for a batch window is not knowable from a
|
|
156
|
+
* log, and nothing here claims it — the field is arithmetic, the decision
|
|
157
|
+
* is the reader's.
|
|
158
|
+
*/
|
|
159
|
+
batchOnTarget: {
|
|
160
|
+
targetUsd: number;
|
|
161
|
+
} | null;
|
|
123
162
|
/** Always true. A field, not a comment, so a rendering can print it. */
|
|
124
163
|
sameTokensAssumed: true;
|
|
125
164
|
}
|
package/dist/reprice.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reprice.d.ts","sourceRoot":"","sources":["../src/reprice.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAEH,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,kBAAkB,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"reprice.d.ts","sourceRoot":"","sources":["../src/reprice.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAEH,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;;;;;;OAeG;IACH,iBAAiB,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACrE;AAED,uEAAuE;AACvE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE;QACN,EAAE,EAAE,MAAM,CAAC;QACX,WAAW,EAAE,MAAM,CAAC;QACpB,oDAAoD;QACpD,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF;;;OAGG;IACH,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,4EAA4E;IAC5E,eAAe,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD;;;OAGG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;;;;;;OAeG;IACH,aAAa,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5C,wEAAwE;IACxE,iBAAiB,EAAE,IAAI,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,IAAI,CACb,cAAc,EACd,aAAa,GAAG,iBAAiB,GAAG,oBAAoB,GAAG,oBAAoB,GAAG,cAAc,CACjG,EACD,KAAK,EAAE,YAAY,EACnB,EAAE,GAAE,IAAiB,GACpB,MAAM,CAWR;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,gBAAgB,EAC3B,EAAE,GAAE,IAAiB,GACpB,aAAa,GAAG,IAAI,CAmHtB"}
|
package/dist/reprice.js
CHANGED
|
@@ -51,6 +51,32 @@ export function repriceProfile(report, targetId, catalogue, on = new Date()) {
|
|
|
51
51
|
}
|
|
52
52
|
const targetUsd = priceTokensOn(breakdown, target, on);
|
|
53
53
|
assumedWriteTtlCalls += breakdown.assumedWriteTtlCalls;
|
|
54
|
+
/**
|
|
55
|
+
* Cache traffic the target could not grant. The comparison is against the
|
|
56
|
+
* slice's *largest* call: if even that one sits under the target's cache
|
|
57
|
+
* minimum, no call in the slice could create an entry, and that is a fact
|
|
58
|
+
* rather than a guess. A slice whose largest call clears the minimum may
|
|
59
|
+
* still hold smaller calls that do not — undecidable per call from an
|
|
60
|
+
* aggregate, so nothing is claimed there.
|
|
61
|
+
*/
|
|
62
|
+
const cacheTokens = breakdown.cacheReadTokens + breakdown.cacheWrite5mTokens + breakdown.cacheWrite1hTokens;
|
|
63
|
+
// A null minimum is an *unknown* one — overlay-added models leave it null
|
|
64
|
+
// rather than invent a number — and nothing can be claimed against a
|
|
65
|
+
// threshold nobody stated. Unqualified is the only honest rendering there.
|
|
66
|
+
const cacheBeyondTarget = cacheTokens > 0 &&
|
|
67
|
+
target.cacheMinTokens !== null &&
|
|
68
|
+
breakdown.maxCallInputTokens < target.cacheMinTokens
|
|
69
|
+
? {
|
|
70
|
+
minTokens: target.cacheMinTokens,
|
|
71
|
+
noCacheUsd: priceTokensOn({
|
|
72
|
+
inputTokens: breakdown.inputTokens + cacheTokens,
|
|
73
|
+
cacheReadTokens: 0,
|
|
74
|
+
cacheWrite5mTokens: 0,
|
|
75
|
+
cacheWrite1hTokens: 0,
|
|
76
|
+
outputTokens: breakdown.outputTokens,
|
|
77
|
+
}, target, on),
|
|
78
|
+
}
|
|
79
|
+
: null;
|
|
54
80
|
slices.push({
|
|
55
81
|
label: slice.label,
|
|
56
82
|
model: slice.model,
|
|
@@ -59,12 +85,28 @@ export function repriceProfile(report, targetId, catalogue, on = new Date()) {
|
|
|
59
85
|
targetUsd,
|
|
60
86
|
deltaUsd: targetUsd - breakdown.totalUsd,
|
|
61
87
|
maxCallInputTokens: breakdown.maxCallInputTokens,
|
|
88
|
+
cacheBeyondTarget,
|
|
62
89
|
});
|
|
63
90
|
}
|
|
64
91
|
slices.sort((a, b) => a.deltaUsd - b.deltaUsd || b.currentUsd - a.currentUsd);
|
|
65
92
|
overContext.sort((a, b) => b.currentUsd - a.currentUsd);
|
|
66
93
|
const currentUsd = slices.reduce((sum, s) => sum + s.currentUsd, 0);
|
|
67
94
|
const targetUsd = slices.reduce((sum, s) => sum + s.targetUsd, 0);
|
|
95
|
+
/**
|
|
96
|
+
* The same movable tokens, batched on the target. Computed from the token
|
|
97
|
+
* aggregates rather than by discounting `targetUsd`, because the discount
|
|
98
|
+
* covers input and output while cache traffic rides through unchanged.
|
|
99
|
+
*/
|
|
100
|
+
const batchRate = multipliersFor(target).batch;
|
|
101
|
+
let batchOnTarget = null;
|
|
102
|
+
if (batchRate !== null && batchRate < 1 && slices.length > 0) {
|
|
103
|
+
const { inputPerMTok, outputPerMTok } = effectivePricing(target, on);
|
|
104
|
+
const movable = report.byLabelAndModel.filter((slice) => slice.model !== target.id && slice.breakdown.maxCallInputTokens <= target.contextWindow);
|
|
105
|
+
const inOutUsd = movable.reduce((sum, slice) => sum +
|
|
106
|
+
(slice.breakdown.inputTokens / 1_000_000) * inputPerMTok +
|
|
107
|
+
(slice.breakdown.outputTokens / 1_000_000) * outputPerMTok, 0);
|
|
108
|
+
batchOnTarget = { targetUsd: targetUsd - inOutUsd * (1 - batchRate) };
|
|
109
|
+
}
|
|
68
110
|
return {
|
|
69
111
|
target: { id: target.id, displayName: target.displayName, contextWindow: target.contextWindow },
|
|
70
112
|
slices,
|
|
@@ -76,6 +118,7 @@ export function repriceProfile(report, targetId, catalogue, on = new Date()) {
|
|
|
76
118
|
assumedWriteTtlCalls,
|
|
77
119
|
unpricedModels: report.unpricedModels,
|
|
78
120
|
unpricedCalls: report.unpriced.calls,
|
|
121
|
+
batchOnTarget,
|
|
79
122
|
sameTokensAssumed: true,
|
|
80
123
|
};
|
|
81
124
|
}
|
package/dist/reprice.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reprice.js","sourceRoot":"","sources":["../src/reprice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"reprice.js","sourceRoot":"","sources":["../src/reprice.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.
|
|
3
|
+
"version": "1.32.0",
|
|
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/reprice.ts
CHANGED
|
@@ -74,6 +74,23 @@ export interface RepricedSlice {
|
|
|
74
74
|
deltaUsd: number;
|
|
75
75
|
/** The slice's largest single call, cache reads and writes included. */
|
|
76
76
|
maxCallInputTokens: number;
|
|
77
|
+
/**
|
|
78
|
+
* Present when the slice's cache traffic could not exist on the target.
|
|
79
|
+
*
|
|
80
|
+
* A cache entry only forms above the model's minimum prompt size, and when
|
|
81
|
+
* even this slice's largest call sits under the target's minimum, none of
|
|
82
|
+
* its calls could create one — so `targetUsd`, which grants the cache
|
|
83
|
+
* traffic the target's discounted rates, is priced on entries the target
|
|
84
|
+
* would refuse to create. That error flatters the move, which is exactly
|
|
85
|
+
* the direction this repository refuses. `noCacheUsd` is the same tokens
|
|
86
|
+
* with every cache token at the full input rate: the figure the target
|
|
87
|
+
* would actually bill if the entries cannot form. The truth sits at
|
|
88
|
+
* `noCacheUsd` (no entries) — not between the two by interpolation.
|
|
89
|
+
*
|
|
90
|
+
* Null when the slice has no cache traffic, or when its calls clear the
|
|
91
|
+
* target's minimum — where the standard figure stands unqualified.
|
|
92
|
+
*/
|
|
93
|
+
cacheBeyondTarget: { minTokens: number; noCacheUsd: number } | null;
|
|
77
94
|
}
|
|
78
95
|
|
|
79
96
|
/** A slice holding a call the target model could not have accepted. */
|
|
@@ -122,6 +139,23 @@ export interface RepriceReport {
|
|
|
122
139
|
*/
|
|
123
140
|
unpricedModels: string[];
|
|
124
141
|
unpricedCalls: number;
|
|
142
|
+
/**
|
|
143
|
+
* The moved bill with the target's Batch API on top, over the same movable
|
|
144
|
+
* slices — or null when the target sells no batch discount, which is a
|
|
145
|
+
* different statement from a $0 saving.
|
|
146
|
+
*
|
|
147
|
+
* The other half of "priced whole": routing and batching combine by
|
|
148
|
+
* discounting the *target's* rates, not by adding two savings — the same
|
|
149
|
+
* never-summed rule the levers learned when $12.60 plus $10.50 exceeded
|
|
150
|
+
* the $21.00 slice they came from. The discount covers input and output,
|
|
151
|
+
* cache traffic priced unchanged, matching the levers' convention exactly
|
|
152
|
+
* so the two surfaces cannot disagree about what batching is worth.
|
|
153
|
+
*
|
|
154
|
+
* Whether these calls can wait for a batch window is not knowable from a
|
|
155
|
+
* log, and nothing here claims it — the field is arithmetic, the decision
|
|
156
|
+
* is the reader's.
|
|
157
|
+
*/
|
|
158
|
+
batchOnTarget: { targetUsd: number } | null;
|
|
125
159
|
/** Always true. A field, not a comment, so a rendering can print it. */
|
|
126
160
|
sameTokensAssumed: true;
|
|
127
161
|
}
|
|
@@ -194,6 +228,38 @@ export function repriceProfile(
|
|
|
194
228
|
}
|
|
195
229
|
const targetUsd = priceTokensOn(breakdown, target, on);
|
|
196
230
|
assumedWriteTtlCalls += breakdown.assumedWriteTtlCalls;
|
|
231
|
+
/**
|
|
232
|
+
* Cache traffic the target could not grant. The comparison is against the
|
|
233
|
+
* slice's *largest* call: if even that one sits under the target's cache
|
|
234
|
+
* minimum, no call in the slice could create an entry, and that is a fact
|
|
235
|
+
* rather than a guess. A slice whose largest call clears the minimum may
|
|
236
|
+
* still hold smaller calls that do not — undecidable per call from an
|
|
237
|
+
* aggregate, so nothing is claimed there.
|
|
238
|
+
*/
|
|
239
|
+
const cacheTokens =
|
|
240
|
+
breakdown.cacheReadTokens + breakdown.cacheWrite5mTokens + breakdown.cacheWrite1hTokens;
|
|
241
|
+
// A null minimum is an *unknown* one — overlay-added models leave it null
|
|
242
|
+
// rather than invent a number — and nothing can be claimed against a
|
|
243
|
+
// threshold nobody stated. Unqualified is the only honest rendering there.
|
|
244
|
+
const cacheBeyondTarget =
|
|
245
|
+
cacheTokens > 0 &&
|
|
246
|
+
target.cacheMinTokens !== null &&
|
|
247
|
+
breakdown.maxCallInputTokens < target.cacheMinTokens
|
|
248
|
+
? {
|
|
249
|
+
minTokens: target.cacheMinTokens,
|
|
250
|
+
noCacheUsd: priceTokensOn(
|
|
251
|
+
{
|
|
252
|
+
inputTokens: breakdown.inputTokens + cacheTokens,
|
|
253
|
+
cacheReadTokens: 0,
|
|
254
|
+
cacheWrite5mTokens: 0,
|
|
255
|
+
cacheWrite1hTokens: 0,
|
|
256
|
+
outputTokens: breakdown.outputTokens,
|
|
257
|
+
},
|
|
258
|
+
target,
|
|
259
|
+
on,
|
|
260
|
+
),
|
|
261
|
+
}
|
|
262
|
+
: null;
|
|
197
263
|
slices.push({
|
|
198
264
|
label: slice.label,
|
|
199
265
|
model: slice.model,
|
|
@@ -202,6 +268,7 @@ export function repriceProfile(
|
|
|
202
268
|
targetUsd,
|
|
203
269
|
deltaUsd: targetUsd - breakdown.totalUsd,
|
|
204
270
|
maxCallInputTokens: breakdown.maxCallInputTokens,
|
|
271
|
+
cacheBeyondTarget,
|
|
205
272
|
});
|
|
206
273
|
}
|
|
207
274
|
|
|
@@ -211,6 +278,29 @@ export function repriceProfile(
|
|
|
211
278
|
const currentUsd = slices.reduce((sum, s) => sum + s.currentUsd, 0);
|
|
212
279
|
const targetUsd = slices.reduce((sum, s) => sum + s.targetUsd, 0);
|
|
213
280
|
|
|
281
|
+
/**
|
|
282
|
+
* The same movable tokens, batched on the target. Computed from the token
|
|
283
|
+
* aggregates rather than by discounting `targetUsd`, because the discount
|
|
284
|
+
* covers input and output while cache traffic rides through unchanged.
|
|
285
|
+
*/
|
|
286
|
+
const batchRate = multipliersFor(target).batch;
|
|
287
|
+
let batchOnTarget: { targetUsd: number } | null = null;
|
|
288
|
+
if (batchRate !== null && batchRate < 1 && slices.length > 0) {
|
|
289
|
+
const { inputPerMTok, outputPerMTok } = effectivePricing(target, on);
|
|
290
|
+
const movable = report.byLabelAndModel.filter(
|
|
291
|
+
(slice) =>
|
|
292
|
+
slice.model !== target.id && slice.breakdown.maxCallInputTokens <= target.contextWindow,
|
|
293
|
+
);
|
|
294
|
+
const inOutUsd = movable.reduce(
|
|
295
|
+
(sum, slice) =>
|
|
296
|
+
sum +
|
|
297
|
+
(slice.breakdown.inputTokens / 1_000_000) * inputPerMTok +
|
|
298
|
+
(slice.breakdown.outputTokens / 1_000_000) * outputPerMTok,
|
|
299
|
+
0,
|
|
300
|
+
);
|
|
301
|
+
batchOnTarget = { targetUsd: targetUsd - inOutUsd * (1 - batchRate) };
|
|
302
|
+
}
|
|
303
|
+
|
|
214
304
|
return {
|
|
215
305
|
target: { id: target.id, displayName: target.displayName, contextWindow: target.contextWindow },
|
|
216
306
|
slices,
|
|
@@ -222,6 +312,7 @@ export function repriceProfile(
|
|
|
222
312
|
assumedWriteTtlCalls,
|
|
223
313
|
unpricedModels: report.unpricedModels,
|
|
224
314
|
unpricedCalls: report.unpriced.calls,
|
|
315
|
+
batchOnTarget,
|
|
225
316
|
sameTokensAssumed: true,
|
|
226
317
|
};
|
|
227
318
|
}
|