o
    پi                     @   sn   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 eeZG dd deZdS )    N)List)Tool)BaseFormatDetector)StreamingParseResultStructureInfo_GetInfoFuncc                       sx   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 fddZdefddZ  ZS )Qwen25Detectora  
    Detector for Qwen 2.5 and Qwen 3 model function call format.

    Format Structure:
    ```
    <tool_call>
{"name":"func1", "arguments":{...}}
</tool_call>
<tool_call>
{"name":"func2", "arguments":{...}}
</tool_call>
    ```

    Key Components:
    - Tool Call Tags: `<tool_call>` and `</tool_call>` wrap each individual call
    - Function Call Object: JSON object with "name" and "arguments" fields

    Reference: https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct?chat_template=default
    c                    s&   t    d| _d| _d| _d| _dS )zJ
        Initializes the detector with necessary state variables.
        z<tool_call>
z
</tool_call>
 N)super__init__	bot_token	eot_tokentool_call_separator_normal_text_bufferself	__class__ \/home/ubuntu/.local/lib/python3.10/site-packages/sglang/srt/function_call/qwen25_detector.pyr   !   s
   

zQwen25Detector.__init__textreturnc                 C   s
   | j |v S )z7Check if the text contains a Qwen 2.5 format tool call.)r   )r   r   r   r   r   has_tool_call+   s   
zQwen25Detector.has_tool_calltoolsc                 C   s   | | j}|dkr|d|  n|}| j|vrt|g dS t| j dt| j }t||tj}g }|D ]4}zt	
| }	|| |	| W q: t	jyn }
 ztd| dt|
  W Y d}
~
q:d}
~
ww t||dS )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.
        N)normal_textcallsz(.*?)zFailed to parse JSON part: z, JSON parse error: )findr   stripr   reescaper   findallDOTALLjsonloadsextendparse_base_jsonJSONDecodeErrorloggerwarningstr)r   r   r   idxr   patternmatch_result_listr   match_resultparsed_caller   r   r   detect_and_parse/   s&   
zQwen25Detector.detect_and_parsenew_textc                    s   t  ||}|jrQ|  j|j7  _| jdd }|| jv r-| j|d}d| _||_|S | | j|}|rJ| jd|  |_| j| d | _|S | j|_d| _|S )z
        Streaming incremental parsing for Qwen 2.5 tool calls.
        Uses base class implementation with buffering to handle partial end tokens.
           Nr
   )r   parse_streaming_incrementr   r   r   replace_ends_with_partial_token)r   r3   r   resultend_token_without_newlinecleaned_textpartial_match_lenr   r   r   r5   K   s.   
z(Qwen25Detector.parse_streaming_incrementc                 C   s   dd S )Nc                 S   s   t d|  d dddS )Nz<tool_call>
{"name":"z", "arguments":z}
</tool_call>z<tool_call>)beginendtrigger)r   )namer   r   r   <lambda>t   s
    
z/Qwen25Detector.structure_info.<locals>.<lambda>r   r   r   r   r   structure_infos   s   zQwen25Detector.structure_info)__name__
__module____qualname____doc__r   r+   boolr   r   r   r   r2   r5   r   rA   __classcell__r   r   r   r   r      s    
(r   )r$   loggingr    typingr   &sglang.srt.entrypoints.openai.protocolr   -sglang.srt.function_call.base_format_detectorr   #sglang.srt.function_call.core_typesr   r   r   	getLoggerrB   r)   r   r   r   r   r   <module>   s    
