Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions tests/tool_parsers/test_glm47_moe_tool_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ def test_args_with_newlines(self, glm47_tool_parser, mock_request):
assert r.tools_called
assert json.loads(r.tool_calls[0].function.arguments) == {"city": "Beijing"}

def test_whitespace_preserved_in_arg_values(self, glm47_tool_parser, mock_request):
out = "<tool_call>get_weather<arg_key>city</arg_key><arg_value> Beijing </arg_value></tool_call>"
r = glm47_tool_parser.extract_tool_calls(out, request=mock_request)
assert r.tools_called
assert json.loads(r.tool_calls[0].function.arguments) == {"city": " Beijing "}

def test_content_before(self, glm47_tool_parser, mock_request):
out = "Checking.<tool_call>get_current_date</tool_call>"
r = glm47_tool_parser.extract_tool_calls(out, request=mock_request)
Expand Down
30 changes: 30 additions & 0 deletions tests/tool_parsers/test_glm4_moe_tool_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,36 @@ def test_extract_tool_calls_numeric_deserialization(glm4_moe_tool_parser, mock_r
assert isinstance(args["enabled"], bool)


def test_whitespace_preserved_in_arg_values(glm4_moe_tokenizer):
"""Test that string arguments preserve leading and trailing whitespace."""
tools = [
ChatCompletionToolsParam(
function=FunctionDefinition(
name="apply_diff",
parameters={
"type": "object",
"properties": {
"s": {"type": "string"},
},
"required": ["s"],
},
),
),
]
parser = Glm4MoeModelToolParser(glm4_moe_tokenizer, tools=tools)
request = ChatCompletionRequest(model=MODEL, messages=[], tools=tools)

model_output = """<tool_call>apply_diff
<arg_key>s</arg_key>
<arg_value> indented code </arg_value>
</tool_call>"""

extracted_tool_calls = parser.extract_tool_calls(model_output, request=request)
args = json.loads(extracted_tool_calls.tool_calls[0].function.arguments)

assert args["s"] == " indented code "


def test_zero_argument_tool_call(glm4_moe_tool_parser, mock_request):
"""Regression: zero-argument tool call crash (PR #32321)."""
model_output = """<tool_call>get_time
Expand Down
7 changes: 4 additions & 3 deletions vllm/tool_parsers/glm4_moe_tool_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,10 @@ def extract_tool_calls(
arg_dct: dict[str, Any] = {}
for key, value in pairs:
arg_key = key.strip()
arg_val = value.strip()
if not self._is_string_type(tc_name, arg_key, self.tools):
arg_val = self._deserialize(arg_val)
if self._is_string_type(tc_name, arg_key, self.tools):
arg_val = value
else:
arg_val = self._deserialize(value.strip())
logger.debug("arg_key = %s, arg_val = %s", arg_key, arg_val)
arg_dct[arg_key] = arg_val
tool_calls.append(
Expand Down
Loading