Add Inkling model support (#31681)
Co-authored-by: Chunan Zeng <zcnrex@gmail.com> Co-authored-by: Ke Bao <ispobaoke@gmail.com> Co-authored-by: Yanbin Jiang <jybsuper@gmail.com> Co-authored-by: Yuhao Yang <47235274+yhyang201@users.noreply.github.com> Co-authored-by: Qiaolin Yu <qiaolin.yu@radixark.ai> Co-authored-by: Zhichen Zeng <zczeng@uw.edu> Co-authored-by: Aurick Qiao <aurick@thinkingmachines.ai> Co-authored-by: Joseph <jk@thinkingmachines.ai>
This commit is contained in:
co-authored by
Chunan Zeng
Ke Bao
Yanbin Jiang
Yuhao Yang
Qiaolin Yu
Zhichen Zeng
Aurick Qiao
Joseph
parent
829e9ce9d5
commit
02236fa38c
@@ -9,6 +9,7 @@ from sglang.srt.parser.reasoning_parser import (
|
||||
Gemma4Detector,
|
||||
Glm45Detector,
|
||||
HunyuanDetector,
|
||||
InklingDetector,
|
||||
KimiDetector,
|
||||
KimiK2Detector,
|
||||
Nemotron3Detector,
|
||||
@@ -166,6 +167,89 @@ class TestQwen3Detector(CustomTestCase):
|
||||
self.assertEqual(result.reasoning_text, "")
|
||||
|
||||
|
||||
class TestInklingDetector(CustomTestCase):
|
||||
def test_streaming_routes_blocks_across_all_string_boundaries(self):
|
||||
detector = InklingDetector()
|
||||
source = (
|
||||
"<|message_model|><|content_thinking|>think<|end_message|>"
|
||||
"<|message_model|><|content_text|>answer<|end_message|>"
|
||||
"<|content_model_end_sampling|>"
|
||||
)
|
||||
reasoning = ""
|
||||
content = ""
|
||||
for char in source:
|
||||
result = detector.parse_streaming_increment(char)
|
||||
reasoning += result.reasoning_text
|
||||
content += result.normal_text
|
||||
self.assertEqual(reasoning, "think")
|
||||
self.assertEqual(content, "answer")
|
||||
|
||||
def test_tool_header_is_preserved_for_the_tool_parser(self):
|
||||
detector = InklingDetector()
|
||||
source = (
|
||||
"<|message_model|>weather<|content_invoke_tool_json|>"
|
||||
'{"name":"weather","args":{"city":"SF"}}<|end_message|>'
|
||||
)
|
||||
content = ""
|
||||
for char in source:
|
||||
content += detector.parse_streaming_increment(char).normal_text
|
||||
self.assertEqual(content, source)
|
||||
|
||||
def test_quoted_message_model_token_inside_content_is_preserved(self):
|
||||
"""Bug regression: the header branch flipped to header state on ANY
|
||||
<|message_model|> occurrence, so a literal token the model wrote
|
||||
inside a content block (e.g. quoting the protocol) silently swallowed
|
||||
all payload text up to the next control token."""
|
||||
detector = InklingDetector()
|
||||
source = (
|
||||
"<|message_model|><|content_text|>Header token: <|message_model|>"
|
||||
" then more text<|end_message|>"
|
||||
)
|
||||
result = detector.detect_and_parse(source)
|
||||
self.assertEqual(
|
||||
result.normal_text, "Header token: <|message_model|> then more text"
|
||||
)
|
||||
|
||||
def test_control_token_inside_tool_header_shares_the_full_alphabet(self):
|
||||
"""Bug regression: the tool-call detector validated headers against
|
||||
INKLING_SPECIAL_TOKENS while the reasoning parser keyed on the larger
|
||||
control alphabet (+ <|model_trigger_generation|>), so a control token
|
||||
smuggled inside a header passed one machine and not the other."""
|
||||
from sglang.srt.function_call.inkling_detector import (
|
||||
InklingDetector as ToolDetector,
|
||||
)
|
||||
|
||||
detector = ToolDetector()
|
||||
prefix, name = detector._split_trailing_tool_header(
|
||||
"<|message_model|>weather<|model_trigger_generation|>"
|
||||
)
|
||||
self.assertIsNone(name)
|
||||
|
||||
def test_continuation_stream_text_survives_chunk_boundaries(self):
|
||||
"""Bug regression: text arriving with no open block (a
|
||||
continue_final_message stream resumes MID text block) was routed to
|
||||
content only when a chunk held no control token; a chunk like
|
||||
'ld<|end_message|>' silently dropped the 'ld'. All out-of-block text
|
||||
must reach content regardless of chunking."""
|
||||
source = (
|
||||
" world<|end_message|><|message_model|><|content_text|>next<|end_message|>"
|
||||
)
|
||||
for chunks in (
|
||||
[source],
|
||||
[
|
||||
" wor",
|
||||
"ld<|end_message|>",
|
||||
"<|message_model|><|content_text|>next<|end_message|>",
|
||||
],
|
||||
list(source),
|
||||
):
|
||||
detector = InklingDetector()
|
||||
content = ""
|
||||
for chunk in chunks:
|
||||
content += detector.parse_streaming_increment(chunk).normal_text
|
||||
self.assertEqual(content, " worldnext", msg=f"chunks={chunks!r}")
|
||||
|
||||
|
||||
class TestKimiDetector(CustomTestCase):
|
||||
def setUp(self):
|
||||
self.detector = KimiDetector()
|
||||
|
||||
Reference in New Issue
Block a user