feat: price audio tokens beside input and output - #103
Merged
Conversation
models.dev quotes input_audio and output_audio in dollars per million tokens, in the same units as input and output. The parser filed both under ModelOperationPricing, whose AudioInput means a flat price for one audio input. A catalog built from that mapping claimed a $1.00 fee per audio file where a $1.00 per-million-token rate belongs. Add AudioInput and AudioOutput to ModelTokenPricing, map both from the source, and extend the pricing validation and the two deep copies. The per-operation prices stay: 12 deepinfra offerings do publish a flat audio price, and the two concepts now coexist. ModelTokenPricing.MarshalYAML is hand written, one branch per field, and the human workspace stores YAML. A new price that misses a branch would encode to JSON and vanish from YAML. The round-trip test walks the struct by reflection, so every future token price is covered when it is declared. Claude-Session: https://claude.ai/code/session_0131AtNgj1Qagv2csZGuxPFM
…ies reasoning Catalog generation aborts on one model: "reasoning controls and subordinate capabilities require reasoning support". Two authority policies disagree about an absent value. Features merges under EmptyAuthoritative, so a provider capability record wins even where it denies reasoning. Reasoning and ReasoningTokens merge under EmptyAbsent, so models.dev fills the gap that record left. The merged model then carries effort levels while declaring no reasoning support, and catalog validation rejects the pair. Drop the orphaned facts instead of inventing the support they need. The merger reads sources, and no source claimed that support. Claude-Session: https://claude.ai/code/session_0131AtNgj1Qagv2csZGuxPFM
The verification gate runs gomarkdoc in check mode over every package that carries a generate.go. The two audio price fields and the parser comment changes moved the generated output, so the gate failed on stale files. Claude-Session: https://claude.ai/code/session_0131AtNgj1Qagv2csZGuxPFM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
models.dev quotes
input_audioandoutput_audioin dollars per million tokens, in the same units asinputandoutput. The parser filed both underModelOperationPricing, whoseAudioInputmeans a flat price for one audio input. A catalog built from that mapping claimed a $1.00 fee per audio file where a $1.00 per-million-token rate belongs.What changed
ModelTokenPricinggainsAudioInputandAudioOutput, with matchingMarshalYAMLbranches.fix(reconciler): a second commit stops the merger from emitting a model that carries reasoning controls while declaring no reasoning support. Two authority policies disagree about an absent value, and the pair they produce makes catalog generation abort on one model.Per-operation audio prices stay. 12 deepinfra offerings do publish a flat audio price, so the two concepts now coexist rather than one overwriting the other.
Effect on the catalog
Regenerated locally against the vendored models.dev snapshot, isolated against the same regeneration run without this change:
tokens.audio_inputtokens.audio_outputThe source snapshot records
input_audioon 74 models andoutput_audioon 18, across 18 providers. Starmap tracks 12 of those providers.A three-way read of
google-ai-studio/gemini-2.5-flashshows the fact today is not merely misfiled but lost:operations.audio_input: 1.0(a flat fee)maintokens.audio_input.per_1m: 1.0No catalog regeneration is included here. The nightly Catalog Generation workflow owns that step: it runs with eight provider API keys, and a local run without them degrades provider-sourced facts to models.dev values.
Verification
go test ./...andgo vet ./...are clean under Go 1.25.12, the toolchain the PR gate pins.pkg/catalogs/artifact.TestBundleReproducibleFixtureHashesfails on Go 1.27 and passes on 1.25.12. The artifact is gzip-compressed, and the golden checksum tracks one compressor. This predates the branch — it reproduces identically atmain— and is noted rather than changed here.https://claude.ai/code/session_0131AtNgj1Qagv2csZGuxPFM