agl 41.1.0 → 41.2.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/changelog.md +13 -0
- package/dist_serve/bundle.js +1734 -1734
- package/dist_serve/bundle.js.map +2 -2
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/aglapi/aglapisurface.document.js +2 -2
- package/dist_ts/classes.inferencegateway.js +4 -3
- package/dist_ts/classes.inferenceusage.d.ts +19 -7
- package/dist_ts/classes.inferenceusage.js +49 -13
- package/dist_ts/classes.inferenceusagetap.d.ts +15 -3
- package/dist_ts/classes.inferenceusagetap.js +16 -9
- package/dist_ts/classes.usagefeed.js +3 -2
- package/dist_ts_interfaces/interfaces.d.ts +1 -1
- package/dist_ts_interfaces/interfaces.js +1 -1
- package/dist_ts_interfaces/metrics.d.ts +29 -7
- package/dist_ts_interfaces/metrics.js +14 -1
- package/package.json +5 -5
- package/readme.md +15 -4
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/aglapi/aglapisurface.document.ts +2 -2
- package/ts/classes.inferencegateway.ts +3 -2
- package/ts/classes.inferenceusage.ts +58 -19
- package/ts/classes.inferenceusagetap.ts +27 -8
- package/ts/classes.usagefeed.ts +2 -1
- package/ts_interfaces/interfaces.ts +1 -1
- package/ts_interfaces/metrics.ts +34 -7
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/classes.controllersocketclient.ts +5 -2
- package/ts_web/elements.metricsboard.ts +68 -18
|
@@ -13,23 +13,29 @@ export interface IMetricsBoardSender {
|
|
|
13
13
|
): Promise<TRequest['response']>;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
type TUsageCounts =
|
|
17
|
-
|
|
16
|
+
type TUsageCounts = interfaces.IControllerUsageCounts;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A table row's counts: its buckets' counts, their total tokens and whether that total is a lower bound
|
|
20
|
+
* (some bucket of it has unknown cache counts and a provider `controllerUsageTotalIsLowerBound` marks).
|
|
21
|
+
*/
|
|
22
|
+
interface IMetricsRowCounts extends TUsageCounts {
|
|
23
|
+
totalTokens: number;
|
|
24
|
+
totalLowerBound: boolean;
|
|
25
|
+
}
|
|
18
26
|
|
|
19
27
|
/** A model's usage over the window: one row of the models table. */
|
|
20
|
-
export interface IMetricsModelRow extends
|
|
28
|
+
export interface IMetricsModelRow extends IMetricsRowCounts {
|
|
21
29
|
key: string;
|
|
22
30
|
provider: interfaces.TControllerUsageProvider;
|
|
23
31
|
model: string;
|
|
24
|
-
totalTokens: number;
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
/** One session on one harness of the opened model: one row of the drill-down table. */
|
|
28
|
-
export interface IMetricsSessionRow extends
|
|
35
|
+
export interface IMetricsSessionRow extends IMetricsRowCounts {
|
|
29
36
|
key: string;
|
|
30
37
|
harness: string;
|
|
31
38
|
session: string;
|
|
32
|
-
totalTokens: number;
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
const windowOptions: { key: interfaces.TControllerUsageWindow; label: string; description: string }[] = [
|
|
@@ -42,12 +48,15 @@ const modelKey = (bucketArg: Pick<interfaces.IControllerUsageBucket, 'provider'
|
|
|
42
48
|
`${bucketArg.provider}/${bucketArg.model}`
|
|
43
49
|
);
|
|
44
50
|
|
|
45
|
-
/** Every token a call counted: input, output
|
|
51
|
+
/** Every token a call counted: input, output and the cache reads and writes it stated. */
|
|
46
52
|
const totalTokens = (countsArg: TUsageCounts): number => (
|
|
47
53
|
countsArg.inputTokens + countsArg.outputTokens + countsArg.cacheReadTokens + countsArg.cacheWriteTokens
|
|
48
54
|
);
|
|
49
55
|
|
|
50
|
-
const emptyCounts = (): TUsageCounts => ({ calls: 0, inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0
|
|
56
|
+
const emptyCounts = (): TUsageCounts => ({ calls: 0, inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0,
|
|
57
|
+
cacheReadUnknownCalls: 0, cacheWriteUnknownCalls: 0 });
|
|
58
|
+
|
|
59
|
+
const emptyRowCounts = (): IMetricsRowCounts => ({ ...emptyCounts(), totalTokens: 0, totalLowerBound: false });
|
|
51
60
|
|
|
52
61
|
const addCounts = (targetArg: TUsageCounts, bucketArg: TUsageCounts): void => {
|
|
53
62
|
targetArg.calls += bucketArg.calls;
|
|
@@ -55,6 +64,31 @@ const addCounts = (targetArg: TUsageCounts, bucketArg: TUsageCounts): void => {
|
|
|
55
64
|
targetArg.outputTokens += bucketArg.outputTokens;
|
|
56
65
|
targetArg.cacheReadTokens += bucketArg.cacheReadTokens;
|
|
57
66
|
targetArg.cacheWriteTokens += bucketArg.cacheWriteTokens;
|
|
67
|
+
targetArg.cacheReadUnknownCalls += bucketArg.cacheReadUnknownCalls;
|
|
68
|
+
targetArg.cacheWriteUnknownCalls += bucketArg.cacheWriteUnknownCalls;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const addBucket = (rowArg: IMetricsRowCounts, bucketArg: interfaces.IControllerUsageBucket): void => {
|
|
72
|
+
addCounts(rowArg, bucketArg);
|
|
73
|
+
rowArg.totalTokens += totalTokens(bucketArg);
|
|
74
|
+
rowArg.totalLowerBound ||= interfaces.controllerUsageTotalIsLowerBound[bucketArg.provider]
|
|
75
|
+
&& (bucketArg.cacheReadUnknownCalls > 0 || bucketArg.cacheWriteUnknownCalls > 0);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/** The cache counts the board states: reads and writes, each with the calls that did not state theirs. */
|
|
79
|
+
const cacheCounts = {
|
|
80
|
+
cacheReadTokens: 'cacheReadUnknownCalls',
|
|
81
|
+
cacheWriteTokens: 'cacheWriteUnknownCalls',
|
|
82
|
+
} as const satisfies Record<string, keyof TUsageCounts>;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* A cache count as the board states it: what the calls stated; "≥" before it when some calls did not state theirs, as
|
|
86
|
+
* those read or wrote an unknown number, not none; and "Unknown" when no call stated any.
|
|
87
|
+
*/
|
|
88
|
+
const cacheText = (countsArg: TUsageCounts, keyArg: keyof typeof cacheCounts, formatArg: Intl.NumberFormat): string => {
|
|
89
|
+
const stated = countsArg[keyArg], unknownCalls = countsArg[cacheCounts[keyArg]];
|
|
90
|
+
return unknownCalls === 0 ? formatArg.format(stated)
|
|
91
|
+
: stated === 0 && unknownCalls === countsArg.calls ? 'Unknown' : `≥ ${formatArg.format(stated)}`;
|
|
58
92
|
};
|
|
59
93
|
|
|
60
94
|
const compactNumber = new Intl.NumberFormat(undefined, { notation: 'compact', maximumFractionDigits: 1 });
|
|
@@ -68,7 +102,8 @@ const pointTimeFormatters: Record<interfaces.TControllerUsageSpan, (epochMsArg:
|
|
|
68
102
|
hour: (epochMsArg) => momentFormat.formatRange(epochMsArg, epochMsArg + interfaces.controllerUsageSpanMs.hour),
|
|
69
103
|
};
|
|
70
104
|
|
|
71
|
-
|
|
105
|
+
/** The count columns; a cache count as `cacheText` states it, and the total with "≥" when it is a lower bound. */
|
|
106
|
+
const countColumns = <TRow extends IMetricsRowCounts>(): plugins.deesCatalog.Column<TRow>[] => (
|
|
72
107
|
([
|
|
73
108
|
['calls', 'Calls'],
|
|
74
109
|
['inputTokens', 'Input'],
|
|
@@ -80,7 +115,9 @@ const countColumns = <TRow extends TUsageCounts & { totalTokens: number }>(): pl
|
|
|
80
115
|
key: keyArg,
|
|
81
116
|
header: headerArg,
|
|
82
117
|
align: 'end' as const,
|
|
83
|
-
renderer: (valueArg: number) =>
|
|
118
|
+
renderer: (valueArg: number, rowArg: TRow) => (keyArg === 'cacheReadTokens' || keyArg === 'cacheWriteTokens'
|
|
119
|
+
? cacheText(rowArg, keyArg, fullNumber)
|
|
120
|
+
: keyArg === 'totalTokens' && rowArg.totalLowerBound ? `≥ ${fullNumber.format(valueArg)}` : fullNumber.format(valueArg)),
|
|
84
121
|
}))
|
|
85
122
|
);
|
|
86
123
|
|
|
@@ -375,11 +412,10 @@ export class AglMetricsBoard extends plugins.deesElement.DeesElement {
|
|
|
375
412
|
const key = modelKey(bucket);
|
|
376
413
|
let row = rows.get(key);
|
|
377
414
|
if (!row) {
|
|
378
|
-
row = { key, provider: bucket.provider, model: bucket.model, ...
|
|
415
|
+
row = { key, provider: bucket.provider, model: bucket.model, ...emptyRowCounts() };
|
|
379
416
|
rows.set(key, row);
|
|
380
417
|
}
|
|
381
|
-
|
|
382
|
-
row.totalTokens += totalTokens(bucket);
|
|
418
|
+
addBucket(row, bucket);
|
|
383
419
|
}
|
|
384
420
|
return [...rows.values()];
|
|
385
421
|
}
|
|
@@ -393,11 +429,10 @@ export class AglMetricsBoard extends plugins.deesElement.DeesElement {
|
|
|
393
429
|
const key = JSON.stringify([bucket.harness, bucket.session]);
|
|
394
430
|
let row = rows.get(key);
|
|
395
431
|
if (!row) {
|
|
396
|
-
row = { key, harness, session, ...
|
|
432
|
+
row = { key, harness, session, ...emptyRowCounts() };
|
|
397
433
|
rows.set(key, row);
|
|
398
434
|
}
|
|
399
|
-
|
|
400
|
-
row.totalTokens += totalTokens(bucket);
|
|
435
|
+
addBucket(row, bucket);
|
|
401
436
|
}
|
|
402
437
|
return [...rows.values()];
|
|
403
438
|
}
|
|
@@ -409,12 +444,27 @@ export class AglMetricsBoard extends plugins.deesElement.DeesElement {
|
|
|
409
444
|
return [
|
|
410
445
|
{ id: 'input', title: 'Input', value: value(counts.inputTokens), unit: 'tokens', type: 'number', icon: 'lucide:ArrowDownToLine' },
|
|
411
446
|
{ id: 'output', title: 'Output', value: value(counts.outputTokens), unit: 'tokens', type: 'number', icon: 'lucide:ArrowUpFromLine' },
|
|
412
|
-
|
|
413
|
-
|
|
447
|
+
this.cacheTile(counts, knownArg, 'cacheReadTokens'),
|
|
448
|
+
this.cacheTile(counts, knownArg, 'cacheWriteTokens'),
|
|
414
449
|
{ id: 'calls', title: 'Calls', value: value(counts.calls), type: 'number', icon: 'lucide:Activity' },
|
|
415
450
|
];
|
|
416
451
|
}
|
|
417
452
|
|
|
453
|
+
/**
|
|
454
|
+
* A cache read or write tile: "Unknown" without a unit when no call stated its count, "≥" the stated count when some
|
|
455
|
+
* did not, and then how many calls left it unknown.
|
|
456
|
+
*/
|
|
457
|
+
private cacheTile(countsArg: TUsageCounts, knownArg: boolean, keyArg: keyof typeof cacheCounts): plugins.deesCatalog.IStatsTile {
|
|
458
|
+
const text = knownArg ? cacheText(countsArg, keyArg, compactNumber) : '–';
|
|
459
|
+
const unknownCalls = countsArg[cacheCounts[keyArg]];
|
|
460
|
+
const tile = keyArg === 'cacheReadTokens' ? { id: 'cacheRead', title: 'Cache read', icon: 'lucide:DatabaseZap' }
|
|
461
|
+
: { id: 'cacheWrite', title: 'Cache write', icon: 'lucide:Database' };
|
|
462
|
+
return { ...tile, value: text, ...(text === 'Unknown' ? {} : { unit: 'tokens' }), type: 'number',
|
|
463
|
+
...(knownArg && unknownCalls > 0
|
|
464
|
+
? { description: `Unknown for ${fullNumber.format(unknownCalls)} of ${fullNumber.format(countsArg.calls)} calls` }
|
|
465
|
+
: {}) };
|
|
466
|
+
}
|
|
467
|
+
|
|
418
468
|
/**
|
|
419
469
|
* One series per model, the largest first, each drawn from zero: its tokens per minute in every span of the window,
|
|
420
470
|
* the empty ones as 0. A minute that is still open is left out, as its count is partial; the totals and tables keep
|