@pydantic/genai-prices 0.0.7 → 0.0.12
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/data.js +24 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.umd.cjs +61 -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/data.js
CHANGED
|
@@ -1973,6 +1973,30 @@ export const data = [
|
|
|
1973
1973
|
output_mtok: 0.24,
|
|
1974
1974
|
},
|
|
1975
1975
|
},
|
|
1976
|
+
{
|
|
1977
|
+
id: 'openai/gpt-oss-120b',
|
|
1978
|
+
description: "GPT-OSS 120B is OpenAI's flagship open source model, built on a Mixture-of-Experts (MoE) architecture with\n120 billion parameters and 128 experts.\n",
|
|
1979
|
+
match: {
|
|
1980
|
+
equals: 'openai/gpt-oss-120b',
|
|
1981
|
+
},
|
|
1982
|
+
context_window: 131072,
|
|
1983
|
+
prices: {
|
|
1984
|
+
input_mtok: 0.15,
|
|
1985
|
+
output_mtok: 0.75,
|
|
1986
|
+
},
|
|
1987
|
+
},
|
|
1988
|
+
{
|
|
1989
|
+
id: 'openai/gpt-oss-20b',
|
|
1990
|
+
description: "GPT-OSS 20B is OpenAI's flagship open source model, built on a Mixture-of-Experts (MoE) architecture with\n20 billion parameters and 32 experts.\n",
|
|
1991
|
+
match: {
|
|
1992
|
+
equals: 'openai/gpt-oss-20b',
|
|
1993
|
+
},
|
|
1994
|
+
context_window: 131072,
|
|
1995
|
+
prices: {
|
|
1996
|
+
input_mtok: 0.1,
|
|
1997
|
+
output_mtok: 0.5,
|
|
1998
|
+
},
|
|
1999
|
+
},
|
|
1976
2000
|
],
|
|
1977
2001
|
},
|
|
1978
2002
|
{
|
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
|
@@ -1978,6 +1978,30 @@
|
|
|
1978
1978
|
input_mtok: 0.24,
|
|
1979
1979
|
output_mtok: 0.24
|
|
1980
1980
|
}
|
|
1981
|
+
},
|
|
1982
|
+
{
|
|
1983
|
+
id: "openai/gpt-oss-120b",
|
|
1984
|
+
description: "GPT-OSS 120B is OpenAI's flagship open source model, built on a Mixture-of-Experts (MoE) architecture with\n120 billion parameters and 128 experts.\n",
|
|
1985
|
+
match: {
|
|
1986
|
+
equals: "openai/gpt-oss-120b"
|
|
1987
|
+
},
|
|
1988
|
+
context_window: 131072,
|
|
1989
|
+
prices: {
|
|
1990
|
+
input_mtok: 0.15,
|
|
1991
|
+
output_mtok: 0.75
|
|
1992
|
+
}
|
|
1993
|
+
},
|
|
1994
|
+
{
|
|
1995
|
+
id: "openai/gpt-oss-20b",
|
|
1996
|
+
description: "GPT-OSS 20B is OpenAI's flagship open source model, built on a Mixture-of-Experts (MoE) architecture with\n20 billion parameters and 32 experts.\n",
|
|
1997
|
+
match: {
|
|
1998
|
+
equals: "openai/gpt-oss-20b"
|
|
1999
|
+
},
|
|
2000
|
+
context_window: 131072,
|
|
2001
|
+
prices: {
|
|
2002
|
+
input_mtok: 0.1,
|
|
2003
|
+
output_mtok: 0.5
|
|
2004
|
+
}
|
|
1981
2005
|
}
|
|
1982
2006
|
]
|
|
1983
2007
|
},
|
|
@@ -10630,18 +10654,26 @@
|
|
|
10630
10654
|
return calcTieredPrice(price, tokens);
|
|
10631
10655
|
}
|
|
10632
10656
|
function calcPrice(usage, modelPrice) {
|
|
10633
|
-
let
|
|
10634
|
-
|
|
10635
|
-
|
|
10636
|
-
|
|
10637
|
-
|
|
10638
|
-
|
|
10639
|
-
|
|
10640
|
-
|
|
10657
|
+
let input_price = 0;
|
|
10658
|
+
let output_price = 0;
|
|
10659
|
+
input_price += calcMtokPrice(modelPrice.input_mtok, usage.input_tokens);
|
|
10660
|
+
input_price += calcMtokPrice(modelPrice.cache_write_mtok, usage.cache_write_tokens);
|
|
10661
|
+
input_price += calcMtokPrice(modelPrice.cache_read_mtok, usage.cache_read_tokens);
|
|
10662
|
+
input_price += calcMtokPrice(modelPrice.input_audio_mtok, usage.input_audio_tokens);
|
|
10663
|
+
input_price += calcMtokPrice(
|
|
10664
|
+
modelPrice.cache_audio_read_mtok,
|
|
10665
|
+
usage.cache_audio_read_tokens);
|
|
10666
|
+
output_price += calcMtokPrice(modelPrice.output_mtok, usage.output_tokens);
|
|
10667
|
+
output_price += calcMtokPrice(modelPrice.output_audio_mtok, usage.output_audio_tokens);
|
|
10641
10668
|
if (modelPrice.requests_kcount !== void 0) {
|
|
10642
|
-
|
|
10669
|
+
input_price += modelPrice.requests_kcount / 1e3;
|
|
10643
10670
|
}
|
|
10644
|
-
|
|
10671
|
+
const total_price = input_price + output_price;
|
|
10672
|
+
return {
|
|
10673
|
+
input_price,
|
|
10674
|
+
output_price,
|
|
10675
|
+
total_price
|
|
10676
|
+
};
|
|
10645
10677
|
}
|
|
10646
10678
|
function getActiveModelPrice(model, timestamp) {
|
|
10647
10679
|
if (!Array.isArray(model.prices)) {
|
|
@@ -10655,9 +10687,17 @@
|
|
|
10655
10687
|
return cond.prices;
|
|
10656
10688
|
}
|
|
10657
10689
|
} else if (cond.constraint.type === "time_of_date") {
|
|
10658
|
-
const t = timestamp.
|
|
10659
|
-
|
|
10660
|
-
|
|
10690
|
+
const t = timestamp.toISOString().slice(11, 19);
|
|
10691
|
+
const startTime = cond.constraint.start_time;
|
|
10692
|
+
const endTime = cond.constraint.end_time;
|
|
10693
|
+
if (endTime < startTime) {
|
|
10694
|
+
if (t >= startTime || t < endTime) {
|
|
10695
|
+
return cond.prices;
|
|
10696
|
+
}
|
|
10697
|
+
} else {
|
|
10698
|
+
if (t >= startTime && t < endTime) {
|
|
10699
|
+
return cond.prices;
|
|
10700
|
+
}
|
|
10661
10701
|
}
|
|
10662
10702
|
}
|
|
10663
10703
|
}
|
|
@@ -10672,9 +10712,11 @@
|
|
|
10672
10712
|
if (!model) return null;
|
|
10673
10713
|
const timestamp = options.timestamp || /* @__PURE__ */ new Date();
|
|
10674
10714
|
const model_price = getActiveModelPrice(model, timestamp);
|
|
10675
|
-
const
|
|
10715
|
+
const priceResult = calcPrice(usage, model_price);
|
|
10676
10716
|
return {
|
|
10677
|
-
|
|
10717
|
+
input_price: priceResult.input_price,
|
|
10718
|
+
output_price: priceResult.output_price,
|
|
10719
|
+
total_price: priceResult.total_price,
|
|
10678
10720
|
provider,
|
|
10679
10721
|
model,
|
|
10680
10722
|
model_price,
|
|
@@ -10690,9 +10732,11 @@
|
|
|
10690
10732
|
if (!model) return null;
|
|
10691
10733
|
const timestamp = options.timestamp || /* @__PURE__ */ new Date();
|
|
10692
10734
|
const model_price = getActiveModelPrice(model, timestamp);
|
|
10693
|
-
const
|
|
10735
|
+
const priceResult = calcPrice(usage, model_price);
|
|
10694
10736
|
return {
|
|
10695
|
-
|
|
10737
|
+
input_price: priceResult.input_price,
|
|
10738
|
+
output_price: priceResult.output_price,
|
|
10739
|
+
total_price: priceResult.total_price,
|
|
10696
10740
|
provider,
|
|
10697
10741
|
model,
|
|
10698
10742
|
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