o
    -i                     @   s   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Z	d dl
mZ d dlmZ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 d d
lmZmZ eeZG dd dZe dG dd deZ!dS )    N)Sequence)Any)ParserCreate)make_tool_call_id)ChatCompletionRequestChatCompletionToolsParam)DeltaFunctionCallDeltaMessageDeltaToolCallExtractedToolCallInformationFunctionCallToolCall)init_logger)TokenizerLike)
ToolParserToolParserManagerc                   @   s   e Zd ZdZdd Zdd Zdedefdd	Zd
edefddZ	de
fddZdedefddZdedefddZdede
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B ef fdd Zd!edefd"d#Zdedefd$d%Zd&efd'd(ZdKd)edB fd*d+Zd,ed-eeef fd.d/Zd0efd1d2Zd,efd3d4Zd5d6 Zd7ee dB fd8d9Zd,ed-eeef dedB fd:d;Z d,ed-eeef dedB fd<d=Z!dedefd>d?Z"d@edefdAdBZ#dCed@ede$fdDdEZ%dFe$d@edefdGdHZ&dIdJ Z'dS )LStreamingXMLToolCallParserze
    Simplified streaming XML tool call parser
    Supports streaming input, parsing, and output
    c                 C   s6   |    d | _d| _d| _d| _d| _d| _d| _d S )N<tool_call>z</tool_call>
<function=z</function><parameter=</parameter>)reset_streaming_statetoolstool_call_start_tokentool_call_end_tokenfunction_start_tokenfunction_end_tokenparameter_start_tokenparameter_end_tokenself r!   b/home/ubuntu/veenaModal/venv/lib/python3.10/site-packages/vllm/tool_parsers/step3p5_tool_parser.py__init__(   s   
z#StreamingXMLToolCallParser.__init__c                 C   s   g | _ d| _d| _d| _d| _d| _i | _d| _d| _d| _	d| _
d| _d| _d| _d| _d| _d| _d| _d| _d| _d| _t | _|   dS )zReset streaming parsing stater   NF )deltastool_call_indexcurrent_call_idlast_completed_call_idcurrent_function_namecurrent_function_open
parameterscurrent_param_namecurrent_param_valuecurrent_param_value_convertedcurrent_param_is_firstshould_emit_end_newlinestart_quote_emittedstreaming_bufferlast_processed_postext_content_buffer_pre_inside_parameter_pre_param_buffer_pre_current_param_namedefer_current_parameterdeferred_param_raw_valuer   parsersetup_parserr   r!   r!   r"   r   4   s.   z0StreamingXMLToolCallParser.reset_streaming_state	xml_chunkreturnc           
   
      s  t  j}  j|7  _  }|rz\ j|d } jdurA j|v rAt fdd|D }|sA jr9 d  j	rA d  jdurm j
|v rmt fdd|D }|sm jr` d  j	rh d  d W n ty } ztd| W Y d}~nd}~ww  |}|S  jr jd	krt jd
}	 |	 d _|	S  jdurۈ j|v s j
|v rۈ jr d  j|v rʈ j	rʈ d  j
|v rԈ d  |}|S tdd
S )a  
        Parse single streaming XML chunk and return Delta response
        This is the actual streaming interface that receives chunks
        one by one and maintains internal state

        Args:
            xml_chunk: Single XML chunk string
        Returns:
            DeltaMessage: Contains delta information generated by this chunk,
            returns empty response if no complete elements
        Nc                 3   .    | ]}|j ot fd d|j D V  qdS )c                 3   s<    | ]}|j o|j jkot|j jto|j jd v V  qdS ))}{}N)functionidr'   
isinstance	argumentsstr.0tcr   r!   r"   	<genexpr>y   s    


UStreamingXMLToolCallParser.parse_single_streaming_chunks.<locals>.<genexpr>.<genexpr>N
tool_callsanyrG   tdr   r!   r"   rI   v       
zKStreamingXMLToolCallParser.parse_single_streaming_chunks.<locals>.<genexpr>	parameterrA   c                 3   r>   )c                 3   s8    | ]}|j d ko|jo|jjdko|j jkV  qdS )rA   r$   N)typerA   rD   rB   r'   rF   r   r!   r"   rI      s    



rJ   NrK   rN   r   r!   r"   rI      rP   	tool_callzError with fallback parsing: %sr   contentr$   )lenr%   r2   _process_complete_xml_elementsr'   r   rM   r,   _end_elementr)   r   	Exceptionloggerwarning$_merge_new_deltas_to_single_responser4   r&   r	   _emit_delta)
r    r<   initial_delta_countfound_elements
new_deltashas_function_closehas_toolcall_closeeresult_delta
text_deltar!   r   r"   parse_single_streaming_chunksV   sn   


















z8StreamingXMLToolCallParser.parse_single_streaming_chunkstextc                 C   s2   dddddd}|  D ]
\}}|||}q|S )z
        Escape XML special characters
        Args:
            text: Original text
        Returns:
            Escaped text
        z&amp;z&lt;z&gt;z&quot;z&apos;)&<>"')itemsreplace)r    rg   xml_escapescharescaper!   r!   r"   _escape_xml_special_chars   s   	z4StreamingXMLToolCallParser._escape_xml_special_charsc                 C   s|  d}| j t| jk r| | j \}}|du r	 |S | |r"|| _ qzv| |}| ds6| drL| jdkrL| j	rLt
| j	d}| | d| _	| dr| jdkr| jr| jr| jrf| d | jrn| d	 t
dddt| jd
 | jd	tddddgd}| | |   | j|d d}W n ty } ztd| W Y d}~nd}~ww || _ | j t| jk s
|S )z
        Process complete XML elements in buffer

        Returns:
            bool: Whether complete elements were found and processed
        FNr   z<function name=r   rT   r$   rQ   rA      namerD   indexrB   rR   rA   )rolerU   reasoning_contentrL   Tz#Error when parsing XML elements: %s)r3   rV   r2   _find_next_complete_element_should_skip_element_preprocess_xml_chunkstrip
startswithr&   r4   r	   r]   r'   r)   r,   rX   r*   r
   r   !_reset_xml_parser_after_tool_callr:   ParserY   rZ   r[   )r    	found_anyelementend_pospreprocessed_elementre   final_deltarc   r!   r!   r"   rW      sn   A








Fz9StreamingXMLToolCallParser._process_complete_xml_elementschunkc              	   C   s|  |  |}dD ]}d| d}||vrq||}||d }|d}|dt|}|dkrA|dks8||k rA||d| v rAq||t| d }tdd t|D t|}	|d|	 }
|
sbq|
| drt|
t|d	 d }
|
r|
d  s|
d d
v s|
dd }
|
r|
d  s|
d d
v r|
sq|dkr| |
sq|d| d|d|	  d| d|
 dd	}q|S )a  
        Fallback: fix incomplete <parameter=xxx or <function=xxx tags
        (missing >)
        Examples: <parameter=-C: -> <parameter=-C>, <parameter=parameter=-n:
        -> <parameter=-n>
        Also handles missing = cases: <function xxx> -> <function=xxx>,
        <functionxxx> -> <function=xxx>
        Only fixes tags that pass validation (parameter exists in tool definition)
        )rQ   rA   ri   =Nrj   c                 s   s     | ]\}}|d v r|V  qdS )) 
ri   Nr!   )rG   ichr!   r!   r"   rI   Y  s    zJStreamingXMLToolCallParser._fix_incomplete_tag_in_chunk.<locals>.<genexpr>rs   )-_rQ   )	#_fix_missing_equals_in_function_tagfindrV   next	enumerater~   isalnum_validate_parameter_namern   )r    r   tag_typepattern	start_idx	after_taggt_poslt_posrU   r   tag_namer!   r!   r"   _fix_incomplete_tag_in_chunk7  sP   




(z7StreamingXMLToolCallParser._fix_incomplete_tag_in_chunkc           	      C   s   d|v r|S d}t ||}|r2|d }|r2| |r2|d}d| d}|||d}|S d}t ||}|r^|d }|r^| |r^|d}d| d}|||d}|S |S )a  
        Fix missing = in function tags: <function xxx> or <functionxxx>
        Examples:
          <function execute_bash> -> <function=execute_bash>
          <functionexecute_bash> -> <function=execute_bash>
        Only fixes if function name exists in tool definition
        r   z(<function\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*>rs   r   rj   z%<function([a-zA-Z_][a-zA-Z0-9_]*)\s*>)researchgroupr}   _validate_function_namern   )	r    r   pattern1match1	func_nameoriginalfixedpattern2match2r!   r!   r"   r   y  s*   	

z>StreamingXMLToolCallParser._fix_missing_equals_in_function_tagr   c                 C   sV   | j sdS | j D ] }t|dr(|jdkr(t|dr(t|jdr(|jj|kr( dS qdS )z1Check if function name exists in tool definitionsFrR   rA   ru   T)r   hasattrrR   rA   ru   )r    r   toolr!   r!   r"   r     s   


z2StreamingXMLToolCallParser._validate_function_name
param_namec                 C   s   | j r| jsdS | j D ]?}t|drJ|jdkrJt|drJt|jdrJ|jj| jkrJt|jds2 dS |jj}t|trG|	d|}||v   S  dS qdS )z?Check if parameter exists in current function's tool definitionTrR   rA   ru   r+   
properties)
r   r)   r   rR   rA   ru   r+   rC   dictget)r    r   r   paramsr   r!   r!   r"   r     s*   



 z3StreamingXMLToolCallParser._validate_parameter_namer   c                 C   s\   | | js| | js| | jrdS | jdu r$|r$|  j|7  _dS | jdur+dS | S )z
        Determine whether an element should be skipped

        Args:
            element: Element to evaluate

        Returns:
            bool: True means should skip, False means should process
        FNT)r~   r   r   r   r'   r4   )r    r   r!   r!   r"   r{     s   



z/StreamingXMLToolCallParser._should_skip_element	start_posNc                 C   s  | j |d }|sd|fS |dr|dod|dd v}|do-d|dd v}|s2|r[|r6dnd	}d
| d}||}|dkr[|d|t|  }||| t| fS |dd}	|dd}
|	dkr|
dkr|	|
k r}|d|	 ||	 fS |d|
d  ||
 d fS |	dkr|d|	 ||	 fS |
dkr|d|
d  ||
 d fS | jdu r|ddt| krd|fS |ds|ddt| krd|fS ||t| fS d|fS |d}|dkr|d| }||| fS |}||t| fS )a  
        Find next complete XML element from specified position

        Args:
            start_pos: Position to start searching

        Returns:
            (Complete element string, element end position),
            returns (None, start_pos) if no complete element found
        Nri   r   rj   r   r   r   rQ   rA   z</r   rs   r   )r2   r~   splitr   rV   r'   )r    r   bufferis_incomplete_paramis_incomplete_funcr   closing_tagclosing_poscomplete_elementtag_endtag_end2next_tag_postext_content	remainingr!   r!   r"   rz     sP   



z6StreamingXMLToolCallParser._find_next_complete_elementinitial_countc           
      C   s&  t | j|krtddS | j|d }t |dkr|d S g }d}|D ]b}|jr-||j7 }|jr|jD ]Q}d}|D ]}|j|jkrE|} nq9|r|jr|jrX|jjrX|jj|j_|jrw|jjdurw|jjdu rkd|j_|jj}	|j j|	7  _|j	r~|j	|_	q3|
| q3q#t|r||dS d|dS )a  
        Merge newly generated deltas from this processing
        into a single DeltaMessage

        Args:
            initial_count: Delta count before processing

        Returns:
            Merged DeltaMessage containing all newly generated delta information
        NrT   rs   r   r$   )rU   rL   )rV   r%   r	   rU   rL   rB   rA   ru   rD   rR   append)
r    r   r`   merged_tool_callsmerged_contentdeltarS   existing_callexistingnew_argsr!   r!   r"   r\   C  sP   



z?StreamingXMLToolCallParser._merge_new_deltas_to_single_responsec                 C   s  d}| | js| | jrd}| | js'| | js'| ds'td|r)d}| | js5| | jr7d}| j	dusF| dsF| drK| 
|}tdd	|}td
d|}|}| jr| dr| j}d| _|| _d| _d| _d| _| |}| dS | jdkr| jr| | jnd}|dv }|dv p| dp| d}	d|v pd|v pd|v }
d}|	rd}n
|r|
rd|v rd}|sd| _| |S |  j|7  _dS | drtd|}|r|d| _d| _d| _|S |s| |}|S )z
        Preprocess XML chunk, handle non-standard formats,
        and escape special characters

        Args:
            chunk: Original XML chunk

        Returns:
            Processed XML chunk
        FTz
<function z^<function[a-zA-Z_]Nz	<functionz
<parameterz<function=([^>]+)>z<function name="\1">z<parameter=([^>]+)>z<parameter name="\1">r   r$   string)object)arrayarrsequencer   list[{(rl   z<parameter name=z<parameter name="([^"]+)">rs   )r~   r   r   r   r   r   matchr   r   r'   r   subr5   r6   r8   r9   r7   rr   _get_param_typer   )r    r   is_tool_call	processedoriginal_chunk	body_text	safe_text
param_typeis_object_typeis_complex_typehas_container_hint
need_defermr!   r!   r"   r|     s   








	


z0StreamingXMLToolCallParser._preprocess_xml_chunkr   c                 C   s   | j | dS )z&Emit Delta response (streaming output)N)r%   r   )r    r   r!   r!   r"   r]     s   z&StreamingXMLToolCallParser._emit_deltaincoming_tagc                 C   sL   | j r| d |dv r| jr| d |dkr"| jr$| d dS dS dS )a  Before starting to process new elements,
        if there are unclosed tags from before,
        automatically complete their endings to the parser.
        - If there are unclosed parameters,
        it's equivalent to feeding `</parameter>`
        - When about to start a new function or tool_call,
        if there are unclosed functions, complete `</function>`.
        - When about to start a new tool_call,
        if there are unclosed tool_calls, complete `</tool_call>`.
        rQ   )rA   rS   rA   rS   N)r,   rX   r)   r'   )r    r   r!   r!   r"   $_auto_close_open_parameter_if_needed  s   

z?StreamingXMLToolCallParser._auto_close_open_parameter_if_neededru   attrsc              	   C   s  |dkrdS |dkr"|  d i | _t | _d| _|  jd7  _dS |ds+|dkrd| js4| di  |  d | ||}|| _	d| _
|rbtt| jd | jdt|ddd	gd
}| | dS dS |dsm|dkr|  d | ||}|| _d| _d| _d| _|r| jsd| d}tt| jd | jdtd|dd	gd
}| | d| _dS d| d}tt| jd | jdtd|dd	gd
}| | d| _dS dS dS )zHandle XML start element eventsrootNrS   Trs   rA   r$   rt   rv   rL   rQ   Fz{"z": z, ")r   r+   r   r'   r/   r&   r~   _start_element_extract_function_namer)   r*   r	   r
   r   r]   _extract_parameter_namer,   r-   r.   r1   )r    ru   r   function_namer   r   
json_startjson_continuer!   r!   r"   r   %  s   






z)StreamingXMLToolCallParser._start_elementdatac           	   	   C   s~  |r| j r| jr+|}| jrd| }d| _|dr"d| _|dd }|  j|7  _dS | | j }| js?|dr?|dd }|dv rb| jsbtt	| j
d | jdtdd	d
dgd}| | d| _|sfdS |}| jrrd| }d| _|drd| _|dd }|  j|7  _| | j|}| ||}|t| jd }|| _tt	| j
d | jdtd|d
dgd}| | dS dS dS )z Handle XML character data eventsr   FTNr   rs   r   rE   rg   varcharrp   enumrA   rk   rt   rv   r   )r,   r8   r0   endswithr-   r   r~   r1   r	   r
   r&   r'   r   r]   _convert_param_value_convert_for_json_streamingrV   r.   )	r    r   original_datar   quote_deltaconverted_valueoutput_data
delta_datar   r!   r!   r"   
_char_data  sn   







z%StreamingXMLToolCallParser._char_datac              	   C   s  |dkrdS | ds|dks|dkr| jr|   | ds#|dkr| jr| j}| j}| jr| jr5| jn|}d}d}z| jrD|d }n|}t|}t	j
|dd}W n tye   t	j
|dd}|}Y nw tt| jd	 | jdtd|d
dgd}| | d| _|| j|< d| _d| _d| _d| _d| _d| _dS | |}	| ||	}
|	dv r|s| jstt| jd	 | jdtddd
dgd}| | ntt| jd	 | jdtddd
dgd}| | d| _|
| j|< d| _d| _d| _d| _dS | ds|dkrB| jr!tt| jd	 | jdtddd
dgd}| | ntt| jd	 | jdtddd
dgd}| | d| _d| _dS |dkr| jrY| jrT| d | d tt| jd	 | jdtddd
dgd}| | | j rt| jd}| | |   dS dS )zHandle XML end element eventsr   NrA   rS   rQ   r   Fensure_asciirs   rt   rv   r   r$   r   z""rk   r?   r@   rT   )r~   r,   r   r-   r8   r9   r0   astliteral_evaljsondumpsrY   r	   r
   r&   r'   r   r]   r+   r.   r1   r   r   r*   r)   rX   r4   r}   r   )r    ru   r   param_valueraw_textparsed_valueoutput_argumentsraw_for_parser   r   r   re   r!   r!   r"   rX     s   
























z'StreamingXMLToolCallParser._end_elementc                 C   s*   d| j _| j| j _| j| j _| j| j _dS )z Set up XML parser event handlersTN)r:   buffer_textr   StartElementHandlerrX   EndElementHandlerr   CharacterDataHandlerr   r!   r!   r"   r;   y  s   

z'StreamingXMLToolCallParser.setup_parserr   c                 C   s
   || _ dS )z"Set tool configuration informationN)r   )r    r   r!   r!   r"   	set_tools  s   
z$StreamingXMLToolCallParser.set_toolsc                 C   L   |r
d|v r
|d S d|v r$| dd}t|dkr$|d dkr$|d S dS )z*Extract function name from various formatsru   r   rs      r   rA   Nr   rV   r    ru   r   partsr!   r!   r"   r        z1StreamingXMLToolCallParser._extract_function_namec                 C   r  )z+Extract parameter name from various formatsru   r   rs   r  r   rQ   Nr  r  r!   r!   r"   r     r  z2StreamingXMLToolCallParser._extract_parameter_namec                 C   s  | j r| jsdS | j D ]x}t|drt|drt|jdsq|jdkr|jj| jkrt|jds3 dS |jj}t|trad|v ra|d }||v r^t|| tr^| 	t
|| dd  S  dS t|tr||v r|| }t|tr| 	t
|dd  S  dS qdS )zGet parameter type based on tool configuration, defaults to string
        Args:
            param_name: Parameter name

        Returns:
            Parameter type
        r   rR   rA   ru   r+   r   )r   r)   r   rA   rR   ru   r+   rC   r   repair_param_typerE   r   )r    r   r   r   r   param_configr!   r!   r"   r     sD   




	
 z*StreamingXMLToolCallParser._get_param_typer   c                 C   sz   |dv s9| ds9| ds9| ds9| ds9| ds9| ds9| ds9|d	v s9|d
v s9| ds9| dr;|S dS )zRepair unknown parameter types by treating them as string
        Args:
            param_type: Parameter type

        Returns:
            Repaired parameter type
        r   intuintlongshortunsignednumfloatbooleanboolbinary)r   r   r   r   r   r   r   )r~   )r    r   r!   r!   r"   r	    s.   	z,StreamingXMLToolCallParser.repair_param_typer   c              	   C   s  |  dkrdS |   }|dv r|S |ds-|ds-|ds-|ds-|drEzt|W S  ttfyD   td	| Y |S w |d
sO|drvzt|}|t| dkr_|W S t|W S  ttfyu   td| Y |S w |dv r|  }|dkS |S )zConvert value based on parameter type
        Args:
            param_value: Parameter value
            param_type: Parameter type

        Returns:
            Converted value
        nullNr   r  r  r  r  r  z<Parsed value '%s' is not an integer, degenerating to string.r  r  r   z9Parsed value '%s' is not a float, degenerating to string.r  true)	lowerr}   r~   r  
ValueError	TypeErrorrZ   r[   r  )r    r   r   float_param_valuer!   r!   r"   r     sV   	
z/StreamingXMLToolCallParser._convert_param_valuer   c                 C   sN   |du s|dkr
dS |dv rt j|dddd S t|ts%t j|ddS |S )a   Convert converted_value based on
        whether it's empty and if type is string
        Args:
            converted_value: Converted value
            param_type: Parameter type

        Returns:
            Converted string for streaming output
        Nr$   r   Fr   rs   r   )r   r   rC   rE   )r    r   r   r!   r!   r"   r     s   
z6StreamingXMLToolCallParser._convert_for_json_streamingc                 C   s   t  | _|   | jr| j| _d| _d| _d| _i | _d| _d| _	d| _
d| _d| _d| _d| _d| _d| _d| _d| _d| _dS )z
        Each tool_call is treated as a separate XML document,
        so we need to reset the parser after each tool_call.
        NFr$   )r   r:   r;   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r4   r5   r6   r7   r8   r9   r   r!   r!   r"   r   *  s(   
z<StreamingXMLToolCallParser._reset_xml_parser_after_tool_call)N)(__name__
__module____qualname____doc__r#   r   rE   r	   rf   rr   r  rW   r   r   r   r   r{   r  tuplerz   r\   r|   r]   r   r   r   r   rX   r;   r   r   r  r   r   r   r	  r   r   r   r   r!   r!   r!   r"   r   "   s>    "{QB'$W@ ZK 0""(2r   step3p5c                       s   e Zd Zdef 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defddZ  ZS )Step3p5ToolParser	tokenizerc                    s4   t  | t | _g | _g | _td| jj	 d S )Nz)vLLM Successfully import tool parser %s !)
superr#   r   r:   prev_tool_call_arrstreamed_args_for_toolrZ   info	__class__r  )r    r#  r(  r!   r"   r#   M  s   zStep3p5ToolParser.__init__model_outputrequestr=   c              
   C   sV  | j   g | _g | _|r| j |j | j |}|js%tg d|j	dS g }|jD ]t}|j
r|j
jr|t|j|jt|j
j|j
jdd |jd urO|jnt| jd }t| j|krm| jddd t| j|ks]t| j|kr| jd t| j|kst|j
j| j| d< |j
j| j| d< |j
jr|j
j| j|< q*t|t|d	k|j	dS )
NF)rL   tools_calledrU   rt   )rB   rR   rA   rs   r$   ru   rD   r   )r:   r   r%  r&  r  r   rf   rL   r   rU   rA   ru   r   r   rB   rR   r   rD   rw   rV   )r    r*  r+  resultrL   rS   
tool_indexr!   r!   r"   extract_tool_callsY  s`   



z$Step3p5ToolParser.extract_tool_callsprevious_textcurrent_text
delta_textprevious_token_idscurrent_token_idsdelta_token_idsNc                 C   st  |s| j   g | _g | _|r| j |j |s?|r?|| j j|| j j }|dkr2| j j	dks8| j j	s=|r=t
ddS d S | j |}	|	r|	jr|	jD ]j}
|
jr|
jd urZ|
jnt| jd }t| j|krx| jddd t| j|ksht| j|kr| jd t| j|ks|
jjr|
jj| j| d< |
jjd ur| j| d  |
jj7  < | j|  |
jj7  < qM|	S )Nr   r$   rT   rs   rt   ru   rD   )r:   r   r%  r&  r  r   countr   r   r&   r	   rf   rL   rA   rw   rV   r   ru   rD   )r    r0  r1  r2  r3  r4  r5  r+  
open_callsr-  rS   r.  r!   r!   r"   extract_tool_calls_streaming  s\   






z.Step3p5ToolParser.extract_tool_calls_streamingc                 C   s   dS )zE
        Skip the remaining_call calculation in serving_chat
        Fr!   r   r!   r!   r"   2parser_should_check_for_unstreamed_tool_arg_tokens  s   zDStep3p5ToolParser.parser_should_check_for_unstreamed_tool_arg_tokens)r  r  r  r   r#   rE   r   r   r/  r   r  r	   r8  r  r9  __classcell__r!   r!   r)  r"   r"  K  s6    
B	
Hr"  )"r   r   collections.abcr   typingr   xml.parsers.expatr   regexr   vllm.entrypoints.chat_utilsr   0vllm.entrypoints.openai.chat_completion.protocolr   r   'vllm.entrypoints.openai.engine.protocolr   r	   r
   r   r   r   vllm.loggerr   vllm.tokenizersr   &vllm.tool_parsers.abstract_tool_parserr   r   r  rZ   r   register_moduler"  r!   r!   r!   r"   <module>   s4              3