Skip to content

vllm.parser.deepseek_v4

DeepSeek V4 parser: <think>/</think> reasoning plus DSML tool calls in a single state machine.

DeepSeek V4 output format::

<think>
...reasoning...
</think>
<|DSML|tool_calls>
<|DSML|invoke name="func_name">
<|DSML|parameter name="location" string="true">杭州</|DSML|parameter>
<|DSML|parameter name="count" string="false">5</|DSML|parameter>
</|DSML|invoke>
</|DSML|tool_calls>

_match_open_param(raw_args, pos, partial_param_re, param_start)

Return (name, is_str, value, held_back) for the trailing open param.

An unfinished next parameter tag (param_start with no > after it) is cut from the value; held_back reports whether that happened.

Source code in vllm/parser/deepseek_v4.py
def _match_open_param(
    raw_args: str, pos: int, partial_param_re: re.Pattern, param_start: str
) -> tuple[str, str | None, str, bool] | None:
    """Return (name, is_str, value, held_back) for the trailing open param.

    An unfinished next parameter tag (``param_start`` with no ``>`` after it)
    is cut from the value; ``held_back`` reports whether that happened.
    """
    pm = partial_param_re.search(raw_args, pos)
    if pm is None:
        return None
    value = pm.group(3)
    cut = value.find(param_start, value.rfind(">") + 1)
    if cut >= 0:
        return pm.group(1), pm.group(2), value[:cut], True
    return pm.group(1), pm.group(2), value, False

_param_patterns(param_start, param_close)

Complete and trailing-partial parameter regexes for one DSML dialect.

The string attribute is optional: the model sometimes omits it, and dropping such a parameter hands the client a tool call with no arguments. The trailing-partial regex captures the open value up to the end of the text; _match_open_param holds back an unfinished next parameter tag so a streamed string value never includes it.

Source code in vllm/parser/deepseek_v4.py
def _param_patterns(
    param_start: str, param_close: str
) -> tuple[re.Pattern, re.Pattern]:
    """Complete and trailing-partial parameter regexes for one DSML dialect.

    The ``string`` attribute is optional: the model sometimes omits it, and
    dropping such a parameter hands the client a tool call with no arguments.
    The trailing-partial regex captures the open value up to the end of the
    text; ``_match_open_param`` holds back an unfinished next parameter tag
    so a streamed string value never includes it.
    """
    start, close = re.escape(param_start), re.escape(param_close)
    head = rf'{start}\s+name="([^"]+)"(?:\s+string="([^"]*)")?\s*>'
    return (
        re.compile(rf"{head}(.*?)(?:{close}|(?={start}\s+name=))", re.DOTALL),
        re.compile(rf"{head}(.*)\Z", re.DOTALL),
    )