mrkeyoor.com_
Sat 19 Sept 21:41 UTC
PyPIAI / MLupdated 19 Sept 2026

genai-prices review

genai-prices 0.1.4 estimates the cost of inference calls from reported usage and a model reference. Its bundled database accounts for provider-specific model IDs, dated price changes, cache reads and writes, long-context tiers, and time-dependent rates. extract_usage can turn several provider response shapes into the library's Usage model, while calc_price returns the matched provider, model, and price breakdown. Version 0.1.4 accepts fractional usage such as audio seconds, adds GLM-5.3 prices for Z.AI and OpenRouter, and adds GPT-5.6 pricing for AWS Bedrock. The maintainers explicitly say these estimates are not guaranteed to match a bill.

Verdict

genai-prices 0.1.4 installed in 0.6 seconds, occupied 11 MB, and imported in 0.63 seconds in our sandbox with 0 audit findings. Use it for estimates and comparisons where matched-model details are retained; do not use its self-described approximate data for invoices or bill reconciliation.

We installed it

Lab card: what happened when we installed genai-pricesScreenshot of genai-prices documentation
Install✓ · 0.6s12 packages on disk · 11 MB
Importimport genai_prices in 0.63s · pure Python · py.typed · requires Python >=3.10
Known vulns0(pip-audit)

Answers from our run

Does genai-prices install cleanly?

Yes. In a fresh container with an empty cache, pip install genai-prices finished in 0.6s, leaving 12 packages and 11 MB on disk. pip-audit reported no known vulnerabilities.

What does genai-prices need to run?

Python >=3.10, and nothing compiled: it is pure Python. In our run import genai_prices succeeded in 0.63s, and the package ships py.typed for type checkers.

genai-prices or litellm: which should you use?

litellm: Use it when routing model calls and calculating their cost should happen in the same gateway layer. genai-prices 0.1.4 installed in 0.6 seconds, occupied 11 MB, and imported in 0.63 seconds in our sandbox with 0 audit findings.

When should you not use genai-prices?

The number will drive an invoice, customer credit, or financial reconciliation. The project warns that provider pricing cannot be processed with complete accuracy.

API stability2/5The package is at 0.1.4 and has already frozen its v1 data files in favor of a v2 schema. Core names such as Usage, calc_price, extract_usage, and UpdatePrices are documented, but new billing units and provider response shapes can change validation and matching behavior. Version 0.1.4 extends every reportable unit from integer-only assumptions to finite non-negative fractional values, a useful change that can still alter downstream types and serialization.
Docs3/5The Python README covers installation, cache token accounting, provider response extraction, both UpdatePrices lifecycles, sync and async waiting, CLI flags, and version 0.1.4 fractional-number semantics with Decimal examples. It also states the accuracy limit plainly. There is no generated API reference yet; maintainers direct readers to source code, so edge cases around matching, exceptions, and supported response shapes take more work to confirm.
Maintenance5/5Version 0.1.4 shipped on August 19, 2026, and the repository was pushed on August 25. The unarchived project has 356 stars and GitHub reports 78 open issues and pull requests. Releases 0.1.1 through 0.1.4 landed within 19 days, carrying provider corrections, new models, fractional usage, lockfile work, and price-history fixes. That pace suits volatile pricing data, though consumers should expect frequent upgrades.
Ecosystem4/5PyPIStats recorded 5,897,697 downloads in the latest week. The repository publishes Python and JavaScript clients plus raw v2 JSON and schemas, and its data feeds tools in the Pydantic stack. The README lists 34 provider families, including OpenAI, Anthropic, AWS Bedrock, Azure, Google, OpenRouter, and several hosted Hugging Face backends. Coverage is broad, but model aliases and provider billing rules still require project-specific checks.

Use it if

  • An internal dashboard needs comparable estimated LLM costs across several providers.
  • Provider response payloads need normalization before cache, input, output, or duration rates can be applied.
  • Historic or tiered prices matter when recalculating older usage records.
  • Engineers want a CLI for quick model comparisons alongside a typed Python API.
Skip it if

Setup reality

We installed genai-prices 0.1.4 in 0.6 seconds in a fresh Python 3.12 container. Twelve packages used 11 MB on disk, and pip-audit found 0 known vulnerabilities. The pure-Python package has 5 direct dependencies, requires Python 3.10 or newer, and includes py.typed. import genai_prices completed successfully in 0.63 seconds.

The default install exposes the calculation API. Rich terminal tables and help need the cli extra, which adds pydantic-settings, Rich, and rich-argparse. No provider credentials are required because the package consumes usage records rather than calling model APIs. Pass provider_id whenever it is known; model matching can otherwise select a plausible model from another provider. Log the matched provider and model beside each estimate.

Bundled data stays at the package release snapshot. UpdatePrices is opt-in and downloads the v2 data file from GitHub immediately, then every hour. Only one updater may run in a process. start(wait=True) blocks until the first refresh, while the context-manager form needs an explicit wait() if initial requests must avoid bundled data. A locked-down service must allow raw.githubusercontent.com or accept stale prices until the next release.

Version 0.1.4 permits finite non-negative int, float, or Decimal usage values. Cache-read and cache-write tokens are subsets of total input_tokens, so their sum cannot exceed that total. Float arithmetic uses the shortest round-trippable decimal representation; use Decimal before values lose precision when fractional billing units matter. Decimal values also need custom handling before standard JSON serialization.

Patterns

Price input and output tokens calculate-token-price

from genai_prices import Usage, calc_price

price = calc_price(
    Usage(input_tokens=1_000, output_tokens=100),
    model_ref='gpt-4o',
    provider_id='openai',
)
print(price.input_price, price.output_price, price.total_price)

provider_id narrows model matching. Save price.provider and price.model with the total so a surprising match can be audited.

Include cache reads and writes price-cached-input

usage = Usage(
    input_tokens=4_740,
    cache_read_tokens=0,
    cache_write_tokens=4_735,
    output_tokens=255,
)
price = calc_price(usage, 'claude-sonnet-4-20250514', provider_id='anthropic')

input_tokens is the full input count. Cache reads and writes are partitions of that total and cannot add up to more than it.

Preserve fractional duration with Decimal record-fractional-usage

from decimal import Decimal
from genai_prices import Usage

usage = Usage(audio_seconds=Decimal('0.1')) + Usage(audio_seconds=0.2)
assert usage.audio_seconds == Decimal('0.3')

Version 0.1.4 preserves Decimal when any operand is Decimal. Standard json.dumps still needs a conversion rule for that value.

Parse an Anthropic response extract-anthropic-usage

from genai_prices import extract_usage

payload = {
    'model': 'claude-sonnet-4-20250514',
    'usage': {
        'input_tokens': 504,
        'cache_creation_input_tokens': 123,
        'cache_read_input_tokens': 0,
        'output_tokens': 97,
    },
}
price = extract_usage(payload, provider_id='anthropic').calc_price()

The extractor maps Anthropic's cache creation and cache read fields, which have rates distinct from uncached input.

Parse an OpenAI chat response extract-openai-chat-usage

payload = {
    'model': 'gpt-5',
    'usage': {'prompt_tokens': 100, 'completion_tokens': 200},
}
extracted = extract_usage(payload, provider_id='openai', api_flavor='chat')
print(extracted.calc_price().total_price)

api_flavor='chat' selects chat-completions field names. The Responses API uses a different payload shape.

Refresh prices inside a context refresh-with-context

from genai_prices import UpdatePrices, Usage, calc_price

with UpdatePrices() as updater:
    updater.wait()
    price = calc_price(Usage(input_tokens=123, output_tokens=456), 'gpt-5')

wait() blocks for the first GitHub download. Without it, early calculations can use the data bundled in version 0.1.4.

Run the updater for a service lifetime refresh-in-service

updater = UpdatePrices()
updater.start(wait=True)
try:
    serve_requests()
finally:
    updater.stop()

Only one UpdatePrices instance may run in a process. stop() ends its background thread during shutdown.

Wait for a shared updater asynchronously await-price-refresh

from genai_prices import wait_prices_updated_async

await wait_prices_updated_async()
result = calculate_current_batch()

This waits for the process-wide updater when the caller does not own its instance; some code still has to start UpdatePrices first.

Compare models from the shell compare-models-cli

uvx genai-prices calc --input-tokens 100000 --output-tokens 3000 o1 o3 claude-opus-4

uvx supplies the command in an isolated environment. A local pip install needs genai-prices[cli] for Rich output.

Inspect known providers and models list-models-cli

uvx genai-prices list --plain

Use the listed identifiers when fuzzy matching picks an unexpected provider or model. The plain flag avoids colored table output.

Store the selected price record audit-matched-model

price = calc_price(usage, model_ref=model_name, provider_id=provider)
record = {
    'estimated_total': str(price.total_price),
    'matched_provider': price.provider.name,
    'matched_model': price.model.name,
}

The returned match is part of the estimate. Persist it with usage so later price-data changes do not hide what was selected.

Read the current raw price database download-v2-data

import httpx

url = 'https://raw.githubusercontent.com/pydantic/genai-prices/refs/heads/main/prices/new_data/v2/data.json'
data = httpx.get(url, timeout=10).raise_for_status().json()

The v2 file is current. The older prices/data.json files are frozen and no longer receive provider or model updates.

Alternatives

PackageRegistryPick it when
litellmPyPIUse it when routing model calls and calculating their cost should happen in the same gateway layer.
tokencostPyPIUse it for a smaller prompt-and-completion calculator without this project's historic and fractional-unit model.
tiktokenPyPIUse it to count supported model tokens before a request instead of pricing provider-reported usage afterward.

More ai / ml guides

openai · mcp · huggingface-hub · @modelcontextprotocol/sdk · scikit-learn · tiktoken · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.