fix(cost): apply Together AI cache read pricing and per-model registry rates - #38280
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Greptile SummaryThe PR corrects Together AI cost accounting for cached input tokens and registry-priced models.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| litellm/cost_calculator.py | Selects Together registry pricing before falling back to parameter-size buckets; the previously flagged redundant comments have been removed. |
| litellm/llms/together_ai/cost_calculator.py | Adds a helper that detects whether a Together model has registry input pricing. |
| model_prices_and_context_window.json | Updates Qwen3.7-Max input, output, and cached-input rates. |
| litellm/model_prices_and_context_window_backup.json | Keeps the backup pricing registry synchronized with the primary registry. |
| tests/test_litellm/test_cost_calculator.py | Adds regression coverage for cached-token pricing and registry-versus-bucket selection. |
| tests/test_litellm/test_together_ai_model_metadata.py | Verifies Together cache metadata and representative model rates. |
Reviews (4): Last reviewed commit: "Merge remote-tracking branch 'origin/lit..." | Re-trigger Greptile
|
bugbot run |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Registry skip zeros unpriced models
- has_together_registry_entry now only reports True when the registry row carries input_cost_per_token, output_cost_per_token, or tiered_pricing, so metadata-only Together rows still fall through to the size-bucket rewrite.
Or push these changes by commenting:
@cursor push 68d624d752
Preview (68d624d752)
diff --git a/litellm/llms/together_ai/cost_calculator.py b/litellm/llms/together_ai/cost_calculator.py
--- a/litellm/llms/together_ai/cost_calculator.py
+++ b/litellm/llms/together_ai/cost_calculator.py
@@ -19,9 +19,13 @@
from litellm.types.utils import CallTypes
+_PRICING_KEYS: Final = ("input_cost_per_token", "output_cost_per_token", "tiered_pricing")
+
+
def has_together_registry_entry(model: str, cost_map: Mapping[str, object]) -> bool:
stripped: Final = model.removeprefix("together_ai/")
- return f"together_ai/{stripped}" in cost_map
+ entry: Final = cost_map.get(f"together_ai/{stripped}")
+ return isinstance(entry, Mapping) and any(entry.get(key) is not None for key in _PRICING_KEYS)
# Extract the number of billion parameters from the model name
diff --git a/tests/test_litellm/test_cost_calculator.py b/tests/test_litellm/test_cost_calculator.py
--- a/tests/test_litellm/test_cost_calculator.py
+++ b/tests/test_litellm/test_cost_calculator.py
@@ -3838,3 +3838,19 @@
)
assert cost == pytest.approx((23 + 15) * 9e-07, rel=1e-9)
+
+
+def test_completion_cost_together_metadata_only_registry_row_falls_back_to_size_bucket(_local_model_cost_map):
+ """Regression: Together registry rows that only carry capability metadata (no
+ input_cost_per_token/output_cost_per_token/tiered_pricing) must not short-circuit the
+ size-bucket rewrite. Otherwise models like togethercomputer/CodeLlama-34b-Instruct
+ resolve to $0 spend instead of the 21.1b-41b bucket rate."""
+
+ cost = completion_cost(
+ completion_response=_together_chat_response(
+ model="togethercomputer/CodeLlama-34b-Instruct", prompt_tokens=23, completion_tokens=15, cached_tokens=0
+ ),
+ custom_llm_provider="together_ai",
+ )
+
+ assert cost == pytest.approx((23 + 15) * 8e-07, rel=1e-9)You can send follow-ups to the cloud agent here.
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit abe9af6. Configure here.
…itellm_together_cache_pricing # Conflicts: # litellm/model_prices_and_context_window_backup.json # model_prices_and_context_window.json # tests/test_litellm/test_cost_calculator.py
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit dbadee7. Configure here.

TLDR
Problem this solves:
Muse-Glimmer-30B, 33 models in the registry) were still priced by the size bucket, so their registry rates were ignored and cached tokens were billed at $0How it solves it:
User Flow
Before: a registry-mapped Together model with a size in its name bills the size bucket, so recorded spend ignores its registry rates and bills cache hits at $0
together_ai/meta-models/Muse-Glimmer-30Band a ~13k token prompt; the response header showsx-litellm-response-cost: 0.0106976for 13356 prompt and 16 completion tokens, which is 13372 x $0.80/M (the 21.1B-41B bucket) against Together's $0.35/M input and $1.50/M outputprompt_tokens_details.cached_tokens: 13344x-litellm-response-cost: 0.0000224: the 12 uncached prompt tokens and the output at the bucket rate, the 13344 cached tokens at $0 while Together invoices them at $0.04/MAfter: the same requests bill Together's registry rates, cache hits included
together_ai/meta-models/Muse-Glimmer-30Band a ~13k token prompt; the response header showsx-litellm-response-cost: 0.0045726for 12996 prompt and 16 completion tokens (12996 x $0.35/M + 16 x $1.50/M)prompt_tokens_details.cached_tokens: 12992x-litellm-response-cost: 0.00054508: 4 uncached tokens at $0.35/M, 12992 cached tokens at $0.04/M, and 16 output tokens at $1.50/MRelevant issues
Linear ticket
Resolves LIT-5972
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*,make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more@greptileaito re-request a review after pushing changes)Delays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
Screenshots / Proof of Fix
Live proxy against the real Together API, one leg per commit: Before at 67c7b97 (the current merge base with litellm_internal_staging), After at dbadee7 (the PR tip). Each leg boots one proxy process with
--num_workers 2on its own random port withLITELLM_LOCAL_MODEL_COST_MAP=Trueand this config:Every payload carries a ~13k token system corpus plus a one-line user question (
max_tokens: 16), salted per leg and per endpoint so each leg starts with a cold Together cache. The chat completions pair sends the same request twice: the first warms the cache, the identical second hits it. Together's published Muse-Glimmer-30B rates: input $0.35/M, cached input $0.04/M, output $1.50/M; the 21.1B-41B size bucket is $0.80/M in and out with no cache read price. Each line below is one request: thex-litellm-response-costheader followed by the response's usage blockBefore (67c7b97, port 48430)
Muse-Glimmer-30B bills the bucket on all three routes: chat1 is 13372 x $0.80/M, responses and messages are 13012 x $0.80/M, and chat2 bills its 13344 cached tokens at $0 (12 x $0.80/M + 16 x $0.80/M = $0.0000224). The
x-litellm-response-cost-cache-readheader is absent on chat2. DeepSeek-V4-Flash-0731 already bills registry rates and cache reads at this base (ds2 = 1 x $0.14/M + 13692 x $0.03/M + 16 x $0.28/M) because staging carries its cache price since 4456a44; its name has no size marker, so the bucket never applied to itAfter (dbadee7, port 42191)
Muse-Glimmer-30B now bills the registry: chat1 is 12996 x $0.35/M + 16 x $1.50/M, chat2 bills 4 uncached tokens at $0.35/M, 12992 cached tokens at $0.04/M ($0.00051968 in the cache-read header) and 16 output tokens at $1.50/M, and responses is 13716 x $0.35/M + 16 x $1.50/M. DeepSeek is unchanged between the legs, as expected. The
/v1/messagesheader still reads the bucket at the tip: that route prices the deployment by its aliasmuse-glimmer-30b, whose30btrips the bucket fallback before the registry lookup runs (#38578, pre-existing and identical on the Before leg, see Caveats)Type
🐛 Bug Fix
Caveats (if any)
Medium
/v1/messagesthe response-cost header prices a Together deployment by its alias, so an alias carrying a size marker (muse-glimmer-30b) still bills the size bucket on that route, unchanged from before this PR;/v1/chat/completionsand/v1/responsesbill the registry. The alias is not a registry name, so the gate here cannot fix it; tracked as [Bug]: /v1/messages prices Together deployments by their alias, so a size marker in the alias bills the size bucket #38578 for the messages route's cost pathLow
Final Attestation
The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR
abe9af6 passes /live-pr-risk
dbadee7 passes /live-pr-risk (merge of staging with the PR delta unchanged; the merge-ref check re-ran the top scenarios live on the merged tree, results above)