o
    پi67                     @   s   d dl Z d dlZ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 d dlmZmZ eeZG dd deZdS )	    N)Allow)Tool)BaseFormatDetector)StreamingParseResultStructureInfoToolCallItem_GetInfoFunc)_find_common_prefix_partial_json_loadsc                       s   e Zd ZdZ fddZdedefddZ	dd	ed
edefddZ	dede
e defddZdede
e defddZdefddZ  ZS )DeepSeekV32Detectoru  
    Detector for DeepSeek V3.2 model function call format.

    The DeepSeek V3.2 format uses XML-like DSML tags to delimit function calls.
    Supports two parameter formats:

    Format 1 - XML Parameter Tags:
    ```
    <｜DSML｜function_calls>
        <｜DSML｜invoke name="function_name">
        <｜DSML｜parameter name="param_name" string="true">value</｜DSML｜parameter>
        ...
    </｜DSML｜invoke>
    </｜DSML｜function_calls>
    ```

    Format 2 - Direct JSON:
    ```
    <｜DSML｜function_calls>
        <｜DSML｜invoke name="function_name">
        {
            "param_name": "value"
        }
    </｜DSML｜invoke>
    </｜DSML｜function_calls>
    ```

    Examples:
    ```
    <｜DSML｜function_calls>
        <｜DSML｜invoke name="get_favorite_tourist_spot">
        <｜DSML｜parameter name="city" string="true">San Francisco</｜DSML｜parameter>
    </｜DSML｜invoke>
    </｜DSML｜function_calls>

    <｜DSML｜function_calls>
        <｜DSML｜invoke name="get_favorite_tourist_spot">
        { "city": "San Francisco" }
    </｜DSML｜invoke>
    </｜DSML｜function_calls>
    ```

    Key Components:
    - Tool Calls Section: Wrapped between `<｜DSML｜function_calls>` and `</｜DSML｜function_calls>`
    - Individual Tool Call: Wrapped between `<｜DSML｜invoke name="...">` and `</｜DSML｜invoke>`
    - Parameters: Either XML tags or direct JSON format
    - Supports multiple tool calls

    Reference: DeepSeek V3.2 format specification
    c                    sH   t    d| _d| _d| _d| _d| _d| _d| _g d| _	d	| _
d S )
Nu   <｜DSML｜function_calls>u   </｜DSML｜function_calls>   </｜DSML｜invoke>uW   <｜DSML｜parameter\s+name="([^"]+)"\s+string="([^"]+)"\s*>(.*?)</｜DSML｜parameter>uA   <｜DSML｜parameter\s+name="([^"]+)"\s+string="([^"]+)"\s*>(.*)$u:   <｜DSML｜function_calls>(.*?)</｜DSML｜function_calls>uB   <｜DSML｜invoke\s+name="([^"]+)"\s*>(.*?)(</｜DSML｜invoke>|$))</
   ｜DSML｜	parameter)super__init__	bot_token	eot_tokeninvoke_end_tokenparameter_regexpartial_parameter_regexfunction_calls_regexinvoke_regexprefix_parameter_end_callcurrent_tool_idself	__class__ a/home/ubuntu/.local/lib/python3.10/site-packages/sglang/srt/function_call/deepseekv32_detector.pyr   H   s   


zDeepSeekV32Detector.__init__textreturnc                 C   s   | j |v pd|v S )z;Check if the text contains a deepseek v32 format tool call.   <｜DSML｜invoke)r   )r   r"   r    r    r!   has_tool_callZ   s   z!DeepSeekV32Detector.has_tool_callFinvoke_contentallow_partialc              
   C   s  |  }|dr*|dr*zt|}t|tr|W S W n tjtfy)   Y nw i }t	t
| j|t
j}d}|D ]=}|d}|d}	|d}
| }|	dkr[|
  ||< q;zt|
  ||< W q; tjtfyx   |
  ||< Y q;w |r||d }t| jD ]}||}qt
| j|t
j}|r|d }
r|d}|ddkr|
  ||< |S t|
tjd ||< |S )	u  
        Parse parameters from either XML-like format or JSON format to dict.

        Supports two formats:
        1. XML parameter tags: <｜DSML｜parameter name="..." string="...">value</｜DSML｜parameter>
        2. Direct JSON: { "key": "value" }
        {}r            trueN)strip
startswithendswithjsonloads
isinstancedictJSONDecodeError
ValueErrorlistrefinditerr   DOTALLgroupendreversedr   rstripsearchr   r
   r   ALL)r   r&   r'   invoke_content_stripped
parametersparam_matcheslast_match_endmatch
param_name
param_typeparam_valueremaining_contenttokenpartial_matchr    r    r!   _parse_parameters_from_xml^   s^   






z.DeepSeekV32Detector._parse_parameters_from_xmltoolsc              
   C   s  | | j}|dkr|d|  n|}| j|vrt|g dS g }zBt| j|tj}|s4t|g dW S |d}t	| j
|tj}|D ]\}	}
}| |
}|	|d}|| || qDt||dW S  ty } ztd|  t|dW  Y d}~S d}~ww )a$  
        One-time parsing: Detects and parses tool calls in the provided text.

        :param text: The complete text to parse.
        :param tools: List of available tools.
        :return: ParseResult indicating success or failure, consumed text, leftover text, and parsed calls.
        r   Nnormal_textcallsr*   )namerB   zError in detect_and_parse: rO   )findr   r.   r   r8   r?   r   r:   r;   findallr   rL   extendparse_base_json	Exceptionloggererror)r   r"   rM   idxrO   rP   function_calls_matchfunction_calls_contentinvoke_matches	func_namer&   _	func_argsmatch_resulter    r    r!   detect_and_parse   s6   




z$DeepSeekV32Detector.detect_and_parsenew_textc              
      s  |  j |7  _ | j  g d}t fdd|D }g d}t fdd|D }|  sL|sL|sLd| _ | j| jfD ]}| v rF |d q:t dS g }z	 tj| j	 tj
d	}	|	s]n|	d
 }
|	d}t|	d}| jdkrd| _g | _dg| _t| j| jkr| ji  t| j| jkst| j| jkr| jd t| j| jks| js|t| j|
dd d| _| j|| d}tj|dd}t| j| j }| j| j d}d}|r||d }n#|dur
tj|dd}||kr
t||}t||kr
||d }|r"|t| jd|d | j| j  |7  < |
|d| j| j< |rE |	 d | _ | j  |  jd
7  _d| _qO	 td|dW S  tyl } ztd|  t dW  Y d}~S d}~ww )z
        Streaming incremental parsing tool calls for DeepSeekV32 format.
        Supports multiple consecutive invoke blocks and argument streaming.
        )r      <｜   </｜c                 3   s    | ]}| v V  qd S Nr    ).0markercurrent_textr    r!   	<genexpr>   s    z@DeepSeekV32Detector.parse_streaming_increment.<locals>.<genexpr>)<re   r   rf   c                 3   s    | ]
}   |V  qd S rg   )r>   r0   )rh   prefixrj   r    r!   rl      s    
 rR   T)patternstringflagsr*   r+   r,   r   r   )
tool_indexrQ   rB   )r'   F)ensure_ascii	argumentsN)rQ   ru   rN   z$Error in parse_streaming_increment: )_bufferanyr%   r   r   replacer   r8   r?   r   r:   r;   r.   boolr   prev_tool_call_arrstreamed_args_for_toollenappendcurrent_tool_name_sentr   rL   r1   dumpsgetr	   r<   rW   rX   rY   )r   rd   rM   dsml_markerspotentially_dsmldsml_prefixesends_with_prefixe_token	all_callsinvoke_matchr^   r&   is_tool_endcurrent_paramscurrent_args_jsonsent_lenprev_paramsargument_diffprev_args_jsonrn   rb   r    rj   r!   parse_streaming_increment   s   





z-DeepSeekV32Detector.parse_streaming_incrementc                 C   s   dd S )Nc                 S   s   t d|  ddddS )Nu   <｜DSML｜invoke name="z">r   r$   )beginr<   trigger)r   )rQ   r    r    r!   <lambda>^  s
    
z4DeepSeekV32Detector.structure_info.<locals>.<lambda>r    r   r    r    r!   structure_info]  s   z"DeepSeekV32Detector.structure_info)F)__name__
__module____qualname____doc__r   strry   r%   r4   rL   r7   r   r   rc   r   r   r   __classcell__r    r    r   r!   r      s,    3
I,
 r   )r1   loggingr8    partial_json_parser.core.optionsr   &sglang.srt.entrypoints.openai.protocolr   -sglang.srt.function_call.base_format_detectorr   #sglang.srt.function_call.core_typesr   r   r   r   sglang.srt.function_call.utilsr	   r
   	getLoggerr   rX   r   r    r    r    r!   <module>   s    
