| 1 | # SPDX-License-Identifier: Apache-2.0 |
| 2 | # SPDX-FileCopyrightText: Copyright contributors to the vLLM project |
| 3 | |
| 4 | |
| 5 | import pytest |
| 6 | |
| 7 | from tests.tool_parsers.common_tests import ( |
| 8 | ToolParserTestConfig, |
| 9 | ToolParserTests, |
| 10 | ) |
| 11 | from vllm.tokenizers import TokenizerLike, get_tokenizer |
| 12 | |
| 13 | |
| 14 | class TestDeepSeekV3ToolParser(ToolParserTests): |
| 15 | @pytest.fixture(scope="class") |
| 16 | def tokenizer(self) -> TokenizerLike: |
| 17 | return get_tokenizer("deepseek-ai/DeepSeek-V3") |
| 18 | |
| 19 | @pytest.fixture |
| 20 | def test_config(self) -> ToolParserTestConfig: |
| 21 | return ToolParserTestConfig( |
| 22 | parser_name="deepseek_v3", |
| 23 | # Test data |
| 24 | no_tool_calls_output=( |
| 25 | "How can I help you today? I can check weather for you." |
| 26 | ), |
| 27 | single_tool_call_output="""<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather |
| 28 | ```json |
| 29 | {"city": "Tokyo", "unit": "celsius"} |
| 30 | ```<|tool▁call▁end|><|tool▁calls▁end|>""", |
| 31 | parallel_tool_calls_output="""<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather |
| 32 | ```json |
| 33 | {"city": "Tokyo", "unit": "celsius"} |
| 34 | ```<|tool▁call▁end|><|tool▁call▁begin|>function<|tool▁sep|>search_hotels |
| 35 | ```json |
| 36 | {"location": "Tokyo", "check_in": "2025-01-15"} |
| 37 | ```<|tool▁call▁end|><|tool▁calls▁end|>""", |
| 38 | various_data_types_output=( |
| 39 | """<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>test_function |
| 40 | ```json |
| 41 | """ |
| 42 | """{"string_field": "hello", "int_field": 42, "float_field": 3.14, """ |
| 43 | """"bool_field": true, "null_field": null, """ |
| 44 | """"array_field": ["a", "b", "c"], """ |
| 45 | """"object_field": {"nested": "value"}, """ |
| 46 | """"empty_array": [], "empty_object": {}} |
| 47 | ```<|tool▁call▁end|><|tool▁calls▁end|>""" |
| 48 | ), |
| 49 | empty_arguments_output="""<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_current_time |
| 50 | ```json |
| 51 | {} |
| 52 | ```<|tool▁call▁end|><|tool▁calls▁end|>""", |
| 53 | surrounding_text_output=( |
| 54 | """Let me check the weather for you.""" |
| 55 | """<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather |
| 56 | ```json |
| 57 | {"city": "Paris"} |
| 58 | ```<|tool▁call▁end|><|tool▁calls▁end|>""" |
| 59 | ), |
| 60 | escaped_strings_output=( |
| 61 | """<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>send_message |
| 62 | ```json |
| 63 | """ |
| 64 | """{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", """ |
| 65 | """"newline": "line1\\nline2"} |
| 66 | ```<|tool▁call▁end|><|tool▁calls▁end|>""" |
| 67 | ), |
| 68 | malformed_input_outputs=[ |
| 69 | """<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather |
| 70 | ```json |
| 71 | {"city": "Tokyo" |
| 72 | ```<|tool▁call▁end|><|tool▁calls▁end|>""", |
| 73 | """<|tool▁calls▁begin|>function<|tool▁sep|>get_weather |
| 74 | ```json |
| 75 | {"city": "Tokyo"} |
| 76 | ```<|tool▁calls▁end|>""", |
| 77 | ], |
| 78 | # Expected results |
| 79 | single_tool_call_expected_name="get_weather", |
| 80 | single_tool_call_expected_args={"city": "Tokyo", "unit": "celsius"}, |
| 81 | single_tool_call_expected_content=None, |
| 82 | parallel_tool_calls_count=2, |
| 83 | parallel_tool_calls_names=["get_weather", "search_hotels"], |
| 84 | # xfail markers |
| 85 | xfail_streaming={}, |
| 86 | xfail_nonstreaming={ |
| 87 | "test_malformed_input": ( |
| 88 | "Parser sets tools_called=True even when tool_calls is " |
| 89 | "empty (detects start token but fails to parse)" |
| 90 | ), |
| 91 | }, |
| 92 | ) |