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
2 changes: 1 addition & 1 deletion megatron_runtime/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ dependencies = [
"nvidia-ml-py==13.580.82",
"nvidia-modelopt>=0.42.0a0",
"nvidia-resiliency-ext<0.5",
"openai>=2.14.0",
"openai>=2.14.0,<3",
"peft>=0.14.0",
"polars>=1.26.0",
"pydantic>=2.12",
Expand Down
59 changes: 6 additions & 53 deletions megatron_runtime/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ requires-python = ">=3.12"
dependencies = [
"aiohttp>=3.10.0",
"anthropic>=0.77.0",
"openai>=2.14.0",
"openai>=2.14.0,<3",
"pydantic>=2.12",
"requests>=2.32.0",
"typing-extensions>=4.13",
Expand Down
1 change: 1 addition & 0 deletions src/art/megatron/model_support/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
"Qwen/Qwen3.5-4B",
"Qwen/Qwen3.5-27B",
"Qwen/Qwen3.6-27B",
"Qwen/Qwen3.8-27B",
),
default_target_modules=_QWEN3_5_DENSE_TARGET_MODULES,
native_vllm_lora_status=_VALIDATED_NATIVE_VLLM_LORA_STATUS,
Expand Down
2 changes: 1 addition & 1 deletion src/art/trainer_rank/_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1417,7 +1417,7 @@ def _validate_checkpoint_adapter_config(
raise TypeError(
"adapter_config['base_model_name_or_path'] must be a string"
)
if base_model.startswith(("Qwen/Qwen3.5-", "Qwen/Qwen3.6-")):
if base_model.startswith(("Qwen/Qwen3.5-", "Qwen/Qwen3.6-", "Qwen/Qwen3.8-")):
dimensions = {
"num_attention_heads": getattr(
self.runtime.provider, "num_attention_heads", None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,10 @@ def install_megatron_qwen35_gdn_fp32_reference(
*,
base_model: str,
) -> None:
model_key = base_model.lower()
if "qwen3.5" not in model_key and "qwen3_5" not in model_key:
from art.megatron.model_support.registry import get_model_support_handler

handler = get_model_support_handler(base_model)
if handler.key not in {"qwen3_5_dense", "qwen3_5_moe"}:
return
from art.megatron.gdn import operator as gdn_operator

Expand Down
6 changes: 4 additions & 2 deletions tests/integration/megatron/model_support/hf_parity_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1109,8 +1109,10 @@ def _hf_prefix_tree_paths(


def _install_hf_qwen35_gdn_fp32_reference(model: Any, *, base_model: str) -> None:
model_key = base_model.lower()
if "qwen3.5" not in model_key and "qwen3_5" not in model_key:
from art.megatron.model_support.registry import get_model_support_handler

handler = get_model_support_handler(base_model)
if handler.key not in {"qwen3_5_dense", "qwen3_5_moe"}:
return
patched = 0
for module in model.modules():
Expand Down
10 changes: 10 additions & 0 deletions tests/integration/megatron/model_support/test_provider_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ def test_openpipe_qwen3_14b_instruct_uses_qwen3_dense_support() -> None:
assert handler.key == "qwen3_dense"


def test_qwen38_27b_uses_qwen35_dense_support() -> None:
spec = get_model_support_spec("Qwen/Qwen3.8-27B")
handler = get_model_support_handler("Qwen/Qwen3.8-27B")

assert spec.key == "qwen3_5_dense"
assert spec.is_moe is False
assert spec.native_vllm_lora_status == "validated"
assert handler.key == "qwen3_5_dense"


def test_meta_llama_32_1b_instruct_uses_llama3_dense_support() -> None:
model = "meta-llama/Llama-3.2-1B-Instruct"
spec = get_model_support_spec(model)
Expand Down
16 changes: 16 additions & 0 deletions tests/integration/megatron/model_support/test_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,22 @@ def test_validated_architecture_representative_models_are_fixed() -> None:
]


def test_qwen38_uses_its_measured_throughput_fingerprint() -> None:
qwen35 = handler_workflow_resources_for_base_model("Qwen/Qwen3.5-27B")
qwen38 = handler_workflow_resources_for_base_model("Qwen/Qwen3.8-27B")
assert qwen35 is not None and qwen35.e2e_throughput is not None
assert qwen38 is not None and qwen38.e2e_throughput is not None
qwen35_config = qwen35.e2e_throughput.throughput
qwen38_config = qwen38.e2e_throughput.throughput
assert qwen35_config is not None and qwen38_config is not None
assert qwen35_config.thresholds["b300"].calibration_fingerprint == (
"5617e8880591545a3281ff14d1fe5197eeefc21a81ec80d1a107fd31421d37a0"
)
assert qwen38_config.thresholds["b300"].calibration_fingerprint == (
"b07ee7ec6338ec021463a43a90fc96c5c5a036b4a04d90b80e1d22c1eef86774"
)


def test_dsv4_runtime_stages_use_full_model_resources() -> None:
resources = handler_workflow_resources_for_base_model(
"deepseek-ai/DeepSeek-V4-Flash"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"Qwen/Qwen3-32B": "9216db5781bf21249d130ec9da846c4624c16137",
"Qwen/Qwen3-30B-A3B": "ad44e777bcd18fa416d9da3bd8f70d33ebb85d39",
"Qwen/Qwen3.5-27B": "fc05daec18b0a78c049392ed2e771dde82bdf654",
"Qwen/Qwen3.8-27B": "1d4bf0f2ff6012fd82039f2fa52739d0dd7c60c0",
"Qwen/Qwen3.5-35B-A3B": "59d61f3ce65a6d9863b86d2e96597125219dc754",
"google/gemma-4-31B-it": "842da3794eaa0b77d5f08bae87a17459d91ff475",
"google/gemma-4-26B-A4B-it": "4d7ae4984b7db7de8f8457170b3f1a419ee76d52",
Expand Down
20 changes: 19 additions & 1 deletion tests/integration/megatron/model_support/workflow_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,9 @@ class HandlerWorkflowResources(BaseModel):
(81_700, 76_400, 4_850, 0.88, 2.5),
),
}
_B300_THROUGHPUT_FINGERPRINT_OVERRIDES = {
"Qwen/Qwen3.8-27B": "b07ee7ec6338ec021463a43a90fc96c5c5a036b4a04d90b80e1d22c1eef86774",
}
_H200_THROUGHPUT_FLOORS = {
"llama3_dense": (18_300, 17_200, 4_400, 0.89, 7.0),
"qwen3_dense": (24_100, 23_100, 5_000, 0.91, 7.0),
Expand Down Expand Up @@ -554,7 +557,22 @@ def handler_workflow_resources_for_base_model(
base_model,
allow_unvalidated_arch=allow_unvalidated_arch,
)
return HANDLER_WORKFLOW_RESOURCES.get(spec.handler_key)
resources = HANDLER_WORKFLOW_RESOURCES.get(spec.handler_key)
fingerprint = _B300_THROUGHPUT_FINGERPRINT_OVERRIDES.get(base_model)
if resources is None or resources.e2e_throughput is None or fingerprint is None:
return resources
stage = resources.e2e_throughput
config = stage.throughput
if config is None:
raise RuntimeError(f"missing throughput config for {base_model}")
thresholds = dict(config.thresholds)
thresholds["b300"] = thresholds["b300"].model_copy(
update={"calibration_fingerprint": fingerprint}
)
config = config.model_copy(update={"thresholds": thresholds})
return resources.model_copy(
update={"e2e_throughput": stage.model_copy(update={"throughput": config})}
)


def _h200_equivalent_slots_for_total_gib(total_gib: float) -> int:
Expand Down
10 changes: 8 additions & 2 deletions tests/unit/test_trainer_rank_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,13 @@ def test_checkpoint_slot_adapter_config_is_validated_and_copied() -> None:
trainer._validate_checkpoint_adapter_config("student", {"r": 8}, alpha=None)


def test_qwen35_checkpoint_adapter_config_captures_attention_dimensions() -> None:
@pytest.mark.parametrize(
"base_model",
("Qwen/Qwen3.5-4B", "Qwen/Qwen3.6-27B", "Qwen/Qwen3.8-27B"),
)
def test_qwen35_checkpoint_adapter_config_captures_attention_dimensions(
base_model: str,
) -> None:
runtime = _runtime()
runtime.provider.num_attention_heads = 16
runtime.provider.num_query_groups = 4
Expand All @@ -988,7 +994,7 @@ def test_qwen35_checkpoint_adapter_config_captures_attention_dimensions() -> Non
retained = trainer._validate_checkpoint_adapter_config(
"student",
{
"base_model_name_or_path": "Qwen/Qwen3.5-4B",
"base_model_name_or_path": base_model,
"r": 8,
"lora_alpha": 16,
"target_modules": ["q_proj"],
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading