Skip to content

vllm_mlx.reasoning.think_parser

Base parser for models using ... tags for reasoning.

View the complete module source at #L1-L462.

API details

Each callable below includes its exact signature, type annotations, inputs, defaults, return contract, documented exceptions, implementation source, and parsed docstring sections when the source provides them.

vllm_mlx.reasoning.think_parser

Base parser for models using ... tags for reasoning.

This module provides BaseThinkingReasoningParser, a concrete implementation for extracting reasoning content from models that use thinking tags.

Supports three scenarios: 1. Both tags in output: reasoningcontent 2. Only closing tag (think injected in prompt): reasoningcontent 3. No tags: pure content

Performance: The streaming parser uses a simple state machine to track the current phase (pre-think / thinking / content). Tag completion is detected against the accumulated text for correctness when <think> / </think> are split across delta boundaries, but phase tracking still avoids the old whole-output rescanning behavior.

vllm_mlx.reasoning.think_parser.logger module-attribute

logger = logging.getLogger(__name__)

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser

BaseThinkingReasoningParser(tokenizer=None)

Bases: ReasoningParser

Base parser for models using ... style tags.

This parser handles the common pattern where reasoning content is wrapped in special tags. Subclasses define the specific start and end tokens.

Supports "implicit reasoning mode" where is injected in the prompt and only appears in the model output. This is common with AI agents like OpenCode that force models to reason by injecting thinking tags.

The streaming parser uses a state machine with three phases:

pre_think -> thinking -> content

Transitions are tracked by parser state. Accumulated text is consulted only to detect when a start/end tag has completed across delta boundaries.

Source code in vllm_mlx/reasoning/think_parser.py
def __init__(self, tokenizer=None):
    super().__init__(tokenizer)
    # Streaming state — reset per request via reset_state()
    self._phase: str = "pre_think"  # "pre_think" | "thinking" | "content"
    self._content_started = False
    self._content_buffer = ""
    # Tool call promotion state.
    self._in_tool_call = False
    self._tool_call_buffer = ""

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.start_token abstractmethod property

start_token: str

The token/tag that starts reasoning content (e.g., '').

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.end_token abstractmethod property

end_token: str

The token/tag that ends reasoning content (e.g., '').

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._TOOL_CALL_START class-attribute instance-attribute

_TOOL_CALL_START = '<tool_call>'

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._TOOL_CALL_END class-attribute instance-attribute

_TOOL_CALL_END = '</tool_call>'

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._TOOL_CALL_CLOSED_RE class-attribute instance-attribute

_TOOL_CALL_CLOSED_RE = re.compile('<tool_call>(.*?)</tool_call>', re.DOTALL)

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._TOOL_CALL_UNCLOSED_RE class-attribute instance-attribute

_TOOL_CALL_UNCLOSED_RE = re.compile('<tool_call>\\s*[\\{<].*$', re.DOTALL)

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._phase instance-attribute

_phase: str = 'pre_think'

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._content_started instance-attribute

_content_started = False

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._content_buffer instance-attribute

_content_buffer = ''

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._in_tool_call instance-attribute

_in_tool_call = False

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._tool_call_buffer instance-attribute

_tool_call_buffer = ''

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.reset_state

reset_state()

Reset state machine for a new streaming request.

Source code in vllm_mlx/reasoning/think_parser.py
def reset_state(self):
    """Reset state machine for a new streaming request."""
    self._phase = "pre_think"
    self._content_started = False
    self._content_buffer = ""
    self._in_tool_call = False
    self._tool_call_buffer = ""

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.extract_reasoning

extract_reasoning(model_output: str) -> tuple[str | None, str | None]

Extract reasoning from complete output.

Handles three cases: 1. Both tags present: reasoningcontent 2. Only closing tag: reasoningcontent (think in prompt) 3. No tags: pure content

Parameters:

  • model_output (str) –

    Complete model output text.

Returns:

  • tuple[str | None, str | None]

    (reasoning, content) tuple. Either may be None.

Source code in vllm_mlx/reasoning/think_parser.py
def extract_reasoning(
    self,
    model_output: str,
) -> tuple[str | None, str | None]:
    """
    Extract reasoning from complete output.

    Handles three cases:
    1. Both tags present: <think>reasoning</think>content
    2. Only closing tag: reasoning</think>content (think in prompt)
    3. No tags: pure content

    Args:
        model_output: Complete model output text.

    Returns:
        (reasoning, content) tuple. Either may be None.
    """
    text = model_output

    if self.end_token in text:
        reasoning, content = self._extract_complete_reasoning(text)
        return self._promote_tool_calls(reasoning, content)

    if self.start_token in text:
        _, _, reasoning = text.partition(self.start_token)
        reasoning = reasoning.strip() or None
        return self._promote_tool_calls(reasoning, None)

    return None, model_output

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.extract_reasoning_streaming

extract_reasoning_streaming(previous_text: str, current_text: str, delta_text: str) -> DeltaMessage | None

Extract reasoning from a streaming delta using state-machine tracking.

Instead of rescanning the full accumulated text on every token, this method tracks the current phase (pre_think / thinking / content) and only consults accumulated text to detect completed start/end tags that were split across delta boundaries.

Handles three scenarios: 1. Explicit ... in model output 2. Implicit mode ( in prompt, only in output) 3. No tags at all (pure content after first token with no reasoning)

Parameters:

  • previous_text (str) –

    Text accumulated before this delta.

  • current_text (str) –

    Text including this delta.

  • delta_text (str) –

    Just the new text in this chunk.

Returns:

  • DeltaMessage | None

    DeltaMessage with reasoning and/or content, or None to skip.

Source code in vllm_mlx/reasoning/think_parser.py
def extract_reasoning_streaming(
    self,
    previous_text: str,
    current_text: str,
    delta_text: str,
) -> DeltaMessage | None:
    """
    Extract reasoning from a streaming delta using state-machine tracking.

    Instead of rescanning the full accumulated text on every token, this
    method tracks the current phase (pre_think / thinking / content) and
    only consults accumulated text to detect completed start/end tags that
    were split across delta boundaries.

    Handles three scenarios:
    1. Explicit <think>...</think> in model output
    2. Implicit mode (<think> in prompt, only </think> in output)
    3. No tags at all (pure content after first token with no reasoning)

    Args:
        previous_text: Text accumulated before this delta.
        current_text: Text including this delta.
        delta_text: Just the new text in this chunk.

    Returns:
        DeltaMessage with reasoning and/or content, or None to skip.
    """
    if not delta_text:
        return None

    start_tok = self.start_token
    end_tok = self.end_token

    # ── Phase: pre_think ──────────────────────────────────────
    # Haven't seen a completed tag yet. Could be:
    # - About to see <think> (explicit reasoning)
    # - Already inside implicit reasoning (think was in prompt)
    # - No reasoning at all (pure content model)
    if self._phase == "pre_think":
        if start_tok in current_text:
            self._phase = "thinking"
            idx = delta_text.find(start_tok)
            after = delta_text[idx + len(start_tok) :] if idx >= 0 else delta_text

            if end_tok in after:
                self._phase = "content"
                eidx = after.find(end_tok)
                reasoning = after[:eidx]
                content = after[eidx + len(end_tok) :]
                return self._transition_to_content(reasoning, content)

            tc_start = self._TOOL_CALL_START
            if tc_start in after:
                tc_idx = after.find(tc_start)
                self._in_tool_call = True
                self._tool_call_buffer = after[tc_idx:]
                before = after[:tc_idx]
                return DeltaMessage(reasoning=before) if before else None

            return DeltaMessage(reasoning=after) if after else None

        # Implicit mode: </think> completed without an explicit <think>.
        if end_tok in current_text:
            self._phase = "content"
            idx = delta_text.find(end_tok)
            if idx >= 0:
                reasoning = delta_text[:idx]
                content = delta_text[idx + len(end_tok) :]
            else:
                reasoning = None
                content = delta_text
            return self._transition_to_content(reasoning, content)

        # No tags — default to reasoning (implicit mode assumption).
        # If the model doesn't use thinking at all, the server's
        # non-parser path handles it. This path only activates when
        # a reasoning parser is explicitly configured.
        return DeltaMessage(reasoning=delta_text)

    # ── Phase: thinking ───────────────────────────────────────
    # Inside a reasoning block, waiting for end tag.
    # Also detects <tool_call> blocks and promotes them to content.
    if self._phase == "thinking":
        if self._in_tool_call:
            return self._thinking_tool_call(previous_text, current_text, delta_text)

        tc_start = self._TOOL_CALL_START
        if tc_start in current_text and tc_start not in previous_text:
            self._in_tool_call = True
            idx = delta_text.find(tc_start)
            if idx >= 0:
                reasoning = delta_text[:idx]
                self._tool_call_buffer = delta_text[idx:]
            else:
                self._tool_call_buffer = tc_start
                reasoning = delta_text
            return DeltaMessage(reasoning=reasoning) if reasoning else None

        if end_tok in current_text and end_tok not in previous_text:
            self._phase = "content"
            idx = delta_text.find(end_tok)
            if idx >= 0:
                reasoning = delta_text[:idx]
                content = delta_text[idx + len(end_tok) :]
            else:
                reasoning = delta_text
                content = None
            return self._transition_to_content(reasoning, content)
        return DeltaMessage(reasoning=delta_text)

    # ── Phase: content ────────────────────────────────────────
    # Past the reasoning block — everything is content.
    return self._content_delta(delta_text)

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._extract_complete_reasoning

_extract_complete_reasoning(text: str) -> tuple[str | None, str | None]

Split complete output into leading reasoning spans and final content.

Source code in vllm_mlx/reasoning/think_parser.py
def _extract_complete_reasoning(self, text: str) -> tuple[str | None, str | None]:
    """Split complete output into leading reasoning spans and final content."""
    reasoning_parts: list[str] = []
    remainder = text

    while remainder:
        stripped = remainder.lstrip()

        if stripped.startswith(self.start_token):
            after_start = stripped[len(self.start_token) :]
            reasoning, found, after_end = after_start.partition(self.end_token)
            if not found:
                reasoning_parts.append(reasoning)
                remainder = ""
                break
            if reasoning.strip():
                reasoning_parts.append(reasoning.strip())
            remainder = after_end
            continue

        start_idx = stripped.find(self.start_token)
        end_idx = stripped.find(self.end_token)
        if end_idx != -1 and (start_idx == -1 or end_idx < start_idx):
            reasoning = stripped[:end_idx]
            if reasoning.strip():
                reasoning_parts.append(reasoning.strip())
            remainder = stripped[end_idx + len(self.end_token) :]
            continue

        remainder = stripped
        break

    reasoning = "\n".join(reasoning_parts).strip() or None
    content = remainder.strip() or None
    return reasoning, content

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._transition_to_content

_transition_to_content(reasoning: str | None, content: str | None) -> DeltaMessage | None

Return a delta while suppressing leading post-transition think blocks.

Source code in vllm_mlx/reasoning/think_parser.py
def _transition_to_content(
    self, reasoning: str | None, content: str | None
) -> DeltaMessage | None:
    """Return a delta while suppressing leading post-transition think blocks."""
    reasoning, content = self._promote_tool_calls(reasoning, content)
    content_msg = self._content_delta(content or "")
    extra_reasoning = content_msg.reasoning if content_msg else None
    final_content = content_msg.content if content_msg else None
    reasoning_text = (reasoning or "") + (extra_reasoning or "")
    if not reasoning_text and not final_content:
        return None
    return DeltaMessage(
        reasoning=reasoning_text or None,
        content=final_content or None,
    )

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._content_delta

_content_delta(delta_text: str) -> DeltaMessage | None

Emit content after consuming repeated leading think blocks.

Source code in vllm_mlx/reasoning/think_parser.py
def _content_delta(self, delta_text: str) -> DeltaMessage | None:
    """Emit content after consuming repeated leading think blocks."""
    if not delta_text and not self._content_buffer:
        return None

    if self._content_started:
        return DeltaMessage(content=delta_text) if delta_text else None

    self._content_buffer += delta_text
    buffer = self._content_buffer.lstrip()
    reasoning_parts: list[str] = []

    while buffer:
        if buffer.startswith(self.end_token):
            buffer = buffer[len(self.end_token) :].lstrip()
            continue

        if buffer.startswith(self.start_token):
            after_start = buffer[len(self.start_token) :]
            end_idx = after_start.find(self.end_token)
            if end_idx == -1:
                self._content_buffer = buffer
                return None
            reasoning = after_start[:end_idx]
            if reasoning:
                reasoning_parts.append(reasoning)
            buffer = after_start[end_idx + len(self.end_token) :].lstrip()
            continue

        if self.start_token.startswith(buffer):
            self._content_buffer = buffer
            return None

        if self.end_token.startswith(buffer):
            self._content_buffer = buffer
            return None

        self._content_started = True
        self._content_buffer = ""
        return DeltaMessage(
            reasoning="".join(reasoning_parts) or None,
            content=buffer,
        )

    self._content_buffer = ""
    if reasoning_parts:
        return DeltaMessage(reasoning="".join(reasoning_parts))
    return None

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._thinking_tool_call

_thinking_tool_call(previous_text: str, current_text: str, delta_text: str) -> DeltaMessage | None

Handle streaming while inside a during thinking phase.

Source code in vllm_mlx/reasoning/think_parser.py
def _thinking_tool_call(
    self,
    previous_text: str,
    current_text: str,
    delta_text: str,
) -> DeltaMessage | None:
    """Handle streaming while inside a <tool_call> during thinking phase."""
    tc_end = self._TOOL_CALL_END
    end_tok = self.end_token

    if tc_end in current_text and tc_end not in previous_text:
        self._tool_call_buffer += delta_text
        idx = self._tool_call_buffer.find(tc_end)
        promoted = self._tool_call_buffer[: idx + len(tc_end)]
        remainder = self._tool_call_buffer[idx + len(tc_end) :]
        self._tool_call_buffer = ""
        self._in_tool_call = False
        logger.warning("Promoted streaming tool_call block from reasoning")

        if end_tok in remainder:
            self._phase = "content"
            eidx = remainder.find(end_tok)
            reasoning = remainder[:eidx].strip() or None
            after_think = remainder[eidx + len(end_tok) :]
            content_msg = self._content_delta(after_think) if after_think else None
            final_content = promoted + (
                (content_msg.content or "") if content_msg else ""
            )
            extra_r = content_msg.reasoning if content_msg else None
            r_text = (reasoning or "") + (extra_r or "")
            return DeltaMessage(
                content=final_content or None,
                reasoning=r_text or None,
            )

        tc_start = self._TOOL_CALL_START
        if tc_start in remainder:
            tc_idx = remainder.find(tc_start)
            self._in_tool_call = True
            self._tool_call_buffer = remainder[tc_idx:]
            reasoning = remainder[:tc_idx].strip() or None
            return DeltaMessage(content=promoted, reasoning=reasoning)

        reasoning = remainder.strip() or None
        return DeltaMessage(content=promoted, reasoning=reasoning)

    if end_tok in current_text and end_tok not in previous_text:
        self._tool_call_buffer += delta_text
        self._in_tool_call = False
        self._phase = "content"
        logger.warning(
            "Promoted unclosed streaming tool_call "
            "(think ended before tool_call closed)"
        )
        idx = self._tool_call_buffer.find(end_tok)
        if idx >= 0:
            promoted = self._tool_call_buffer[:idx]
            after = self._tool_call_buffer[idx + len(end_tok) :]
        else:
            promoted = self._tool_call_buffer
            after = ""
        self._tool_call_buffer = ""
        content_msg = self._content_delta(after) if after else None
        final_content = (
            promoted + (content_msg.content or "") if content_msg else promoted
        )
        return DeltaMessage(content=final_content or None)

    self._tool_call_buffer += delta_text
    return None

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.finalize_stream

finalize_stream() -> DeltaMessage | None

Flush any buffered tool call text at end of stream.

Source code in vllm_mlx/reasoning/think_parser.py
def finalize_stream(self) -> DeltaMessage | None:
    """Flush any buffered tool call text at end of stream."""
    if self._in_tool_call and self._tool_call_buffer:
        promoted = self._tool_call_buffer
        self._tool_call_buffer = ""
        self._in_tool_call = False
        logger.warning("Promoted unclosed streaming tool_call at stream end")
        return DeltaMessage(content=promoted)
    return None

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._promote_tool_calls classmethod

_promote_tool_calls(reasoning: str | None, content: str | None) -> tuple[str | None, str | None]
Source code in vllm_mlx/reasoning/think_parser.py
@classmethod
def _promote_tool_calls(
    cls, reasoning: str | None, content: str | None
) -> tuple[str | None, str | None]:
    if not reasoning or "<tool_call>" not in reasoning:
        return reasoning, content

    # Closed regex first: extract complete <tool_call>...</tool_call> blocks.
    # Then unclosed regex on the already-stripped reasoning.
    closed: list[str] = []

    def _collect_closed(match):
        closed.append(match.group(0))
        return ""

    cleaned = cls._TOOL_CALL_CLOSED_RE.sub(_collect_closed, reasoning)

    unclosed_match = cls._TOOL_CALL_UNCLOSED_RE.search(cleaned)
    unclosed_block = None
    if unclosed_match:
        unclosed_block = unclosed_match.group(0)
        cleaned = cleaned[: unclosed_match.start()]

    cleaned = cleaned.strip() or None
    promoted_count = len(closed) + (1 if unclosed_block else 0)

    if promoted_count == 0:
        return reasoning, content

    result_content = content or ""

    if unclosed_block:
        result_content = (
            unclosed_block + "\n" + result_content
            if result_content
            else unclosed_block
        )

    if closed:
        closed_text = "\n".join(closed)
        result_content = (
            result_content + "\n" + closed_text if result_content else closed_text
        )

    result_content = result_content.strip() or None

    logger.warning(
        "Promoted %d tool_call block(s) from reasoning to content "
        "(%d closed, %d unclosed)",
        promoted_count,
        len(closed),
        1 if unclosed_block else 0,
    )

    return cleaned, result_content

Complete contract reference

Expand any definition for its exact inputs, annotations, defaults, return contract, directly raised exceptions, source-grounded behavior, and immutable line link. This section includes private and nested definitions that ordinary API generators omit.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser · class
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser(tokenizer = None)

Base parser for models using ... style tags.

Parameters

Name Type Required Default Description
tokenizer not annotated no None Optional positional or keyword input; defaults to None.

Returns

  • Constructs: vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser

Exceptions and behavior

Class BaseThinkingReasoningParser derives from ReasoningParser and declares 12 direct member(s). No direct raise statement appears in this definition.

View source #L29-L462.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.start_token · method
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.start_token() -> str

The token/tag that starts reasoning content (e.g., '').

Parameters

This callable has no explicit inputs.

Returns

  • Type: str

Exceptions and behavior

Method BaseThinkingReasoningParser.start_token contains no state mutation, call, raise, return, await, or yield. No direct raise statement appears in this definition.

View source #L50-L51.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.end_token · method
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.end_token() -> str

The token/tag that ends reasoning content (e.g., '').

Parameters

This callable has no explicit inputs.

Returns

  • Type: str

Exceptions and behavior

Method BaseThinkingReasoningParser.end_token contains no state mutation, call, raise, return, await, or yield. No direct raise statement appears in this definition.

View source #L55-L56.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.__init__ · method
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.__init__(tokenizer = None) -> not annotated

Method BaseThinkingReasoningParser.__init__ updates self._phase, self._content_started, self._content_buffer, self._in_tool_call; calls super().__init__, super.

Parameters

Name Type Required Default Description
tokenizer not annotated no None Optional positional or keyword input; defaults to None.

Returns

  • Type: not annotated

Exceptions and behavior

Method BaseThinkingReasoningParser.__init__ updates self._phase, self._content_started, self._content_buffer, self._in_tool_call; calls super().__init__, super. No direct raise statement appears in this definition.

View source #L63-L71.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.reset_state · method
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.reset_state() -> not annotated

Reset state machine for a new streaming request.

Parameters

This callable has no explicit inputs.

Returns

  • Type: not annotated

Exceptions and behavior

Method BaseThinkingReasoningParser.reset_state updates self._phase, self._content_started, self._content_buffer, self._in_tool_call. No direct raise statement appears in this definition.

View source #L73-L79.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.extract_reasoning · method
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.extract_reasoning(model_output: str) -> tuple[str | None, str | None]

Extract reasoning from complete output.

Parameters

Name Type Required Default Description
model_output str yes none Complete model output text.

Returns

  • Type: tuple[str | None, str | None]
  • Direct return expressions: self._promote_tool_calls(reasoning, content); self._promote_tool_calls(reasoning, None); (None, model_output)

Exceptions and behavior

Method BaseThinkingReasoningParser.extract_reasoning calls self._extract_complete_reasoning, self._promote_tool_calls, text.partition, reasoning.strip; has 3 explicit return paths. No direct raise statement appears in this definition.

View source #L81-L110.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.extract_reasoning_streaming · method
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.extract_reasoning_streaming(previous_text: str, current_text: str, delta_text: str) -> DeltaMessage | None

Extract reasoning from a streaming delta using state-machine tracking.

Parameters

Name Type Required Default Description
previous_text str yes none Text accumulated before this delta.
current_text str yes none Text including this delta.
delta_text str yes none Just the new text in this chunk.

Returns

  • Type: DeltaMessage | None
  • Direct return expressions: None; self._transition_to_content(reasoning, content); DeltaMessage(reasoning=before) if before else None; DeltaMessage(reasoning=after) if after else None; DeltaMessage(reasoning=delta_text); self._thinking_tool_call(previous_text, current_text, delta_text); DeltaMessage(reasoning=reasoning) if reasoning else None; self._content_delta(delta_text)

Exceptions and behavior

Method BaseThinkingReasoningParser.extract_reasoning_streaming updates self._phase, self._in_tool_call, self._tool_call_buffer; calls delta_text.find, len, after.find, self._transition_to_content; has 8 explicit return paths. No direct raise statement appears in this definition.

View source #L112-L224.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._extract_complete_reasoning · method
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._extract_complete_reasoning(text: str) -> tuple[str | None, str | None]

Split complete output into leading reasoning spans and final content.

Parameters

Name Type Required Default Description
text str yes none Required positional or keyword input.

Returns

  • Type: tuple[str | None, str | None]
  • Direct return expressions: (reasoning, content)

Exceptions and behavior

Method BaseThinkingReasoningParser._extract_complete_reasoning calls remainder.lstrip, stripped.startswith, len, after_start.partition; returns (reasoning, content). No direct raise statement appears in this definition.

View source #L226-L260.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._transition_to_content · method
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._transition_to_content(reasoning: str | None, content: str | None) -> DeltaMessage | None

Return a delta while suppressing leading post-transition think blocks.

Parameters

Name Type Required Default Description
reasoning str \| None yes none Required positional or keyword input.
content str \| None yes none Required positional or keyword input.

Returns

  • Type: DeltaMessage | None
  • Direct return expressions: None; DeltaMessage(reasoning=reasoning_text or None, content=final_content or None)

Exceptions and behavior

Method BaseThinkingReasoningParser._transition_to_content calls self._promote_tool_calls, self._content_delta, DeltaMessage; has 2 explicit return paths. No direct raise statement appears in this definition.

View source #L262-L276.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._content_delta · method
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._content_delta(delta_text: str) -> DeltaMessage | None

Emit content after consuming repeated leading think blocks.

Parameters

Name Type Required Default Description
delta_text str yes none Required positional or keyword input.

Returns

  • Type: DeltaMessage | None
  • Direct return expressions: None; DeltaMessage(content=delta_text) if delta_text else None; DeltaMessage(reasoning=''.join(reasoning_parts) or None, content=buffer); DeltaMessage(reasoning=''.join(reasoning_parts))

Exceptions and behavior

Method BaseThinkingReasoningParser._content_delta updates self._content_buffer, self._content_started; calls DeltaMessage, self._content_buffer.lstrip, buffer.startswith, buffer[len(self.end_token):].lstrip; has 4 explicit return paths. No direct raise statement appears in this definition.

View source #L278-L325.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._thinking_tool_call · method
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._thinking_tool_call(previous_text: str, current_text: str, delta_text: str) -> DeltaMessage | None

Handle streaming while inside a during thinking phase.

Parameters

Name Type Required Default Description
previous_text str yes none Required positional or keyword input.
current_text str yes none Required positional or keyword input.
delta_text str yes none Required positional or keyword input.

Returns

  • Type: DeltaMessage | None
  • Direct return expressions: DeltaMessage(content=final_content or None, reasoning=r_text or None); DeltaMessage(content=promoted, reasoning=reasoning); DeltaMessage(content=final_content or None); None

Exceptions and behavior

Method BaseThinkingReasoningParser._thinking_tool_call updates self._tool_call_buffer, self._in_tool_call, self._phase; calls self._tool_call_buffer.find, len, logger.warning, remainder.find; has 4 explicit return paths. No direct raise statement appears in this definition.

View source #L327-L396.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.finalize_stream · method
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser.finalize_stream() -> DeltaMessage | None

Flush any buffered tool call text at end of stream.

Parameters

This callable has no explicit inputs.

Returns

  • Type: DeltaMessage | None
  • Direct return expressions: DeltaMessage(content=promoted); None

Exceptions and behavior

Method BaseThinkingReasoningParser.finalize_stream updates self._tool_call_buffer, self._in_tool_call; calls logger.warning, DeltaMessage; has 2 explicit return paths. No direct raise statement appears in this definition.

View source #L398-L406.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._promote_tool_calls · method
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._promote_tool_calls(reasoning: str | None, content: str | None) -> tuple[str | None, str | None]

Method BaseThinkingReasoningParser._promote_tool_calls calls cls._TOOL_CALL_CLOSED_RE.sub, cls._TOOL_CALL_UNCLOSED_RE.search, unclosed_match.group, unclosed_match.start; has 2 explicit return paths.

Parameters

Name Type Required Default Description
reasoning str \| None yes none Required positional or keyword input.
content str \| None yes none Required positional or keyword input.

Returns

  • Type: tuple[str | None, str | None]
  • Direct return expressions: (reasoning, content); (cleaned, result_content)

Exceptions and behavior

Method BaseThinkingReasoningParser._promote_tool_calls calls cls._TOOL_CALL_CLOSED_RE.sub, cls._TOOL_CALL_UNCLOSED_RE.search, unclosed_match.group, unclosed_match.start; has 2 explicit return paths. No direct raise statement appears in this definition.

View source #L409-L462.

vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._promote_tool_calls._collect_closed · nested function
vllm_mlx.reasoning.think_parser.BaseThinkingReasoningParser._promote_tool_calls._collect_closed(match) -> not annotated

Nested Function BaseThinkingReasoningParser._promote_tool_calls._collect_closed calls closed.append, match.group; returns ''.

Parameters

Name Type Required Default Description
match not annotated yes none Required positional or keyword input.

Returns

  • Type: not annotated
  • Direct return expressions: ''

Exceptions and behavior

Nested Function BaseThinkingReasoningParser._promote_tool_calls._collect_closed calls closed.append, match.group; returns ''. No direct raise statement appears in this definition.

View source #L419-L421.

Complete symbol map

This map also includes private definitions and nested helpers. The signature column exposes every explicit input even when an internal helper has no dedicated parameter prose.

Symbol Kind Signature and inputs What it does Source
BaseThinkingReasoningParser class BaseThinkingReasoningParser(tokenizer = None) Base parser for models using ... style tags. #L29-L462
BaseThinkingReasoningParser.start_token method BaseThinkingReasoningParser.start_token() -> str The token/tag that starts reasoning content (e.g., ''). #L50-L51
BaseThinkingReasoningParser.end_token method BaseThinkingReasoningParser.end_token() -> str The token/tag that ends reasoning content (e.g., ''). #L55-L56
BaseThinkingReasoningParser.__init__ method BaseThinkingReasoningParser.__init__(tokenizer = None) -> not annotated Method BaseThinkingReasoningParser.__init__ updates self._phase, self._content_started, self._content_buffer, self._in_tool_call; calls super().__init__, super. #L63-L71
BaseThinkingReasoningParser.reset_state method BaseThinkingReasoningParser.reset_state() -> not annotated Reset state machine for a new streaming request. #L73-L79
BaseThinkingReasoningParser.extract_reasoning method BaseThinkingReasoningParser.extract_reasoning(model_output: str) -> tuple[str \| None, str \| None] Extract reasoning from complete output. #L81-L110
BaseThinkingReasoningParser.extract_reasoning_streaming method BaseThinkingReasoningParser.extract_reasoning_streaming(previous_text: str, current_text: str, delta_text: str) -> DeltaMessage \| None Extract reasoning from a streaming delta using state-machine tracking. #L112-L224
BaseThinkingReasoningParser._extract_complete_reasoning method BaseThinkingReasoningParser._extract_complete_reasoning(text: str) -> tuple[str \| None, str \| None] Split complete output into leading reasoning spans and final content. #L226-L260
BaseThinkingReasoningParser._transition_to_content method BaseThinkingReasoningParser._transition_to_content(reasoning: str \| None, content: str \| None) -> DeltaMessage \| None Return a delta while suppressing leading post-transition think blocks. #L262-L276
BaseThinkingReasoningParser._content_delta method BaseThinkingReasoningParser._content_delta(delta_text: str) -> DeltaMessage \| None Emit content after consuming repeated leading think blocks. #L278-L325
BaseThinkingReasoningParser._thinking_tool_call method BaseThinkingReasoningParser._thinking_tool_call(previous_text: str, current_text: str, delta_text: str) -> DeltaMessage \| None Handle streaming while inside a during thinking phase. #L327-L396
BaseThinkingReasoningParser.finalize_stream method BaseThinkingReasoningParser.finalize_stream() -> DeltaMessage \| None Flush any buffered tool call text at end of stream. #L398-L406
BaseThinkingReasoningParser._promote_tool_calls method BaseThinkingReasoningParser._promote_tool_calls(reasoning: str \| None, content: str \| None) -> tuple[str \| None, str \| None] Method BaseThinkingReasoningParser._promote_tool_calls calls cls._TOOL_CALL_CLOSED_RE.sub, cls._TOOL_CALL_UNCLOSED_RE.search, unclosed_match.group, unclosed_match.start; has 2 explicit return paths. #L409-L462
BaseThinkingReasoningParser._promote_tool_calls._collect_closed nested function BaseThinkingReasoningParser._promote_tool_calls._collect_closed(match) -> not annotated Nested Function BaseThinkingReasoningParser._promote_tool_calls._collect_closed calls closed.append, match.group; returns ''. #L419-L421