o
    iJ                     @   s&  d dl Z d dlmZ d dlmZ d dlmZ d dlmZm	Z	m
Z
mZmZmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZmZ d dlmZmZmZmZ d dlm Z  d dl!m"Z" d dl#m$Z$ d dl%m&Z& d dl'm(Z( d dl)m*Z* e"e+Z,G dd dZ-G dd de-Z.G dd de.Z/dS )    N)abstractmethod)Sequence)cached_property)ResponseFunctionToolCallResponseOutputItemResponseOutputMessageResponseOutputTextResponseReasoningItemToolChoiceFunction)Logprob)Content)TypeAdapter)make_tool_call_id)"ChatCompletionNamedToolChoiceParamChatCompletionRequest)DeltaMessageExtractedToolCallInformationFunctionCallFunctionDefinition)ResponsesRequest)init_logger)ReasoningParser)TokenizerLike)
ToolParser)random_uuidc                   @   s(  e Zd ZU dZdZee dB ed< dZee	 dB ed< de
fddZedeeef fd	d
ZededB fddZejdedB ddfddZede	dB fddZejde	dB ddfddZedee defddZdee dee defddZedee dee fddZe			d3dedededed ee dB dee fd!d"ZededeeB de edB edB f fd#d$Z!ed%ed&ed'ed(e"e d)e"e d*e"e de#dB fd+d,Z$dedefd-d.Z%ededede&fd/d0Z'ed%ed&ed'ed(e"e d)e"e d*e"e dede#dB fd1d2Z(dS )4ParseraW  
    Abstract Parser class that unifies ReasoningParser and ToolParser into
    a single interface for parsing model output.

    This class provides a unified way to handle both reasoning extraction
    (e.g., chain-of-thought content in <think> tags) and tool call extraction
    (e.g., function calls in XML/JSON format) from model outputs.

    Subclasses can either:
    1. Override the abstract methods directly for custom parsing logic
    2. Set `reasoning_parser` and `tool_parser` properties to delegate to
       existing parser implementations

    Class Attributes:
        reasoning_parser_cls: The ReasoningParser class to use (for compatibility
            with code that needs the class, not instance).
        tool_parser_cls: The ToolParser class to use (for compatibility with
            code that needs the class, not instance).
    Nreasoning_parser_clstool_parser_cls	tokenizerc                 O   s   || _ d| _d| _dS )z
        Initialize the Parser.

        Args:
            tokenizer: The tokenizer used by the model. This is required for
                token-based parsing operations.
        N)model_tokenizer_reasoning_parser_tool_parser)selfr   argskwargs r%   Q/home/ubuntu/vllm_env/lib/python3.10/site-packages/vllm/parser/abstract_parser.py__init__H   s   
zParser.__init__returnc                 C   s
   | j  S )z.Get the vocabulary mapping from tokens to IDs.)r   	get_vocabr"   r%   r%   r&   vocabT   s   
zParser.vocabc                 C      | j S )z(The underlying reasoning parser, if any.r    r*   r%   r%   r&   reasoning_parserY      zParser.reasoning_parserparserc                 C   
   || _ d S Nr-   r"   r0   r%   r%   r&   r.   ^      
c                 C   r,   )z#The underlying tool parser, if any.r!   r*   r%   r%   r&   tool_parserb   r/   zParser.tool_parserc                 C   r1   r2   r5   r3   r%   r%   r&   r6   g   r4   	input_idsc                 C      dS )a[  
        Check if the reasoning content ends in the input_ids.

        Used by structured engines like `xgrammar` to check if the
        reasoning content ends in the model output.

        Args:
            input_ids: The token IDs of the model output.

        Returns:
            True if the reasoning content ends in the input_ids.
        Nr%   r"   r7   r%   r%   r&   is_reasoning_endm       zParser.is_reasoning_end	delta_idsc                 C   s
   |  |S )a7  
        Check if the reasoning content ends during a decode step.

        Args:
            input_ids: The entire model output token IDs.
            delta_ids: The last few computed tokens at the current decode step.

        Returns:
            True if the reasoning content ends in the delta_ids.
        )r:   )r"   r7   r<   r%   r%   r&   is_reasoning_end_streaming|   s   
z!Parser.is_reasoning_end_streamingc                 C   r8   )a+  
        Extract content token IDs from the input_ids.

        This extracts the non-reasoning content (e.g., everything after
        the </think> tag).

        Args:
            input_ids: The token IDs of the model output.

        Returns:
            The extracted content token IDs.
        Nr%   r9   r%   r%   r&   extract_content_ids   r;   zParser.extract_content_idsFrandommodel_outputrequestenable_auto_toolstool_call_id_typelogprobsc                 C   r8   )a  
        Extract reasoning, content, and tool calls from a complete
        model-generated string and return as ResponseOutputItem objects.

        Used for non-streaming responses where we have the entire model
        response available before sending to the client.

        Args:
            model_output: The complete model-generated string.
            request: The request object used to generate the output.
            enable_auto_tools: Whether to enable automatic tool call parsing.
            tool_call_id_type: Type of tool call ID generation ("random", etc).
            logprobs: Pre-computed logprobs for the output text, if any.

        Returns:
            A list of ResponseOutputItem objects.
        Nr%   )r"   r@   rA   rB   rC   rD   r%   r%   r&   extract_response_outputs   r;   zParser.extract_response_outputsc                 C   r8   )a  
        Extract reasoning content from a complete model-generated string.

        Used for non-streaming responses where we have the entire model
        response available before sending to the client.

        Args:
            model_output: The complete model-generated string.
            request: The request object used to generate the output.

        Returns:
            A tuple of (reasoning_content, response_content).
        Nr%   r"   r@   rA   r%   r%   r&   extract_reasoning   r;   zParser.extract_reasoningprevious_textcurrent_text
delta_textprevious_token_idscurrent_token_idsdelta_token_idsc                 C   r8   )a"  
        Extract reasoning content from a streaming delta message.

        Args:
            previous_text: Text from all previous tokens.
            current_text: Text including the current delta.
            delta_text: The new text in this delta.
            previous_token_ids: Token IDs from previous generation.
            current_token_ids: All token IDs including current.
            delta_token_ids: The new token IDs in this delta.

        Returns:
            A DeltaMessage with reasoning and/or content fields, or None.
        Nr%   r"   rH   rI   rJ   rK   rL   rM   r%   r%   r&   extract_reasoning_streaming   r;   z"Parser.extract_reasoning_streamingc                 C   s   |S )a9  
        Adjust the request parameters for tool calling.

        Can be overridden by subclasses to modify request parameters
        (e.g., setting structured output schemas for tool calling).

        Args:
            request: The original request.

        Returns:
            The adjusted request.
        r%   )r"   rA   r%   r%   r&   adjust_request   s   zParser.adjust_requestc                 C   r8   )a`  
        Extract tool calls from a complete model-generated string.

        Used for non-streaming responses.

        Args:
            model_output: The complete model-generated string.
            request: The request object used to generate the output.

        Returns:
            ExtractedToolCallInformation containing the tool calls.
        Nr%   rF   r%   r%   r&   extract_tool_calls   r;   zParser.extract_tool_callsc                 C   r8   )a5  
        Extract tool calls from a streaming delta message.

        Args:
            previous_text: Text from all previous tokens.
            current_text: Text including the current delta.
            delta_text: The new text in this delta.
            previous_token_ids: Token IDs from previous generation.
            current_token_ids: All token IDs including current.
            delta_token_ids: The new token IDs in this delta.
            request: The request object.

        Returns:
            A DeltaMessage with tool_calls field, or None.
        Nr%   r"   rH   rI   rJ   rK   rL   rM   rA   r%   r%   r&   extract_tool_calls_streaming  r;   z#Parser.extract_tool_calls_streamingFr?   N))__name__
__module____qualname____doc__r   typer   __annotations__r   r   r   r'   r   dictstrintr+   propertyr.   setterr6   r   listboolr:   r=   r>   r   r   r   rE   r   tuplerG   r   r   rO   rP   r   rQ   rS   r%   r%   r%   r&   r   .   s   
 

	r   c                   @   s$  e Zd ZdZdedeeB deedB edB f fddZ				ddeded
e	dede
e dB de
e fddZdededB d
e	dee
e edB f fddZdedededee dee dee dedB fddZdededefddZdedededee dee dee dededB fddZdS )DelegatingParsera  
    A Parser implementation that delegates to separate ReasoningParser and
    ToolParser instances.

    This is the recommended base class for creating model-specific parsers
    that combine existing reasoning and tool parser implementations.
    Subclasses should set `self._reasoning_parser` and `self._tool_parser`
    in their `__init__` method.

    If either parser is None, the corresponding methods will return default
    values (no reasoning extraction, no tool calls).
    r@   rA   r(   Nc                 C   s    | j d u r	d |fS | j ||S r2   )r    rG   rF   r%   r%   r&   rG   0  s   
z"DelegatingParser.extract_reasoningFr?   rB   rC   rD   c              	   C   s   |  ||\}}| j|||d\}}g }	|r-tdt  g dt|ddgd d}
|	|
 |rJt|g d|d}td	t  |gd
ddd}|	| |rvt|D ]%\}}t	dt  |j
r`|j
nt||j|ddd|j|jd}|	| qP|	S )N)rA   contentrB   rs_	reasoningreasoning_text)textrY   )idsummaryrY   rd   statusoutput_text)rh   annotationsrY   rD   msg_	assistant	completedmessage)ri   rd   rolerk   rY   fc_)id_type	func_nameidxfunction_call)ri   call_idrY   rk   name	arguments)rG   _parse_tool_callsr	   r   ResponseReasoningTextContentappendr   r   	enumerater   ri   r   ry   rz   )r"   r@   rA   rB   rC   rD   rf   rd   
tool_callsoutputsreasoning_itemres_text_partmessage_itemhistory_tool_call_cnt	tool_calltool_call_itemr%   r%   r&   rE   9  sd   	



	


z)DelegatingParser.extract_response_outputsrd   c                 C   sN  g }|j r t|j tr |dusJ |t|j j|d |dfS |j r?t|j tr?|dus/J |t|j jj|d |dfS |j dkra|dusJJ tt	t
 |}|dd |D  |dfS | jdur|r|j dksr|j du r| jj|dur{|nd|d}|dur|jr|d	d |jD  |j}|r| dkrd}||fS g |fS )
a4  
        TODO(qandrew): merge _parse_tool_calls_from_content
        for ChatCompletions into this function
        Parse tool calls from content based on request tool_choice settings.

        Returns:
            A tuple of (function_calls, remaining_content) if tool calls
            were parsed
        Nry   rz   requiredc                 s   s*    | ]}t |jtj|jd ddV  qdS )F)ensure_asciir   N)r   ry   jsondumps
parameters.0r   r%   r%   r&   	<genexpr>  s    
z5DelegatingParser._parse_tool_calls.<locals>.<genexpr>auto )rA   c                 s   s(    | ]}t |j|jj|jjd V  qdS ))ri   ry   rz   N)r   ri   functionry   rz   r   r%   r%   r&   r     s    
)tool_choice
isinstancer
   r}   r   ry   r   r   r   r`   r   validate_jsonextendr!   rQ   tools_calledr   rd   strip)r"   rA   rd   rB   function_callsr   tool_call_inforemaining_contentr%   r%   r&   r{     sN   



z"DelegatingParser._parse_tool_callsrH   rI   rJ   rK   rL   rM   c                 C   s*   | j d u r
t|dS | j ||||||S )N)rd   )r    r   rO   rN   r%   r%   r&   rO     s   
	
z,DelegatingParser.extract_reasoning_streamingc                 C   s&   | j d u rtdg |dS | j ||S )NF)r   r   rd   )r!   r   rQ   rF   r%   r%   r&   rQ     s
   
z#DelegatingParser.extract_tool_callsc              	   C   s&   | j d u rd S | j |||||||S r2   )r!   rS   rR   r%   r%   r&   rS     s   

z-DelegatingParser.extract_tool_calls_streamingrT   )rU   rV   rW   rX   r\   r   r   rb   rG   ra   r`   r   r   rE   r   r{   r   r]   r   rO   r   rQ   rS   r%   r%   r%   r&   rc   "  s    


K
K

	rc   c                       sP   e Zd ZU dZdZee dB ed< dZee	 dB ed< de
f fddZ  ZS )_WrappedParsera  
    A DelegatingParser subclass that instantiates parsers from class attributes.

    This class is used to dynamically create a parser that wraps individual
    ReasoningParser and ToolParser classes. The class attributes
    `reasoning_parser_cls` and `tool_parser_cls` should be set before
    instantiation.

    Usage:
        _WrappedParser.reasoning_parser_cls = MyReasoningParser
        _WrappedParser.tool_parser_cls = MyToolParser
        parser = _WrappedParser(tokenizer)
    Nr   r   r   c                    sH   t  | | jjd ur| j|| _| jjd ur"| j|| _d S d S r2   )superr'   	__class__r   r    r   r!   )r"   r   r   r%   r&   r'     s   z_WrappedParser.__init__)rU   rV   rW   rX   r   rY   r   rZ   r   r   r   r'   __classcell__r%   r%   r   r&   r     s
   
 r   )0r   abcr   collections.abcr   	functoolsr   openai.types.responsesr   r   r   r   r	   r
   +openai.types.responses.response_output_textr   .openai.types.responses.response_reasoning_itemr   r|   pydanticr   vllm.entrypoints.chat_utilsr   0vllm.entrypoints.openai.chat_completion.protocolr   r   'vllm.entrypoints.openai.engine.protocolr   r   r   r   *vllm.entrypoints.openai.responses.protocolr   vllm.loggerr   $vllm.reasoning.abs_reasoning_parsersr   vllm.tokenizersr   &vllm.tool_parsers.abstract_tool_parserr   
vllm.utilsr   rU   loggerr   rc   r   r%   r%   r%   r&   <module>   s.     u d