From a831eb503f54874c543947faeeecec2e2135c4a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=93=E5=A4=A9=E8=8E=B2?= <91449279+yitianlian@users.noreply.github.com> Date: Fri, 27 Feb 2026 04:04:08 +0800 Subject: [PATCH 1/2] Fix #1578: prevent arg suffix concatenation in convert checkpoint --- slime/utils/external_utils/command_utils.py | 3 +- tests/utils/test_command_utils.py | 36 +++++++++++++++++++++ workflows/issue-1578.md | 29 +++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 tests/utils/test_command_utils.py create mode 100644 workflows/issue-1578.md diff --git a/slime/utils/external_utils/command_utils.py b/slime/utils/external_utils/command_utils.py index 9f51ecdf20..50ab51e81e 100644 --- a/slime/utils/external_utils/command_utils.py +++ b/slime/utils/external_utils/command_utils.py @@ -28,6 +28,7 @@ def convert_checkpoint( hf_checkpoint: str | None = None, ): hf_checkpoint = hf_checkpoint or f"/root/models/{model_name}" + normalized_extra_args = f" {extra_args.strip()}" if extra_args.strip() else "" # TODO shall we make it in host-mapped folder and thus can cache it to speedup CI path_dst = f"{dir_dst}/{model_name}_torch_dist" @@ -59,7 +60,7 @@ def convert_checkpoint( "${MODEL_ARGS[@]} " f"--hf-checkpoint {hf_checkpoint} " f"--save {path_dst}" - f"{extra_args}" + f"{normalized_extra_args}" ) diff --git a/tests/utils/test_command_utils.py b/tests/utils/test_command_utils.py new file mode 100644 index 0000000000..7ab80d47c0 --- /dev/null +++ b/tests/utils/test_command_utils.py @@ -0,0 +1,36 @@ +import importlib +import sys +import types + +fake_typer = types.ModuleType("typer") +fake_typer.Option = lambda *args, **kwargs: None +sys.modules.setdefault("typer", fake_typer) + +fake_misc = types.ModuleType("slime.utils.misc") +fake_misc.exec_command = lambda *args, **kwargs: None +sys.modules["slime.utils.misc"] = fake_misc + +U = importlib.import_module("slime.utils.external_utils.command_utils") + + +def test_convert_checkpoint_keeps_extra_args_separated(monkeypatch, tmp_path): + captured = [] + + def fake_exec_command(cmd: str, capture_output: bool = False): + captured.append(cmd) + return "" + + monkeypatch.setattr(U, "exec_command", fake_exec_command) + + U.convert_checkpoint( + model_name="demo-model", + megatron_model_type="qwen2.5-0.5B", + num_gpus_per_node=1, + dir_dst=str(tmp_path), + extra_args="--disable-bias-linear --untie-embeddings-and-output-weights", + ) + + assert len(captured) == 1 + cmd = captured[0] + save_arg = f"--save {tmp_path}/demo-model_torch_dist" + assert f"{save_arg} --disable-bias-linear --untie-embeddings-and-output-weights" in cmd diff --git a/workflows/issue-1578.md b/workflows/issue-1578.md new file mode 100644 index 0000000000..1e3a1fff98 --- /dev/null +++ b/workflows/issue-1578.md @@ -0,0 +1,29 @@ +# Issue #1578 Workflow + +1) Issue 链接与摘要 +- URL: https://github.com/THUDM/slime/issues/1578 +- 现象:HF -> Megatron 转换时,传入模型参数会发生黏连,导致 flag 名异常(如 `--disable-bias-linear...`)。 +- 期望:命令行参数应按独立 token 透传,不应被拼接。 + +2) 根因分析 +- `slime/utils/external_utils/command_utils.py::convert_checkpoint()` 拼接命令时,`--save {path_dst}` 与 `extra_args` 之间没有保证空格分隔。 +- 当调用方传入不带前导空格的 `extra_args` 时,会与前一个参数黏连。 + +3) 修改清单 +- `slime/utils/external_utils/command_utils.py` + - 新增 `normalized_extra_args = f" {extra_args.strip()}" if extra_args.strip() else ""` + - 命令拼接改用 `normalized_extra_args`,保证参数边界。 +- `tests/utils/test_command_utils.py` + - 新增轻量单测,验证 `--save ...` 后的 `extra_args` 有空格分隔。 + +4) 如何验证 +- 本机最小验证(CPU): + - `python3.12` 注入最小 fake module 后调用 `convert_checkpoint()`,断言生成命令包含: + `--save /tmp/slime-test/demo-model_torch_dist --disable-bias-linear --untie-embeddings-and-output-weights` + - 结果:通过(输出 `ok`)。 +- 额外建议(有完整 Python/pytest 环境时): + - `PYTHONPATH=. pytest -q tests/utils/test_command_utils.py` + +5) 可选 PR 草稿 +- 标题:Fix command arg concatenation in convert_checkpoint +- Body:Normalize and prepend whitespace for `extra_args` in `convert_checkpoint()` to avoid merged CLI flags during HF->Megatron conversion. From efa4c870a4cd768248ce387ed73fedaa10fbb5c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=93=E5=A4=A9=E8=8E=B2?= <91449279+yitianlian@users.noreply.github.com> Date: Fri, 27 Feb 2026 10:19:41 +0800 Subject: [PATCH 2/2] chore: remove workflow doc and branch-only test --- tests/utils/test_command_utils.py | 36 ------------------------------- workflows/issue-1578.md | 29 ------------------------- 2 files changed, 65 deletions(-) delete mode 100644 tests/utils/test_command_utils.py delete mode 100644 workflows/issue-1578.md diff --git a/tests/utils/test_command_utils.py b/tests/utils/test_command_utils.py deleted file mode 100644 index 7ab80d47c0..0000000000 --- a/tests/utils/test_command_utils.py +++ /dev/null @@ -1,36 +0,0 @@ -import importlib -import sys -import types - -fake_typer = types.ModuleType("typer") -fake_typer.Option = lambda *args, **kwargs: None -sys.modules.setdefault("typer", fake_typer) - -fake_misc = types.ModuleType("slime.utils.misc") -fake_misc.exec_command = lambda *args, **kwargs: None -sys.modules["slime.utils.misc"] = fake_misc - -U = importlib.import_module("slime.utils.external_utils.command_utils") - - -def test_convert_checkpoint_keeps_extra_args_separated(monkeypatch, tmp_path): - captured = [] - - def fake_exec_command(cmd: str, capture_output: bool = False): - captured.append(cmd) - return "" - - monkeypatch.setattr(U, "exec_command", fake_exec_command) - - U.convert_checkpoint( - model_name="demo-model", - megatron_model_type="qwen2.5-0.5B", - num_gpus_per_node=1, - dir_dst=str(tmp_path), - extra_args="--disable-bias-linear --untie-embeddings-and-output-weights", - ) - - assert len(captured) == 1 - cmd = captured[0] - save_arg = f"--save {tmp_path}/demo-model_torch_dist" - assert f"{save_arg} --disable-bias-linear --untie-embeddings-and-output-weights" in cmd diff --git a/workflows/issue-1578.md b/workflows/issue-1578.md deleted file mode 100644 index 1e3a1fff98..0000000000 --- a/workflows/issue-1578.md +++ /dev/null @@ -1,29 +0,0 @@ -# Issue #1578 Workflow - -1) Issue 链接与摘要 -- URL: https://github.com/THUDM/slime/issues/1578 -- 现象:HF -> Megatron 转换时,传入模型参数会发生黏连,导致 flag 名异常(如 `--disable-bias-linear...`)。 -- 期望:命令行参数应按独立 token 透传,不应被拼接。 - -2) 根因分析 -- `slime/utils/external_utils/command_utils.py::convert_checkpoint()` 拼接命令时,`--save {path_dst}` 与 `extra_args` 之间没有保证空格分隔。 -- 当调用方传入不带前导空格的 `extra_args` 时,会与前一个参数黏连。 - -3) 修改清单 -- `slime/utils/external_utils/command_utils.py` - - 新增 `normalized_extra_args = f" {extra_args.strip()}" if extra_args.strip() else ""` - - 命令拼接改用 `normalized_extra_args`,保证参数边界。 -- `tests/utils/test_command_utils.py` - - 新增轻量单测,验证 `--save ...` 后的 `extra_args` 有空格分隔。 - -4) 如何验证 -- 本机最小验证(CPU): - - `python3.12` 注入最小 fake module 后调用 `convert_checkpoint()`,断言生成命令包含: - `--save /tmp/slime-test/demo-model_torch_dist --disable-bias-linear --untie-embeddings-and-output-weights` - - 结果:通过(输出 `ok`)。 -- 额外建议(有完整 Python/pytest 环境时): - - `PYTHONPATH=. pytest -q tests/utils/test_command_utils.py` - -5) 可选 PR 草稿 -- 标题:Fix command arg concatenation in convert_checkpoint -- Body:Normalize and prepend whitespace for `extra_args` in `convert_checkpoint()` to avoid merged CLI flags during HF->Megatron conversion.