Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/filters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,11 @@ snapshot_vllm:
- 'deploy/operator/internal/dynamo/backend_vllm.go'

snapshot_sglang:
- 'components/src/dynamo/sglang/args.py'
- 'components/src/dynamo/sglang/snapshot.py'
# The SGLang runtime tag controls the engine version exercised by this suite,
# so engine bumps must trigger it. Deliberately omit broad pyproject.toml.
- 'container/context.yaml'
- 'deploy/operator/internal/dynamo/backend_sglang.go'
Comment thread
galletas1712 marked this conversation as resolved.
Resolved

snapshot_trtllm:
Expand Down
10 changes: 10 additions & 0 deletions .github/scripts/test-filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,16 @@ const testCases = [
},
desc: 'sglang snapshot.py gates only sglang checkpoint tests'
},
{
file: 'container/context.yaml',
expect: {
snapshot: false,
snapshot_vllm: false,
snapshot_sglang: true,
snapshot_trtllm: false,
},
desc: 'runtime tag changes gate the SGLang checkpoint tests'
},
{
file: 'components/src/dynamo/trtllm/snapshot.py',
expect: {
Expand Down
13 changes: 11 additions & 2 deletions components/src/dynamo/sglang/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,8 +549,13 @@ async def parse_args(args: list[str]) -> Config:
if should_fetch_model(parsed_args, model_path):
await fetch_model(model_path)

if is_snapshot_enabled():
snapshot_enabled = is_snapshot_enabled()
if snapshot_enabled:
configure_snapshot_capture_env()
# SGLang reads these raw fields before late resolution, so snapshot mode
# must set them before ServerArgs creation.
parsed_args.enable_memory_saver = True
parsed_args.enable_forward_pass_metrics = False

# TODO: sglang downloads the model in `from_cli_args`, which means we had to
# fetch_model (download the model) here, in `parse_args`. `parse_args` should not
Expand All @@ -571,7 +576,11 @@ async def parse_args(args: list[str]) -> Config:
parsed_args.enable_memory_saver = True

fpm_source = _forward_pass_metrics_source(dynamo_config)
if fpm_source and not getattr(parsed_args, "enable_forward_pass_metrics", False):
if (
not snapshot_enabled
and fpm_source
and not getattr(parsed_args, "enable_forward_pass_metrics", False)
):
parsed_args.enable_forward_pass_metrics = True
logging.info("Enabled forward_pass_metrics from %s", fpm_source)

Expand Down
71 changes: 71 additions & 0 deletions components/src/dynamo/sglang/tests/test_sglang_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,77 @@ def resolve(parsed_args):
await parse_args(sys.argv[1:])


@pytest.mark.asyncio
@pytest.mark.parametrize(
Comment thread
galletas1712 marked this conversation as resolved.
Resolved
("snapshot_enabled", "expected"),
[
(False, False),
(True, True),
],
)
async def test_parse_args_sets_raw_memory_saver_before_resolution(
monkeypatch, mock_sglang_cli, tmp_path, snapshot_enabled, expected
):
monkeypatch.setattr(
"dynamo.sglang.args.configure_snapshot_capture_env", lambda: None
)
monkeypatch.delenv("DYN_GMS_USE_V1", raising=False)
if snapshot_enabled:
monkeypatch.setenv(SNAPSHOT_CONTROL_DIR_ENV, str(tmp_path))
monkeypatch.setenv("NCCL_CUMEM_ENABLE", "0")
else:
monkeypatch.delenv(SNAPSHOT_CONTROL_DIR_ENV, raising=False)
server_args = SimpleNamespace(
disaggregation_mode="null",
dllm_algorithm=None,
kv_events_config=None,
get_model_config=lambda: SimpleNamespace(is_multimodal=False),
)

def resolve(parsed_args):
# SGLang 0.5.19 copies this raw field unchanged; late resolution does
# not update it before the parent process launches the scheduler.
server_args.enable_memory_saver = parsed_args.enable_memory_saver
return server_args

monkeypatch.setattr("dynamo.sglang.args.ServerArgs.from_cli_args", resolve)
mock_sglang_cli(model=str(tmp_path))

config = await parse_args(sys.argv[1:])

assert config.server_args.enable_memory_saver is expected


@pytest.mark.asyncio
async def test_parse_args_disables_raw_fpm_for_snapshot_with_metric_port(
monkeypatch, mock_sglang_cli, tmp_path
):
monkeypatch.setattr(
"dynamo.sglang.args.configure_snapshot_capture_env", lambda: None
)
monkeypatch.delenv("DYN_GMS_USE_V1", raising=False)
monkeypatch.setenv(SNAPSHOT_CONTROL_DIR_ENV, str(tmp_path))
monkeypatch.setenv("DYN_FORWARDPASS_METRIC_PORT", "23456")
server_args = SimpleNamespace(
disaggregation_mode="null",
dllm_algorithm=None,
enable_forward_pass_metrics=False,
kv_events_config=None,
get_model_config=lambda: SimpleNamespace(is_multimodal=False),
)

def resolve(parsed_args):
assert parsed_args.enable_forward_pass_metrics is False
return server_args

monkeypatch.setattr("dynamo.sglang.args.ServerArgs.from_cli_args", resolve)
mock_sglang_cli(model=str(tmp_path))

config = await parse_args(sys.argv[1:])

assert config.server_args.enable_forward_pass_metrics is False


def test_compat_filters_async_generate_kwargs_for_older_engines():
class OldEngine:
async def async_generate(self, input_ids=None, sampling_params=None):
Expand Down
Loading