fix(sampling): reject conflicting structural tag constraints (#32525)
This commit is contained in:
@@ -196,9 +196,12 @@ class SamplingParams(msgspec.Struct, kw_only=True, array_like=True):
|
||||
self.json_schema,
|
||||
self.regex,
|
||||
self.ebnf,
|
||||
self.structural_tag,
|
||||
] # since mutually exclusive, only one can be set
|
||||
if sum(x is not None for x in grammars) > 1:
|
||||
raise ValueError("Only one of regex, json_schema, or ebnf can be set.")
|
||||
raise ValueError(
|
||||
"Only one of json_schema, regex, ebnf, or structural_tag can be set."
|
||||
)
|
||||
|
||||
def normalize(self, tokenizer):
|
||||
# Process stop strings
|
||||
|
||||
@@ -77,6 +77,12 @@ class TestSamplingParamsInit(CustomTestCase):
|
||||
class TestSamplingParamsVerify(CustomTestCase):
|
||||
|
||||
VOCAB_SIZE = 32000
|
||||
GRAMMAR_VALUES = {
|
||||
"json_schema": '{"type":"object"}',
|
||||
"regex": "abc",
|
||||
"ebnf": 'root ::= "abc"',
|
||||
"structural_tag": '{"structures":[],"triggers":[]}',
|
||||
}
|
||||
|
||||
def _make(self, **kwargs):
|
||||
"""Helper: create SamplingParams with safe defaults, override with kwargs."""
|
||||
@@ -273,21 +279,25 @@ class TestSamplingParamsVerify(CustomTestCase):
|
||||
sp.verify(self.VOCAB_SIZE)
|
||||
|
||||
def test_multiple_grammars_raises(self):
|
||||
"""Test that verify() rejects setting both json_schema and regex (mutually exclusive)."""
|
||||
sp = self._make(json_schema='{"type":"object"}', regex="abc")
|
||||
with self.assertRaises(ValueError):
|
||||
sp.verify(self.VOCAB_SIZE)
|
||||
"""Reject structural_tag combined with any other grammar constraint.
|
||||
|
||||
Constraint selection is a fixed if/elif chain, so a constraint left out of
|
||||
this check is silently dropped with no error to the caller.
|
||||
"""
|
||||
for other in ("json_schema", "regex", "ebnf"):
|
||||
with self.subTest(other=other):
|
||||
sp = self._make(
|
||||
structural_tag=self.GRAMMAR_VALUES["structural_tag"],
|
||||
**{other: self.GRAMMAR_VALUES[other]},
|
||||
)
|
||||
with self.assertRaisesRegex(ValueError, "Only one of"):
|
||||
sp.verify(self.VOCAB_SIZE)
|
||||
|
||||
def test_single_grammar_valid(self):
|
||||
"""Test that setting only one grammar type is accepted."""
|
||||
sp = self._make(json_schema='{"type":"object"}')
|
||||
sp.verify(self.VOCAB_SIZE)
|
||||
|
||||
def test_all_three_grammars_set_raises(self):
|
||||
"""Test that verify() rejects setting json_schema, regex, and ebnf together."""
|
||||
sp = self._make(json_schema="{}", regex="a", ebnf="rule")
|
||||
with self.assertRaises(ValueError):
|
||||
sp.verify(self.VOCAB_SIZE)
|
||||
"""Test that each grammar constraint is valid on its own."""
|
||||
for grammar, value in self.GRAMMAR_VALUES.items():
|
||||
with self.subTest(grammar=grammar):
|
||||
self._make(**{grammar: value}).verify(self.VOCAB_SIZE)
|
||||
|
||||
|
||||
class TestSamplingParamsNormalize(CustomTestCase):
|
||||
|
||||
Reference in New Issue
Block a user