@pydantic/genai-prices 0.0.7 → 0.0.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/README.md +25 -5
- package/dist/__tests__/comprehensive.test.d.ts +1 -0
- package/dist/async/calcPriceAsync.js +4 -2
- package/dist/cli.js +3 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.umd.cjs +37 -17
- package/dist/priceCalc.d.ts +2 -2
- package/dist/priceCalc.js +35 -13
- package/dist/sync/calcPriceSync.js +4 -2
- package/dist/types.d.ts +8 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,6 +13,12 @@ Library and CLI for calculating LLM API prices, supporting browser, Node.js and
|
|
|
13
13
|
|
|
14
14
|
## API Usage
|
|
15
15
|
|
|
16
|
+
The library provides separated input and output pricing, giving you detailed breakdown of costs:
|
|
17
|
+
|
|
18
|
+
- `result.total_price` - Total cost for the request
|
|
19
|
+
- `result.input_price` - Cost for input/prompt tokens
|
|
20
|
+
- `result.output_price` - Cost for output/completion tokens
|
|
21
|
+
|
|
16
22
|
### Node.js & Browser (Library)
|
|
17
23
|
|
|
18
24
|
```js
|
|
@@ -23,7 +29,11 @@ const usage = { input_tokens: 1000, output_tokens: 100 }
|
|
|
23
29
|
// Sync (works everywhere, including browser)
|
|
24
30
|
const result = calcPriceSync(usage, 'gpt-3.5-turbo', { providerId: 'openai' })
|
|
25
31
|
if (result) {
|
|
26
|
-
console.log(
|
|
32
|
+
console.log(
|
|
33
|
+
`$${result.total_price} (input: $${result.input_price}, output: $${result.output_price})`,
|
|
34
|
+
result.provider.name,
|
|
35
|
+
result.model.name,
|
|
36
|
+
)
|
|
27
37
|
} else {
|
|
28
38
|
console.log('No price found for this model/provider combination')
|
|
29
39
|
}
|
|
@@ -31,7 +41,11 @@ if (result) {
|
|
|
31
41
|
// Async (works everywhere)
|
|
32
42
|
const asyncResult = await calcPriceAsync(usage, 'gpt-3.5-turbo', { providerId: 'openai' })
|
|
33
43
|
if (asyncResult) {
|
|
34
|
-
console.log(
|
|
44
|
+
console.log(
|
|
45
|
+
`$${asyncResult.total_price} (input: $${asyncResult.input_price}, output: $${asyncResult.output_price})`,
|
|
46
|
+
asyncResult.provider.name,
|
|
47
|
+
asyncResult.model.name,
|
|
48
|
+
)
|
|
35
49
|
} else {
|
|
36
50
|
console.log('No price found for this model/provider combination')
|
|
37
51
|
}
|
|
@@ -44,7 +58,11 @@ import { calcPriceSync, calcPriceAsync } from './dist/index.js'
|
|
|
44
58
|
const usage = { input_tokens: 1000, output_tokens: 100 }
|
|
45
59
|
const result = calcPriceSync(usage, 'gpt-3.5-turbo', { providerId: 'openai' })
|
|
46
60
|
if (result) {
|
|
47
|
-
console.log(
|
|
61
|
+
console.log(
|
|
62
|
+
`$${result.total_price} (input: $${result.input_price}, output: $${result.output_price})`,
|
|
63
|
+
result.provider.name,
|
|
64
|
+
result.model.name,
|
|
65
|
+
)
|
|
48
66
|
}
|
|
49
67
|
```
|
|
50
68
|
|
|
@@ -110,7 +128,7 @@ const result = calcPriceSync(usage, 'non-existent-model')
|
|
|
110
128
|
if (result === null) {
|
|
111
129
|
console.log('No pricing information available for this model')
|
|
112
130
|
} else {
|
|
113
|
-
console.log(`Price: $${result.
|
|
131
|
+
console.log(`Total Price: $${result.total_price} (input: $${result.input_price}, output: $${result.output_price})`)
|
|
114
132
|
}
|
|
115
133
|
|
|
116
134
|
// Async version also returns null
|
|
@@ -118,7 +136,9 @@ const asyncResult = await calcPriceAsync(usage, 'non-existent-model', { provider
|
|
|
118
136
|
if (asyncResult === null) {
|
|
119
137
|
console.log('No pricing information available for this model/provider combination')
|
|
120
138
|
} else {
|
|
121
|
-
console.log(
|
|
139
|
+
console.log(
|
|
140
|
+
`Total Price: $${asyncResult.total_price} (input: $${asyncResult.input_price}, output: $${asyncResult.output_price})`,
|
|
141
|
+
)
|
|
122
142
|
}
|
|
123
143
|
```
|
|
124
144
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -11,9 +11,11 @@ export async function calcPriceAsync(usage, modelRef, options = {}) {
|
|
|
11
11
|
return null;
|
|
12
12
|
const timestamp = options.timestamp || new Date();
|
|
13
13
|
const model_price = getActiveModelPrice(model, timestamp);
|
|
14
|
-
const
|
|
14
|
+
const priceResult = calcModelPrice(usage, model_price);
|
|
15
15
|
return {
|
|
16
|
-
|
|
16
|
+
input_price: priceResult.input_price,
|
|
17
|
+
output_price: priceResult.output_price,
|
|
18
|
+
total_price: priceResult.total_price,
|
|
17
19
|
provider,
|
|
18
20
|
model,
|
|
19
21
|
model_price,
|
package/dist/cli.js
CHANGED
|
@@ -126,7 +126,9 @@ async function main() {
|
|
|
126
126
|
['Model', result.model.name || result.model.id],
|
|
127
127
|
['Model Prices', JSON.stringify(result.model_price)],
|
|
128
128
|
['Context Window', w !== undefined ? w.toLocaleString() : undefined],
|
|
129
|
-
['Price', `$${result.
|
|
129
|
+
['Total Price', `$${result.total_price}`],
|
|
130
|
+
['Input Price', `$${result.input_price}`],
|
|
131
|
+
['Output Price', `$${result.output_price}`],
|
|
130
132
|
];
|
|
131
133
|
for (const [key, value] of output) {
|
|
132
134
|
if (value !== undefined) {
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,4 @@ export { calcPriceSync } from './sync/calcPriceSync.js';
|
|
|
2
2
|
export { calcPriceAsync } from './async/calcPriceAsync.js';
|
|
3
3
|
export { getProvidersSync, getProvidersAsync, enableAutoUpdate, isLocalDataOutdated, prefetchAsync, getEnvironmentInfo, } from './dataLoader.js';
|
|
4
4
|
export { matchProvider, matchModel } from './matcher.js';
|
|
5
|
-
export type { Usage, PriceCalculation, PriceCalculationResult, Provider, ModelInfo } from './types.js';
|
|
5
|
+
export type { Usage, PriceCalculation, PriceCalculationResult, Provider, ModelInfo, CalcPrice } from './types.js';
|
package/dist/index.umd.cjs
CHANGED
|
@@ -10630,18 +10630,26 @@
|
|
|
10630
10630
|
return calcTieredPrice(price, tokens);
|
|
10631
10631
|
}
|
|
10632
10632
|
function calcPrice(usage, modelPrice) {
|
|
10633
|
-
let
|
|
10634
|
-
|
|
10635
|
-
|
|
10636
|
-
|
|
10637
|
-
|
|
10638
|
-
|
|
10639
|
-
|
|
10640
|
-
|
|
10633
|
+
let input_price = 0;
|
|
10634
|
+
let output_price = 0;
|
|
10635
|
+
input_price += calcMtokPrice(modelPrice.input_mtok, usage.input_tokens);
|
|
10636
|
+
input_price += calcMtokPrice(modelPrice.cache_write_mtok, usage.cache_write_tokens);
|
|
10637
|
+
input_price += calcMtokPrice(modelPrice.cache_read_mtok, usage.cache_read_tokens);
|
|
10638
|
+
input_price += calcMtokPrice(modelPrice.input_audio_mtok, usage.input_audio_tokens);
|
|
10639
|
+
input_price += calcMtokPrice(
|
|
10640
|
+
modelPrice.cache_audio_read_mtok,
|
|
10641
|
+
usage.cache_audio_read_tokens);
|
|
10642
|
+
output_price += calcMtokPrice(modelPrice.output_mtok, usage.output_tokens);
|
|
10643
|
+
output_price += calcMtokPrice(modelPrice.output_audio_mtok, usage.output_audio_tokens);
|
|
10641
10644
|
if (modelPrice.requests_kcount !== void 0) {
|
|
10642
|
-
|
|
10645
|
+
input_price += modelPrice.requests_kcount / 1e3;
|
|
10643
10646
|
}
|
|
10644
|
-
|
|
10647
|
+
const total_price = input_price + output_price;
|
|
10648
|
+
return {
|
|
10649
|
+
input_price,
|
|
10650
|
+
output_price,
|
|
10651
|
+
total_price
|
|
10652
|
+
};
|
|
10645
10653
|
}
|
|
10646
10654
|
function getActiveModelPrice(model, timestamp) {
|
|
10647
10655
|
if (!Array.isArray(model.prices)) {
|
|
@@ -10655,9 +10663,17 @@
|
|
|
10655
10663
|
return cond.prices;
|
|
10656
10664
|
}
|
|
10657
10665
|
} else if (cond.constraint.type === "time_of_date") {
|
|
10658
|
-
const t = timestamp.
|
|
10659
|
-
|
|
10660
|
-
|
|
10666
|
+
const t = timestamp.toISOString().slice(11, 19);
|
|
10667
|
+
const startTime = cond.constraint.start_time;
|
|
10668
|
+
const endTime = cond.constraint.end_time;
|
|
10669
|
+
if (endTime < startTime) {
|
|
10670
|
+
if (t >= startTime || t < endTime) {
|
|
10671
|
+
return cond.prices;
|
|
10672
|
+
}
|
|
10673
|
+
} else {
|
|
10674
|
+
if (t >= startTime && t < endTime) {
|
|
10675
|
+
return cond.prices;
|
|
10676
|
+
}
|
|
10661
10677
|
}
|
|
10662
10678
|
}
|
|
10663
10679
|
}
|
|
@@ -10672,9 +10688,11 @@
|
|
|
10672
10688
|
if (!model) return null;
|
|
10673
10689
|
const timestamp = options.timestamp || /* @__PURE__ */ new Date();
|
|
10674
10690
|
const model_price = getActiveModelPrice(model, timestamp);
|
|
10675
|
-
const
|
|
10691
|
+
const priceResult = calcPrice(usage, model_price);
|
|
10676
10692
|
return {
|
|
10677
|
-
|
|
10693
|
+
input_price: priceResult.input_price,
|
|
10694
|
+
output_price: priceResult.output_price,
|
|
10695
|
+
total_price: priceResult.total_price,
|
|
10678
10696
|
provider,
|
|
10679
10697
|
model,
|
|
10680
10698
|
model_price,
|
|
@@ -10690,9 +10708,11 @@
|
|
|
10690
10708
|
if (!model) return null;
|
|
10691
10709
|
const timestamp = options.timestamp || /* @__PURE__ */ new Date();
|
|
10692
10710
|
const model_price = getActiveModelPrice(model, timestamp);
|
|
10693
|
-
const
|
|
10711
|
+
const priceResult = calcPrice(usage, model_price);
|
|
10694
10712
|
return {
|
|
10695
|
-
|
|
10713
|
+
input_price: priceResult.input_price,
|
|
10714
|
+
output_price: priceResult.output_price,
|
|
10715
|
+
total_price: priceResult.total_price,
|
|
10696
10716
|
provider,
|
|
10697
10717
|
model,
|
|
10698
10718
|
model_price,
|
package/dist/priceCalc.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { Usage, ModelPrice, ModelInfo } from './types.js';
|
|
2
|
-
export declare function calcPrice(usage: Usage, modelPrice: ModelPrice):
|
|
1
|
+
import { Usage, ModelPrice, ModelInfo, CalcPrice } from './types.js';
|
|
2
|
+
export declare function calcPrice(usage: Usage, modelPrice: ModelPrice): CalcPrice;
|
|
3
3
|
export declare function getActiveModelPrice(model: ModelInfo, timestamp: Date): ModelPrice;
|
package/dist/priceCalc.js
CHANGED
|
@@ -29,18 +29,27 @@ function calcMtokPrice(price, tokens, _field) {
|
|
|
29
29
|
return calcTieredPrice(price, tokens);
|
|
30
30
|
}
|
|
31
31
|
export function calcPrice(usage, modelPrice) {
|
|
32
|
-
let
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
let input_price = 0;
|
|
33
|
+
let output_price = 0;
|
|
34
|
+
// Input-related prices
|
|
35
|
+
input_price += calcMtokPrice(modelPrice.input_mtok, usage.input_tokens, 'input_mtok');
|
|
36
|
+
input_price += calcMtokPrice(modelPrice.cache_write_mtok, usage.cache_write_tokens, 'cache_write_mtok');
|
|
37
|
+
input_price += calcMtokPrice(modelPrice.cache_read_mtok, usage.cache_read_tokens, 'cache_read_mtok');
|
|
38
|
+
input_price += calcMtokPrice(modelPrice.input_audio_mtok, usage.input_audio_tokens, 'input_audio_mtok');
|
|
39
|
+
input_price += calcMtokPrice(modelPrice.cache_audio_read_mtok, usage.cache_audio_read_tokens, 'cache_audio_read_mtok');
|
|
40
|
+
// Output-related prices
|
|
41
|
+
output_price += calcMtokPrice(modelPrice.output_mtok, usage.output_tokens, 'output_mtok');
|
|
42
|
+
output_price += calcMtokPrice(modelPrice.output_audio_mtok, usage.output_audio_tokens, 'output_audio_mtok');
|
|
43
|
+
// Requests price (counted as input cost)
|
|
40
44
|
if (modelPrice.requests_kcount !== undefined) {
|
|
41
|
-
|
|
45
|
+
input_price += modelPrice.requests_kcount / 1000;
|
|
42
46
|
}
|
|
43
|
-
|
|
47
|
+
const total_price = input_price + output_price;
|
|
48
|
+
return {
|
|
49
|
+
input_price,
|
|
50
|
+
output_price,
|
|
51
|
+
total_price,
|
|
52
|
+
};
|
|
44
53
|
}
|
|
45
54
|
export function getActiveModelPrice(model, timestamp) {
|
|
46
55
|
if (!Array.isArray(model.prices)) {
|
|
@@ -57,9 +66,22 @@ export function getActiveModelPrice(model, timestamp) {
|
|
|
57
66
|
}
|
|
58
67
|
}
|
|
59
68
|
else if (cond.constraint.type === 'time_of_date') {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
69
|
+
// Extract UTC time to match constraint times which are in UTC (with 'Z' suffix)
|
|
70
|
+
const t = timestamp.toISOString().slice(11, 19); // Get "HH:MM:SS" from ISO string
|
|
71
|
+
const startTime = cond.constraint.start_time;
|
|
72
|
+
const endTime = cond.constraint.end_time;
|
|
73
|
+
// Handle time ranges that span midnight (end time < start time)
|
|
74
|
+
if (endTime < startTime) {
|
|
75
|
+
// Time is in range if it's >= start OR < end
|
|
76
|
+
if (t >= startTime || t < endTime) {
|
|
77
|
+
return cond.prices;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// Normal time range (start <= time < end)
|
|
82
|
+
if (t >= startTime && t < endTime) {
|
|
83
|
+
return cond.prices;
|
|
84
|
+
}
|
|
63
85
|
}
|
|
64
86
|
}
|
|
65
87
|
}
|
|
@@ -11,9 +11,11 @@ export function calcPriceSync(usage, modelRef, options = {}) {
|
|
|
11
11
|
return null;
|
|
12
12
|
const timestamp = options.timestamp || new Date();
|
|
13
13
|
const model_price = getActiveModelPrice(model, timestamp);
|
|
14
|
-
const
|
|
14
|
+
const priceResult = calcModelPrice(usage, model_price);
|
|
15
15
|
return {
|
|
16
|
-
|
|
16
|
+
input_price: priceResult.input_price,
|
|
17
|
+
output_price: priceResult.output_price,
|
|
18
|
+
total_price: priceResult.total_price,
|
|
17
19
|
provider,
|
|
18
20
|
model,
|
|
19
21
|
model_price,
|
package/dist/types.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ export interface Usage {
|
|
|
6
6
|
input_audio_tokens?: number;
|
|
7
7
|
cache_audio_read_tokens?: number;
|
|
8
8
|
output_audio_tokens?: number;
|
|
9
|
-
requests?: number;
|
|
10
9
|
}
|
|
11
10
|
export interface Tier {
|
|
12
11
|
start: number;
|
|
@@ -74,8 +73,15 @@ export interface Provider {
|
|
|
74
73
|
provider_match?: MatchLogic;
|
|
75
74
|
models: ModelInfo[];
|
|
76
75
|
}
|
|
76
|
+
export interface CalcPrice {
|
|
77
|
+
input_price: number;
|
|
78
|
+
output_price: number;
|
|
79
|
+
total_price: number;
|
|
80
|
+
}
|
|
77
81
|
export interface PriceCalculation {
|
|
78
|
-
|
|
82
|
+
input_price: number;
|
|
83
|
+
output_price: number;
|
|
84
|
+
total_price: number;
|
|
79
85
|
provider: Provider;
|
|
80
86
|
model: ModelInfo;
|
|
81
87
|
model_price: ModelPrice;
|
package/package.json
CHANGED