mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-19 00:01:29 +00:00
fix(ui): persist disabling cache control injection points on model update
Turning Cache Control off on the model edit screen omitted the field from the PATCH body, which the backend reads as leave unchanged, so the stored cache_control_injection_points list survived the save. The dashboard now sends an explicit null when a stored list is being disabled, and update_db_model clears that field on null the same way it already clears the mirrored pricing fields. Omitted keys keep the stored value Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
02a20fe264
commit
696587c4ab
4 changed files with 56 additions and 3 deletions
|
|
@ -144,6 +144,8 @@ if TYPE_CHECKING:
|
|||
from prisma import types as prisma_types
|
||||
|
||||
router: Final = APIRouter()
|
||||
CLEARABLE_LITELLM_PARAMS: Final = frozenset({"cache_control_injection_points"})
|
||||
NULL_CLEARABLE_LITELLM_PARAMS: Final = frozenset((*SPECIAL_MODEL_INFO_PARAMS, *CLEARABLE_LITELLM_PARAMS))
|
||||
|
||||
|
||||
async def update_team(*args, **kwargs):
|
||||
|
|
@ -898,7 +900,7 @@ def update_db_model(db_model: Deployment, updated_patch: updateDeployment) -> Pr
|
|||
# clear propagates to both blobs.
|
||||
if updated_patch.litellm_params:
|
||||
for field in updated_patch.litellm_params.model_fields_set:
|
||||
if field in SPECIAL_MODEL_INFO_PARAMS and getattr(updated_patch.litellm_params, field) is None:
|
||||
if getattr(updated_patch.litellm_params, field) is None and field in NULL_CLEARABLE_LITELLM_PARAMS:
|
||||
merged_litellm_params.pop(field, None)
|
||||
merged_model_info.pop(field, None)
|
||||
elif (
|
||||
|
|
|
|||
|
|
@ -3864,6 +3864,54 @@ class TestModelInfoServerDerivedPricingFilter:
|
|||
assert written["access_groups"] == ["prod"]
|
||||
|
||||
|
||||
class TestUpdateDBModelClearCacheControlInjectionPoints:
|
||||
def test_explicit_null_removes_stored_injection_points(self):
|
||||
from litellm.proxy.management_endpoints.model_management_endpoints import (
|
||||
update_db_model,
|
||||
)
|
||||
from litellm.types.router import LiteLLM_Params, ModelInfo, updateLiteLLMParams
|
||||
|
||||
db_model = Deployment(
|
||||
model_name="haiku-cached",
|
||||
litellm_params=LiteLLM_Params(
|
||||
model="anthropic/claude-haiku-4-5",
|
||||
cache_control_injection_points=[{"location": "message", "role": "system"}],
|
||||
),
|
||||
model_info=ModelInfo(id="dep-cache-0"),
|
||||
)
|
||||
patch = updateDeployment(
|
||||
litellm_params=updateLiteLLMParams(cache_control_injection_points=None)
|
||||
)
|
||||
|
||||
result = update_db_model(db_model=db_model, updated_patch=patch)
|
||||
|
||||
params = json.loads(result["litellm_params"])
|
||||
assert "cache_control_injection_points" not in params
|
||||
assert params["model"] == "anthropic/claude-haiku-4-5"
|
||||
|
||||
def test_omitted_key_keeps_stored_injection_points(self):
|
||||
from litellm.proxy.management_endpoints.model_management_endpoints import (
|
||||
update_db_model,
|
||||
)
|
||||
from litellm.types.router import LiteLLM_Params, ModelInfo, updateLiteLLMParams
|
||||
|
||||
db_model = Deployment(
|
||||
model_name="haiku-cached",
|
||||
litellm_params=LiteLLM_Params(
|
||||
model="anthropic/claude-haiku-4-5",
|
||||
cache_control_injection_points=[{"location": "message", "role": "system"}],
|
||||
),
|
||||
model_info=ModelInfo(id="dep-cache-0"),
|
||||
)
|
||||
patch = updateDeployment(litellm_params=updateLiteLLMParams(tpm=10))
|
||||
|
||||
result = update_db_model(db_model=db_model, updated_patch=patch)
|
||||
|
||||
params = json.loads(result["litellm_params"])
|
||||
assert params["cache_control_injection_points"] == [{"location": "message", "role": "system"}]
|
||||
assert params["tpm"] == 10
|
||||
|
||||
|
||||
class TestGetModelInfoWithIdBlocked:
|
||||
"""`ProxyConfig.get_model_info_with_id` must propagate the DB-level `blocked`
|
||||
column into the in-memory `model_info` dict so the router filter can read it."""
|
||||
|
|
|
|||
|
|
@ -1785,7 +1785,7 @@ describe("ModelInfoView", () => {
|
|||
expect(payload.litellm_params.cache_control_injection_points).toEqual([{ location: "message", role: "user" }]);
|
||||
});
|
||||
|
||||
it("drops the stored injection points when the operator turns the toggle off", async () => {
|
||||
it("sends an explicit null when the operator turns the toggle off so the backend clears the stored points", async () => {
|
||||
withCachePoints([{ location: "message", role: "user" }]);
|
||||
const user = userEvent.setup();
|
||||
await enterEditMode(user);
|
||||
|
|
@ -1793,7 +1793,7 @@ describe("ModelInfoView", () => {
|
|||
await user.click(screen.getByRole("switch"));
|
||||
const payload = await save(user);
|
||||
|
||||
expect(payload.litellm_params).not.toHaveProperty("cache_control_injection_points");
|
||||
expect(payload.litellm_params.cache_control_injection_points).toBeNull();
|
||||
});
|
||||
|
||||
it("adds a typed index as a string, matching what the deployment already stores", async () => {
|
||||
|
|
|
|||
|
|
@ -352,8 +352,11 @@ export default function ModelInfoView({
|
|||
}
|
||||
|
||||
// Handle cache control settings
|
||||
const hadInjectionPoints = Boolean(localModelData?.litellm_params?.cache_control_injection_points);
|
||||
if (values.cache_control && (values.cache_control_injection_points?.length ?? 0) > 0) {
|
||||
updatedLitellmParams.cache_control_injection_points = values.cache_control_injection_points;
|
||||
} else if (hadInjectionPoints) {
|
||||
updatedLitellmParams.cache_control_injection_points = null;
|
||||
} else {
|
||||
delete updatedLitellmParams.cache_control_injection_points;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue