@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / e2db2b4234
Fork 0

A high-throughput and memory-efficient inference and serving engine for LLMs

Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git

Synced Nov 5, 23:30 UTC

[Tool Parser][1/3] Pass tools to ToolParser constructor (#38029)

Signed-off-by: sfeng33 <4florafeng@gmail.com>

Flora Feng committed Mar 25, 2026 at 22:29 UTC e2db2b42347ae27da3083c530c71b251861ed220
38 files changed +147 -92
vllm/entrypoints/openai/chat_completion/serving.py
+2 -2
@@ -565,7 +565,7 @@ class OpenAIServingChat(OpenAIServing):
565 )
566
567 tool_parsers: list[ToolParser | None] = [
568 - self.tool_parser(tokenizer)
568 + self.tool_parser(tokenizer, request.tools)
569 ] * num_choices
570 else:
571 tool_parsers = [None] * num_choices
@@ -1331,7 +1331,7 @@ class OpenAIServingChat(OpenAIServing):
1331 "Tokenizer not available when `skip_tokenizer_init=True`"
1332 )
1333
1334 - tool_parser = self.tool_parser(tokenizer)
1334 + tool_parser = self.tool_parser(tokenizer, request.tools)
1335 # NOTE: We use token_ids for openai tool parser
1336 tool_call_info = tool_parser.extract_tool_calls(
1337 "",
vllm/entrypoints/openai/engine/serving.py
+1 -1
@@ -925,7 +925,7 @@ class OpenAIServing:
925
926 # Automatic Tool Call Parsing
927 try:
928 - tool_parser = tool_parser_cls(tokenizer)
928 + tool_parser = tool_parser_cls(tokenizer, request.tools)
929 except RuntimeError as e:
930 logger.exception("Error in tool parser creation.")
931 raise e
vllm/entrypoints/openai/parser/responses_parser.py
+1 -1
@@ -52,7 +52,7 @@ class ResponsesParser:
52 self.reasoning_parser_instance = reasoning_parser_cls(tokenizer)
53 self.tool_parser_instance = None
54 if tool_parser_cls is not None:
55 - self.tool_parser_instance = tool_parser_cls(tokenizer)
55 + self.tool_parser_instance = tool_parser_cls(tokenizer, request.tools)
56
57 # Store the last finish_reason to determine response status
58 self.finish_reason: str | None = None
vllm/entrypoints/openai/responses/serving.py
+1 -1
@@ -1344,7 +1344,7 @@ class OpenAIServingResponses(OpenAIServing):
1344 reasoning_parser = self.parser.reasoning_parser_cls(tokenizer)
1345 tool_parser = None
1346 if self.parser and self.parser.tool_parser_cls:
1347 - tool_parser = self.parser.tool_parser_cls(tokenizer)
1347 + tool_parser = self.parser.tool_parser_cls(tokenizer, request.tools)
1348 reasoning_ended = False
1349 tool_call_text_started = False
1350 previous_text = ""
vllm/entrypoints/serve/render/serving.py
+3 -1
@@ -545,6 +545,8 @@ class OpenAIServingRender:
545 )
546 raise NotImplementedError(msg)
547 tokenizer = renderer.get_tokenizer()
548 - request = tool_parser(tokenizer).adjust_request(request=request) # type: ignore[arg-type]
548 + request = tool_parser(tokenizer, request.tools).adjust_request(
549 + request=request # type: ignore[arg-type]
550 + )
551
552 return conversation, [engine_input]
vllm/tool_parsers/abstract_tool_parser.py
+14 -2
@@ -5,13 +5,18 @@ import importlib
5 import os
6 from collections.abc import Callable, Sequence
7 from functools import cached_property
8 +from typing import TypeAlias
9
10 from openai.types.responses import (
11 ResponseFormatTextJSONSchemaConfig,
12 ResponseTextConfig,
13 )
14 +from openai.types.responses.tool import Tool as ResponsesTool
15
14 -from vllm.entrypoints.openai.chat_completion.protocol import ChatCompletionRequest
16 +from vllm.entrypoints.openai.chat_completion.protocol import (
17 + ChatCompletionRequest,
18 + ChatCompletionToolsParam,
19 +)
20 from vllm.entrypoints.openai.engine.protocol import (
21 DeltaMessage,
22 ExtractedToolCallInformation,
@@ -30,6 +35,8 @@ from vllm.utils.import_utils import import_from_path
35
36 logger = init_logger(__name__)
37
38 +Tool: TypeAlias = ChatCompletionToolsParam | ResponsesTool
39 +
40
41 class ToolParser:
42 """
@@ -38,7 +45,11 @@ class ToolParser:
45 derived classes.
46 """
47
41 - def __init__(self, tokenizer: TokenizerLike):
48 + def __init__(
49 + self,
50 + tokenizer: TokenizerLike,
51 + tools: list[Tool] | None = None,
52 + ):
53 self.prev_tool_call_arr: list[dict] = []
54 # the index of the tool call that is currently being parsed
55 self.current_tool_id: int = -1
@@ -46,6 +57,7 @@ class ToolParser:
57 self.streamed_args_for_tool: list[str] = []
58
59 self.model_tokenizer = tokenizer
60 + self.tools = tools
61
62 @cached_property
63 def vocab(self) -> dict[str, int]:
vllm/tool_parsers/deepseekv31_tool_parser.py
+3 -3
@@ -19,14 +19,14 @@ from vllm.entrypoints.openai.engine.protocol import (
19 )
20 from vllm.logger import init_logger
21 from vllm.tokenizers import TokenizerLike
22 -from vllm.tool_parsers.abstract_tool_parser import ToolParser
22 +from vllm.tool_parsers.abstract_tool_parser import Tool, ToolParser
23
24 logger = init_logger(__name__)
25
26
27 class DeepSeekV31ToolParser(ToolParser):
28 - def __init__(self, tokenizer: TokenizerLike):
29 - super().__init__(tokenizer)
28 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
29 + super().__init__(tokenizer, tools)
30
31 self.current_tool_name_sent: bool = False
32 self.prev_tool_call_arr: list[dict] = []
vllm/tool_parsers/deepseekv32_tool_parser.py
+3 -2
@@ -22,6 +22,7 @@ from vllm.entrypoints.openai.engine.protocol import (
22 from vllm.logger import init_logger
23 from vllm.tokenizers import TokenizerLike
24 from vllm.tool_parsers.abstract_tool_parser import (
25 + Tool,
26 ToolParser,
27 )
28
@@ -43,8 +44,8 @@ class DeepSeekV32ToolParser(ToolParser):
44 </|DSML|function_calls>
45 """
46
46 - def __init__(self, tokenizer: TokenizerLike):
47 - super().__init__(tokenizer)
47 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
48 + super().__init__(tokenizer, tools)
49
50 self.prev_tool_call_arr: list[dict] = []
51
vllm/tool_parsers/deepseekv3_tool_parser.py
+3 -2
@@ -20,6 +20,7 @@ from vllm.entrypoints.openai.engine.protocol import (
20 from vllm.logger import init_logger
21 from vllm.tokenizers import TokenizerLike
22 from vllm.tool_parsers.abstract_tool_parser import (
23 + Tool,
24 ToolParser,
25 )
26
@@ -27,8 +28,8 @@ logger = init_logger(__name__)
28
29
30 class DeepSeekV3ToolParser(ToolParser):
30 - def __init__(self, tokenizer: TokenizerLike):
31 - super().__init__(tokenizer)
31 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
32 + super().__init__(tokenizer, tools)
33
34 self.current_tool_name_sent: bool = False
35 self.prev_tool_call_arr: list[dict] = []
vllm/tool_parsers/ernie45_tool_parser.py
+3 -2
@@ -20,6 +20,7 @@ from vllm.entrypoints.openai.engine.protocol import (
20 from vllm.logger import init_logger
21 from vllm.tokenizers import TokenizerLike
22 from vllm.tool_parsers.abstract_tool_parser import (
23 + Tool,
24 ToolParser,
25 )
26
@@ -27,12 +28,12 @@ logger = init_logger(__name__)
28
29
30 class Ernie45ToolParser(ToolParser):
30 - def __init__(self, tokenizer: TokenizerLike):
31 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
32 """
33 Ernie thinking model format:
34 abc\n</think>\n\n\n<tool_call>\ndef\n</tool_call>\n
35 """
35 - super().__init__(tokenizer)
36 + super().__init__(tokenizer, tools)
37 self.current_tool_name_sent = False
38 self.prev_tool_call_arr: list[dict] = []
39 self.current_tool_id = -1
vllm/tool_parsers/functiongemma_tool_parser.py
+3 -3
@@ -20,7 +20,7 @@ from vllm.entrypoints.openai.engine.protocol import (
20 )
21 from vllm.logger import init_logger
22 from vllm.tokenizers import TokenizerLike
23 -from vllm.tool_parsers.abstract_tool_parser import ToolParser
23 +from vllm.tool_parsers.abstract_tool_parser import Tool, ToolParser
24
25 logger = init_logger(__name__)
26
@@ -33,8 +33,8 @@ class FunctionGemmaToolParser(ToolParser):
33 <start_function_call>call:func_name{param:<escape>value<escape>}<end_function_call>
34 """
35
36 - def __init__(self, tokenizer: TokenizerLike):
37 - super().__init__(tokenizer)
36 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
37 + super().__init__(tokenizer, tools)
38
39 # Streaming state
40 self.current_tool_name_sent: bool = False
vllm/tool_parsers/gigachat3_tool_parser.py
+3 -3
@@ -20,7 +20,7 @@ from vllm.entrypoints.openai.engine.protocol import (
20 )
21 from vllm.logger import init_logger
22 from vllm.tokenizers import TokenizerLike
23 -from vllm.tool_parsers.abstract_tool_parser import ToolParser
23 +from vllm.tool_parsers.abstract_tool_parser import Tool, ToolParser
24
25 logger = init_logger(__name__)
26
@@ -46,8 +46,8 @@ ARGS_REGEX = re.compile(
46
47
48 class GigaChat3ToolParser(ToolParser):
49 - def __init__(self, tokenizer: TokenizerLike):
50 - super().__init__(tokenizer)
49 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
50 + super().__init__(tokenizer, tools)
51 self.tool_started: bool = False
52 self.tool_name_sent: bool = False
53 self.tool_id: str | None = None
vllm/tool_parsers/glm47_moe_tool_parser.py
+3 -2
@@ -16,14 +16,15 @@ import regex as re
16
17 from vllm.logger import init_logger
18 from vllm.tokenizers import TokenizerLike
19 +from vllm.tool_parsers.abstract_tool_parser import Tool
20 from vllm.tool_parsers.glm4_moe_tool_parser import Glm4MoeModelToolParser
21
22 logger = init_logger(__name__)
23
24
25 class Glm47MoeModelToolParser(Glm4MoeModelToolParser):
25 - def __init__(self, tokenizer: TokenizerLike):
26 - super().__init__(tokenizer)
26 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
27 + super().__init__(tokenizer, tools)
28 # GLM-4.7 format: <tool_call>func_name[<arg_key>...]*</tool_call>
29 # The function name can be followed by a newline, whitespace, or
30 # directly by <arg_key> tags (no separator). The arg section is
vllm/tool_parsers/glm4_moe_tool_parser.py
+4 -4
@@ -21,7 +21,6 @@ import regex as re
21 from vllm.entrypoints.chat_utils import make_tool_call_id
22 from vllm.entrypoints.openai.chat_completion.protocol import (
23 ChatCompletionRequest,
24 - ChatCompletionToolsParam,
24 )
25 from vllm.entrypoints.openai.engine.protocol import (
26 DeltaFunctionCall,
@@ -34,6 +33,7 @@ from vllm.entrypoints.openai.engine.protocol import (
33 from vllm.logger import init_logger
34 from vllm.tokenizers import TokenizerLike
35 from vllm.tool_parsers.abstract_tool_parser import (
36 + Tool,
37 ToolParser,
38 )
39
@@ -48,8 +48,8 @@ class Glm4MoeModelToolParser(ToolParser):
48 rather than waiting for the complete </arg_value> tag.
49 """
50
51 - def __init__(self, tokenizer: TokenizerLike):
52 - super().__init__(tokenizer)
51 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
52 + super().__init__(tokenizer, tools)
53 # Stateful streaming fields
54 self.current_tool_name_sent: bool = False
55 self.prev_tool_call_arr: list[dict[str, Any]] = []
@@ -122,7 +122,7 @@ class Glm4MoeModelToolParser(ToolParser):
122 def _is_string_type(
123 tool_name: str,
124 arg_name: str,
125 - tools: list[ChatCompletionToolsParam] | None,
125 + tools: list[Tool] | None,
126 ) -> bool:
127 if tools is None:
128 return False
vllm/tool_parsers/granite4_tool_parser.py
+3 -2
@@ -22,6 +22,7 @@ from vllm.entrypoints.openai.engine.protocol import (
22 from vllm.logger import init_logger
23 from vllm.tokenizers import TokenizerLike
24 from vllm.tool_parsers.abstract_tool_parser import (
25 + Tool,
26 ToolParser,
27 )
28
@@ -43,8 +44,8 @@ FuncT = TypeVar("FuncT", bound=_FunctionCallCtor)
44
45
46 class Granite4ToolParser(ToolParser):
46 - def __init__(self, tokenizer: TokenizerLike):
47 - super().__init__(tokenizer)
47 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
48 + super().__init__(tokenizer, tools)
49
50 self.prev_tool_call_arr: list[dict] = []
51 self.current_tool_id: int = -1
vllm/tool_parsers/granite_20b_fc_tool_parser.py
+3 -2
@@ -24,6 +24,7 @@ from vllm.entrypoints.openai.engine.protocol import (
24 from vllm.logger import init_logger
25 from vllm.tokenizers import TokenizerLike
26 from vllm.tool_parsers.abstract_tool_parser import (
27 + Tool,
28 ToolParser,
29 )
30 from vllm.tool_parsers.utils import (
@@ -46,8 +47,8 @@ class Granite20bFCToolParser(ToolParser):
47 are all set
48 """
49
49 - def __init__(self, tokenizer: TokenizerLike):
50 - super().__init__(tokenizer)
50 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
51 + super().__init__(tokenizer, tools)
52
53 self.bot_token = "<function_call>"
54 self.tool_start_token = self.bot_token
vllm/tool_parsers/granite_tool_parser.py
+3 -2
@@ -22,6 +22,7 @@ from vllm.entrypoints.openai.engine.protocol import (
22 from vllm.logger import init_logger
23 from vllm.tokenizers import TokenizerLike
24 from vllm.tool_parsers.abstract_tool_parser import (
25 + Tool,
26 ToolParser,
27 )
28 from vllm.tool_parsers.utils import (
@@ -44,8 +45,8 @@ class GraniteToolParser(ToolParser):
45 are all set
46 """
47
47 - def __init__(self, tokenizer: TokenizerLike):
48 - super().__init__(tokenizer)
48 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
49 + super().__init__(tokenizer, tools)
50 # for granite 3.0, the token `<|tool_call|>`
51 self.bot_token = "<|tool_call|>"
52 # for granite 3.1, the string `<tool_call>`
vllm/tool_parsers/hermes_tool_parser.py
+3 -2
@@ -23,6 +23,7 @@ from vllm.entrypoints.openai.engine.protocol import (
23 from vllm.logger import init_logger
24 from vllm.tokenizers import TokenizerLike
25 from vllm.tool_parsers.abstract_tool_parser import (
26 + Tool,
27 ToolParser,
28 )
29 from vllm.utils.mistral import is_mistral_tokenizer
@@ -31,8 +32,8 @@ logger = init_logger(__name__)
32
33
34 class Hermes2ProToolParser(ToolParser):
34 - def __init__(self, tokenizer: TokenizerLike):
35 - super().__init__(tokenizer)
35 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
36 + super().__init__(tokenizer, tools)
37
38 if is_mistral_tokenizer(tokenizer):
39 logger.error("Detected Mistral tokenizer when using a Hermes model")
vllm/tool_parsers/hunyuan_a13b_tool_parser.py
+3 -2
@@ -22,6 +22,7 @@ from vllm.entrypoints.openai.engine.protocol import (
22 from vllm.logger import init_logger
23 from vllm.tokenizers import TokenizerLike
24 from vllm.tool_parsers.abstract_tool_parser import (
25 + Tool,
26 ToolParser,
27 )
28 from vllm.tool_parsers.utils import consume_space
@@ -31,8 +32,8 @@ logger = init_logger(__name__)
32
33
34 class HunyuanA13BToolParser(ToolParser):
34 - def __init__(self, tokenizer: TokenizerLike):
35 - super().__init__(tokenizer)
35 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
36 + super().__init__(tokenizer, tools)
37
38 # Initialize state for streaming mode
39 self.prev_tool_calls: list[dict] = []
vllm/tool_parsers/internlm2_tool_parser.py
+3 -2
@@ -22,6 +22,7 @@ from vllm.entrypoints.openai.engine.protocol import (
22 from vllm.logger import init_logger
23 from vllm.tokenizers import TokenizerLike
24 from vllm.tool_parsers.abstract_tool_parser import (
25 + Tool,
26 ToolParser,
27 )
28 from vllm.tool_parsers.utils import extract_intermediate_diff
@@ -30,8 +31,8 @@ logger = init_logger(__name__)
31
32
33 class Internlm2ToolParser(ToolParser):
33 - def __init__(self, tokenizer: TokenizerLike):
34 - super().__init__(tokenizer)
34 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
35 + super().__init__(tokenizer, tools)
36 self.position = 0
37
38 def adjust_request(self, request: ChatCompletionRequest) -> ChatCompletionRequest:
vllm/tool_parsers/jamba_tool_parser.py
+3 -3
@@ -22,7 +22,7 @@ from vllm.entrypoints.openai.engine.protocol import (
22 )
23 from vllm.logger import init_logger
24 from vllm.tokenizers import TokenizerLike
25 -from vllm.tool_parsers import ToolParser
25 +from vllm.tool_parsers.abstract_tool_parser import Tool, ToolParser
26 from vllm.tool_parsers.utils import extract_intermediate_diff
27 from vllm.utils.mistral import is_mistral_tokenizer
28
@@ -30,8 +30,8 @@ logger = init_logger(__name__)
30
31
32 class JambaToolParser(ToolParser):
33 - def __init__(self, tokenizer: TokenizerLike):
34 - super().__init__(tokenizer)
33 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
34 + super().__init__(tokenizer, tools)
35
36 if is_mistral_tokenizer(self.model_tokenizer):
37 raise ValueError(
vllm/tool_parsers/kimi_k2_tool_parser.py
+3 -2
@@ -20,6 +20,7 @@ from vllm.entrypoints.openai.engine.protocol import (
20 from vllm.logger import init_logger
21 from vllm.tokenizers import TokenizerLike
22 from vllm.tool_parsers.abstract_tool_parser import (
23 + Tool,
24 ToolParser,
25 )
26
@@ -27,8 +28,8 @@ logger = init_logger(__name__)
28
29
30 class KimiK2ToolParser(ToolParser):
30 - def __init__(self, tokenizer: TokenizerLike):
31 - super().__init__(tokenizer)
31 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
32 + super().__init__(tokenizer, tools)
33 self.current_tool_name_sent: bool = False
34 self.prev_tool_call_arr: list[dict] = []
35 self.current_tool_id: int = -1
vllm/tool_parsers/llama4_pythonic_tool_parser.py
+7 -2
@@ -17,6 +17,7 @@ from vllm.entrypoints.openai.engine.protocol import (
17 )
18 from vllm.logger import init_logger
19 from vllm.tool_parsers.abstract_tool_parser import (
20 + Tool,
21 ToolParser,
22 )
23 from vllm.tool_parsers.utils import (
@@ -47,8 +48,12 @@ class Llama4PythonicToolParser(ToolParser):
48 re.DOTALL,
49 )
50
50 - def __init__(self, tokenizer: PreTrainedTokenizerBase):
51 - super().__init__(tokenizer)
51 + def __init__(
52 + self,
53 + tokenizer: PreTrainedTokenizerBase,
54 + tools: list[Tool] | None = None,
55 + ):
56 + super().__init__(tokenizer, tools)
57
58 # Rename for readability. This is NOT a tool id.
59 @property
vllm/tool_parsers/llama_tool_parser.py
+7 -2
@@ -24,6 +24,7 @@ from vllm.entrypoints.openai.engine.protocol import (
24 )
25 from vllm.logger import init_logger
26 from vllm.tool_parsers.abstract_tool_parser import (
27 + Tool,
28 ToolParser,
29 )
30 from vllm.tool_parsers.utils import (
@@ -44,8 +45,12 @@ class Llama3JsonToolParser(ToolParser):
45 llama4_json are set.
46 """
47
47 - def __init__(self, tokenizer: PreTrainedTokenizerBase):
48 - super().__init__(tokenizer)
48 + def __init__(
49 + self,
50 + tokenizer: PreTrainedTokenizerBase,
51 + tools: list[Tool] | None = None,
52 + ):
53 + super().__init__(tokenizer, tools)
54
55 # initialize properties used for state when parsing tool calls in
56 # streaming mode
vllm/tool_parsers/longcat_tool_parser.py
+3 -2
@@ -4,12 +4,13 @@
4 import regex as re
5
6 from vllm.tokenizers import TokenizerLike
7 +from vllm.tool_parsers.abstract_tool_parser import Tool
8 from vllm.tool_parsers.hermes_tool_parser import Hermes2ProToolParser
9
10
11 class LongcatFlashToolParser(Hermes2ProToolParser):
11 - def __init__(self, tokenizer: TokenizerLike):
12 - super().__init__(tokenizer)
12 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
13 + super().__init__(tokenizer, tools)
14
15 self.tool_call_start_token: str = "<longcat_tool_call>"
16 self.tool_call_end_token: str = "</longcat_tool_call>"
vllm/tool_parsers/minimax_m2_tool_parser.py
+3 -2
@@ -22,6 +22,7 @@ from vllm.entrypoints.openai.engine.protocol import (
22 from vllm.logger import init_logger
23 from vllm.tokenizers import TokenizerLike
24 from vllm.tool_parsers.abstract_tool_parser import (
25 + Tool,
26 ToolParser,
27 )
28
@@ -29,8 +30,8 @@ logger = init_logger(__name__)
30
31
32 class MinimaxM2ToolParser(ToolParser):
32 - def __init__(self, tokenizer: TokenizerLike):
33 - super().__init__(tokenizer)
33 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
34 + super().__init__(tokenizer, tools)
35
36 self.prev_tool_call_arr: list[dict] = []
37
vllm/tool_parsers/minimax_tool_parser.py
+3 -2
@@ -22,6 +22,7 @@ from vllm.entrypoints.openai.engine.protocol import (
22 from vllm.logger import init_logger
23 from vllm.tokenizers import TokenizerLike
24 from vllm.tool_parsers.abstract_tool_parser import (
25 + Tool,
26 ToolParser,
27 )
28 from vllm.tool_parsers.utils import extract_intermediate_diff
@@ -30,8 +31,8 @@ logger = init_logger(__name__)
31
32
33 class MinimaxToolParser(ToolParser):
33 - def __init__(self, tokenizer: TokenizerLike):
34 - super().__init__(tokenizer)
34 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
35 + super().__init__(tokenizer, tools)
36
37 # Initialize streaming state for tracking tool call progress
38 self.streaming_state: dict[str, Any] = {
vllm/tool_parsers/mistral_tool_parser.py
+3 -2
@@ -26,6 +26,7 @@ from vllm.entrypoints.openai.engine.protocol import (
26 from vllm.logger import init_logger
27 from vllm.tokenizers import TokenizerLike
28 from vllm.tool_parsers.abstract_tool_parser import (
29 + Tool,
30 ToolParser,
31 )
32 from vllm.utils.mistral import is_mistral_tokenizer
@@ -78,8 +79,8 @@ class MistralToolParser(ToolParser):
79 Used when --enable-auto-tool-choice --tool-call-parser mistral are all set
80 """
81
81 - def __init__(self, tokenizer: TokenizerLike):
82 - super().__init__(tokenizer)
82 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
83 + super().__init__(tokenizer, tools)
84
85 if not is_mistral_tokenizer(self.model_tokenizer):
86 logger.info("Non-Mistral tokenizer detected when using a Mistral model...")
vllm/tool_parsers/olmo3_tool_parser.py
+7 -2
@@ -17,6 +17,7 @@ from vllm.entrypoints.openai.engine.protocol import (
17 )
18 from vllm.logger import init_logger
19 from vllm.tool_parsers.abstract_tool_parser import (
20 + Tool,
21 ToolParser,
22 )
23 from vllm.tool_parsers.utils import (
@@ -51,8 +52,12 @@ class Olmo3PythonicToolParser(ToolParser):
52 re.DOTALL,
53 )
54
54 - def __init__(self, tokenizer: PreTrainedTokenizerBase):
55 - super().__init__(tokenizer)
55 + def __init__(
56 + self,
57 + tokenizer: PreTrainedTokenizerBase,
58 + tools: list[Tool] | None = None,
59 + ):
60 + super().__init__(tokenizer, tools)
61
62 # Rename for readability. This is NOT a tool id.
63 @property
vllm/tool_parsers/openai_tool_parser.py
+3 -2
@@ -16,6 +16,7 @@ from vllm.entrypoints.openai.engine.protocol import (
16 from vllm.entrypoints.openai.parser.harmony_utils import parse_output_into_messages
17 from vllm.logger import init_logger
18 from vllm.tool_parsers.abstract_tool_parser import (
19 + Tool,
20 ToolParser,
21 )
22
@@ -28,8 +29,8 @@ logger = init_logger(__name__)
29
30
31 class OpenAIToolParser(ToolParser):
31 - def __init__(self, tokenizer: "TokenizerLike"):
32 - super().__init__(tokenizer)
32 + def __init__(self, tokenizer: "TokenizerLike", tools: list[Tool] | None = None):
33 + super().__init__(tokenizer, tools)
34
35 def extract_tool_calls(
36 self,
vllm/tool_parsers/phi4mini_tool_parser.py
+7 -2
@@ -20,6 +20,7 @@ from vllm.entrypoints.openai.engine.protocol import (
20 )
21 from vllm.logger import init_logger
22 from vllm.tool_parsers.abstract_tool_parser import (
23 + Tool,
24 ToolParser,
25 )
26
@@ -35,8 +36,12 @@ class Phi4MiniJsonToolParser(ToolParser):
36 are all set
37 """
38
38 - def __init__(self, tokenizer: PreTrainedTokenizerBase) -> None:
39 - super().__init__(tokenizer)
39 + def __init__(
40 + self,
41 + tokenizer: PreTrainedTokenizerBase,
42 + tools: list[Tool] | None = None,
43 + ) -> None:
44 + super().__init__(tokenizer, tools)
45
46 # initialize properties used for state when parsing tool calls in
47 # streaming mode
vllm/tool_parsers/pythonic_tool_parser.py
+7 -2
@@ -17,6 +17,7 @@ from vllm.entrypoints.openai.engine.protocol import (
17 )
18 from vllm.logger import init_logger
19 from vllm.tool_parsers.abstract_tool_parser import (
20 + Tool,
21 ToolParser,
22 )
23 from vllm.tool_parsers.utils import (
@@ -49,8 +50,12 @@ class PythonicToolParser(ToolParser):
50 re.DOTALL,
51 )
52
52 - def __init__(self, tokenizer: PreTrainedTokenizerBase):
53 - super().__init__(tokenizer)
53 + def __init__(
54 + self,
55 + tokenizer: PreTrainedTokenizerBase,
56 + tools: list[Tool] | None = None,
57 + ):
58 + super().__init__(tokenizer, tools)
59
60 # Rename for readability. This is NOT a tool id.
61 @property
vllm/tool_parsers/qwen3coder_tool_parser.py
+5 -7
@@ -10,7 +10,6 @@ import regex as re
10
11 from vllm.entrypoints.openai.chat_completion.protocol import (
12 ChatCompletionRequest,
13 - ChatCompletionToolsParam,
13 )
14 from vllm.entrypoints.openai.engine.protocol import (
15 DeltaFunctionCall,
@@ -23,6 +22,7 @@ from vllm.entrypoints.openai.engine.protocol import (
22 from vllm.logger import init_logger
23 from vllm.tokenizers import TokenizerLike
24 from vllm.tool_parsers.abstract_tool_parser import (
25 + Tool,
26 ToolParser,
27 )
28
@@ -30,8 +30,8 @@ logger = init_logger(__name__)
30
31
32 class Qwen3CoderToolParser(ToolParser):
33 - def __init__(self, tokenizer: TokenizerLike):
34 - super().__init__(tokenizer)
33 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
34 + super().__init__(tokenizer, tools)
35
36 self.current_tool_name_sent: bool = False
37 self.prev_tool_call_arr: list[dict] = []
@@ -109,9 +109,7 @@ class Qwen3CoderToolParser(ToolParser):
109 self.accumulated_params = {}
110 self.streaming_request = None
111
112 - def _get_arguments_config(
113 - self, func_name: str, tools: list[ChatCompletionToolsParam] | None
114 - ) -> dict:
112 + def _get_arguments_config(self, func_name: str, tools: list[Tool] | None) -> dict:
113 """Extract argument configuration for a function."""
114 if tools is None:
115 return {}
@@ -246,7 +244,7 @@ class Qwen3CoderToolParser(ToolParser):
244 return param_value
245
246 def _parse_xml_function_call(
249 - self, function_call_str: str, tools: list[ChatCompletionToolsParam] | None
247 + self, function_call_str: str, tools: list[Tool] | None
248 ) -> ToolCall | None:
249 # Extract function name
250 end_index = function_call_str.find(">")
vllm/tool_parsers/qwen3xml_tool_parser.py
+5 -5
@@ -11,7 +11,6 @@ import regex as re
11 from vllm.entrypoints.chat_utils import make_tool_call_id
12 from vllm.entrypoints.openai.chat_completion.protocol import (
13 ChatCompletionRequest,
14 - ChatCompletionToolsParam,
14 )
15 from vllm.entrypoints.openai.engine.protocol import (
16 DeltaFunctionCall,
@@ -24,6 +23,7 @@ from vllm.entrypoints.openai.engine.protocol import (
23 from vllm.logger import init_logger
24 from vllm.tokenizers import TokenizerLike
25 from vllm.tool_parsers.abstract_tool_parser import (
26 + Tool,
27 ToolParser,
28 )
29
@@ -40,7 +40,7 @@ class StreamingXMLToolCallParser:
40 self.reset_streaming_state()
41
42 # Tool configuration information
43 - self.tools: list[ChatCompletionToolsParam] | None = None
43 + self.tools: list[Tool] | None = None
44 self.tool_call_start_token: str = "<tool_call>"
45 self.tool_call_end_token: str = "</tool_call>"
46 self.function_start_token: str = "<function="
@@ -961,7 +961,7 @@ class StreamingXMLToolCallParser:
961 self.parser.EndElementHandler = self._end_element
962 self.parser.CharacterDataHandler = self._char_data
963
964 - def set_tools(self, tools: list[ChatCompletionToolsParam] | None):
964 + def set_tools(self, tools: list[Tool] | None):
965 """Set tool configuration information"""
966 self.tools = tools
967
@@ -1167,8 +1167,8 @@ class StreamingXMLToolCallParser:
1167
1168
1169 class Qwen3XMLToolParser(ToolParser):
1170 - def __init__(self, tokenizer: TokenizerLike):
1171 - super().__init__(tokenizer)
1170 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
1171 + super().__init__(tokenizer, tools)
1172 self.parser = StreamingXMLToolCallParser()
1173
1174 # Add missing attributes for compatibility with serving_chat.py
vllm/tool_parsers/seed_oss_tool_parser.py
+4 -4
@@ -13,7 +13,6 @@ import regex as re
13
14 from vllm.entrypoints.openai.chat_completion.protocol import (
15 ChatCompletionRequest,
16 - ChatCompletionToolsParam,
16 )
17 from vllm.entrypoints.openai.engine.protocol import (
18 DeltaFunctionCall,
@@ -26,6 +25,7 @@ from vllm.entrypoints.openai.engine.protocol import (
25 from vllm.logger import init_logger
26 from vllm.tokenizers import TokenizerLike
27 from vllm.tool_parsers.abstract_tool_parser import (
28 + Tool,
29 ToolParser,
30 )
31
@@ -36,8 +36,8 @@ class SeedOssToolParser(ToolParser):
36 TOOL_CALL_START = "<seed:tool_call>"
37 TOOL_CALL_END = "</seed:tool_call>"
38
39 - def __init__(self, tokenizer: TokenizerLike):
40 - super().__init__(tokenizer)
39 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
40 + super().__init__(tokenizer, tools)
41
42 # --- streaming state ---
43 self._reset_streaming_state()
@@ -109,7 +109,7 @@ class SeedOssToolParser(ToolParser):
109 self.json_closed = False
110
111 def _parse_xml_function_call(
112 - self, function_call_str: str, tools: list[ChatCompletionToolsParam] | None
112 + self, function_call_str: str, tools: list[Tool] | None
113 ) -> ToolCall | None:
114 def get_arguments_config(func_name: str) -> dict:
115 if tools is None:
vllm/tool_parsers/step3_tool_parser.py
+3 -2
@@ -22,6 +22,7 @@ from vllm.entrypoints.openai.engine.protocol import (
22 from vllm.logger import init_logger
23 from vllm.tokenizers import TokenizerLike
24 from vllm.tool_parsers.abstract_tool_parser import (
25 + Tool,
26 ToolParser,
27 )
28 from vllm.utils import random_uuid
@@ -43,8 +44,8 @@ class Step3ToolParser(ToolParser):
44 TOOL_SEP = "<|tool_sep|>"
45 SPECIAL_TOKENS = [TOOL_CALLS_BEGIN, TOOL_CALLS_END, TOOL_CALL_BEGIN, TOOL_CALL_END]
46
46 - def __init__(self, tokenizer: TokenizerLike):
47 - super().__init__(tokenizer)
47 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
48 + super().__init__(tokenizer, tools)
49 self.position = 0
50 # Explicit state flags for robust streaming
51 self.tool_block_started = False
vllm/tool_parsers/step3p5_tool_parser.py
+5 -6
@@ -11,7 +11,6 @@ import regex as re
11 from vllm.entrypoints.chat_utils import make_tool_call_id
12 from vllm.entrypoints.openai.chat_completion.protocol import (
13 ChatCompletionRequest,
14 - ChatCompletionToolsParam,
14 )
15 from vllm.entrypoints.openai.engine.protocol import (
16 DeltaFunctionCall,
@@ -23,7 +22,7 @@ from vllm.entrypoints.openai.engine.protocol import (
22 )
23 from vllm.logger import init_logger
24 from vllm.tokenizers import TokenizerLike
26 -from vllm.tool_parsers.abstract_tool_parser import ToolParser
25 +from vllm.tool_parsers.abstract_tool_parser import Tool, ToolParser
26
27 logger = init_logger(__name__)
28
@@ -38,7 +37,7 @@ class StreamingXMLToolCallParser:
37 self.reset_streaming_state()
38
39 # Tool configuration information
41 - self.tools: list[ChatCompletionToolsParam] | None = None
40 + self.tools: list[Tool] | None = None
41 self.tool_call_start_token: str = "<tool_call>"
42 self.tool_call_end_token: str = "</tool_call>"
43 self.function_start_token: str = "<function="
@@ -1161,7 +1160,7 @@ class StreamingXMLToolCallParser:
1160 self.parser.EndElementHandler = self._end_element
1161 self.parser.CharacterDataHandler = self._char_data
1162
1164 - def set_tools(self, tools: list[ChatCompletionToolsParam] | None):
1163 + def set_tools(self, tools: list[Tool] | None):
1164 """Set tool configuration information"""
1165 self.tools = tools
1166
@@ -1365,8 +1364,8 @@ class StreamingXMLToolCallParser:
1364
1365
1366 class Step3p5ToolParser(ToolParser):
1368 - def __init__(self, tokenizer: TokenizerLike):
1369 - super().__init__(tokenizer)
1367 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
1368 + super().__init__(tokenizer, tools)
1369 self.parser = StreamingXMLToolCallParser()
1370
1371 # Add missing attributes for compatibility with serving_chat.py
vllm/tool_parsers/xlam_tool_parser.py
+4 -2
@@ -6,6 +6,7 @@ from collections.abc import Sequence
6 from typing import Any, Optional, Union
7
8 import regex as re
9 +
10 from vllm.entrypoints.openai.chat_completion.protocol import (
11 ChatCompletionRequest,
12 )
@@ -19,6 +20,7 @@ from vllm.entrypoints.openai.engine.protocol import (
20 ToolCall,
21 )
22 from vllm.tool_parsers.abstract_tool_parser import (
23 + Tool,
24 ToolParser,
25 )
26 from vllm.logger import init_logger
@@ -29,8 +31,8 @@ logger = init_logger(__name__)
31
32
33 class xLAMToolParser(ToolParser):
32 - def __init__(self, tokenizer: TokenizerLike):
33 - super().__init__(tokenizer)
34 + def __init__(self, tokenizer: TokenizerLike, tools: list[Tool] | None = None):
35 + super().__init__(tokenizer, tools)
36
37 # Initialize state for streaming mode
38 self.prev_tool_calls: list[dict] = []