@pydantic/genai-prices 0.0.20 → 0.0.21
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/LICENSE +21 -0
- package/README.md +59 -147
- package/dist/cli.js +11684 -150
- package/dist/index.cjs +10 -0
- package/dist/index.d.cts +146 -0
- package/dist/index.d.ts +146 -5
- package/dist/index.js +11032 -4
- package/package.json +55 -28
- package/dist/__tests__/calcPrice.test.d.ts +0 -1
- package/dist/__tests__/comprehensive.test.d.ts +0 -1
- package/dist/__tests__/matcher.test.d.ts +0 -1
- package/dist/async/calcPriceAsync.d.ts +0 -8
- package/dist/async/calcPriceAsync.js +0 -24
- package/dist/cli.d.ts +0 -1
- package/dist/data.d.ts +0 -2
- package/dist/data.js +0 -10605
- package/dist/dataLoader.d.ts +0 -18
- package/dist/dataLoader.js +0 -146
- package/dist/index.umd.cjs +0 -10914
- package/dist/matcher.d.ts +0 -3
- package/dist/matcher.js +0 -43
- package/dist/priceCalc.d.ts +0 -3
- package/dist/priceCalc.js +0 -90
- package/dist/sync/calcPriceSync.d.ts +0 -8
- package/dist/sync/calcPriceSync.js +0 -24
- package/dist/types.d.ts +0 -95
- package/dist/types.js +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) Pydantic Services Inc. 2025 to present
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,103 +1,54 @@
|
|
|
1
|
-
# genai-prices
|
|
1
|
+
# @pydantic/genai-prices
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
JavaScript package and command-line tool for calculating LLM API prices.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Basic usage
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **Async API**: Fetches and caches price data from GitHub, works in browser, Node.js, Cloudflare, Deno, etc.
|
|
9
|
-
- **Environment-agnostic design**: Sync/async distinction is about API style, not environment.
|
|
10
|
-
- **Smart provider and model matching** with flexible options.
|
|
11
|
-
- **CLI** for quick price calculations with auto-update support.
|
|
12
|
-
- **Browser support** with a single bundle and test page.
|
|
7
|
+
### `calcPrice`
|
|
13
8
|
|
|
14
|
-
|
|
9
|
+
The package exports a function for price calculation that, by default, uses the bundled price data.
|
|
15
10
|
|
|
16
|
-
|
|
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
|
-
|
|
22
|
-
### Node.js & Browser (Library)
|
|
23
|
-
|
|
24
|
-
```js
|
|
25
|
-
import { calcPriceSync, calcPriceAsync } from '@pydantic/genai-prices'
|
|
11
|
+
```ts
|
|
12
|
+
import { calcPrice } from '@pydantic/genai-prices'
|
|
26
13
|
|
|
27
14
|
const usage = { input_tokens: 1000, output_tokens: 100 }
|
|
28
15
|
|
|
29
|
-
|
|
30
|
-
|
|
16
|
+
const result = calcPrice(usage, 'gpt-3.5-turbo', { providerId: 'openai' })
|
|
17
|
+
|
|
31
18
|
if (result) {
|
|
32
19
|
console.log(
|
|
33
20
|
`$${result.total_price} (input: $${result.input_price}, output: $${result.output_price})`,
|
|
34
21
|
result.provider.name,
|
|
35
|
-
result.model.name
|
|
36
|
-
)
|
|
37
|
-
} else {
|
|
38
|
-
console.log('No price found for this model/provider combination')
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Async (works everywhere)
|
|
42
|
-
const asyncResult = await calcPriceAsync(usage, 'gpt-3.5-turbo', { providerId: 'openai' })
|
|
43
|
-
if (asyncResult) {
|
|
44
|
-
console.log(
|
|
45
|
-
`$${asyncResult.total_price} (input: $${asyncResult.input_price}, output: $${asyncResult.output_price})`,
|
|
46
|
-
asyncResult.provider.name,
|
|
47
|
-
asyncResult.model.name,
|
|
22
|
+
result.model.name
|
|
48
23
|
)
|
|
49
24
|
} else {
|
|
50
25
|
console.log('No price found for this model/provider combination')
|
|
51
26
|
}
|
|
52
27
|
```
|
|
53
28
|
|
|
54
|
-
###
|
|
55
|
-
|
|
56
|
-
```js
|
|
57
|
-
import { calcPriceSync, calcPriceAsync } from './dist/index.js'
|
|
58
|
-
const usage = { input_tokens: 1000, output_tokens: 100 }
|
|
59
|
-
const result = calcPriceSync(usage, 'gpt-3.5-turbo', { providerId: 'openai' })
|
|
60
|
-
if (result) {
|
|
61
|
-
console.log(
|
|
62
|
-
`$${result.total_price} (input: $${result.input_price}, output: $${result.output_price})`,
|
|
63
|
-
result.provider.name,
|
|
64
|
-
result.model.name,
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### Global CLI Installation
|
|
70
|
-
|
|
71
|
-
You can install the CLI globally to use the `genai-prices` command from anywhere:
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
npm install -g @pydantic/genai-prices
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
After installing globally, you can run:
|
|
29
|
+
### `updatePrices`
|
|
78
30
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
genai-prices list
|
|
82
|
-
```
|
|
31
|
+
You can optionally use `updatePrices` to implement logic that can periodically update the data used by `calcPrice`.
|
|
32
|
+
See the `src/examples/browser` directory for an example that implements a local storage-backed auto-update and `src/examples/node-script.ts` for an example of a file-based asynchronous auto-update implementation.
|
|
83
33
|
|
|
84
|
-
|
|
34
|
+
`calcPrice` is a synchronous function that uses the currently available data - either the bundled one, or the last data fetched from the `updatePrices` setup. To force `calcPrice` to await potential in-progress data updates that can happen in `enableAutoUpdate`, await the `waitForUpdate()` return value before calling `calcPrice`
|
|
85
35
|
|
|
86
|
-
|
|
36
|
+
```ts
|
|
37
|
+
import { calcPrice, updatePrices } from '@pydantic/genai-prices'
|
|
87
38
|
|
|
88
|
-
|
|
89
|
-
# Basic usage
|
|
90
|
-
genai-prices gpt-3.5-turbo --input-tokens 1000 --output-tokens 100
|
|
39
|
+
enableAutoUpdate(/** auto-update logic */)
|
|
91
40
|
|
|
92
|
-
|
|
93
|
-
genai-prices gpt-3.5-turbo --input-tokens 1000 --output-tokens 100 --auto-update
|
|
41
|
+
// ...
|
|
94
42
|
|
|
95
|
-
|
|
96
|
-
|
|
43
|
+
// this guarantees that the latest data is used
|
|
44
|
+
await waitForUpdate()
|
|
45
|
+
const result = calcPrice(usage, 'gpt-5', { providerId: 'openai' })
|
|
97
46
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
47
|
+
console.log(
|
|
48
|
+
`$${result.total_price} (input: $${result.input_price}, output: $${result.output_price})`,
|
|
49
|
+
result.provider.name,
|
|
50
|
+
result.model.name
|
|
51
|
+
)
|
|
101
52
|
```
|
|
102
53
|
|
|
103
54
|
### Provider Matching
|
|
@@ -105,7 +56,7 @@ genai-prices list openai
|
|
|
105
56
|
The library uses intelligent provider matching:
|
|
106
57
|
|
|
107
58
|
1. **Explicit provider**: Use `providerId` parameter or `provider:model` format
|
|
108
|
-
2. **Model-based matching**: Uses provider's `model_match` logic (e.g., OpenAI matches models starting with "gpt-")
|
|
59
|
+
2. **Model-based matching**: Uses the provider's `model_match` logic (e.g., OpenAI matches models starting with "gpt-")
|
|
109
60
|
3. **Fallback**: Tries to match based on model name patterns
|
|
110
61
|
|
|
111
62
|
**Best practices:**
|
|
@@ -116,15 +67,15 @@ The library uses intelligent provider matching:
|
|
|
116
67
|
|
|
117
68
|
### Error Handling
|
|
118
69
|
|
|
119
|
-
|
|
70
|
+
When a model or provider is not found, the library returns `null`. This makes it easier to handle cases where pricing information might not be available.
|
|
120
71
|
|
|
121
72
|
```js
|
|
122
|
-
import {
|
|
73
|
+
import { calcPrice } from '@pydantic/genai-prices'
|
|
123
74
|
|
|
124
75
|
const usage = { input_tokens: 1000, output_tokens: 100 }
|
|
125
76
|
|
|
126
77
|
// Returns null if model/provider not found
|
|
127
|
-
const result =
|
|
78
|
+
const result = calcPrice(usage, 'non-existent-model')
|
|
128
79
|
if (result === null) {
|
|
129
80
|
console.log('No pricing information available for this model')
|
|
130
81
|
} else {
|
|
@@ -132,63 +83,14 @@ if (result === null) {
|
|
|
132
83
|
}
|
|
133
84
|
|
|
134
85
|
// Async version also returns null
|
|
135
|
-
const asyncResult = await
|
|
86
|
+
const asyncResult = await calcPrice(usage, 'non-existent-model', { awaitAutoUpdate: true, providerId: 'unknown-provider' })
|
|
136
87
|
if (asyncResult === null) {
|
|
137
88
|
console.log('No pricing information available for this model/provider combination')
|
|
138
89
|
} else {
|
|
139
|
-
console.log(
|
|
140
|
-
`Total Price: $${asyncResult.total_price} (input: $${asyncResult.input_price}, output: $${asyncResult.output_price})`,
|
|
141
|
-
)
|
|
90
|
+
console.log(`Total Price: $${asyncResult.total_price} (input: $${asyncResult.input_price}, output: $${asyncResult.output_price})`)
|
|
142
91
|
}
|
|
143
92
|
```
|
|
144
93
|
|
|
145
|
-
**TypeScript users**: The return type is `PriceCalculation | null` (exported as `PriceCalculationResult`).
|
|
146
|
-
|
|
147
|
-
## Testing
|
|
148
|
-
|
|
149
|
-
### Node.js Test
|
|
150
|
-
|
|
151
|
-
Run:
|
|
152
|
-
|
|
153
|
-
```bash
|
|
154
|
-
node tests/test-error-handling.js
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
This tests error handling, sync/async API, and providerId usage.
|
|
158
|
-
|
|
159
|
-
### Browser Test
|
|
160
|
-
|
|
161
|
-
1. Build the package: `npm run build`
|
|
162
|
-
2. Serve the directory: `npx serve .` or `python3 -m http.server`
|
|
163
|
-
3. Open `tests/test-browser.html` in your browser.
|
|
164
|
-
4. Enter a provider (e.g., `openai`) and model (e.g., `gpt-3.5-turbo`) and run the test.
|
|
165
|
-
|
|
166
|
-
## Architecture
|
|
167
|
-
|
|
168
|
-
### Folder Structure
|
|
169
|
-
|
|
170
|
-
```
|
|
171
|
-
src/
|
|
172
|
-
├── sync/
|
|
173
|
-
│ └── calcPriceSync.ts # Sync API implementation
|
|
174
|
-
├── async/
|
|
175
|
-
│ └── calcPriceAsync.ts # Async API implementation
|
|
176
|
-
├── dataLoader.ts # Data loader (sync + async)
|
|
177
|
-
├── index.ts # Entry point (exports both sync + async)
|
|
178
|
-
├── cli.ts # CLI tool
|
|
179
|
-
├── types.ts # Shared types (snake_case, matches JSON)
|
|
180
|
-
├── matcher.ts # Shared matching logic
|
|
181
|
-
├── priceCalc.ts # Shared price calculation
|
|
182
|
-
└── __tests__/ # Tests
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
### Design Principles
|
|
186
|
-
|
|
187
|
-
- **Environment-agnostic APIs**: Sync/async is about API style, not environment
|
|
188
|
-
- **Single data loader**: Handles all environments with embedded data for sync and remote fetch for async
|
|
189
|
-
- **Cross-environment compatibility**: Both sync and async APIs can be used in Node.js, browser, Cloudflare, etc.
|
|
190
|
-
- **No mapping needed**: All types and data use snake_case, matching the JSON schema
|
|
191
|
-
|
|
192
94
|
## Troubleshooting
|
|
193
95
|
|
|
194
96
|
### Common Issues
|
|
@@ -198,26 +100,36 @@ src/
|
|
|
198
100
|
- Try using `provider:model` format in CLI
|
|
199
101
|
- Use `--auto-update` flag to fetch latest data
|
|
200
102
|
- Check that the model name is correct and supported by the provider
|
|
201
|
-
- **Build errors**: Ensure you have run the build and that your data is up to date.
|
|
202
103
|
|
|
203
|
-
|
|
104
|
+
## CLI
|
|
105
|
+
|
|
106
|
+
The easiest way to run the latest version of the package as a CLI tool is through npx:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npx @pydantic/genai-prices@latest
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
For example:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npx @pydantic/genai-prices@latest calc gpt-4 --input-tokens 1000 --output-tokens 500
|
|
116
|
+
npx @pydantic/genai-prices@latest list
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
You can also install it globally and then use the `genai-prices` command:
|
|
204
120
|
|
|
205
121
|
```bash
|
|
206
|
-
|
|
207
|
-
genai-prices gpt-3.5-turbo --auto-update
|
|
208
|
-
genai-prices claude-3-5-sonnet --auto-update
|
|
209
|
-
genai-prices gemini-1.5-pro --auto-update
|
|
210
|
-
|
|
211
|
-
# Explicit provider specification
|
|
212
|
-
genai-prices openai:gpt-3.5-turbo
|
|
213
|
-
genai-prices anthropic:claude-3-5-sonnet
|
|
214
|
-
genai-prices google:gemini-1.5-pro
|
|
122
|
+
npm i -g @pydantic/genai-prices
|
|
215
123
|
```
|
|
216
124
|
|
|
217
|
-
|
|
125
|
+
```bash
|
|
126
|
+
# Basic usage
|
|
127
|
+
genai-prices gpt-5 --input-tokens 1000 --output-tokens 100
|
|
128
|
+
|
|
129
|
+
# Specify provider explicitly
|
|
130
|
+
genai-prices openai:gpt-5 --input-tokens 1000 --output-tokens 100
|
|
218
131
|
|
|
219
|
-
|
|
220
|
-
-
|
|
221
|
-
-
|
|
222
|
-
|
|
223
|
-
- Provider matching logic is in `matcher.ts` and should be environment-agnostic
|
|
132
|
+
# List available providers and models
|
|
133
|
+
genai-prices list
|
|
134
|
+
genai-prices list openai
|
|
135
|
+
```
|