o
    پiL&                     @   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 eeZG dd deZdS )	    N)List)Tool)BaseFormatDetector)StreamingParseResultStructureInfoToolCallItem_GetInfoFunc)_is_complete_jsonc                       st   e Zd ZdZ fddZ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 )KimiK2Detectorav  
    Detector for Kimi K2 model function call format.

    Format Structure:
    ```
    <|tool_calls_section_begin|>
    <|tool_call_begin|>functions.{func_name}:{index}<|tool_call_argument_begin|>{json_args}<|tool_call_end|>
    <|tool_calls_section_end|>
    ```

    Reference: https://huggingface.co/moonshotai/Kimi-K2-Instruct/blob/main/docs/tool_call_guidance.md
    c                    sX   t    d| _d| _d| _d| _tdtj| _	tdtj| _
d| _td| _d S )	N<|tool_calls_section_begin|>z<|tool_calls_section_end|>z<|tool_call_begin|><|tool_call_end|>z<\|tool_call_begin\|>\s*(?P<tool_call_id>[\w\.]+:\d+)\s*<\|tool_call_argument_begin\|>\s*(?P<function_arguments>\{.*?\})\s*<\|tool_call_end\|>zu<\|tool_call_begin\|>\s*(?P<tool_call_id>[\w\.]+:\d+)\s*<\|tool_call_argument_begin\|>\s*(?P<function_arguments>\{.*) z2^(?:functions\.)?(?P<name>[\w\.]+):(?P<index>\d+)$)super__init__	bot_token	eot_tokentool_call_start_tokentool_call_end_tokenrecompileDOTALLtool_call_regexstream_tool_call_portion_regex_last_argumentstool_call_id_regex)self	__class__ \/home/ubuntu/.local/lib/python3.10/site-packages/sglang/srt/function_call/kimik2_detector.pyr   !   s"   

zKimiK2Detector.__init__textreturnc                 C   s
   | j |v S )z5Check if the text contains a KimiK2 format tool call.)r   )r   r    r   r   r   has_tool_call;   s   
zKimiK2Detector.has_tool_calltoolsc              
   C   s   | j |vrt|g dS zU| j|}td| g }|D ]3}|\}}| j|}|s1td| q|	d}	t
|	d}
td|	  |t|
|	|d q|d|| j  }t||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.
        normal_textcallszfunction_call_tuples: %s"Unexpected tool_call_id format: %snameindexzfunction_name 
tool_indexr(   
parametersNzError in detect_and_parse: r%   )r   r   r   findallloggerdebugr   matchwarninggroupintappendr   find	Exceptionerror)r   r    r#   function_call_tuples
tool_callsr1   function_idfunction_argsmfunction_namefunction_idxcontenter   r   r   detect_and_parse?   s:   

zKimiK2Detector.detect_and_parsenew_textc              
   C   s  |  j |7  _ | j }| j|v p| j|v }|s1d| _ | j| jfD ]}||v r+||d}qt|dS t| ds<| || _	g }z| j
|}|rR|d}|d}	| j|}
|
shtd| td|dW S |
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| _|i d| j| j< n|	| jr|	t| jd n|	}|ddd
 }|r|t| jd|d |  j|7  _| j| j  |7  < |	ddd
 }t|rRzt|}|| j| j d< W n tjy!   Y nw d}t||tj }|r9||! d | _ nd| _ td|d}|  jd7  _d| _d| _|W S td|dW S  t"yx } zt#d|  t|dW  Y d}~S d}~ww )zM
        Streaming incremental parsing tool calls for KimiK2 format.
        r   r-   _tool_indicestool_call_idfunction_argumentsr'   r$   r(   r   r*   T)r(   	argumentsNr      rH   z+<\|tool_call_begin\|>.*?<\|tool_call_end\|>Fz$Error in parse_streaming_increment: )$_bufferr   r   r   r   replacer   hasattr_get_tool_indicesrD   r   searchr3   r   r1   r/   r2   current_tool_idprev_tool_call_arrstreamed_args_for_toollenr5   current_tool_name_sentr   
startswithr   splitr	   jsonloadsJSONDecodeErrorr   r   endr7   r8   )r   rC   r#   current_textr"   e_tokenr&   r1   r;   r<   r=   r>   argument_diffparsed_args_diffparsed_argstool_call_end_patternresultrA   r   r   r   parse_streaming_incrementn   s   









z(KimiK2Detector.parse_streaming_incrementc                 C   s   dt dtfdd}|S )zAReturn function that creates StructureInfo for guided generation.r(   r!   c                 S   s   t d|  ddddS )Nz9<|tool_calls_section_begin|><|tool_call_begin|>functions.z:0<|tool_call_argument_begin|>z+<|tool_call_end|><|tool_calls_section_end|>r   )beginrY   trigger)r   )r(   r   r   r   get_info   s
   
z/KimiK2Detector.structure_info.<locals>.get_info)strr   )r   rd   r   r   r   structure_info   s   zKimiK2Detector.structure_info)__name__
__module____qualname____doc__r   re   boolr"   r   r   r   rB   ra   r   rf   __classcell__r   r   r   r   r
      s    /
yr
   )rV   loggingr   typingr   &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	   	getLoggerrg   r/   r
   r   r   r   r   <module>   s    
