Skip to content

Commit fdf59d3

Browse files
authored
[Bugfix] fix tool_parser error handling when serve a model not support it (#8709)
1 parent b22b798 commit fdf59d3

File tree

3 files changed

+31
-10
lines changed

3 files changed

+31
-10
lines changed

vllm/entrypoints/openai/serving_chat.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -302,10 +302,6 @@ async def chat_completion_stream_generator(
302302
finish_reason_sent = [False] * num_choices
303303
num_prompt_tokens = 0
304304

305-
tool_parsers: List[Optional[ToolParser]] = [
306-
self.tool_parser(tokenizer) if self.tool_parser else None
307-
] * num_choices
308-
309305
if isinstance(request.tool_choice, ChatCompletionNamedToolChoiceParam):
310306
tool_choice_function_name = request.tool_choice.function.name
311307
else:
@@ -324,6 +320,21 @@ async def chat_completion_stream_generator(
324320
else:
325321
previous_texts, all_previous_token_ids = None, None
326322

323+
# Prepare the tool parser if it's needed
324+
try:
325+
if tool_choice_auto and self.tool_parser:
326+
tool_parsers: List[Optional[ToolParser]] = [
327+
self.tool_parser(tokenizer)
328+
] * num_choices
329+
else:
330+
tool_parsers = [None] * num_choices
331+
except RuntimeError as e:
332+
logger.error("Error in tool parser creation: %s", e)
333+
data = self.create_streaming_error_response(str(e))
334+
yield f"data: {data}\n\n"
335+
yield "data: [DONE]\n\n"
336+
return
337+
327338
try:
328339
async for res in result_generator:
329340
if res.prompt_token_ids is not None:
@@ -704,7 +715,12 @@ async def chat_completion_full_generator(
704715
or request.tool_choice is None) and self.enable_auto_tools \
705716
and self.tool_parser:
706717

707-
tool_parser = self.tool_parser(tokenizer)
718+
try:
719+
tool_parser = self.tool_parser(tokenizer)
720+
except RuntimeError as e:
721+
logger.error("Error in tool parser creation: %s", e)
722+
return self.create_error_response(str(e))
723+
708724
tool_call_info = tool_parser.extract_tool_calls(
709725
output.text, request=request)
710726
tools_called = tool_call_info.tools_called

vllm/entrypoints/openai/tool_parsers/hermes_tool_parser.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ def __init__(self, tokenizer: AnyTokenizer):
5050
raise ValueError(
5151
"The model tokenizer must be passed to the ToolParser "
5252
"constructor during construction.")
53-
self.tool_call_start_token_id: int = self.model_tokenizer.vocab[
54-
self.tool_call_start_token]
55-
self.tool_call_end_token_id: int = self.model_tokenizer.vocab[
56-
self.tool_call_end_token]
53+
self.tool_call_start_token_id: int = self.model_tokenizer.vocab.get(
54+
self.tool_call_start_token, None)
55+
self.tool_call_end_token_id: int = self.model_tokenizer.vocab.get(
56+
self.tool_call_end_token, None)
5757
if not self.tool_call_start_token_id or not self.tool_call_end_token_id:
5858
raise RuntimeError(
5959
"Hermes 2 Pro Tool parser could not locate tool call start/end "

vllm/entrypoints/openai/tool_parsers/mistral_tool_parser.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,13 @@ def __init__(self, tokenizer: AnyTokenizer):
6161
self.streamed_args_for_tool: List[str] = [
6262
] # map what has been streamed for each tool so far to a list
6363
self.bot_token = "[TOOL_CALLS]"
64-
self.bot_token_id = self.model_tokenizer.get_vocab()[self.bot_token]
64+
self.bot_token_id = self.model_tokenizer.get_vocab().get(
65+
self.bot_token, None)
6566
self.tool_call_regex = re.compile(r"\[{.*?}\]", re.DOTALL)
67+
if not self.bot_token_id:
68+
raise RuntimeError(
69+
"Mistral Tool Parser could not locate the tool call token in "
70+
"the tokenizer!")
6671

6772
def extract_tool_calls(
6873
self,

0 commit comments

Comments
 (0)