o
    
۾iW2                     @   s   d dl Z d dlZd dlmZ d dlm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mZmZ d dlmZ d dlmZ eeZG d	d
 d
eZG dd deZde jdefddZde j defddZ!de"de#e"e"f dB fddZ$de"dede%de"dedB f
ddZ&dS )    N)Sequence)Any)PreTrainedTokenizerBase)ChatCompletionRequest)DeltaFunctionCallDeltaMessageDeltaToolCallExtractedToolCallInformationFunctionCallToolCall)init_logger)
ToolParserc                   @   s   e Zd ZdS )_UnexpectedAstErrorN)__name__
__module____qualname__ r   r   a/home/ubuntu/.local/lib/python3.10/site-packages/vllm/tool_parsers/llama4_pythonic_tool_parser.pyr      s    r   c                       s   e Zd ZdZedejZdef fddZ	e
defddZejd	edd
fddZdededefddZdedededee dee dee deded
B fddZ  ZS )Llama4PythonicToolParserz
    Toolcall parser for Llama4 that produce tool calls in a pythonic style
    Use --enable-auto-tool-choice --tool-call-parser llama4_pythonic
    z\[([a-zA-Z]+\w*\(([a-zA-Z]+\w*=.*,\s*)*([a-zA-Z]+\w*=.*\s)?\),\s*)*([a-zA-Z]+\w*\(([a-zA-Z]+\w*=.*,\s*)*([a-zA-Z]+\w*=.*\s*)?\)\s*)+\]	tokenizerc                    s   t  | d S N)super__init__)selfr   	__class__r   r   r   5   s   z!Llama4PythonicToolParser.__init__returnc                 C   s   | j S r   current_tool_id)r   r   r   r   current_tool_index9   s   z+Llama4PythonicToolParser.current_tool_indexvalueNc                 C   s
   || _ d S r   r   )r   r    r   r   r   r   =   s   
model_outputrequestc                 C   s  | dr|tdd }|dd}d}z| jj|tjddu}W n ty6   t	d t
d| Y nw |s@tdg |d	S z0t|}t|jd
 dd}t|tjrmtdd |jD rmtddd |jD dd	W S td ty   td tdg |d	 Y S w )zH
        Extract the tool calls from a complete model response.
        <|python_start|>N<|python_end|> F)timeoutz7Regex timeout occurred when matching tool call pattern.z3Regex timeout occurred when matching user input: %s)tools_called
tool_callscontentr   r    c                 s       | ]	}t |tjV  qd S r   
isinstanceastCall.0er   r   r   	<genexpr>d       
z>Llama4PythonicToolParser.extract_tool_calls.<locals>.<genexpr>Tc                 S      g | ]}t |qS r   _handle_single_toolr/   r   r   r   
<listcomp>i       z?Llama4PythonicToolParser.extract_tool_calls.<locals>.<listcomp>,Tool output must be a list of function callsz,Error in extracting tool call from response.)
startswithlenreplaceTOOL_CALL_REGEXmatchenvs%VLLM_TOOL_PARSE_REGEX_TIMEOUT_SECONDSTimeoutErrorloggerwarningdebugr	   r-   parsegetattrbodyr,   Listalleltsr   	Exception	exception)r   r!   r"   is_tool_call_patternmoduleparsedr   r   r   extract_tool_callsA   sV   
	

	

z+Llama4PythonicToolParser.extract_tool_callsprevious_textcurrent_text
delta_textprevious_token_idscurrent_token_idsdelta_token_idsc                 C   s.  | ds| dst|dS z| dr|tdd  }|dr+|d |d }t|}|d u r6W d S |\}	}
t|	}t|j	d dd }t
|tjrXtdd |jD s\td	d
d |jD }g }t|D ]t\}}|| jk rtqj|| _t| j|kr| jd |t|d k pd|
v}|r|  jd7  _|s|
d d nd}|s|
d dkr|d }|dd}t| j| |||}|d ur|| |jd ur|jjd ur| j|  |jj7  < qj|r| jsdi ig| _|rt|dW S |
s| jdkrtddW S W d S  ty   td td Y d S w )N[r#   )r)   r$   r   r    c                 s   r*   r   r+   r/   r   r   r   r2      r3   zHLlama4PythonicToolParser.extract_tool_calls_streaming.<locals>.<genexpr>r9   c                 S   r4   r   r5   r/   r   r   r   r7      r8   zILlama4PythonicToolParser.extract_tool_calls_streaming.<locals>.<listcomp>r%      z)])}'"	arguments)r(   z+Error trying to handle streaming tool call.z=Skipping chunk as a result of tool streaming extraction error)r:   r   r;   endswithrfind_make_valid_pythonr-   rE   rF   rG   r,   rH   rI   rJ   r   	enumerater   streamed_args_for_toolappendr<   _compute_tool_deltafunctionr^   prev_tool_call_arrr   rK   rB   rL   rD   )r   rQ   rR   rS   rT   rU   rV   r"   valid_and_added_text
valid_text
added_textrN   rO   r(   tool_deltasindexnew_callnew_call_completewithheld_suffixdeltar   r   r   extract_tool_calls_streamingz   s|   









z5Llama4PythonicToolParser.extract_tool_calls_streaming)r   r   r   __doc__recompileDOTALLr=   r   r   propertyintr   setterstrr   r	   rP   r   r   rq   __classcell__r   r   r   r   r   #   sF    
9	r   valr   c                 C   sv   t | tjr	| jS t | tjr)tdd | jD stddd t| j| j	D S t | tj
r7dd | jD S td)	Nc                 s   r*   r   )r,   r-   Constant)r0   kr   r   r   r2      s    z'_get_parameter_value.<locals>.<genexpr>z/Dict tool call arguments must have literal keysc                 S   s   i | ]
\}}|j t|qS r   )r    _get_parameter_value)r0   r}   vr   r   r   
<dictcomp>   s    
z(_get_parameter_value.<locals>.<dictcomp>c                 S   r4   r   )r~   )r0   r   r   r   r   r7      s    z(_get_parameter_value.<locals>.<listcomp>z$Tool call arguments must be literals)r,   r-   r|   r    DictrI   keysr   zipvaluesrH   rJ   )r{   r   r   r   r~      s   r~   callc                 C   sX   t | jtjstd| jj}i }| jD ]
}t|j||j	< qt
dt|t|ddS )NzInvalid tool call namerf   namer^   )typerf   )r,   funcr-   Namer   idkeywordsr~   r    argr   r
   jsondumps)r   function_namer^   keywordr   r   r   r6      s   
r6   textc                 C   sF  g }t | D ]m\}}|dv r|| q|dkr%|r | dkr$tdq|dkr6|r1| dkr5tdq|dkrG|rB| d	krFtd
q|dv rs|re|d |kre|dkr`| |d  dkr`q|  q|rn|d dv rnq|| q|  } | ds| drd S |r|d d	kr| d | d	 }|d}|d}||krd S |r|d dkr| d | d }|d}|d}	||	krd S | dr| d d } |r|d dkr| ds| dsd S d}
t|D ]1}|dkr|
d7 }
q|dkr|
d7 }
q|d	kr	|
d7 }
q|dkr|
d7 }
q|dkr|
d7 }
q| |
 |
fS )N>   {(rW   ]rW   zMismatched square bracketsrZ   r   zMismatched parenthesesr[   r   zMismatched curly braces>   r]   r\   r   rX   \=:,r%   r\   r]   )	rb   rd   popr   rstripr_   r`   countreversed)r   bracket_stackrl   chartrailing_dict_textnum_keys
num_valuestrailing_params_textnum_full_param_namesnum_full_param_valuesrj   r   r   r   ra      s   













ra   previously_sent_argsrm   rl   ro   c                 C   sz   |j j}|r||sJ |d t|  }| s't|jd|t|j j|ddS |t| d  }|r;td |t|ddS d S )Nrf   r   )r   r   rl   rf   )r^   )r   rl   rf   )rf   r^   r_   r;   r   r   r   r   )r   rm   rl   ro   new_call_argsarg_diffr   r   r   re   >  s,   
re   )'r-   r   collections.abcr   typingr   regexrs   transformersr   	vllm.envsr?   0vllm.entrypoints.openai.chat_completion.protocolr   'vllm.entrypoints.openai.engine.protocolr   r   r   r	   r
   r   vllm.loggerr   &vllm.tool_parsers.abstract_tool_parserr   r   rB   rK   r   r   exprr~   r.   r6   ry   tuplera   rw   re   r   r   r   r   <module>   s:     9F