Skip to content

Commit 3a5ea75

Browse files
authored
[Feature] Support DeepSeekV3 Function Call (#17784)
Signed-off-by: 许文卿 <xwq391974@alibaba-inc.com> Signed-off-by: Xu Wenqing <xuwq1993@qq.com>
1 parent 891b9d3 commit 3a5ea75

File tree

4 files changed

+473
-1
lines changed

4 files changed

+473
-1
lines changed

docs/source/features/tool_calling.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,13 @@ For Qwen2.5, the chat template in tokenizer_config.json has already included sup
236236

237237
Flags: `--tool-call-parser hermes`
238238

239+
### DeepSeek-V3 Models (`deepseek_v3`)
240+
241+
Supported models:
242+
* `deepseek-ai/DeepSeek-V3-0324`
243+
244+
Flags: `--tool-call-parser deepseek_v3 --chat-template examples/tool_chat_template_deepseekv3.jinja`
245+
239246
### Models with Pythonic Tool Calls (`pythonic`)
240247

241248
A growing number of models output a python list to represent tool calls instead of using JSON. This has the advantage of inherently supporting parallel tool calls and removing ambiguity around the JSON schema required for tool calls. The `pythonic` tool parser can support such models.
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
{% if not add_generation_prompt is defined %}
2+
{% set add_generation_prompt = false %}
3+
{% endif %}
4+
5+
{% set ns = namespace(is_first=false, is_tool=false, is_output_first=true, system_prompt='', is_first_sp=true, is_last_user=false) %}
6+
7+
{%- for message in messages %}
8+
{%- if message['role'] == 'system' %}
9+
{%- if ns.is_first_sp %}
10+
{% set ns.system_prompt = ns.system_prompt + message['content'] %}
11+
{% set ns.is_first_sp = false %}
12+
{%- else %}
13+
{% set ns.system_prompt = ns.system_prompt + '\n\n' + message['content'] %}
14+
{%- endif %}
15+
{%- endif %}
16+
{%- endfor %}
17+
18+
{{ bos_token }}
19+
{{ ns.system_prompt }}
20+
{%- if tools %}
21+
{{"\n\n# Tools\n\nYou may call one or more functions to assist with the user query." }}
22+
{%- for tool in tools %}
23+
{{- "\n" }}
24+
{{- tool | tojson }}
25+
{%- endfor %}
26+
{{"\n</tools>\n\n"}}
27+
28+
{{"For function call returns, you should first print <|tool▁calls▁begin|>"}}
29+
30+
{{"For each function call, you should return object like:\n" }}
31+
{{"<|tool▁call▁begin|>function<|tool▁sep|><function_name>\n```json\n<function_arguments_in_json_format>\n```<|tool▁call▁end|>"}}
32+
33+
{{"At the end of function call returns, you should print <|tool▁calls▁end|><|end▁of▁sentence|>"}}
34+
{%- endif %}
35+
36+
{%- for message in messages %}
37+
{%- if message['role'] == 'user' %}
38+
{%- set ns.is_tool = false -%}
39+
{%- set ns.is_first = false -%}
40+
{%- set ns.is_last_user = true -%}
41+
{{'<|User|>' + message['content'] + '<|Assistant|>'}}
42+
{%- endif %}
43+
44+
{%- if message['role'] == 'assistant' and message['tool_calls'] is defined and message['tool_calls'] is not none %}
45+
{%- set ns.is_last_user = false -%}
46+
{%- if ns.is_tool %}
47+
{{'<|tool▁outputs▁end|>'}}
48+
{%- endif %}
49+
{%- set ns.is_first = false %}
50+
{%- set ns.is_tool = false -%}
51+
{%- set ns.is_output_first = true %}
52+
53+
{%- for tool in message['tool_calls'] %}
54+
{%- if not ns.is_first %}
55+
{%- if message['content'] is none %}
56+
{{'<|tool▁calls▁begin|><|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\n' + '```json' + '\n' + tool['function']['arguments']|tojson + '\n' + '```' + '<|tool▁call▁end|>'}}
57+
{%- else %}
58+
{{message['content'] + '<|tool▁calls▁begin|><|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\n' + '```json' + '\n' + tool['function']['arguments']|tojson + '\n' + '```' + '<|tool▁call▁end|>'}}
59+
{%- endif %}
60+
{%- set ns.is_first = true -%}
61+
{%- else %}
62+
{{'\n' + '<|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\n' + '```json' + '\n' + tool['function']['arguments']|tojson + '\n' + '```' + '<|tool▁call▁end|>'}}
63+
{%- endif %}
64+
{%- endfor %}
65+
{{'<|tool▁calls▁end|><|end▁of▁sentence|>'}}
66+
{%- endif %}
67+
{%- if message['role'] == 'assistant' and (message['tool_calls'] is not defined or message['tool_calls'] is none)%}
68+
{%- set ns.is_last_user = false -%}
69+
{%- if ns.is_tool %}
70+
{{'<|tool▁outputs▁end|>' + message['content'] + '<|end▁of▁sentence|>'}}
71+
{%- set ns.is_tool = false -%}
72+
{%- else %}
73+
{% set content = message['content'] %}
74+
{{content + '<|end▁of▁sentence|>'}}
75+
{%- endif %}
76+
{%- endif %}
77+
78+
{%- if message['role'] == 'tool' %}
79+
{%- set ns.is_last_user = false -%}
80+
{%- set ns.is_tool = true -%}
81+
{%- if ns.is_output_first %}
82+
{{'<|tool▁outputs▁begin|><|tool▁output▁begin|>' + message['content'] + '<|tool▁output▁end|>'}}
83+
{%- set ns.is_output_first = false %}
84+
{%- else %}
85+
{{'\n<|tool▁output▁begin|>' + message['content'] + '<|tool▁output▁end|>'}}
86+
{%- endif %}
87+
{%- endif %}
88+
{%- endfor -%}
89+
90+
{% if ns.is_tool %}
91+
{{'<|tool▁outputs▁end|>'}}
92+
{% endif %}
93+
94+
{% if add_generation_prompt and not ns.is_last_user and not ns.is_tool %}
95+
{{'<|Assistant|>'}}
96+
{% endif %}

vllm/entrypoints/openai/tool_parsers/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# SPDX-License-Identifier: Apache-2.0
22

33
from .abstract_tool_parser import ToolParser, ToolParserManager
4+
from .deepseekv3_tool_parser import DeepSeekV3ToolParser
45
from .granite_20b_fc_tool_parser import Granite20bFCToolParser
56
from .granite_tool_parser import GraniteToolParser
67
from .hermes_tool_parser import Hermes2ProToolParser
@@ -15,5 +16,5 @@
1516
"ToolParser", "ToolParserManager", "Granite20bFCToolParser",
1617
"GraniteToolParser", "Hermes2ProToolParser", "MistralToolParser",
1718
"Internlm2ToolParser", "Llama3JsonToolParser", "JambaToolParser",
18-
"PythonicToolParser", "Phi4MiniJsonToolParser"
19+
"PythonicToolParser", "Phi4MiniJsonToolParser", "DeepSeekV3ToolParser"
1920
]

0 commit comments

Comments
 (0)