[Kimi] Support kimi-k3 (#32541)
Co-authored-by: DarkSharpness <76582120+DarkSharpness@users.noreply.github.com> Co-authored-by: Xiaoyu Zhang <1182563586@qq.com> Co-authored-by: Mick <mickjagger19@icloud.com> Co-authored-by: Yuhao Yang <47235274+yhyang201@users.noreply.github.com> Co-authored-by: Cheng Wan <54331508+ch-wan@users.noreply.github.com> Co-authored-by: Ke Bao <ispobaoke@gmail.com> Co-authored-by: Baizhou Zhang <sobereddiezhang@gmail.com> Co-authored-by: Chunan Zeng <zcnrex@gmail.com> Co-authored-by: Khoa Pham <khoa.pham@radixark.ai> Co-authored-by: Ziyi Xu <ziyi.xu@radixark.ai> Co-authored-by: Zijie Xia <37504505+zijiexia@users.noreply.github.com> Co-authored-by: Yuwei An <ayw.sirius19@gmail.com> Co-authored-by: zhangxiaohao <1024393531@qq.com> Co-authored-by: Yangmin Li <yangminl@nvidia.com> Co-authored-by: Julien Lin <jullin@nvidia.com> Co-authored-by: Hao Phan <htphan@nvidia.com> Co-authored-by: Thomas Wang <1am9trash@gmail.com> Co-authored-by: RolaoDenthu <xinyisong0111@gmail.com> Co-authored-by: pigeonsoup <32922982+pigeonsoup@users.noreply.github.com> Co-authored-by: HaiShaw <hixiao@gmail.com> Co-authored-by: Xinyuan Tong <115166877+JustinTong0323@users.noreply.github.com> Co-authored-by: Pranjal Shankhdhar <pranjal.ssh@gmail.com> Co-authored-by: Lee Nau <lee.nau@gmail.com> Co-authored-by: HMING <126185151+Hearum@users.noreply.github.com> Co-authored-by: elvischenv <219235043+elvischenv@users.noreply.github.com> Co-authored-by: Byron Hsu <byronhsu1230@gmail.com> Co-authored-by: Byron Hsu <byron+per@periodiclabs.ai> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Thomas Wang <thomawan@amd.com> Co-authored-by: Xinyi Song <86638975+RolaoDenthu@users.noreply.github.com> Co-authored-by: Mohammad Miadh Angkad <176301910+mmangkad@users.noreply.github.com> Co-authored-by: Cheng Wan <cheng.wan@radixark.ai> Co-authored-by: BBuf <xiaoyu.zhang@radixark.ai> Co-authored-by: Hanming Lu <hanminglu@meta.com> Co-authored-by: Xinyi Song <xinyis10@illinois.edu>
This commit is contained in:
co-authored by
DarkSharpness
Xiaoyu Zhang
Mick
Yuhao Yang
Cheng Wan
Ke Bao
Baizhou Zhang
Chunan Zeng
Khoa Pham
Ziyi Xu
Zijie Xia
Yuwei An
zhangxiaohao
Yangmin Li
Julien Lin
Hao Phan
Thomas Wang
RolaoDenthu
pigeonsoup
HaiShaw
Xinyuan Tong
Pranjal Shankhdhar
Lee Nau
HMING
elvischenv
Byron Hsu
Byron Hsu
Claude Opus 5
Thomas Wang
Xinyi Song
Mohammad Miadh Angkad
Cheng Wan
BBuf
Hanming Lu
Xinyi Song
parent
0753663b8e
commit
abddb1c7e9
@@ -1,102 +0,0 @@
|
||||
"""Unit tests for DCP (Decode Context Parallelism) server args configuration.
|
||||
|
||||
Covers the ``--dcp-comm-backend`` field ({ag_rs, a2a, fi_a2a}) and its
|
||||
validation in ``ServerArgs._handle_dcp_validation``:
|
||||
- a2a / fi_a2a require --dcp-size > 1
|
||||
- fi_a2a requires a CUDA platform (the authoritative MNNVL fabric probe runs
|
||||
later, at model-runner init)
|
||||
- dcp>1 requires CUDA or HIP (base behavior from the merged DCP PR)
|
||||
|
||||
Tests construct with safe defaults (dcp_size=1) then mutate the fields and call
|
||||
``_handle_dcp_validation`` directly, so construction never trips the platform
|
||||
gate; is_cuda / is_hip are patched per-test to pin the platform deterministically
|
||||
(these are CPU-CI tests, where the real is_cuda() is False).
|
||||
"""
|
||||
|
||||
import dataclasses
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from sglang.srt.server_args import ServerArgs
|
||||
from sglang.test.ci.ci_register import register_cpu_ci
|
||||
from sglang.test.test_utils import CustomTestCase
|
||||
|
||||
register_cpu_ci(est_time=5, suite="base-a-test-cpu")
|
||||
|
||||
_mock_device = patch("sglang.srt.server_args.get_device", return_value="cuda")
|
||||
_mock_device.start()
|
||||
|
||||
|
||||
class TestDCPFieldDefaults(CustomTestCase):
|
||||
"""Verify DCP-related dataclass fields exist with correct defaults."""
|
||||
|
||||
def test_dcp_size_field_exists(self):
|
||||
fields = {f.name for f in dataclasses.fields(ServerArgs)}
|
||||
self.assertIn("dcp_size", fields)
|
||||
|
||||
def test_dcp_comm_backend_field_exists(self):
|
||||
fields = {f.name for f in dataclasses.fields(ServerArgs)}
|
||||
self.assertIn("dcp_comm_backend", fields)
|
||||
|
||||
def test_dcp_size_default(self):
|
||||
self.assertEqual(ServerArgs.dcp_size, 1)
|
||||
|
||||
def test_dcp_comm_backend_default(self):
|
||||
self.assertEqual(ServerArgs.dcp_comm_backend, "ag_rs")
|
||||
|
||||
|
||||
class TestDCPCommBackendValidation(CustomTestCase):
|
||||
"""Verify ``_handle_dcp_validation`` accepts/rejects the right combos."""
|
||||
|
||||
@staticmethod
|
||||
def _make_args(dcp_size, dcp_comm_backend):
|
||||
# Construct with safe defaults (dcp_size=1) so __post_init__ never trips
|
||||
# the dcp>1 platform gate, then set the fields under test.
|
||||
args = ServerArgs(model_path="dummy")
|
||||
args.dcp_size = dcp_size
|
||||
args.dcp_comm_backend = dcp_comm_backend
|
||||
return args
|
||||
|
||||
def test_a2a_requires_dcp_size_gt_1(self):
|
||||
args = self._make_args(dcp_size=1, dcp_comm_backend="a2a")
|
||||
with self.assertRaises(ValueError):
|
||||
args._handle_dcp_validation()
|
||||
|
||||
def test_fi_a2a_requires_dcp_size_gt_1(self):
|
||||
args = self._make_args(dcp_size=1, dcp_comm_backend="fi_a2a")
|
||||
with self.assertRaises(ValueError):
|
||||
args._handle_dcp_validation()
|
||||
|
||||
@patch("sglang.srt.server_args.is_hip", return_value=False)
|
||||
@patch("sglang.srt.server_args.is_cuda", return_value=True)
|
||||
def test_a2a_with_dcp_size_2_on_cuda_passes(self, *_):
|
||||
args = self._make_args(dcp_size=2, dcp_comm_backend="a2a")
|
||||
args._handle_dcp_validation() # no raise
|
||||
self.assertEqual(args.dcp_comm_backend, "a2a")
|
||||
|
||||
@patch("sglang.srt.server_args.is_hip", return_value=False)
|
||||
@patch("sglang.srt.server_args.is_cuda", return_value=True)
|
||||
def test_fi_a2a_with_dcp_size_2_on_cuda_passes_server_args(self, *_):
|
||||
# server_args accepts fi_a2a on CUDA; the MNNVL fabric probe is deferred
|
||||
# to model-runner init (init_fi_a2a_workspace).
|
||||
args = self._make_args(dcp_size=2, dcp_comm_backend="fi_a2a")
|
||||
args._handle_dcp_validation() # no raise
|
||||
self.assertEqual(args.dcp_comm_backend, "fi_a2a")
|
||||
|
||||
@patch("sglang.srt.server_args.is_hip", return_value=False)
|
||||
@patch("sglang.srt.server_args.is_cuda", return_value=False)
|
||||
def test_fi_a2a_on_non_cuda_raises(self, *_):
|
||||
args = self._make_args(dcp_size=2, dcp_comm_backend="fi_a2a")
|
||||
with self.assertRaises(ValueError):
|
||||
args._handle_dcp_validation()
|
||||
|
||||
@patch("sglang.srt.server_args.is_hip", return_value=False)
|
||||
@patch("sglang.srt.server_args.is_cuda", return_value=True)
|
||||
def test_ag_rs_with_dcp_size_8_on_cuda_passes(self, *_):
|
||||
args = self._make_args(dcp_size=8, dcp_comm_backend="ag_rs")
|
||||
args._handle_dcp_validation() # no raise
|
||||
self.assertEqual(args.dcp_size, 8)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,89 @@
|
||||
"""Unit tests for the MNNVL auto-inference gate.
|
||||
|
||||
The TP8 best-throughput launch used to require exporting
|
||||
``SGLANG_ENABLE_CUSTOM_ALL_REDUCE_V2_MULTINODE=1`` by hand. It is now
|
||||
capability-inferred; these cases pin the negative-branch contracts so a
|
||||
refactor cannot silently turn the predicate into always-true (engaging fabric
|
||||
paths on non-fabric clusters) or drop the explicit-off override.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
from sglang.srt.environ import envs
|
||||
from sglang.srt.server_args import ServerArgs
|
||||
from sglang.test.ci.ci_register import register_cpu_ci
|
||||
from sglang.test.test_utils import CustomTestCase
|
||||
|
||||
register_cpu_ci(est_time=5, suite="base-a-test-cpu")
|
||||
|
||||
_HANDLE = ServerArgs._handle_custom_all_reduce_v2_multinode
|
||||
|
||||
|
||||
def _cleared(*fields):
|
||||
"""Context helper: run with the given env fields unset, restore after."""
|
||||
import contextlib
|
||||
import os
|
||||
|
||||
@contextlib.contextmanager
|
||||
def ctx():
|
||||
backup = {f.name: os.environ.pop(f.name, None) for f in fields}
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
for name, val in backup.items():
|
||||
if val is None:
|
||||
os.environ.pop(name, None)
|
||||
else:
|
||||
os.environ[name] = val
|
||||
|
||||
return ctx()
|
||||
|
||||
|
||||
class TestCaV2MultinodeAuto(CustomTestCase):
|
||||
def test_fabric_multinode_auto_enables(self):
|
||||
"""GB200/GB300 + nnodes>1 + unset opt-in -> multinode mode on, v2 kept."""
|
||||
with _cleared(
|
||||
envs.SGLANG_ENABLE_CUSTOM_ALL_REDUCE_V2_MULTINODE,
|
||||
envs.SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2,
|
||||
), patch("sglang.srt.server_args.is_mnnvl_fabric_device", return_value=True):
|
||||
_HANDLE(SimpleNamespace(nnodes=2, tp_size=8))
|
||||
self.assertTrue(envs.SGLANG_ENABLE_CUSTOM_ALL_REDUCE_V2_MULTINODE.get())
|
||||
self.assertTrue(envs.SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2.get())
|
||||
|
||||
def test_non_fabric_multinode_still_disables_v2(self):
|
||||
"""Non-fabric multi-node keeps the legacy force-disable (the predicate
|
||||
must not degrade to always-true)."""
|
||||
with _cleared(
|
||||
envs.SGLANG_ENABLE_CUSTOM_ALL_REDUCE_V2_MULTINODE,
|
||||
envs.SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2,
|
||||
), patch("sglang.srt.server_args.is_mnnvl_fabric_device", return_value=False):
|
||||
_HANDLE(SimpleNamespace(nnodes=2, tp_size=8))
|
||||
self.assertFalse(envs.SGLANG_ENABLE_CUSTOM_ALL_REDUCE_V2_MULTINODE.get())
|
||||
self.assertFalse(envs.SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2.get())
|
||||
|
||||
def test_explicit_off_wins_over_fabric(self):
|
||||
"""SGLANG_ENABLE_CUSTOM_ALL_REDUCE_V2_MULTINODE=0 on a fabric device
|
||||
must still force-disable v2 (explicit off beats auto-detection)."""
|
||||
with _cleared(envs.SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2), patch(
|
||||
"sglang.srt.server_args.is_mnnvl_fabric_device", return_value=True
|
||||
), envs.SGLANG_ENABLE_CUSTOM_ALL_REDUCE_V2_MULTINODE.override("0"):
|
||||
_HANDLE(SimpleNamespace(nnodes=2, tp_size=8))
|
||||
self.assertFalse(envs.SGLANG_ENABLE_CUSTOM_ALL_REDUCE_V2_MULTINODE.get())
|
||||
self.assertFalse(envs.SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2.get())
|
||||
|
||||
def test_tp16_not_auto_opted_in(self):
|
||||
"""CustomAllReduceV2 supports world sizes 2..8 only; a TP16 fabric
|
||||
launch must not auto-set the multinode opt-in (it would log
|
||||
'enabling' and then silently fall back downstream)."""
|
||||
with _cleared(
|
||||
envs.SGLANG_ENABLE_CUSTOM_ALL_REDUCE_V2_MULTINODE,
|
||||
envs.SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2,
|
||||
), patch("sglang.srt.server_args.is_mnnvl_fabric_device", return_value=True):
|
||||
_HANDLE(SimpleNamespace(nnodes=2, tp_size=16))
|
||||
self.assertFalse(envs.SGLANG_ENABLE_CUSTOM_ALL_REDUCE_V2_MULTINODE.is_set())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user