Conversation
An OpenTelemetry GenAI source reports one input number for every provider: the semantic conventions define `gen_ai.usage.input_tokens` as the whole input, cached tokens included. The catalog instead records each entry's own convention, because Anthropic reports the uncached remainder while OpenAI reports the total. Pricing an inclusive count against an entry that expects the remainder bills every cached token twice, once at the input rate and again at the cache rate. `cost()` and `price_deployment()` take `input_includes_cache`. When set, the uncached remainder is billed at the input rate and the entry's own rules are not applied a second time, while the long-context size tier is still judged on the whole prompt the provider processed. A total smaller than its own cache counts cannot include them, so it is billed as uncached input and says so with `cache_exceeds_input_total`. The option is opt-in and off by default, so every existing caller prices exactly as before. Ships as metergraph-core 0.2.24. The catalog data is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DkYVigksoSN9N7coWLgmvS
`load_catalog().price` is the public entry point, and it rejected the new keyword rather than passing it to `price_deployment`, so a caller that went through the wrapper got a TypeError and the mode was unreachable there. Found in Codex review of this branch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DkYVigksoSN9N7coWLgmvS
Collaborator
Author
|
Codex reviewed this branch and found one real gap, now fixed in 2817422. [P1] Fixed, with a test that uses the wrapper and asserts an inclusive count prices the same as the equivalent native usage ($0.09178625) and strictly less than pricing the same total as uncached input. The test fails with the one-line forward reverted ( No other findings from the review. |
This branch has not been deployed
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.
Unblocks a fix in
metergraph-internalfor MET-61.Problem
The OTel GenAI semantic conventions define
gen_ai.usage.input_tokensas the whole input, cached tokens included: "This value SHOULD include all types of input tokens, including cached tokens." Every OTLP source reports that one shape, whatever the provider.The catalog records the opposite thing: each entry's own convention, because Anthropic's usage reports the uncached remainder and OpenAI's reports the total. Pricing an inclusive count against an Anthropic entry bills every cached token twice, at the input rate and again at the cache rate. A customer's LiteLLM span (148,661 input including 148,290 cache reads and 369 cache writes, claude-opus-4-8) cost $0.835 instead of $0.092.
metergraph-internal #454 works around this by re-basing the count before calling
cost(), but it can only pass one number, which_price_tokensuses both for billing and for the long-context size tier. So a prompt that is over the threshold only because of cached tokens now misses the premium. Ongemini-2.5-prowith 200,001 input including 50,000 cache reads and 1,000 output, it bills $0.213 where $0.421 is correct. That workaround is live in production today.Change
cost()andprice_deployment()takeinput_includes_cache(defaultFalse, so every existing caller prices exactly as before). When set:input_includes_cache_read/input_includes_cache_writerules are not applied a second time;cache_exceeds_input_total.The catalog data is unchanged. Ships as 0.2.24.
Verification
pytest core/tests -q: 235 passed (230 before, 5 new).catalog.pychange reverted, so they detect the feature being absent:cache_exceeds_input_total;gpt-5.6-luna) prices the same either way, so the cache is never deducted twice;price_deploymentis unchanged unless the option is set.python core/tests/package/verify_artifacts.py: OK for 0.2.24.After this merges
metergraph-internal drops its probe in
worker/main.py_catalog_input_tokens, pinsmetergraph-core>=0.2.24, and passes the option straight through, which also fixes the long-context underbilling above.🤖 Generated with Claude Code
https://claude.ai/code/session_01DkYVigksoSN9N7coWLgmvS