o
    پi                     @   sv   d dl Z 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                       s   e Zd ZdZ fddZdede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 )Llama32Detectorz
    Detector for Llama 3.2 models with json tool call format.

    Format Structure:
    ```
    <python_tag>{"name":"xxx", "arguments":{...}}
    ```
    c                    s   t    d| _d| _d S )N<|python_tag|>;)super__init__	bot_tokentool_call_separatorself	__class__ ]/home/ubuntu/.local/lib/python3.10/site-packages/sglang/srt/function_call/llama32_detector.pyr      s   

zLlama32Detector.__init__textreturnc                 C   s<   zt | }t|trtj|ddW S W |S    Y |S )z+Convert Python dict strings to JSON format.F)ensure_ascii)astliteral_evalstrip
isinstancedictjsondumps)r   r   parsedr   r   r   _convert_python_dict_to_json%   s   
z,Llama32Detector._convert_python_dict_to_jsonc                 C   s   d|v p| dS )z8Check if the text contains a Llama 3.2 format tool call.r	   {)
startswith)r   r   r   r   r   has_tool_call/   s   zLlama32Detector.has_tool_calltoolsc              	   C   s  d|vr| dst|g dS d|v r|jddd\}}nd|}}t }d}|}g }t|}	||	k rz|||d \}
}||
 ||t| j 7 }|}W nw tj	y   zX|}d}t
||	D ]!}|| dkrp|d7 }qc|| d	kr|d8 }|dkr|d } nqc||kr||| }| |}||kr||\}
}||
 |t| j }|}W Y q0W n   Y |d
|d }|dkrY n	|}Y nw ||	k s4|r| ||ng }||	k r||d  nd}t|| |dS )z?Parse function calls from text, handling multiple JSON objects.r	   r!   )normal_textcalls   )maxsplit r   N}z{"name":)r"   r   splitr   JSONDecoderlen
raw_decodeappendr   JSONDecodeErrorranger    findparse_base_jsonr   )r   r   r$   r%   action_textdecoderidxsafe_idxall_actionsaction_text_lenobjenddict_endbrace_countipotential_dictjson_version_next_obj_startr&   trailing_textr   r   r   detect_and_parse5   sj   




&z Llama32Detector.detect_and_parsenew_textc                    sp   |  j |7  _ | j }tdd|}tdd|}| j }|| _ z
t d|}|W S    || _ t || Y S )z3Override to handle Python dict format in streaming.z
'([^']*)':z"\1":z:\s*'([^']*)'z: "\1"r)   )_bufferresubr   parse_streaming_increment)r   rF   r$   converted_bufferoriginal_bufferresultr   r   r   rJ   s   s   z)Llama32Detector.parse_streaming_incrementc                 C   s   dd S )Nc                 S   s   t d|  d dddS )Nz<|python_tag|>{"name":"z", "arguments":r*   r	   )beginr<   trigger)r   )namer   r   r   <lambda>   s
    
z0Llama32Detector.structure_info.<locals>.<lambda>r   r   r   r   r   structure_info   s   zLlama32Detector.structure_info)__name__
__module____qualname____doc__r   strr    boolr#   r   r   r   rE   rJ   r   rR   __classcell__r   r   r   r   r      s    		
>r   )r   r   loggingrH   typingr   &sglang.srt.entrypoints.openai.protocolr   -sglang.srt.function_call.base_format_detectorr   #sglang.srt.function_call.core_typesr   r   r   	getLoggerrS   loggerr   r   r   r   r   <module>   s    
