Repository navigation
fix(model_management): stop persisting cost map pricing as a deployment override - #36222
Conversation
Greptile SummaryThis PR prevents pricing derived from the model cost map from being persisted as a deployment override while preserving explicit overrides in
Confidence Score: 5/5The PR appears safe to merge No blocking failure remains
|
| Filename | Overview |
|---|---|
| litellm/proxy/management_endpoints/model_management_endpoints.py | Filters server-derived pricing from incoming model information on deployment create and update paths |
| litellm/types/utils.py | Defines the shared pricing-field set, tiered-key pattern, and immutable filtering helper |
| litellm/utils.py | Reuses the shared tiered-pricing pattern in the model-info read path |
| tests/test_litellm/proxy/management_endpoints/test_model_management_endpoints.py | Adds regression coverage for filtering derived prices while retaining deployment identity and supported fields |
Reviews (2): Last reviewed commit: "fix(model_management): stop persisting c..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
Removed the new inline comments in the endpoint, types, and tests; context now lives in docstrings and the PR description. |
…nt override /model/info fills a deployment's missing pricing in from the model cost map so the Admin UI has a rate to display. Clients echo that whole model_info blob back on save, and update_db_model merged it into the row, so editing an unrelated setting turned that day's catalog price into a real per-deployment override. After that the deployment ignored the cost map and Reload Price Data could no longer move it, because the reload replays each deployment's stored pricing over the fresh catalog. Drop the derived pricing from incoming model_info on the two write paths. The drop-set is read off the same objects the read path uses, CustomPricingLiteLLMParams plus the tiered *_above_N_tokens pattern that get_model_info passes through and no model declares, so it cannot drift as new rates are added. output_vector_size is exempt: it lives on the pricing model but is an embedding dimension, not a rate. A deployment's own pricing still rides litellm_params, which is untouched, as is the explicit-null clear, which reads the incoming model rather than the filtered dict. The filter sits in the endpoint bodies rather than _add_model_to_db, which master-key rotation reuses to re-serialize every stored deployment.
5a1ec6e to
76cb0fe
Compare
|
@greptileai re review |
|
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 76cb0fe. Configure here.
TLDR
Problem this solves:
How it solves it:
litellm_paramsstays the way to set an overrideRelevant issues
Linear ticket
Resolves LIT-5292
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
@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
Type
🐛 Bug Fix
Changes
GET /model/infofills a deployment's missing pricing in from the model cost map so the Admin UI has a rate to display. Clients echo that wholemodel_infoblob back on save, andupdate_db_modelmerged it into the row, so editing an unrelated setting turned that day's catalog price into a real per-deployment override. After that the deployment ignored the cost map, and Reload Price Data could not move it either, because the reload replays each deployment's stored pricing over the freshly fetched catalog. Clearing the cost fields worked once and then came back on the next save, since that save re-sent the same stale blob.This drops the derived pricing from incoming
model_infoonPOST /model/newandPATCH /model/{id}/update. The drop-set is read off the same objects the read path uses,CustomPricingLiteLLMParamsplus the tiered*_above_N_tokenspattern thatget_model_infopasses through and no model declares, so it cannot drift as new rates are added.output_vector_sizeis exempt because it lives on the pricing model but is an embedding dimension rather than a rate.Three things stay as they are. A deployment's own pricing rides
litellm_params, which is untouched, so every documented way to set an override still works. The explicit-null clear still fires, because it reads the incoming model rather than the filtered dict. And the response shape is unchanged, so the form still displays the effective price.The filter sits in the two endpoint bodies rather than in
_add_model_to_db, which master-key rotation reuses to re-serialize every stored deployment; a filter there would strip the whole table on the next rotation. On the create path the blob is rebuilt from its own dump so the real deployment id rides along, sinceModelInfomints a fresh uuid when the id is absent.Behavior changes worth calling out:
model_infoonPOST/PATCHno longer takes effect. That path is undeclared (ModelInfodoes not declare pricing fields; they rideextra="allow") and undocumented, but it worked. Uselitellm_params, which is what the Admin UI, the Terraform provider, and theliteCLI already do.lite models importof a config.yaml whosemodel_infoblock carries pricing now drops that pricing on import. Move it tolitellm_paramsin the config, or set it after import.Config-based models are unaffected:
patch_modelalready rejects them, and theirmodel_infopricing is read at boot rather than written through these endpoints.Scoped to pricing. The same round-trip also pins
mode,max_tokens, and thesupports_*flags, and that half needs a replacement path formodefirst, so it is a follow-up.QA runbook
Final Attestation
Note
Medium Risk
Changes which pricing fields persist on model create/update (model_info pricing is ignored; litellm_params still authoritative), which affects billing configuration and may surprise callers who set rates only in model_info.
Overview
Fixes deployments getting permanently pinned to catalog prices when the Admin UI saves a model:
/model/infoinjects cost-map rates intomodel_infofor display, and clients that round-trip that blob used to merge those fields into the DB as real overrides.Write-path filtering now strips server-derived pricing from incoming
model_infoon PATCH (update_db_model) and POST/model/new(rebuildsModelInfoso deploymentidis preserved). The drop set lives inwithout_server_derived_pricing/is_server_derived_pricing_keyinlitellm/types/utils.py—CustomPricingLiteLLMParamsfields (exceptoutput_vector_size) plus tiered*_above_*_tokenskeys—aligned with what the read path can emit.litellm_paramspricing is unchanged, so intentional overrides still persist there.ABOVE_THRESHOLD_COST_KEY_PATTERNis shared withlitellm/utils.py(replacing a local duplicate). Tests cover echo saves, tiered keys, exempt fields, and create-path behavior.Reviewed by Cursor Bugbot for commit 76cb0fe. Bugbot is set up for automated code reviews on this repo. Configure here.