mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-14 23:21:35 +00:00
fix(proxy): /config/update litellm_settings merge — request wins
Flip the litellm_settings dict merge from {**incoming, **existing} to
{**existing, **incoming} so the caller's value for any pre-existing key
is what gets persisted. The previous direction silently no-op'd a
request like {"litellm_settings": {"drop_params": false}} when the DB
already held drop_params: true — the endpoint returned 200 OK but the
stored value never changed. router_settings (immediately below) had
been doing the right thing all along; this brings the two sections into
alignment.
success_callback semantics are unchanged: it is still always normalized
to lowercase, and still unioned with any existing list (callbacks are
additive — a caller sends the new entry, not the full set).
Adds a regression test (drop_params: True in DB, request flips to
False, expect persisted False with other keys preserved).
This commit is contained in:
parent
1fd38eb5a5
commit
db5cdfc440
2 changed files with 38 additions and 5 deletions
|
|
@ -12616,10 +12616,13 @@ async def update_config( # noqa: PLR0915
|
|||
existing[k] = encrypt_value_helper(value=v)
|
||||
await _upsert_section("environment_variables", existing)
|
||||
|
||||
# litellm_settings: existing-wins merge (preserving legacy behavior),
|
||||
# except success_callback is always normalized + deduped, and unioned
|
||||
# with any existing list. Normalizing on every write — not only when
|
||||
# an existing entry is present — keeps the DB free of mixed-case
|
||||
# litellm_settings: merge existing + request, request wins (matching
|
||||
# router_settings semantics — the caller's value for any given key is
|
||||
# what gets persisted). success_callback is special-cased: it is
|
||||
# always normalized + deduped, and unioned with any existing list,
|
||||
# because callbacks are additive (callers send the new entry, not
|
||||
# the full set). Normalizing on every write — not only when an
|
||||
# existing entry is present — keeps the DB free of mixed-case
|
||||
# entries that delete_callback (lowercase lookup) cannot find.
|
||||
if config_info.litellm_settings is not None:
|
||||
existing = await _read_section("litellm_settings")
|
||||
|
|
@ -12631,7 +12634,7 @@ async def update_config( # noqa: PLR0915
|
|||
incoming_cb
|
||||
)
|
||||
|
||||
merged = {**updated_litellm_settings, **existing}
|
||||
merged = {**existing, **updated_litellm_settings}
|
||||
|
||||
incoming_cb = updated_litellm_settings.get("success_callback")
|
||||
existing_cb = existing.get("success_callback")
|
||||
|
|
|
|||
|
|
@ -192,6 +192,36 @@ def test_environment_variables_encrypted_before_write(admin_auth, patched_proxy)
|
|||
assert stored == {"OPENAI_API_KEY": "enc:sk-secret"}
|
||||
|
||||
|
||||
def test_litellm_settings_request_wins_for_non_callback_keys(admin_auth, patched_proxy):
|
||||
"""
|
||||
Regression: a /config/update with {"litellm_settings": {"drop_params":
|
||||
False}} when the existing row holds drop_params: True must persist
|
||||
drop_params: False. Previously the merge was {**incoming, **existing},
|
||||
so existing values silently won and the request was a no-op for any
|
||||
pre-existing key.
|
||||
|
||||
Untouched keys must be preserved.
|
||||
"""
|
||||
prisma = patched_proxy(
|
||||
initial_rows={
|
||||
"litellm_settings": {
|
||||
"drop_params": True,
|
||||
"set_verbose": True,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
client = TestClient(app)
|
||||
resp = client.post(
|
||||
"/config/update", json={"litellm_settings": {"drop_params": False}}
|
||||
)
|
||||
|
||||
assert resp.status_code == 200
|
||||
stored = prisma.db.litellm_config.rows["litellm_settings"]
|
||||
assert stored["drop_params"] is False
|
||||
assert stored["set_verbose"] is True
|
||||
|
||||
|
||||
def test_success_callback_unioned_with_existing(admin_auth, patched_proxy):
|
||||
prisma = patched_proxy(
|
||||
initial_rows={"litellm_settings": {"success_callback": ["langfuse"]}}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue