diff --git a/vllm/tool_parsers/seed_oss_tool_parser.py b/vllm/tool_parsers/seed_oss_tool_parser.py index 7dbc6aa49e..a90bdc76d9 100644 --- a/vllm/tool_parsers/seed_oss_tool_parser.py +++ b/vllm/tool_parsers/seed_oss_tool_parser.py @@ -3,11 +3,9 @@ # Adapted from qwen3coder xml parser, All rights reserved. # ruff: noqa: E501 -import ast import json import uuid from collections.abc import Sequence -from typing import Any import regex as re @@ -28,6 +26,11 @@ from vllm.tool_parsers.abstract_tool_parser import ( Tool, ToolParser, ) +from vllm.tool_parsers.utils import ( + coerce_to_schema_type, + extract_types_from_schema, + find_tool_properties, +) logger = init_logger(__name__) @@ -111,129 +114,10 @@ class SeedOssToolParser(ToolParser): def _parse_xml_function_call( self, function_call_str: str, tools: list[Tool] | None ) -> ToolCall | None: - def get_arguments_config(func_name: str) -> dict: - if tools is None: - return {} - for config in tools: - if not hasattr(config, "type") or not ( - hasattr(config, "function") and hasattr(config.function, "name") - ): - continue - if config.type == "function" and config.function.name == func_name: - if not hasattr(config.function, "parameters"): - return {} - params = config.function.parameters - if isinstance(params, dict) and "properties" in params: - return params["properties"] - elif isinstance(params, dict): - return params - else: - return {} - logger.warning("Tool '%s' is not defined in the tools list.", func_name) - return {} - - def convert_param_value( - param_value: str, param_name: str, param_config: dict, func_name: str - ) -> Any: - # Handle null value for any type - if param_value.lower() == "null": - return None - - if param_name not in param_config: - if param_config != {}: - logger.warning( - "Parsed parameter '%s' is not defined in " - "the tool parameters for tool '%s', " - "directly returning the string value.", - param_name, - func_name, - ) - return param_value - - if ( - isinstance(param_config[param_name], dict) - and "type" in param_config[param_name] - ): - param_type = str(param_config[param_name]["type"]).strip().lower() - else: - param_type = "string" - if param_type in ["string", "str", "text", "varchar", "char", "enum"]: - return param_value - elif ( - param_type.startswith("int") - or param_type.startswith("uint") - or param_type.startswith("long") - or param_type.startswith("short") - or param_type.startswith("unsigned") - ): - try: - param_value = int(param_value) # type: ignore - except (ValueError, TypeError): - logger.warning( - "Parsed value '%s' of parameter '%s' is not an integer in tool " - "'%s', degenerating to string.", - param_value, - param_name, - func_name, - ) - return param_value - elif param_type.startswith("num") or param_type.startswith("float"): - try: - float_param_value = float(param_value) - param_value = ( - float_param_value # type: ignore - if float_param_value - int(float_param_value) != 0 - else int(float_param_value) # type: ignore - ) - except (ValueError, TypeError): - logger.warning( - "Parsed value '%s' of parameter '%s' is not a float in tool " - "'%s', degenerating to string.", - param_value, - param_name, - func_name, - ) - return param_value - elif param_type in ["boolean", "bool", "binary"]: - param_value = param_value.lower() - if param_value not in ["true", "false"]: - logger.warning( - "Parsed value '%s' of parameter '%s' is not a boolean " - "(`true` of `false`) in tool '%s', degenerating to false.", - param_value, - param_name, - func_name, - ) - return param_value == "true" - else: - if param_type == "object" or param_type.startswith("dict"): - try: - param_value = json.loads(param_value) - return param_value - except (ValueError, TypeError, json.JSONDecodeError): - logger.warning( - "Parsed value '%s' of parameter '%s' is not a valid JSON " - "object in tool '%s', will try other methods to parse it.", - param_value, - param_name, - func_name, - ) - try: - param_value = ast.literal_eval(param_value) - except (ValueError, SyntaxError): - logger.warning( - "Parsed value '%s' of parameter '%s' cannot be converted via " - "Python `ast.literal_eval()` in tool '%s', degenerating to string.", - param_value, - param_name, - func_name, - ) - return param_value - # Extract function name end_index = function_call_str.index(">") function_name = function_call_str[:end_index] - param_config = get_arguments_config(function_name) + tool_properties = find_tool_properties(tools, function_name) parameters = function_call_str[end_index + 1 :] param_dict = {} for match in self.tool_call_parameter_regex.findall(parameters): @@ -247,9 +131,8 @@ class SeedOssToolParser(ToolParser): if param_value.endswith("\n"): param_value = param_value[:-1] - param_dict[param_name] = convert_param_value( - param_value, param_name, param_config, function_name - ) + param_types = extract_types_from_schema(tool_properties.get(param_name, {})) + param_dict[param_name] = coerce_to_schema_type(param_value, param_types) return ToolCall( type="function", function=FunctionCall(