mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-08 08:08:37 +00:00
proxy: hot-reload config YAML when --reload is set
Uvicorn's --reload only watches *.py by default, so editing the --config YAML did not restart the proxy. _get_reload_options() now extends reload_dirs/reload_includes with the config file's directory and basename when --config is provided.
This commit is contained in:
parent
e9fb29061a
commit
04432e2a2c
2 changed files with 56 additions and 2 deletions
|
|
@ -169,6 +169,28 @@ class ProxyInitializationHelpers:
|
|||
)
|
||||
return uvicorn_args
|
||||
|
||||
@staticmethod
|
||||
def _get_reload_options(config_path: Optional[str]) -> dict:
|
||||
"""
|
||||
Build uvicorn reload kwargs so --reload also reloads when the YAML
|
||||
config file (passed via --config) changes.
|
||||
|
||||
Uvicorn defaults to watching only `*.py` files in CWD; we extend the
|
||||
watch set to include the config file's directory and filename.
|
||||
"""
|
||||
options: dict = {"reload": True}
|
||||
if not config_path:
|
||||
return options
|
||||
config_abs = os.path.abspath(config_path)
|
||||
config_dir = os.path.dirname(config_abs)
|
||||
cwd = os.path.abspath(os.getcwd())
|
||||
reload_dirs = [cwd]
|
||||
if config_dir and config_dir != cwd:
|
||||
reload_dirs.append(config_dir)
|
||||
options["reload_dirs"] = reload_dirs
|
||||
options["reload_includes"] = ["*.py", os.path.basename(config_abs)]
|
||||
return options
|
||||
|
||||
@staticmethod
|
||||
def _init_hypercorn_server(
|
||||
app: FastAPI,
|
||||
|
|
@ -619,7 +641,7 @@ class ProxyInitializationHelpers:
|
|||
"--reload",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
help="Enable uvicorn hot reload (dev only). Incompatible with --num_workers>1, --run_gunicorn, and --run_hypercorn.",
|
||||
help="Enable uvicorn hot reload (dev only). Also reloads when the --config YAML file changes. Incompatible with --num_workers>1, --run_gunicorn, and --run_hypercorn.",
|
||||
)
|
||||
def run_server( # noqa: PLR0915
|
||||
host,
|
||||
|
|
@ -1028,7 +1050,9 @@ def run_server( # noqa: PLR0915
|
|||
uvicorn_args["loop"] = loop_type
|
||||
|
||||
if reload:
|
||||
uvicorn_args["reload"] = True
|
||||
uvicorn_args.update(
|
||||
ProxyInitializationHelpers._get_reload_options(config)
|
||||
)
|
||||
|
||||
uvicorn.run(
|
||||
**uvicorn_args,
|
||||
|
|
|
|||
|
|
@ -133,6 +133,36 @@ class TestProxyInitializationHelpers:
|
|||
)
|
||||
assert args["timeout_worker_healthcheck"] == 15
|
||||
|
||||
def test_get_reload_options_no_config(self):
|
||||
opts = ProxyInitializationHelpers._get_reload_options(None)
|
||||
assert opts == {"reload": True}
|
||||
|
||||
def test_get_reload_options_with_config_in_cwd(self, tmp_path, monkeypatch):
|
||||
config_file = tmp_path / "config.yaml"
|
||||
config_file.write_text("model_list: []\n")
|
||||
monkeypatch.chdir(tmp_path)
|
||||
|
||||
opts = ProxyInitializationHelpers._get_reload_options("config.yaml")
|
||||
|
||||
assert opts["reload"] is True
|
||||
assert opts["reload_dirs"] == [str(tmp_path)]
|
||||
assert opts["reload_includes"] == ["*.py", "config.yaml"]
|
||||
|
||||
def test_get_reload_options_with_config_outside_cwd(self, tmp_path, monkeypatch):
|
||||
cwd_dir = tmp_path / "work"
|
||||
cwd_dir.mkdir()
|
||||
elsewhere = tmp_path / "configs"
|
||||
elsewhere.mkdir()
|
||||
config_file = elsewhere / "proxy.yaml"
|
||||
config_file.write_text("model_list: []\n")
|
||||
monkeypatch.chdir(cwd_dir)
|
||||
|
||||
opts = ProxyInitializationHelpers._get_reload_options(str(config_file))
|
||||
|
||||
assert opts["reload"] is True
|
||||
assert opts["reload_dirs"] == [str(cwd_dir), str(elsewhere)]
|
||||
assert opts["reload_includes"] == ["*.py", "proxy.yaml"]
|
||||
|
||||
@patch("asyncio.run")
|
||||
@patch("builtins.print")
|
||||
def test_init_hypercorn_server(self, mock_print, mock_asyncio_run):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue