Convert SamplingParams to msgspec Struct (#29198)

Co-authored-by: Rain Jiang <96632942+rainj-me@users.noreply.github.com>
This commit is contained in:
Lianmin Zheng
2026-06-24 13:42:45 -07:00
committed by GitHub
co-authored by Rain Jiang
parent d5e9176f65
commit fd87a85388
3 changed files with 158 additions and 58 deletions
@@ -6,9 +6,12 @@ register_cpu_ci(est_time=7, suite="base-a-test-cpu")
register_cpu_ci(est_time=7, suite="base-c-test-cpu")
register_xpu_ci(est_time=10, suite="stage-a-test-1-gpu-xpu")
import copy
import unittest
from unittest.mock import MagicMock
import msgspec
from sglang.srt.sampling.sampling_params import (
MAX_LEN,
TOP_K_ALL,
@@ -363,6 +366,84 @@ class TestSamplingParamsNormalize(CustomTestCase):
self.assertEqual(sp.stop_regex_max_len, 3)
class TestSamplingParamsMsgspecStruct(CustomTestCase):
def test_copy_remains_mutable_and_independent(self):
sp = SamplingParams(max_new_tokens=8, custom_params={"a": 1})
copied = copy.copy(sp)
copied.max_new_tokens = 16
copied.custom_params = {"b": 2}
self.assertEqual(sp.max_new_tokens, 8)
self.assertEqual(sp.custom_params, {"a": 1})
self.assertEqual(copied.max_new_tokens, 16)
self.assertEqual(copied.custom_params, {"b": 2})
def test_none_values_still_use_constructor_defaults(self):
sp = SamplingParams(
temperature=None,
top_p=None,
top_k=None,
min_p=None,
frequency_penalty=None,
presence_penalty=None,
repetition_penalty=None,
min_new_tokens=None,
n=None,
ignore_eos=None,
skip_special_tokens=None,
spaces_between_special_tokens=None,
no_stop_trim=None,
)
self.assertEqual(sp.temperature, 1.0)
self.assertEqual(sp.top_p, 1.0)
self.assertEqual(sp.top_k, TOP_K_ALL)
self.assertEqual(sp.min_p, 0.0)
self.assertEqual(sp.frequency_penalty, 0.0)
self.assertEqual(sp.presence_penalty, 0.0)
self.assertEqual(sp.repetition_penalty, 1.0)
self.assertEqual(sp.min_new_tokens, 0)
self.assertEqual(sp.n, 1)
self.assertFalse(sp.ignore_eos)
self.assertTrue(sp.skip_special_tokens)
self.assertTrue(sp.spaces_between_special_tokens)
self.assertFalse(sp.no_stop_trim)
def test_msgpack_omits_default_fields(self):
encoded = msgspec.msgpack.encode(SamplingParams())
self.assertEqual(msgspec.msgpack.decode(encoded), {})
def test_msgpack_round_trip_preserves_normalized_state(self):
tokenizer = MagicMock()
tokenizer.encode.side_effect = lambda s, add_special_tokens=False: {
"hello": [101, 102],
"world": [201],
}[s]
sp = SamplingParams(
stop=["hello", "world"],
stop_regex=r"[a-z]{3}",
stop_token_ids=[1, 2],
temperature=0.5,
)
sp.normalize(tokenizer)
encoder = msgspec.msgpack.Encoder()
decoder = msgspec.msgpack.Decoder(SamplingParams)
rebuilt = decoder.decode(encoder.encode(sp))
self.assertIsInstance(rebuilt, SamplingParams)
self.assertTrue(rebuilt.is_normalized)
self.assertEqual(rebuilt.stop_strs, ["hello", "world"])
self.assertEqual(rebuilt.stop_str_max_len, 2)
self.assertEqual(rebuilt.stop_regex_strs, [r"[a-z]{3}"])
self.assertEqual(rebuilt.stop_regex_max_len, 3)
self.assertEqual(rebuilt.stop_token_ids, {1, 2})
self.assertEqual(rebuilt.temperature, 0.5)
class TestRegexMaxLength(CustomTestCase):
def test_literal_string(self):