o
    پi?                     @   s   d dl Z d dlZd dlZd dlZd dlmZmZmZ d dlm	Z	 d dl
mZ d dlmZmZmZ eeZdededee	 d	efd
dZded	eeef fddZG dd deZdS )    N)AnyDictList)Tool)BaseFormatDetector)StreamingParseResultToolCallItem_GetInfoFunc	func_namearg_keydefined_toolsreturnc                 C   sV   dd |D }| |vrdS ||  }|j jpi }|di }||vr#dS || ddS )z?Get the expected type for a function argument from tool schema.c                 S   s   i | ]}|j j|qS  )functionname).0toolr   r   [/home/ubuntu/.local/lib/python3.10/site-packages/sglang/srt/function_call/step3_detector.py
<dictcomp>   s    z%get_argument_type.<locals>.<dictcomp>N
propertiestype)r   
parametersget)r
   r   r   	name2toolr   r   r   r   r   r   get_argument_type   s   r   valuec                 C   s@   zzt | }W n	   t| }Y |dfW S    | df Y S )zJParse a string value to appropriate type. Returns (parsed_value, success).TF)jsonloadsastliteral_eval)r   parsed_valuer   r   r   parse_arguments   s   
r!   c                	       s   e Zd ZdZ fddZdedefddZ	dded	ee	 de
eef 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e	 defddZdd ZdefddZdefddZ  ZS )Step3Detectoru  
    Detector for Step3 model function call format.

    The Step3 format uses special Unicode tokens to delimit function calls
    with steptml XML format for invocations.

    Format Structure:
    ```
    <｜tool_calls_begin｜>
    <｜tool_call_begin｜>function<｜tool_sep｜><steptml:invoke name="function_name">
    <steptml:parameter name="param1">value1</steptml:parameter>
    <steptml:parameter name="param2">value2</steptml:parameter>
    </steptml:invoke><｜tool_call_end｜>
    <｜tool_calls_end｜>
    ```
    c                    sp   t    d| _d| _d| _d| _d| _tdtj	| _
tdtj	| _d| _d| _d	| _i | _d| _d| _d S )
Nu   <｜tool_calls_begin｜>u   <｜tool_calls_end｜>u   <｜tool_call_begin｜>u   <｜tool_call_end｜>u   <｜tool_sep｜>z5<steptml:invoke name="([^"]+)">(.+?)</steptml:invoke>z=<steptml:parameter name="([^"]+)">([^<]*)</steptml:parameter>F )super__init__	bot_token	eot_tokentool_call_begintool_call_endtool_seprecompileDOTALLinvoke_regexparam_regex_in_tool_block_tool_block_finished_current_function_name_current_parameters_in_tool_call_function_name_sentself	__class__r   r   r%   =   s$   

zStep3Detector.__init__textr   c                 C   s
   | j |v S )z4Check if the text contains a Step3 format tool call.)r&   )r7   r:   r   r   r   has_tool_callU   s   
zStep3Detector.has_tool_callNtoolsc                 C   s   | j |}|sdi fS |d}|d}i }| j|D ]6}|d}|d }	|rJt|||}
|
rE|
dkrEt|	\}}|||< q|	||< qt|	\}}|||< q||fS )zDParse steptml invoke format to extract function name and parameters.N      string)r.   searchgroupr/   finditerstripr   r!   )r7   r:   r<   invoke_matchr
   params_textparamsparam_match
param_nameparam_valuearg_typer    _r   r   r   _parse_steptml_invokeY   s$   





z#Step3Detector._parse_steptml_invokec              
   C   sF  | j |vrt|g dS zx|| j d\}}| j|vr!t|g dW S || jd\}}g }t| j dt| j }t||tj	D ]5}	|	
d}
| j|
vrPqC|
| jd\}}| dkr`qC| ||\}}|rx||d}|| || qC|| }t||dW S  ty } ztd|  t|dW  Y d}~S d}~ww )	zW
        One-time parsing: Detects and parses tool calls in the provided text.
        normal_textcallsr=   z(.*?)r   r   	argumentszError in detect_and_parse: rN   N)r&   r   splitr'   r+   escaper(   r)   rB   r-   rA   r*   rC   rL   extendparse_base_json	Exceptionloggererror)r7   r:   r<   pre_textresttool_section	post_textrO   tool_call_patternmatchcall_content	type_partinvoke_partr
   rF   actionrN   er   r   r   detect_and_parsex   s:   




zStep3Detector.detect_and_parsenew_textc           
      C   s  |  j |7  _ t| ds| || _| jr | j }d| _ t|dS | jsd| j| j v rL| j | j}| j d| }| j |t	| j d | _ d| _t|dS | 
| j | j}|rYt S | j }d| _ t|dS g }| j| j v r| j | j}| jr| j d| }| j|v r| |}||j ntd | j |t	| j d }	d| _ d| _|   t|	|dS | js| j| j v r| j | j}| j |t	| j d | _ d| _d| _d| _i | _nt S | jr| |S t S )	zA
        Streaming incremental parsing for Step3 format.
        _tool_indicesr#   rR   NTz*Tool block ended with incomplete tool callrM   F)_bufferhasattr_get_tool_indicesrg   r1   r   r0   r&   findlen_ends_with_partial_tokenr'   r4   r)   _parse_partial_tool_callrU   rO   rX   warning_reset_streaming_stater(   r5   r2   r3   )
r7   rf   r<   rN   idxpartial_lenrO   
before_eotresult	remainingr   r   r   parse_streaming_increment   s`   







z'Step3Detector.parse_streaming_incrementc                 C   s  g }| j | jvrt|dS | j| j d\}}| dkr&|   t|dS | jstd|}|r|	d}|| j
v r|| _d| _| jdkrId| _t| j| jkr_| ji  t| j| jksQt| j| jkru| jd t| j| jksg|i d	| j| j< |t| j|dd
 ntd|  |   t|dS t|dS | jri }| j|D ]*}|	d}	|	d }
t| j|	|}|r|dkrt|
\}}|||	< q|
||	< q|| jkrE| jstj|dd}t|dkr|dd }n/d}n,tj| jdd}tj|dd}|dd }|dd }||r!|t|d }nd}|r:|t| j|d | j| j  |7  < || _|| j| j d< | j| jv r| j| j rg|t| jdd | j| j  d7  < | j| j}| j|t| j d | _|   |  jd7  _t|dS )z0Parse partial tool call for streaming scenarios.)rO   r=   r   z<steptml:invoke name="([^"]+)">Tr   r#   rP   )
tool_indexr   r   zInvalid function name: r>   r?   F)ensure_asciiN{)rx   r   rQ   })r*   rh   r   rS   rC   rp   r5   r+   r@   rA   rg   r2   current_tool_idrl   prev_tool_call_arrappendstreamed_args_for_toolr   rX   ro   r/   rB   r   r!   r3   r   dumps
startswithr)   rk   )r7   r<   rO   ra   rb   
name_matchr
   
new_paramsrG   rH   rI   rJ   r    rK   params_contentdiffold_jsonnew_jsonold_without_bracenew_without_braceend_idxr   r   r   rn      s   




	





z&Step3Detector._parse_partial_tool_callc                 C   s   d| _ d| _d| _i | _dS )z,Reset streaming state for the next tool callFr#   N)r4   r5   r2   r3   r6   r   r   r   rp     s   
z$Step3Detector._reset_streaming_statec                 C   s   dS )z<Return True if this detector supports structural tag format.Fr   r6   r   r   r   supports_structural_tag  s   z%Step3Detector.supports_structural_tagc                 C   s   t  N)NotImplementedErrorr6   r   r   r   structure_info  s   zStep3Detector.structure_infor   )__name__
__module____qualname____doc__r%   strboolr;   r   r   tupledictrL   r   re   rv   rn   rp   r   r	   r   __classcell__r   r   r8   r   r"   +   s2    

1
W r"   )r   r   loggingr+   typingr   r   r   &sglang.srt.entrypoints.openai.protocolr   -sglang.srt.function_call.base_format_detectorr   #sglang.srt.function_call.core_typesr   r   r	   	getLoggerr   rX   r   r   r   r   r!   r"   r   r   r   r   <module>   s    
