genaiprices

package module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 10 Imported by: 0

README

Maintainers — upstream sync via Dependabot. A Dependabot PR labelled upstream-release against upstream-watch/requirements.txt signals a new pydantic/genai-prices release. When handling it, refresh the bundled price data (prices/data.json, prices/data_slim.json and their schemas), checking whether prices/data.schema.json changed or upstream shipped bug fixes — if so, the Go implementation must be updated to match before merging.

GenAI Prices (Go)

Calculate prices for calling LLM inference APIs.

This is the Honeycomb fork of pydantic/genai-prices, reduced to the Go implementation plus the bundled price data it depends on. The Python and JavaScript/TypeScript packages that live upstream are not maintained here.

Features

  • Advanced logic for matching on model and provider IDs to maximise the chance of using the correct model
  • Support for historic prices and price changes, e.g. the prices for o3 before and after its price changed
  • Support for variable daily prices, e.g. deepseek off-peak pricing
  • Tiered pricing support for Gemini models where you pay a separate price for very large contexts

Usage

go get github.com/honeycombio/genai-prices
import genaiprices "github.com/honeycombio/genai-prices"

usage := genaiprices.Usage{InputTokens: 1000, OutputTokens: 100}

calc, err := genaiprices.CalcPrice(usage, "gpt-4o-mini",
    genaiprices.WithProviderID("openai"))
if err != nil {
    log.Fatal(err)
}

fmt.Printf("$%.6f (input $%.6f, output $%.6f) — %s / %s\n",
    calc.TotalPrice, calc.InputPrice, calc.OutputPrice,
    calc.Provider.Name, calc.Model.Name)

Provide WithProviderID (or WithProviderAPIURL) when you know the provider for the most reliable matching. See pkg.go.dev for the full API — custom/unpublished providers, extracting usage from a raw API response, and provenance constants (Name, DataSource, Version) for stamping telemetry.

Notes:

  • Prices use float64, matching the upstream pydantic/genai-prices JavaScript implementation.
  • Tiered pricing is threshold-based (cliff): crossing a tier applies that rate to all tokens of that bucket.
  • prices/data.json is generated — DO NOT edit it directly.

Price data

The bundled price catalog is kept in this repository so the Go package can embed it at compile time (//go:embed). The following files are available:

prices/data.json is embedded directly by the Go package (data_slim.json is not used).

These files are sourced from upstream pydantic/genai-prices; see the maintainer note above for how updates flow in via Dependabot.

⚠️ Warning: these prices will not be 100% accurate

This project is a best effort from Pydantic and the community to provide an indicative estimate of the price you might pay for calling an LLM.

The price data cannot be exactly correct because model providers do not provide exact price information for their APIs in a format which can be reliably processed.

If you get a bill you weren't expecting, don't blame us!

If you're a lawyer, please read the LICENSE under which this project is developed, hosted and distributed.

Thanks

This project would not be possible without upstream pydantic/genai-prices and the following existing data sources:

Thanks to all those projects!

Documentation

Overview

Package genaiprices calculates LLM inference API pricing from an embedded catalog of provider and model prices. It is a Go port of the Python and JavaScript genai-prices packages and shares their bundled data (prices/data.json).

Index

Constants

View Source
const DataSource = "pydantic/genai-prices"

DataSource identifies the upstream project the embedded price catalog (data.json) is synced from. The exact upstream data version last synced is tracked in upstream-watch/requirements.txt. See SYNCING.md.

View Source
const Name = "genai-prices"

Name identifies this library in telemetry that records cost-estimate provenance.

View Source
const Version = "0.0.2"

Version is the honeycombio/genai-prices release version. It tracks THIS library's releases, which are deliberately not 1:1 with upstream pydantic/genai-prices data syncs: we can ship engine changes without a data bump, or sync data without a code release. Bump it when cutting a release.

Variables

View Source
var (
	ErrProviderNotFound = errors.New("genaiprices: provider not found")
	ErrModelNotFound    = errors.New("genaiprices: model not found")
)

Sentinel errors returned by CalcPrice / FindProvider, matchable with errors.Is.

Functions

This section is empty.

Types

type ArrayMatch

type ArrayMatch struct {
	Type  string     `json:"type"`
	Field string     `json:"field"`
	Match MatchLogic `json:"match"`
}

ArrayMatch finds the first item in an array whose Field matches Match.

type ConditionalPrice

type ConditionalPrice struct {
	Constraint *Constraint `json:"constraint,omitempty"`
	Prices     ModelPrice  `json:"prices"`
}

ConditionalPrice pairs a set of prices with an optional constraint defining when those prices apply.

type Constraint

type Constraint struct {
	// Kind is either "start_date" or "time_of_date".
	Kind string

	// StartDate is set when Kind == "start_date".
	StartDate time.Time

	// StartTime / EndTime are "HH:MM:SS" UTC strings when Kind == "time_of_date".
	StartTime string
	EndTime   string
}

Constraint defines when a ConditionalPrice is active. The source data distinguishes the two kinds by which fields are present: a start_date marks a date constraint; start_time + end_time mark a daily time-of-day window.

func (*Constraint) UnmarshalJSON

func (c *Constraint) UnmarshalJSON(data []byte) error

type ExtractPath

type ExtractPath struct {
	Steps []PathStep
}

ExtractPath is a path into a decoded JSON response: a sequence of object keys (strings) and ArrayMatch steps. The source encodes it as either a single string or an array of strings/ArrayMatch objects.

func (*ExtractPath) UnmarshalJSON

func (e *ExtractPath) UnmarshalJSON(data []byte) error

type ExtractedUsage

type ExtractedUsage struct {
	Usage    Usage
	Model    *ModelInfo
	Provider *Provider
}

ExtractedUsage is the result of ExtractUsage.

func ExtractUsage

func ExtractUsage(provider *Provider, responseData any, opts ...Option) (*ExtractedUsage, error)

ExtractUsage extracts the model name and token usage from a decoded API response (a map[string]any / []any tree as produced by json.Unmarshal). Pass WithAPIFlavor to select a non-default extractor. The returned ExtractedUsage includes the matched ModelInfo when the model name resolves within the bundled catalog.

type MatchLogic

type MatchLogic struct {
	// contains filtered or unexported fields
}

MatchLogic is the recursive boolean logic used to match a string (a model or provider identifier). Exactly one clause kind is set per node.

func And

func And(clauses ...MatchLogic) MatchLogic

And matches when all child clauses match.

func Contains

func Contains(s string) MatchLogic

Contains matches text containing s (case-insensitive).

func EndsWith

func EndsWith(s string) MatchLogic

EndsWith matches text with suffix s (case-insensitive).

func Equals

func Equals(s string) MatchLogic

Equals matches text equal to s (case-insensitive).

func Or

func Or(clauses ...MatchLogic) MatchLogic

Or matches when any child clause matches.

func Regex

func Regex(s string) MatchLogic

Regex matches text against the regular expression s (case-sensitive).

func StartsWith

func StartsWith(s string) MatchLogic

StartsWith matches text with prefix s (case-insensitive).

func (*MatchLogic) IsMatch

func (m *MatchLogic) IsMatch(text string) bool

IsMatch reports whether text satisfies this match logic. All comparisons are case-insensitive except regex.

func (*MatchLogic) UnmarshalJSON

func (m *MatchLogic) UnmarshalJSON(data []byte) error

type ModelInfo

type ModelInfo struct {
	ID            string     `json:"id"`
	Match         MatchLogic `json:"match"`
	Name          string     `json:"name,omitempty"`
	Description   string     `json:"description,omitempty"`
	ContextWindow *int       `json:"context_window,omitempty"`
	PriceComments string     `json:"price_comments,omitempty"`
	Deprecated    bool       `json:"deprecated,omitempty"`

	// Prices is always normalized to a slice of conditional prices. A bare
	// ModelPrice object in the source data becomes a single entry with a nil
	// constraint. See getActiveModelPrice for how an active price is selected.
	Prices []ConditionalPrice `json:"prices"`
}

ModelInfo is a single model offered by a provider.

func (*ModelInfo) UnmarshalJSON

func (m *ModelInfo) UnmarshalJSON(data []byte) error

UnmarshalJSON normalizes the polymorphic `prices` field (either a single ModelPrice object or an array of ConditionalPrice) into a slice.

type ModelPrice

type ModelPrice struct {
	InputMTok          *Price   `json:"input_mtok,omitempty"`
	CacheWriteMTok     *Price   `json:"cache_write_mtok,omitempty"`
	CacheReadMTok      *Price   `json:"cache_read_mtok,omitempty"`
	OutputMTok         *Price   `json:"output_mtok,omitempty"`
	InputAudioMTok     *Price   `json:"input_audio_mtok,omitempty"`
	CacheAudioReadMTok *Price   `json:"cache_audio_read_mtok,omitempty"`
	OutputAudioMTok    *Price   `json:"output_audio_mtok,omitempty"`
	RequestsKCount     *float64 `json:"requests_kcount,omitempty"`
}

ModelPrice is the set of per-token (per million) prices for a model. A nil pointer field means that bucket is not priced, which the engine relies on.

type Option

type Option func(*resolveOptions)

Option configures CalcPrice, FindProvider and ExtractUsage.

func WithAPIFlavor

func WithAPIFlavor(flavor string) Option

WithAPIFlavor selects the extractor flavor for ExtractUsage (default "default").

func WithProvider

func WithProvider(p *Provider) Option

WithProvider uses the given provider (and only it) instead of the bundled catalog, allowing custom or not-yet-published models.

func WithProviderAPIURL

func WithProviderAPIURL(url string) Option

WithProviderAPIURL selects the provider whose api_pattern matches url.

func WithProviderID

func WithProviderID(id string) Option

WithProviderID selects the provider by its identifier (e.g. "openai"). The special id "litellm" enables "provider/model" prefix handling on the model reference.

func WithTimestamp

func WithTimestamp(t time.Time) Option

WithTimestamp sets the request time used to select conditional/time-of-day prices. Defaults to time.Now().

type PathStep

type PathStep struct {
	Key   string
	Array *ArrayMatch
}

PathStep is one step of an ExtractPath: either an object key or an ArrayMatch.

func (*PathStep) UnmarshalJSON

func (s *PathStep) UnmarshalJSON(data []byte) error

type Price

type Price struct {
	// Flat is the price per million tokens when Tiered is nil.
	Flat float64
	// Tiered, when non-nil, defines threshold (cliff) pricing.
	Tiered *TieredPrices
}

Price is a per-million-token price that is either a flat rate or tiered.

func (*Price) UnmarshalJSON

func (p *Price) UnmarshalJSON(data []byte) error

type PriceCalculation

type PriceCalculation struct {
	InputPrice  float64
	OutputPrice float64
	TotalPrice  float64
	Provider    *Provider
	Model       *ModelInfo
	ModelPrice  ModelPrice
}

PriceCalculation is the result of CalcPrice.

func CalcPrice

func CalcPrice(usage Usage, modelRef string, opts ...Option) (*PriceCalculation, error)

CalcPrice calculates the price for usage of modelRef. Provide WithProviderID or WithProviderAPIURL when known for the most reliable matching; otherwise the model reference is matched against each provider's model_match logic.

It returns ErrProviderNotFound or ErrModelNotFound (matchable with errors.Is) when no match exists.

type Provider

type Provider struct {
	ID                     string           `json:"id"`
	Name                   string           `json:"name"`
	APIPattern             string           `json:"api_pattern"`
	PricingURLs            []string         `json:"pricing_urls,omitempty"`
	Description            string           `json:"description,omitempty"`
	PriceComments          string           `json:"price_comments,omitempty"`
	ModelMatch             *MatchLogic      `json:"model_match,omitempty"`
	ProviderMatch          *MatchLogic      `json:"provider_match,omitempty"`
	Extractors             []UsageExtractor `json:"extractors,omitempty"`
	FallbackModelProviders []string         `json:"fallback_model_providers,omitempty"`
	Models                 []ModelInfo      `json:"models"`
}

Provider is an LLM inference provider together with its models and the logic used to match it and extract usage from its API responses.

func FindProvider

func FindProvider(opts ...Option) (*Provider, error)

FindProvider resolves a provider from the given options (WithProviderID, WithProviderAPIURL, or WithProvider). It returns ErrProviderNotFound if none match.

func Providers

func Providers() []Provider

Providers returns the bundled price catalog. The returned slice is shared; treat it as read-only.

type Tier

type Tier struct {
	Start int     `json:"start"`
	Price float64 `json:"price"`
}

Tier is a single price tier in TieredPrices.

type TieredPrices

type TieredPrices struct {
	Base  float64 `json:"base"`
	Tiers []Tier  `json:"tiers"`
}

TieredPrices is threshold-based (cliff) pricing: crossing a tier applies that tier's rate to ALL tokens.

func (*TieredPrices) UnmarshalJSON

func (t *TieredPrices) UnmarshalJSON(data []byte) error

type Usage

type Usage struct {
	InputTokens          int
	CacheWriteTokens     int
	CacheReadTokens      int
	OutputTokens         int
	InputAudioTokens     int
	CacheAudioReadTokens int
	OutputAudioTokens    int
}

Usage holds token counts for a single LLM call. All fields are optional; InputTokens should INCLUDE cached tokens.

type UsageExtractor

type UsageExtractor struct {
	APIFlavor string                  `json:"api_flavor"`
	Root      ExtractPath             `json:"root"`
	ModelPath ExtractPath             `json:"model_path"`
	Mappings  []UsageExtractorMapping `json:"mappings"`
}

UsageExtractor describes how to pull usage and the model name out of a provider API response for a given API flavor.

type UsageExtractorMapping

type UsageExtractorMapping struct {
	Path     ExtractPath `json:"path"`
	Dest     string      `json:"dest"`
	Required bool        `json:"required"`
}

UsageExtractorMapping maps a path in the response to a Usage field.

Directories

Path Synopsis
packages
go module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL