Upgrade xgrammar to 0.2.1 (#25676)
This commit is contained in:
@@ -147,6 +147,241 @@ class ServingChatTestCase(unittest.TestCase):
|
||||
self.assertFalse(adapted.stream)
|
||||
self.assertEqual(processed, self.basic_req)
|
||||
|
||||
def test_kimi_tool_call_keeps_default_reasoning(self):
|
||||
self.template_manager.reasoning_config = ReasoningToggleConfig(
|
||||
toggle_param="thinking", default_enabled=True
|
||||
)
|
||||
self.tm.server_args.reasoning_parser = "kimi_k2"
|
||||
self.tm.server_args.tool_call_parser = "kimi_k2"
|
||||
self.chat.reasoning_parser = "kimi_k2"
|
||||
self.chat.tool_call_parser = "kimi_k2"
|
||||
|
||||
req = ChatCompletionRequest(
|
||||
model="x",
|
||||
messages=[{"role": "user", "content": "What is 2+2?"}],
|
||||
tools=[
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "add",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {"a": {"type": "integer"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
tool_choice="required",
|
||||
)
|
||||
|
||||
with patch.object(self.chat, "_process_messages") as proc_mock:
|
||||
proc_mock.return_value = MessageProcessingResult(
|
||||
"",
|
||||
[1, 2, 3],
|
||||
None,
|
||||
None,
|
||||
[],
|
||||
[],
|
||||
None,
|
||||
)
|
||||
|
||||
adapted, _ = self.chat._convert_to_internal_request(req)
|
||||
|
||||
self.assertTrue(adapted.require_reasoning)
|
||||
|
||||
def test_kimi_tool_call_keeps_explicit_reasoning(self):
|
||||
self.template_manager.reasoning_config = ReasoningToggleConfig(
|
||||
toggle_param="thinking", default_enabled=True
|
||||
)
|
||||
self.tm.server_args.reasoning_parser = "kimi_k2"
|
||||
self.tm.server_args.tool_call_parser = "kimi_k2"
|
||||
self.chat.reasoning_parser = "kimi_k2"
|
||||
self.chat.tool_call_parser = "kimi_k2"
|
||||
|
||||
req = ChatCompletionRequest(
|
||||
model="x",
|
||||
messages=[{"role": "user", "content": "What is 2+2?"}],
|
||||
tools=[
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "add",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {"a": {"type": "integer"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
tool_choice="required",
|
||||
chat_template_kwargs={"thinking": True},
|
||||
)
|
||||
|
||||
with patch.object(self.chat, "_process_messages") as proc_mock:
|
||||
proc_mock.return_value = MessageProcessingResult(
|
||||
"",
|
||||
[1, 2, 3],
|
||||
None,
|
||||
None,
|
||||
[],
|
||||
[],
|
||||
None,
|
||||
)
|
||||
|
||||
adapted, _ = self.chat._convert_to_internal_request(req)
|
||||
|
||||
self.assertTrue(adapted.require_reasoning)
|
||||
|
||||
def test_kimi_tool_call_respects_explicit_reasoning_disable(self):
|
||||
self.template_manager.reasoning_config = ReasoningToggleConfig(
|
||||
toggle_param="thinking", default_enabled=True
|
||||
)
|
||||
self.tm.server_args.reasoning_parser = "kimi_k2"
|
||||
self.tm.server_args.tool_call_parser = "kimi_k2"
|
||||
self.chat.reasoning_parser = "kimi_k2"
|
||||
self.chat.tool_call_parser = "kimi_k2"
|
||||
|
||||
req = ChatCompletionRequest(
|
||||
model="x",
|
||||
messages=[{"role": "user", "content": "What is 2+2?"}],
|
||||
tools=[
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "add",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {"a": {"type": "integer"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
tool_choice="required",
|
||||
chat_template_kwargs={"thinking": False},
|
||||
)
|
||||
|
||||
with patch.object(self.chat, "_process_messages") as proc_mock:
|
||||
proc_mock.return_value = MessageProcessingResult(
|
||||
"",
|
||||
[1, 2, 3],
|
||||
None,
|
||||
None,
|
||||
[],
|
||||
[],
|
||||
None,
|
||||
)
|
||||
|
||||
adapted, _ = self.chat._convert_to_internal_request(req)
|
||||
|
||||
self.assertFalse(adapted.require_reasoning)
|
||||
|
||||
def test_kimi_tool_call_keeps_template_default_thinking(self):
|
||||
self.template_manager.chat_template_name = None
|
||||
self.template_manager.jinja_template_content_format = "string"
|
||||
self.template_manager.reasoning_config = ReasoningToggleConfig(
|
||||
toggle_param="thinking", default_enabled=True
|
||||
)
|
||||
self.tm.server_args.reasoning_parser = "kimi_k2"
|
||||
self.tm.server_args.tool_call_parser = "kimi_k2"
|
||||
self.chat.reasoning_parser = "kimi_k2"
|
||||
self.chat.tool_call_parser = "kimi_k2"
|
||||
self.tm.tokenizer.apply_chat_template.return_value = [1, 2, 3]
|
||||
|
||||
req = ChatCompletionRequest(
|
||||
model="x",
|
||||
messages=[{"role": "user", "content": "What is 2+2?"}],
|
||||
tools=[
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "add",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {"a": {"type": "integer"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
tool_choice="required",
|
||||
)
|
||||
|
||||
self.chat._process_messages(req, is_multimodal=False)
|
||||
|
||||
kwargs = self.tm.tokenizer.apply_chat_template.call_args.kwargs
|
||||
self.assertNotIn("thinking", kwargs)
|
||||
|
||||
def test_kimi_tool_call_keeps_explicit_template_thinking(self):
|
||||
self.template_manager.chat_template_name = None
|
||||
self.template_manager.jinja_template_content_format = "string"
|
||||
self.template_manager.reasoning_config = ReasoningToggleConfig(
|
||||
toggle_param="thinking", default_enabled=True
|
||||
)
|
||||
self.tm.server_args.reasoning_parser = "kimi_k2"
|
||||
self.tm.server_args.tool_call_parser = "kimi_k2"
|
||||
self.chat.reasoning_parser = "kimi_k2"
|
||||
self.chat.tool_call_parser = "kimi_k2"
|
||||
self.tm.tokenizer.apply_chat_template.return_value = [1, 2, 3]
|
||||
|
||||
req = ChatCompletionRequest(
|
||||
model="x",
|
||||
messages=[{"role": "user", "content": "What is 2+2?"}],
|
||||
tools=[
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "add",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {"a": {"type": "integer"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
tool_choice="required",
|
||||
chat_template_kwargs={"thinking": True},
|
||||
)
|
||||
|
||||
self.chat._process_messages(req, is_multimodal=False)
|
||||
|
||||
kwargs = self.tm.tokenizer.apply_chat_template.call_args.kwargs
|
||||
self.assertTrue(kwargs["thinking"])
|
||||
|
||||
def test_kimi_tool_call_keeps_explicit_template_thinking_false(self):
|
||||
self.template_manager.chat_template_name = None
|
||||
self.template_manager.jinja_template_content_format = "string"
|
||||
self.template_manager.reasoning_config = ReasoningToggleConfig(
|
||||
toggle_param="thinking", default_enabled=True
|
||||
)
|
||||
self.tm.server_args.reasoning_parser = "kimi_k2"
|
||||
self.tm.server_args.tool_call_parser = "kimi_k2"
|
||||
self.chat.reasoning_parser = "kimi_k2"
|
||||
self.chat.tool_call_parser = "kimi_k2"
|
||||
self.tm.tokenizer.apply_chat_template.return_value = [1, 2, 3]
|
||||
|
||||
req = ChatCompletionRequest(
|
||||
model="x",
|
||||
messages=[{"role": "user", "content": "What is 2+2?"}],
|
||||
tools=[
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "add",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {"a": {"type": "integer"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
tool_choice="required",
|
||||
chat_template_kwargs={"thinking": False},
|
||||
)
|
||||
|
||||
self.chat._process_messages(req, is_multimodal=False)
|
||||
|
||||
kwargs = self.tm.tokenizer.apply_chat_template.call_args.kwargs
|
||||
self.assertFalse(kwargs["thinking"])
|
||||
|
||||
def test_jinja_uses_openai_tool_schema_first(self):
|
||||
"""Ensure Jinja chat templates receive OpenAI-shaped tools by default."""
|
||||
self.template_manager.chat_template_name = None
|
||||
@@ -225,6 +460,55 @@ class ServingChatTestCase(unittest.TestCase):
|
||||
second_tools, [tool.function.model_dump() for tool in req.tools]
|
||||
)
|
||||
|
||||
def test_xgrammar_tag_omits_reasoning_when_parser_owns_it(self):
|
||||
"""ReasonerGrammarBackend owns the thinking prefix when a parser is set."""
|
||||
self.template_manager.chat_template_name = None
|
||||
self.template_manager.jinja_template_content_format = "string"
|
||||
self.template_manager.reasoning_config = ReasoningToggleConfig(
|
||||
toggle_param="thinking", default_enabled=True
|
||||
)
|
||||
self.tm.server_args.reasoning_parser = "kimi_k2"
|
||||
self.tm.server_args.tool_call_parser = "kimi_k2"
|
||||
self.chat.reasoning_parser = "kimi_k2"
|
||||
self.chat.tool_call_parser = "kimi_k2"
|
||||
self.tm.tokenizer.apply_chat_template.return_value = [1, 2, 3]
|
||||
|
||||
req = ChatCompletionRequest(
|
||||
model="x",
|
||||
messages=[{"role": "user", "content": "What is 2+2?"}],
|
||||
tools=[
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "add",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {"type": "integer"},
|
||||
"b": {"type": "integer"},
|
||||
},
|
||||
"required": ["a", "b"],
|
||||
},
|
||||
"strict": True,
|
||||
},
|
||||
}
|
||||
],
|
||||
tool_choice="required",
|
||||
)
|
||||
|
||||
with patch(
|
||||
"sglang.srt.entrypoints.openai.serving_chat.FunctionCallParser"
|
||||
) as parser_cls:
|
||||
parser = parser_cls.return_value
|
||||
parser.get_structure_constraint.return_value = ("structural_tag", "tag")
|
||||
|
||||
self.chat._process_messages(req, is_multimodal=False)
|
||||
|
||||
parser.get_structure_constraint.assert_called_once()
|
||||
self.assertFalse(
|
||||
parser.get_structure_constraint.call_args.kwargs["thinking_mode"]
|
||||
)
|
||||
|
||||
def test_stop_str_isolation_between_requests(self):
|
||||
"""Test that stop strings from one request don't affect subsequent requests.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user