Package Exports
- @pydantic/genai-prices
Readme
genai-prices package (JS/TS)
Library and CLI for calculating LLM API prices, supporting browser, Node.js and other environments.
Features
- Sync API: Fast, local price calculation using embedded data. Works in browser, Node.js, Cloudflare, Deno, etc.
- Async API: Fetches and caches price data from GitHub, works in browser, Node.js, Cloudflare, Deno, etc.
- Environment-agnostic design: Sync/async distinction is about API style, not environment.
- Smart provider and model matching with flexible options.
- CLI for quick price calculations with auto-update support.
- Browser support with a single bundle and test page.
API Usage
Node.js & Browser (Library)
import { calcPriceSync, calcPriceAsync } from '@pydantic/genai-prices'
const usage = { input_tokens: 1000, output_tokens: 100 }
// Sync (works everywhere, including browser)
const result = calcPriceSync(usage, 'gpt-3.5-turbo', { providerId: 'openai' })
if (result) {
console.log(result.price, result.provider.name, result.model.name)
} else {
console.log('No price found for this model/provider combination')
}
// Async (works everywhere)
const asyncResult = await calcPriceAsync(usage, 'gpt-3.5-turbo', { providerId: 'openai' })
if (asyncResult) {
console.log(asyncResult.price, asyncResult.provider.name, asyncResult.model.name)
} else {
console.log('No price found for this model/provider combination')
}Browser (Direct Bundle)
import { calcPriceSync, calcPriceAsync } from './dist/index.js'
const usage = { input_tokens: 1000, output_tokens: 100 }
const result = calcPriceSync(usage, 'gpt-3.5-turbo', { providerId: 'openai' })
if (result) {
console.log(result.price, result.provider.name, result.model.name)
}Global CLI Installation
You can install the CLI globally to use the genai-prices command from anywhere:
npm install -g @pydantic/genai-pricesAfter installing globally, you can run:
genai-prices calc gpt-4 --input-tokens 1000 --output-tokens 500
genai-prices listCLI
After global installation, you can use the CLI as follows:
# Basic usage
genai-prices gpt-3.5-turbo --input-tokens 1000 --output-tokens 100
# With auto-update (fetches latest prices from GitHub)
genai-prices gpt-3.5-turbo --input-tokens 1000 --output-tokens 100 --auto-update
# Specify provider explicitly
genai-prices openai:gpt-3.5-turbo --input-tokens 1000 --output-tokens 100
# List available providers and models
genai-prices list
genai-prices list openaiProvider Matching
The library uses intelligent provider matching:
- Explicit provider: Use
providerIdparameter orprovider:modelformat - Model-based matching: Uses provider's
model_matchlogic (e.g., OpenAI matches models starting with "gpt-") - Fallback: Tries to match based on model name patterns
Best practices:
- Always specify
providerIdif you know it (e.g.,openai,google, etc.) for best results - Use
provider:modelformat in CLI for explicit provider selection - The async API with
--auto-updateprovides the most up-to-date pricing
Error Handling
The library returns null when a model or provider is not found, rather than throwing errors. This makes it easier to handle cases where pricing information might not be available:
import { calcPriceSync, calcPriceAsync } from '@pydantic/genai-prices'
const usage = { input_tokens: 1000, output_tokens: 100 }
// Returns null if model/provider not found
const result = calcPriceSync(usage, 'non-existent-model')
if (result === null) {
console.log('No pricing information available for this model')
} else {
console.log(`Price: $${result.price}`)
}
// Async version also returns null
const asyncResult = await calcPriceAsync(usage, 'non-existent-model', { providerId: 'unknown-provider' })
if (asyncResult === null) {
console.log('No pricing information available for this model/provider combination')
} else {
console.log(`Price: $${asyncResult.price}`)
}TypeScript users: The return type is PriceCalculation | null (exported as PriceCalculationResult).
Testing
Node.js Test
Run:
node tests/test-error-handling.jsThis tests error handling, sync/async API, and providerId usage.
Browser Test
- Build the package:
npm run build - Serve the directory:
npx serve .orpython3 -m http.server - Open
tests/test-browser.htmlin your browser. - Enter a provider (e.g.,
openai) and model (e.g.,gpt-3.5-turbo) and run the test.
Architecture
Folder Structure
src/
├── sync/
│ └── calcPriceSync.ts # Sync API implementation
├── async/
│ └── calcPriceAsync.ts # Async API implementation
├── dataLoader.ts # Data loader (sync + async)
├── index.ts # Entry point (exports both sync + async)
├── cli.ts # CLI tool
├── types.ts # Shared types (snake_case, matches JSON)
├── matcher.ts # Shared matching logic
├── priceCalc.ts # Shared price calculation
└── __tests__/ # TestsDesign Principles
- Environment-agnostic APIs: Sync/async is about API style, not environment
- Single data loader: Handles all environments with embedded data for sync and remote fetch for async
- Cross-environment compatibility: Both sync and async APIs can be used in Node.js, browser, Cloudflare, etc.
- No mapping needed: All types and data use snake_case, matching the JSON schema
Troubleshooting
Common Issues
- No price found (returns null):
- Make sure you specify the correct
providerId(e.g.,openai,google,anthropic) - Try using
provider:modelformat in CLI - Use
--auto-updateflag to fetch latest data - Check that the model name is correct and supported by the provider
- Make sure you specify the correct
- Build errors: Ensure you have run the build and that your data is up to date.
Provider Matching Examples
# These should work with auto-update
genai-prices gpt-3.5-turbo --auto-update
genai-prices claude-3-5-sonnet --auto-update
genai-prices gemini-1.5-pro --auto-update
# Explicit provider specification
genai-prices openai:gpt-3.5-turbo
genai-prices anthropic:claude-3-5-sonnet
genai-prices google:gemini-1.5-proMaintainers
- When adding new features, keep sync and async logic in separate files
- Only import Node.js built-ins in Node-only files if absolutely necessary
- Use the main entry for all environments
- All types and data should use snake_case to match the JSON schema
- Provider matching logic is in
matcher.tsand should be environment-agnostic