mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-07 08:26:10 +00:00
Merge 961fe1727c into 44d84360fb
This commit is contained in:
commit
6485193f98
3 changed files with 85 additions and 1 deletions
|
|
@ -1645,6 +1645,8 @@ LITELLM_SETTINGS_SAFE_DB_OVERRIDES: Final = [
|
|||
"cost_margin_config",
|
||||
"block_requests_for_models_without_pricing",
|
||||
"budget_exceeded_throttle_percentage",
|
||||
# Proxy-wide budget stored via POST /config/update; applied to litellm.max_budget on reload.
|
||||
"max_budget",
|
||||
# Every field editable from the Admin UI (proxy_server._GENERAL_SETTINGS_UI_LITELLM_FIELDS)
|
||||
# must be listed here so a DB write from one worker overrides the live litellm attribute on
|
||||
# the others when config reloads; otherwise peer workers stay on their startup value.
|
||||
|
|
|
|||
|
|
@ -3835,6 +3835,27 @@ def _scrub_guardrail_inner(inner: dict[str, JsonValue]) -> None:
|
|||
inner["guardrail"] = None
|
||||
|
||||
|
||||
def _apply_safe_db_litellm_setting(key: str, value: object) -> None:
|
||||
"""Apply a DB-overlaid ``litellm_settings`` key to the live ``litellm`` module.
|
||||
|
||||
``max_budget`` is coerced to float to match startup config loading
|
||||
(``ProxyConfig.load_config``). A ``None`` DB value leaves the current
|
||||
runtime attribute unchanged; a non-numeric value is ignored (with a
|
||||
warning) rather than aborting the reload of an already-running proxy.
|
||||
"""
|
||||
if key == "max_budget":
|
||||
if value is None:
|
||||
return
|
||||
try:
|
||||
budget = float(value)
|
||||
except (TypeError, ValueError):
|
||||
verbose_proxy_logger.warning("Ignoring non-numeric DB litellm_settings.max_budget override: %r", value)
|
||||
return
|
||||
litellm.max_budget = budget
|
||||
return
|
||||
setattr(litellm, key, value)
|
||||
|
||||
|
||||
def _scrub_db_overlay_remote_module_loads(section: str, db_value: JsonValue) -> JsonValue:
|
||||
"""Strip ``s3://`` / ``gcs://`` entries from the DB-overlay value for
|
||||
fields whose contents reach ``get_instance_fn``. The same scheme is
|
||||
|
|
@ -6656,7 +6677,7 @@ class ProxyConfig:
|
|||
elif param_name == "litellm_settings" and isinstance(db_param_value, dict):
|
||||
for key, value in db_param_value.items():
|
||||
if key in LITELLM_SETTINGS_SAFE_DB_OVERRIDES: # params that are safe to override with db values
|
||||
setattr(litellm, key, value)
|
||||
_apply_safe_db_litellm_setting(key, value)
|
||||
|
||||
# If param doesn't exist in config, add it
|
||||
if param_name not in current_config:
|
||||
|
|
|
|||
|
|
@ -9838,6 +9838,67 @@ def test_prompt_caching_settings_propagate_on_config_reload(monkeypatch, field_n
|
|||
assert getattr(litellm, field_name) == db_value
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"db_value, expected",
|
||||
[
|
||||
(10, 10.0),
|
||||
("10", 10.0),
|
||||
(0.5, 0.5),
|
||||
],
|
||||
)
|
||||
def test_max_budget_propagates_on_config_reload(monkeypatch, db_value, expected):
|
||||
"""Regression for #36533: a DB-stored litellm_settings.max_budget must overlay the live
|
||||
litellm.max_budget when config reloads (STORE_MODEL_IN_DB=True). It was absent from
|
||||
LITELLM_SETTINGS_SAFE_DB_OVERRIDES, so peer workers kept enforcing the stale config.yaml value."""
|
||||
import litellm.proxy.proxy_server as ps
|
||||
|
||||
# peer worker booted with the stale config.yaml value
|
||||
monkeypatch.setattr(litellm, "max_budget", 0.00001)
|
||||
|
||||
pc = ps.ProxyConfig()
|
||||
pc._update_config_fields(
|
||||
current_config={"litellm_settings": {}},
|
||||
param_name="litellm_settings",
|
||||
db_param_value={"max_budget": db_value},
|
||||
)
|
||||
|
||||
assert litellm.max_budget == expected
|
||||
assert isinstance(litellm.max_budget, float)
|
||||
|
||||
|
||||
def test_max_budget_none_db_value_leaves_runtime_unchanged(monkeypatch):
|
||||
"""A null DB max_budget must not clobber the running litellm.max_budget."""
|
||||
import litellm.proxy.proxy_server as ps
|
||||
|
||||
monkeypatch.setattr(litellm, "max_budget", 7.5)
|
||||
|
||||
pc = ps.ProxyConfig()
|
||||
pc._update_config_fields(
|
||||
current_config={"litellm_settings": {}},
|
||||
param_name="litellm_settings",
|
||||
db_param_value={"max_budget": None},
|
||||
)
|
||||
|
||||
assert litellm.max_budget == 7.5
|
||||
|
||||
|
||||
def test_max_budget_invalid_db_value_is_ignored(monkeypatch):
|
||||
"""A non-numeric DB max_budget must be skipped (logged), not abort the reload of a
|
||||
running proxy or clobber the live litellm.max_budget."""
|
||||
import litellm.proxy.proxy_server as ps
|
||||
|
||||
monkeypatch.setattr(litellm, "max_budget", 7.5)
|
||||
|
||||
pc = ps.ProxyConfig()
|
||||
pc._update_config_fields(
|
||||
current_config={"litellm_settings": {}},
|
||||
param_name="litellm_settings",
|
||||
db_param_value={"max_budget": "not-a-number"},
|
||||
)
|
||||
|
||||
assert litellm.max_budget == 7.5
|
||||
|
||||
|
||||
def test_get_config_list_marks_untouched_prompt_caching_flag_as_not_set(monkeypatch):
|
||||
"""The flag defaults to False rather than None, so a plain 'is not None' check would
|
||||
report the default as 'In Config' and imply an admin had set it."""
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue