@sisu-ai/mw-usage-tracker 1.0.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/README.md +24 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +46 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +19 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# @sisu-ai/mw-usage-tracker
|
|
2
|
+
|
|
3
|
+
Track token usage across your pipeline and estimate cost.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
```ts
|
|
7
|
+
import { usageTracker } from '@sisu-ai/mw-usage-tracker';
|
|
8
|
+
|
|
9
|
+
const app = new Agent()
|
|
10
|
+
.use(usageTracker({
|
|
11
|
+
'openai:gpt-4o-mini': { inputPer1K: 0.15, outputPer1K: 0.6 },
|
|
12
|
+
'*': { inputPer1K: 0.15, outputPer1K: 0.6 },
|
|
13
|
+
}, { logPerCall: true }))
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## How it works
|
|
17
|
+
- Wraps `ctx.model.generate` for the duration of the pipeline.
|
|
18
|
+
- Accumulates `promptTokens`, `completionTokens`, `totalTokens` from `ModelResponse.usage`.
|
|
19
|
+
- If a price table is provided, computes `costUSD` per call and totals.
|
|
20
|
+
- Writes totals to `ctx.state.usage` and logs them at the end.
|
|
21
|
+
|
|
22
|
+
## Notes
|
|
23
|
+
- Each adapter should map its native usage fields to `ModelResponse.usage`.
|
|
24
|
+
- If a provider doesn’t return usage, you’ll get counts of calls only (no cost).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Middleware } from '@sisu-ai/core';
|
|
2
|
+
export type PriceTable = Record<string, {
|
|
3
|
+
inputPer1K: number;
|
|
4
|
+
outputPer1K: number;
|
|
5
|
+
}>;
|
|
6
|
+
export interface UsageTotals {
|
|
7
|
+
promptTokens: number;
|
|
8
|
+
completionTokens: number;
|
|
9
|
+
totalTokens: number;
|
|
10
|
+
costUSD?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function usageTracker(prices: PriceTable, opts?: {
|
|
13
|
+
logPerCall?: boolean;
|
|
14
|
+
}): Middleware;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export function usageTracker(prices, opts = {}) {
|
|
2
|
+
return async (ctx, next) => {
|
|
3
|
+
// Wrap model.generate to intercept responses
|
|
4
|
+
const orig = ctx.model.generate.bind(ctx.model);
|
|
5
|
+
const price = prices[ctx.model.name] ?? prices['*'];
|
|
6
|
+
const totals = {
|
|
7
|
+
promptTokens: Number(ctx.state?.usage?.promptTokens ?? 0),
|
|
8
|
+
completionTokens: Number(ctx.state?.usage?.completionTokens ?? 0),
|
|
9
|
+
totalTokens: Number(ctx.state?.usage?.totalTokens ?? 0),
|
|
10
|
+
costUSD: Number(ctx.state?.usage?.costUSD ?? 0),
|
|
11
|
+
};
|
|
12
|
+
async function withUsage(...args) {
|
|
13
|
+
const out = await orig(...args);
|
|
14
|
+
const u = out.usage;
|
|
15
|
+
if (u) {
|
|
16
|
+
const p = Number(u.promptTokens ?? 0);
|
|
17
|
+
const c = Number(u.completionTokens ?? 0);
|
|
18
|
+
const t = Number(u.totalTokens ?? (p + c));
|
|
19
|
+
totals.promptTokens += p;
|
|
20
|
+
totals.completionTokens += c;
|
|
21
|
+
totals.totalTokens += t;
|
|
22
|
+
if (price) {
|
|
23
|
+
const cost = (p / 1000) * price.inputPer1K + (c / 1000) * price.outputPer1K;
|
|
24
|
+
totals.costUSD = Number((totals.costUSD ?? 0) + cost);
|
|
25
|
+
}
|
|
26
|
+
if (opts.logPerCall)
|
|
27
|
+
ctx.log.info?.('[usage] call', { promptTokens: p, completionTokens: c, totalTokens: t, estCostUSD: price ? round2((p / 1000) * price.inputPer1K + (c / 1000) * price.outputPer1K) : undefined });
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
ctx.state._origGenerate = orig;
|
|
32
|
+
ctx.model.generate = withUsage;
|
|
33
|
+
await next();
|
|
34
|
+
// Restore
|
|
35
|
+
ctx.model.generate = orig;
|
|
36
|
+
if (!ctx.state.usage)
|
|
37
|
+
ctx.state.usage = {};
|
|
38
|
+
ctx.state.usage.promptTokens = totals.promptTokens;
|
|
39
|
+
ctx.state.usage.completionTokens = totals.completionTokens;
|
|
40
|
+
ctx.state.usage.totalTokens = totals.totalTokens;
|
|
41
|
+
if (price)
|
|
42
|
+
ctx.state.usage.costUSD = round2(totals.costUSD ?? 0);
|
|
43
|
+
ctx.log.info?.('[usage] totals', ctx.state.usage);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function round2(n) { return Math.round(n * 100) / 100; }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../src/index.ts"],"version":"5.9.2"}
|
package/package.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sisu-ai/mw-usage-tracker",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc -b"
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"@sisu-ai/core": "0.2.0"
|
|
18
|
+
}
|
|
19
|
+
}
|