o
    i6                     @   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   Y/home/ubuntu/vllm_env/lib/python3.10/site-packages/vllm/tool_parsers/olmo3_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 )Olmo3PythonicToolParseray  
    Tool call parser for Olmo 3 models that produce tool calls as
    newline-separated pythonic strings.
    Used when --enable-auto-tool-choice --tool-call-parser pythonic are all set
    Code copied from pythonic_tool_parser.py and updated to handle
    - newline separated pythonic tool calls.
    - argument values being null/true/false instead of Pythonic literals.
    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   9   s   z Olmo3PythonicToolParser.__init__returnc                 C   s   | j S r   current_tool_id)r   r   r   r   current_tool_index=   s   z*Olmo3PythonicToolParser.current_tool_indexvalueNc                 C   s
   || _ d S r   r   )r   r    r   r   r   r   A   s   
model_outputrequestc                 C   s0  |}t d|t j}|r|d }ddd | D }d| d}d}z| jj|t	j
d	d
u}W n tyH   td td| Y nw |sRtdg |dS z0t|}t|jd dd
}t|tjrtdd |jD rt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.
        z&<function_calls>(.*?)</function_calls>   , c                 S      g | ]
}|  r|  qS r   strip.0liner   r   r   
<listcomp>T       z>Olmo3PythonicToolParser.extract_tool_calls.<locals>.<listcomp>[]F)timeoutNz7Regex 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r)   er   r   r   	<genexpr>n       
z=Olmo3PythonicToolParser.extract_tool_calls.<locals>.<genexpr>Tc                 S      g | ]}t |qS r   _handle_single_toolr8   r   r   r   r+   s       z,Tool output must be a list of function callsz,Error in extracting tool call from response.)researchDOTALLgroupr'   join
splitlinesTOOL_CALL_REGEXmatchenvs%VLLM_TOOL_PARSE_REGEX_TIMEOUT_SECONDSTimeoutErrorloggerwarningdebugr	   r6   parsegetattrbodyr5   Listalleltsr   	Exception	exception)r   r!   r"   original_model_outputrG   is_tool_call_patternmoduleparsedr   r   r   extract_tool_callsE   sd   

	

z*Olmo3PythonicToolParser.extract_tool_callsprevious_textcurrent_text
delta_textprevious_token_idscurrent_token_idsdelta_token_idsc                 C   sP  | ds
t|dS z| dr|tdd  }|dr'|d td  }t|}|d u r2W d S |\}	}
ddd |	 D }	d|	 d	}	t|	}t	|j
d
 dd }t|tjrftdd |jD sjtddd |jD }g }t|D ]t\}}|| jk rqx|| _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  < qx|r| jsdi ig| _|rt|dW S |
s| jd
krtddW S W d S  ty'   td td Y d S w )N<)r2   z<function_calls>z</function_calls>r$   c                 S   r%   r   r&   r(   r   r   r   r+      r,   zHOlmo3PythonicToolParser.extract_tool_calls_streaming.<locals>.<listcomp>r-   r.   r   r    c                 s   r3   r   r4   r8   r   r   r   r:      r;   zGOlmo3PythonicToolParser.extract_tool_calls_streaming.<locals>.<genexpr>z9Tool output must be a sequence of newline-separated callsc                 S   r<   r   r=   r8   r   r   r   r+      r?    r#   )}'"	arguments)r1   z+Error trying to handle streaming tool call.z=Skipping chunk as a result of tool streaming extraction error)
startswithr   lenendswith_make_valid_pythonrD   rE   r6   rN   rO   rP   r5   rQ   rR   rS   r   	enumerater   streamed_args_for_toolappendreplace_compute_tool_deltafunctionrh   prev_tool_call_arrr   rT   rK   rU   rM   )r   r[   r\   r]   r^   r_   r`   r"   valid_and_added_text
valid_text
added_textrX   rY   r1   tool_deltasindexnew_callnew_call_completewithheld_suffixdeltar   r   r   extract_tool_calls_streaming   s~   









z4Olmo3PythonicToolParser.extract_tool_calls_streaming)r   r   r   __doc__r@   compilerB   rF   r   r   propertyintr   setterstrr   r	   rZ   r   r   r}   __classcell__r   r   r   r   r   #   sF    
?	r   valr   c                 C   s   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 | tjrY| jdv rY| jd	krId S | jd
krPdS | jdkrWdS d S td)Nc                 s   r3   r   )r5   r6   Constant)r)   kr   r   r   r:      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)r)   r   vr   r   r   
<dictcomp>   s    
z(_get_parameter_value.<locals>.<dictcomp>c                 S   r<   r   )r   )r)   r   r   r   r   r+      s    z(_get_parameter_value.<locals>.<listcomp>)nulltruefalser   r   Tr   Fz$Tool call arguments must be literals)r5   r6   r   r    DictrR   keysr   zipvaluesrQ   rS   Nameid)r   r   r   r   r      s&   


r   callc                 C   s\   t | jtjstd| jj}i }| jD ]
}t|j||j	< qt
dt|tj|ddddS )NzInvalid tool call namerr   F)ensure_asciinamerh   )typerr   )r5   funcr6   r   r   r   keywordsr   r    argr   r
   jsondumps)r   function_namerh   keywordr   r   r   r>     s   
r>   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>   {(r-   r.   r-   zMismatched square bracketsrc   r   zMismatched parenthesesre   r   zMismatched curly braces>   rg   rf   rd   r   r#   \=:,rb   rf   rg   )	rm   ro   popr   rstriprk   rfindcountreversed)r   bracket_stackrx   chartrailing_dict_textnum_keys
num_valuestrailing_params_textnum_full_param_namesnum_full_param_valuesrv   r   r   r   rl     s   













rl   previously_sent_argsry   rx   r{   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 )Nrr   r   )r   r   rx   rr   )rh   )r   rx   rr   )rr   rh   rk   rj   r   r   r   r   )r   ry   rx   r{   new_call_argsarg_diffr   r   r   rq   W  s,   
rq   )'r6   r   collections.abcr   typingr   regexr@   transformersr   	vllm.envsrH   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   rK   rT   r   r   exprr   r7   r>   r   tuplerl   r   rq   r   r   r   r   <module>   s:     GF