fix(reasoning): let --enable-strict-thinking works for DeepSeek-V4 (#32400)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Xinyuan Tong <xinyuantong.cs@gmail.com>
This commit is contained in:
co-authored by
Claude Fable 5
Xinyuan Tong
parent
08af5aea57
commit
1d350aaad3
@@ -2,6 +2,14 @@ import inspect
|
|||||||
import re
|
import re
|
||||||
from typing import Dict, List, Optional, Tuple, Type
|
from typing import Dict, List, Optional, Tuple, Type
|
||||||
|
|
||||||
|
from sglang.srt.entrypoints.openai.encoding_dsv4 import dsml_token as dsv4_dsml_token
|
||||||
|
from sglang.srt.entrypoints.openai.encoding_dsv4 import eos_token as dsv4_eos_token
|
||||||
|
from sglang.srt.entrypoints.openai.encoding_dsv4 import (
|
||||||
|
thinking_end_token as dsv4_thinking_end_token,
|
||||||
|
)
|
||||||
|
from sglang.srt.entrypoints.openai.encoding_dsv4 import (
|
||||||
|
thinking_start_token as dsv4_thinking_start_token,
|
||||||
|
)
|
||||||
from sglang.srt.entrypoints.openai.protocol import ChatCompletionRequest
|
from sglang.srt.entrypoints.openai.protocol import ChatCompletionRequest
|
||||||
from sglang.srt.function_call.hunyuan_detector import resolve_hunyuan_tokens
|
from sglang.srt.function_call.hunyuan_detector import resolve_hunyuan_tokens
|
||||||
from sglang.srt.parser.harmony_parser import HarmonyParser
|
from sglang.srt.parser.harmony_parser import HarmonyParser
|
||||||
@@ -897,6 +905,29 @@ class _DeepSeekV3Detector(Qwen3Detector):
|
|||||||
self.reasoning_default = "explicit_thinking"
|
self.reasoning_default = "explicit_thinking"
|
||||||
|
|
||||||
|
|
||||||
|
class DeepSeekV4Detector(BaseReasoningFormatDetector):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
stream_reasoning: bool = True,
|
||||||
|
force_reasoning: bool = False,
|
||||||
|
continue_final_message: bool = False,
|
||||||
|
previous_content: str = "",
|
||||||
|
force_nonempty_content: bool = False,
|
||||||
|
):
|
||||||
|
super().__init__(
|
||||||
|
dsv4_thinking_start_token,
|
||||||
|
dsv4_thinking_end_token,
|
||||||
|
think_excluded_tokens=[dsv4_eos_token, dsv4_dsml_token],
|
||||||
|
force_reasoning=force_reasoning,
|
||||||
|
stream_reasoning=stream_reasoning,
|
||||||
|
continue_final_message=continue_final_message,
|
||||||
|
previous_content=previous_content,
|
||||||
|
thinks_internally=True,
|
||||||
|
reasoning_default="explicit_thinking",
|
||||||
|
force_nonempty_content=force_nonempty_content,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class _MimoDetector(Qwen3Detector):
|
class _MimoDetector(Qwen3Detector):
|
||||||
"""MIMO reuses Qwen3 tokens but requires explicit enable_thinking=True to enable."""
|
"""MIMO reuses Qwen3 tokens but requires explicit enable_thinking=True to enable."""
|
||||||
|
|
||||||
@@ -1385,7 +1416,7 @@ class ReasoningParser:
|
|||||||
"apertus2509": Apertus2509Detector,
|
"apertus2509": Apertus2509Detector,
|
||||||
"deepseek-r1": DeepSeekR1Detector,
|
"deepseek-r1": DeepSeekR1Detector,
|
||||||
"deepseek-v3": _DeepSeekV3Detector,
|
"deepseek-v3": _DeepSeekV3Detector,
|
||||||
"deepseek-v4": _DeepSeekV3Detector,
|
"deepseek-v4": DeepSeekV4Detector,
|
||||||
"glm45": Glm45Detector,
|
"glm45": Glm45Detector,
|
||||||
"hunyuan": HunyuanDetector,
|
"hunyuan": HunyuanDetector,
|
||||||
"gpt-oss": GptOssDetector,
|
"gpt-oss": GptOssDetector,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from sglang.srt.parser.reasoning_parser import (
|
|||||||
Apertus2509Detector,
|
Apertus2509Detector,
|
||||||
BaseReasoningFormatDetector,
|
BaseReasoningFormatDetector,
|
||||||
DeepSeekR1Detector,
|
DeepSeekR1Detector,
|
||||||
|
DeepSeekV4Detector,
|
||||||
Gemma4Detector,
|
Gemma4Detector,
|
||||||
Glm45Detector,
|
Glm45Detector,
|
||||||
HunyuanDetector,
|
HunyuanDetector,
|
||||||
@@ -167,6 +168,21 @@ class TestQwen3Detector(CustomTestCase):
|
|||||||
self.assertEqual(result.reasoning_text, "")
|
self.assertEqual(result.reasoning_text, "")
|
||||||
|
|
||||||
|
|
||||||
|
class TestDeepSeekV4Detector(CustomTestCase):
|
||||||
|
def test_strict_thinking_excludes_deepseek_control_tokens(self):
|
||||||
|
detector = ReasoningParser(model_type="deepseek-v4").detector
|
||||||
|
self.assertIsInstance(detector, DeepSeekV4Detector)
|
||||||
|
self.assertEqual(
|
||||||
|
detector.think_excluded_tokens,
|
||||||
|
["<|end▁of▁sentence|>", "|DSML|"],
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_thinking_stays_explicit_opt_in(self):
|
||||||
|
detector = ReasoningParser(model_type="deepseek-v4").detector
|
||||||
|
self.assertEqual(detector.reasoning_default, "explicit_thinking")
|
||||||
|
self.assertTrue(detector.thinks_internally)
|
||||||
|
|
||||||
|
|
||||||
class TestInklingDetector(CustomTestCase):
|
class TestInklingDetector(CustomTestCase):
|
||||||
def test_streaming_routes_blocks_across_all_string_boundaries(self):
|
def test_streaming_routes_blocks_across_all_string_boundaries(self):
|
||||||
detector = InklingDetector()
|
detector = InklingDetector()
|
||||||
|
|||||||
Reference in New Issue
Block a user