o
    پi%                     @   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
 d dlmZmZmZmZ eeZG dd de
ZdS )	    N)List)Tool)envs)BaseFormatDetector)StreamingParseResultStructureInfoToolCallItem_GetInfoFuncc                       s|   e Zd ZdZ fddZdedefddZ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 )InternlmDetectora  
    Detector for InternLM2/Intern-S1 model function call format.

    The InternLM format uses special tokens to delimit function calls
    with JSON for arguments.

    Format Structure:
    ```
    text<|action_start|> <|plugin|>
    {json}<|action_end|>
    ```

    Examples:
    ```
    What's the weather like?<|action_start|> <|plugin|>
    {"name": "get_weather", "parameters": {"location": "Tokyo"}}<|action_end|>
    ```

    Key Components:
    - Tool Call Start: `<|action_start|> <|plugin|>`
    - Tool Call End: `<|action_end|>`
    - Arguments: JSON object with `name` and `parameters`/`arguments`
    - Supports multiple sequential tool calls in both streaming and non-streaming modes

    c                    s    t    d| _d| _d| _d S )N<|action_start|> <|plugin|>z<|action_end|>r   )super__init__	bot_token	eot_tokenpositionself	__class__ ^/home/ubuntu/.local/lib/python3.10/site-packages/sglang/srt/function_call/internlm_detector.pyr   0   s   

zInternlmDetector.__init__textreturnc                 C   s   | j |v }|S )z8Check if the text contains an InternLM format tool call.)r   )r   r   has_callr   r   r   has_tool_call6   s   
zInternlmDetector.has_tool_callc                 C   s(   d|v r	| dS d|v r| dS dS )zQExtract arguments from object, supporting both 'parameters' and 'arguments' keys.
parameters	argumentsN)get)r   objr   r   r   get_arguments;   s
   

zInternlmDetector.get_argumentstoolsc                 C   s4  | | j}|dkr|d|  n|}| j|vr$td t|g dS t| j dt| j }t	||tj
}|sHtd t|g dS tdt| d g }| |}zt|D ]\}}	|	 }	zYt|	}
|
d	}| |
}|s{i }td
|d  d| dtj|dd  |r||v std| dt|   tj sW q_t|| |tj|ddd}|| W q_ tjy } ztd|d  d|  W Y d}~q_d}~ww tdt| dt|  t||dW S  ty } ztjd| dd t|g dW  Y d}~S d}~ww )as  
        One-time parsing: Detects and parses tool calls in the provided text.
        Supports multiple tool calls in the format:
        <|action_start|> <|plugin|>
{JSON}<|action_end|>

        :param text: The complete text to parse.
        :param tools: List of available tools.
        :return: StreamingParseResult with normal text and parsed tool calls.
        Nz7[InternLM Tool Call] No tool call markers found in text)normal_textcallsz\s*(.*?)z7[InternLM Tool Call] No complete tool call blocks foundz[InternLM Tool Call] Found z tool call(s)namez'[InternLM Tool Call] Parsed tool call #   z: name=z, parameters=F)ensure_asciizA[InternLM Tool Call] Model attempted to call undefined function: z, available_tools=)
tool_indexr$   r   z9[InternLM Tool Call] Failed to parse JSON for tool call #z: z)[InternLM Tool Call] Successfully parsed z" tool call(s), normal_text_length=z0[InternLM Tool Call] Error in detect_and_parse: T)exc_info)findr   striploggerwarningr   reescaper   findallDOTALLinfolen_get_tool_indices	enumeratejsonloadsr   r   dumpslistkeysr   SGLANG_FORWARD_UNKNOWN_TOOLSr   appendJSONDecodeErrorerror	Exception)r   r   r    idxr"   tool_call_patternmatchesr#   tool_indicesaction_jsonaction_dictr$   r   	tool_caller   r   r   detect_and_parseC   s|   









z!InternlmDetector.detect_and_parsenew_textc           	      C   s  |  j |7  _ | j }|| j}|dkrA| jdkr!d| _ tddS | || js>|}d| _ | j|v r9|| jd}t|dS t S || j}|dkr| jdkrZd| _g | _dg| _	t
| j| jkrp| ji  t
| j| jksbt
| j	| jkr| j	d t
| j	| jksx|d|t
| j  }| j||d}|jr| j|jd _|jd jt|jd jd| j| j< |jd j| j	| j< |  jd7  _||t
| j d | _ |S |d| }||d | _ t|dS )	z|
        Streaming incremental parsing for InternLM format.

        Supports a single tool call in streaming mode.
        r!   r    )r"   N)r    )r$   r   r%   )_bufferr)   r   current_tool_idr   _ends_with_partial_tokenr   replaceprev_tool_call_arrstreamed_args_for_toolr2   r;   rG   r#   r'   r$   r5   r6   r   )	r   rH   r    current_textstartr"   endcomplete_sectionresultr   r   r   parse_streaming_increment   sX   







z*InternlmDetector.parse_streaming_incrementc                 C   s   dd S )z
        Return structure information for constrained generation.

        For InternLM format, the structure is:
        - begin: <|action_start|> <|plugin|>

        - end: <|action_end|>
        - trigger: the begin token
        c                 S   s   t d|  d dddS )Nz&<|action_start|> <|plugin|>
{"name": "z", "parameters": z}<|action_end|>r   )beginrR   trigger)r   )r$   r   r   r   <lambda>   s    z1InternlmDetector.structure_info.<locals>.<lambda>r   r   r   r   r   structure_info   s   	zInternlmDetector.structure_info)__name__
__module____qualname____doc__r   strboolr   r   r   r   r   rG   rU   r	   rY   __classcell__r   r   r   r   r
      s    X
Nr
   )r5   loggingr-   typingr   &sglang.srt.entrypoints.openai.protocolr   sglang.srt.environr   -sglang.srt.function_call.base_format_detectorr   #sglang.srt.function_call.core_typesr   r   r   r	   	getLoggerrZ   r+   r
   r   r   r   r   <module>   s   
