Pricing lookup + cost estimation, layered on llm.sdk.registry.
Data flow: (sdk/estimate-cost ...) ─► estimate-cost-for-model │ ▼ registry/lookup ─► merged ModelEntry - override tier (pricing from cost map) - live /models tier - models.dev tier (including bundled snapshot)
The hardcoded pricing snapshot that previously lived here folded into the bundled models.dev snapshot at resources/models-dev-snapshot.json (every former entry verified present with current pricing). Callers who need to inject custom pricing should use llm.sdk.registry/register-entry!, which bypasses the public registries.
The PricingEntry record shape is preserved for callers who already consume it — internally we convert ModelEntry's :model/cost map back to this shape at lookup time.
Pricing lookup + cost estimation, layered on llm.sdk.registry.
Data flow:
(sdk/estimate-cost ...) ─► estimate-cost-for-model
│
▼
registry/lookup ─► merged ModelEntry
- override tier (pricing from cost map)
- live /models tier
- models.dev tier (including bundled snapshot)
The hardcoded pricing snapshot that previously lived here folded into
the bundled models.dev snapshot at resources/models-dev-snapshot.json
(every former entry verified present with current pricing). Callers
who need to inject custom pricing should use
llm.sdk.registry/register-entry!, which bypasses the public registries.
The PricingEntry record shape is preserved for callers who already
consume it — internally we convert ModelEntry's :model/cost map back
to this shape at lookup time.(canonical-cache usage)Build a canonical :response/cache map from a usage map.
Status is :hit when the provider reported a positive cached-input-tokens count, :miss when it explicitly reported 0, and :unknown when the provider did not report cache stats at all.
The usage normalizers omit :usage/cached-input-tokens when the raw provider payload had no cache field — that absence is how :unknown propagates here.
Build a canonical :response/cache map from a usage map. Status is :hit when the provider reported a positive cached-input-tokens count, :miss when it explicitly reported 0, and :unknown when the provider did not report cache stats at all. The usage normalizers omit :usage/cached-input-tokens when the raw provider payload had no cache field — that absence is how :unknown propagates here.
(canonical-cost provider model usage)(canonical-cost provider model usage context)Build a canonical :response/cost map for (provider, model, usage). Returns nil when usage is nil. Optional context identifies an endpoint's guaranteed input/output modalities when provider detail is absent.
Build a canonical :response/cost map for (provider, model, usage). Returns nil when usage is nil. Optional context identifies an endpoint's guaranteed input/output modalities when provider detail is absent.
(cost-result->canonical result pricing breakdown)Convert a modality-specific cost-result into the public :response/cost shape. Used by non-chat drivers whose cost is based on image count, audio duration, or synthesized characters instead of chat token usage.
Convert a modality-specific cost-result into the public :response/cost shape. Used by non-chat drivers whose cost is based on image count, audio duration, or synthesized characters instead of chat token usage.
(embedding-cost usage pricing)Cost for a text embedding call. Embeddings only meter input tokens.
Cost for a text embedding call. Embeddings only meter input tokens.
(estimate-cost usage pricing)(estimate-cost usage pricing context)Compute cost from canonical Usage and a pricing-entry. Returns a cost-result map. Pure — no registry lookup. The optional context identifies endpoint-guaranteed input/output modalities when raw usage omits a split.
Compute cost from canonical Usage and a pricing-entry. Returns a cost-result map. Pure — no registry lookup. The optional context identifies endpoint-guaranteed input/output modalities when raw usage omits a split.
(estimate-cost-for-model provider model usage)Look up pricing through the registry and estimate cost for the given usage. Returns a cost-result. Works for any provider+model the merged registry knows — no manual registration required.
When the provider profile carries a :profile/cost-calculator fn, it is called with {:provider :model :usage :pricing} and must return a cost-result map. This is the escape hatch for providers whose pricing doesn't fit the default per-million-token formula (Perplexity's citation-token surcharge is the canonical example).
Look up pricing through the registry and estimate cost for the given
usage. Returns a cost-result. Works for any provider+model the
merged registry knows — no manual registration required.
When the provider profile carries a :profile/cost-calculator fn, it
is called with {:provider :model :usage :pricing} and must return a
cost-result map. This is the escape hatch for providers whose pricing
doesn't fit the default per-million-token formula (Perplexity's
citation-token surcharge is the canonical example).(estimate-openrouter-cost provider model usage)Estimate cost using OpenRouter billing-route pricing. Does not refresh live data by itself; call fetch-openrouter-pricing! when freshness matters.
Estimate cost using OpenRouter billing-route pricing. Does not refresh live data by itself; call fetch-openrouter-pricing! when freshness matters.
(fetch-openrouter-pricing!)Refresh OpenRouter's live /models catalog. This populates registry live entries under provider :openrouter, including pricing from https://openrouter.ai/api/v1/models. Returns the number of entries fetched, or 0 on failure.
Refresh OpenRouter's live /models catalog. This populates registry live entries under provider :openrouter, including pricing from https://openrouter.ai/api/v1/models. Returns the number of entries fetched, or 0 on failure.
(fetch-pricing! billing-route & {:keys [_api-key]})Refresh pricing for a billing-route by hitting the provider's live /models endpoint via registry/refresh!. Returns the number of entries fetched, or 0 when the provider lacks /models support.
Refresh pricing for a billing-route by hitting the provider's live /models endpoint via registry/refresh!. Returns the number of entries fetched, or 0 when the provider lacks /models support.
(get-openrouter-pricing provider model)Get OpenRouter billing-route pricing for provider/model.
Unlike get-pricing, this deliberately looks under provider :openrouter. Use it when the actual call is routed through OpenRouter or when comparing OpenRouter pricing against direct-provider pricing. Call fetch-openrouter-pricing! first when fresh live data is required.
Get OpenRouter billing-route pricing for provider/model. Unlike get-pricing, this deliberately looks under provider :openrouter. Use it when the actual call is routed through OpenRouter or when comparing OpenRouter pricing against direct-provider pricing. Call fetch-openrouter-pricing! first when fresh live data is required.
(get-pricing provider model)Get the pricing-entry for (provider, model), or nil when no tier of the registry has cost data for the pair. The small official fallback supplements, but never hides, non-nil catalog rates.
Get the pricing-entry for (provider, model), or nil when no tier of the registry has cost data for the pair. The small official fallback supplements, but never hides, non-nil catalog rates.
(image-cost {:keys [usage n-images width height]} pricing)Cost for an image-generation call. Token-metered endpoints use their known text-input/image-output context, while flat-rate endpoints may bill per image or per megapixel.
Cost for an image-generation call. Token-metered endpoints use their known text-input/image-output context, while flat-rate endpoints may bill per image or per megapixel.
(openrouter-model-id provider model)Return the OpenRouter model id for a provider/model pair. If model already contains a slash, it is treated as an OpenRouter id.
Return the OpenRouter model id for a provider/model pair. If model already contains a slash, it is treated as an OpenRouter id.
Best-effort mapping from SDK provider ids to OpenRouter model id prefixes.
This is intentionally conservative. OpenRouter pricing is billing-route pricing for OpenRouter, not proof of the direct provider's current direct API price. Callers can always pass the full OpenRouter model id (for example, "openai/gpt-4o") to avoid inference.
Best-effort mapping from SDK provider ids to OpenRouter model id prefixes. This is intentionally conservative. OpenRouter pricing is billing-route pricing for OpenRouter, not proof of the direct provider's current direct API price. Callers can always pass the full OpenRouter model id (for example, "openai/gpt-4o") to avoid inference.
(pricing-entry
&
{:keys [input output cache-read cache-write request-cost image-input
image-output audio-input audio-output image-cache-read
audio-cache-read image-per-image image-per-megapixel
transcription-per-minute tts-per-million-chars search-per-call
rerank-per-search-unit source source-url pricing-version]})Construct a pricing entry. Token costs are per-million-tokens in USD. Modality-specific token rates are kept distinct from text rates; callers must not substitute one for another.
Per-unit knobs: :image-per-image dollars per image returned :image-per-megapixel dollars per megapixel produced :transcription-per-minute dollars per minute of audio in :tts-per-million-chars dollars per 1M output characters :search-per-call dollars per search query (Perplexity) :rerank-per-search-unit dollars per billed rerank search unit
Construct a pricing entry. Token costs are per-million-tokens in USD. Modality-specific token rates are kept distinct from text rates; callers must not substitute one for another. Per-unit knobs: :image-per-image dollars per image returned :image-per-megapixel dollars per megapixel produced :transcription-per-minute dollars per minute of audio in :tts-per-million-chars dollars per 1M output characters :search-per-call dollars per search query (Perplexity) :rerank-per-search-unit dollars per billed rerank search unit
(register-pricing provider model entry)Register a caller-provided pricing entry as a registry override. Internally converts to ModelEntry shape and pushes into the override tier. The entry argument can be a legacy pricing-entry map, OR a map with :input/:output/:cache-read/:cache-write/:request-cost shorthand.
Register a caller-provided pricing entry as a registry override. Internally converts to ModelEntry shape and pushes into the override tier. The entry argument can be a legacy pricing-entry map, OR a map with :input/:output/:cache-read/:cache-write/:request-cost shorthand.
(rerank-cost usage pricing)Cost for reranking. Provider-reported search units are an explicit billing dimension and are never substituted with request or query counts.
Cost for reranking. Provider-reported search units are an explicit billing dimension and are never substituted with request or query counts.
(resolve-billing-route model & {:keys [provider base-url]})Determine billing route metadata from model name, provider, and an optional base-url. Pure data — not a pricing lookup.
Determine billing route metadata from model name, provider, and an optional base-url. Pure data — not a pricing lookup.
(stamp-response-cost-and-cache response provider-id model)Preserve an existing response cost, estimating from usage only when absent. Cache information is derived from usage. Pure transform — does not touch the wire. Missing usage leaves an absent cost absent and stamps unknown cache information.
Preserve an existing response cost, estimating from usage only when absent. Cache information is derived from usage. Pure transform — does not touch the wire. Missing usage leaves an absent cost absent and stamps unknown cache information.
(transcription-cost {:keys [usage duration-seconds]} pricing)Cost for speech-to-text. Token-billed responses use audio-input/text-output rates. Duration-billed responses use reported seconds and a per-minute rate.
Cost for speech-to-text. Token-billed responses use audio-input/text-output rates. Duration-billed responses use reported seconds and a per-minute rate.
(tts-cost {:keys [characters]} pricing)Cost for a text-to-speech call. Most TTS providers (OpenAI, ElevenLabs) price per million output characters.
Cost for a text-to-speech call. Most TTS providers (OpenAI, ElevenLabs) price per million output characters.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |