diff --git a/tensorrt_llm/serve/tool_parser/deepseekv3_parser.py b/tensorrt_llm/serve/tool_parser/deepseekv3_parser.py index 8cbe2a8c2aef..956dec7ef33a 100644 --- a/tensorrt_llm/serve/tool_parser/deepseekv3_parser.py +++ b/tensorrt_llm/serve/tool_parser/deepseekv3_parser.py @@ -109,7 +109,7 @@ def parse_streaming_increment(self, new_text: str, tools: List[Tool]) -> Streami return StreamingParseResult() normal_text = current_text self._buffer = "" - for e_token in [self.eot_token, "```", "<|tool▁call▁end|>"]: + for e_token in [self.eot_token, "<|tool▁call▁end|>"]: normal_text = normal_text.replace(e_token, "") return StreamingParseResult(normal_text=normal_text) diff --git a/tests/unittest/llmapi/apps/test_tool_parsers.py b/tests/unittest/llmapi/apps/test_tool_parsers.py index ccc82e9adc7e..adababa706e2 100644 --- a/tests/unittest/llmapi/apps/test_tool_parsers.py +++ b/tests/unittest/llmapi/apps/test_tool_parsers.py @@ -1899,6 +1899,22 @@ def test_deepseek_streaming_preserves_withheld_text( sample_tools).normal_text == expected +@pytest.mark.parametrize( + "parser_cls", + [DeepSeekV3Parser, DeepSeekV31Parser, DeepSeekV32Parser, DeepSeekV4Parser]) +def test_deepseek_streaming_keeps_markdown_fences( + sample_tools: list[ChatCompletionToolsParam], + parser_cls: type[BaseToolParser]) -> None: + """Content without tool-call markup is streamed verbatim.""" + text = "Here is the code:\n```python\nprint(1)\n```\nDone." + + streamed = parser_cls().parse_streaming_increment(text, + sample_tools).normal_text + + assert streamed == text, f"Expected {text!r}, got {streamed!r}" + assert parser_cls().detect_and_parse(text, sample_tools).normal_text == text + + @pytest.mark.parametrize( "parser_cls, tool_call_text", [