o
    iWf                     @   s  d dl Z d dlmZ d dlmZmZ d dlmZ d dlm	Z	m
Z
 d dlmZ d dlZd dl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 d dlm Z  d dl!m"Z" ee#Z$e	e
 Z%G dd deZ&G dd deZ'dede(fddZ)G dd de"Z*dS )    N)Sequence)Enumauto)choices)ascii_lettersdigits)Any)Field)ChatCompletionRequest)DeltaFunctionCallDeltaMessageDeltaToolCallExtractedToolCallInformationFunctionCallToolCall)init_logger)TokenizerLike)MistralTokenizer)
ToolParserc                   @   sF   e Zd ZdZe Ze Ze Ze Ze Z	e Z
e Ze Ze ZdS )StreamingStatez6Enum for tracking the current streaming parsing state.N)__name__
__module____qualname____doc__r   WAITING_FOR_TOOL_STARTWAITING_FOR_TOOL_KEYPARSING_NAMEPARSING_NAME_COMPLETEDWAITING_FOR_ARGUMENTS_STARTPARSING_ARGUMENTSPARSING_ARGUMENTS_COMPLETEDTOOL_COMPLETEALL_TOOLS_COMPLETE r#   r#   [/home/ubuntu/vllm_env/lib/python3.10/site-packages/vllm/tool_parsers/mistral_tool_parser.pyr   &   s    
r   c                   @   sF   e Zd ZU edd dZeed< edd Zedede	fdd	Z
d
S )MistralToolCallc                   C   s   t  S )N)r%   generate_random_idr#   r#   r#   r$   <lambda>7   s    zMistralToolCall.<lambda>)default_factoryidc                   C   s   d ttddS )N 	   )k)joinr   ALPHANUMERICr#   r#   r#   r$   r&   9   s   z"MistralToolCall.generate_random_idreturnc                 C   s   |   o	t| dkS )Nr+   )isalnumlen)r)   r#   r#   r$   is_valid_id?   s   zMistralToolCall.is_valid_idN)r   r   r   r	   r)   str__annotations__staticmethodr&   boolr2   r#   r#   r#   r$   r%   6   s   
 
r%   model_tokenizerr/   c                 C   s   t | to	| jdk S )N   )
isinstancer   version)r7   r#   r#   r$   _is_pre_v11_tokeniserD   s   r;   c                       s(  e Zd ZdZdef fddZde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dee dedB fddZdedee fddZejdd Zdedee dedB fddZ						d%dededed ed!ed"edeeef fd#d$Z  ZS )&MistralToolParsera#  
    Tool call parser for Mistral 7B Instruct v0.3, intended for use with
    - [`mistral_common`](https://github.com/mistralai/mistral-common/)
    - the examples/tool_chat_template_mistral.jinja template.

    Used when --enable-auto-tool-choice --tool-call-parser mistral are all set
    	tokenizerc                    s   t  | t| jtstd g | _d| _t	j
| _d | _d | _d| _t| jr1t|  | _d| _| j| j| _tdtj| _t| j| _| jd u rStdd S )Nz<Non-Mistral tokenizer detected when using a Mistral model...Fz[TOOL_CALLS]z\[{.*}\]zJMistral Tool Parser could not locate the tool call token in the tokenizer!)super__init__r9   r7   r   loggerinfoprev_tool_call_arrcurrent_tool_idr   r   streaming_statecurrent_tool_namecurrent_tool_mistral_idstarting_new_toolr;   ijson
parse_coro%update_stream_state_pre_v11_tokenizer	bot_tokenvocabgetbot_token_idrecompileDOTALLtool_call_regex_is_pre_v11RuntimeError)selfr=   	__class__r#   r$   r@   S   s,   


zMistralToolParser.__init__requestr/   c                    s2   t  |}t| jts|jr|jdkrd|_|S )NnoneF)r?   adjust_requestr9   r7   r   toolstool_choiceskip_special_tokens)rV   rY   rW   r#   r$   r[   s   s   

z MistralToolParser.adjust_requestmodel_outputc                 C   sj  | j |vrtdg |dS || j }|d }|dd }| jsFg }|D ]!}d|vr*q#|d}|d| ||d }	}
||	|
d q#nWt|dkrTtd| d	|d  }zt	
|}W n4 t	jy   z| j|d }t	
|}W n tt	jfy   td
 tdg |d Y  Y S w Y nw dd |D }dd |D }td|t|dkr|dS ddS )a  
        Extract the tool calls from a complete model response.

        Content and tool calls formatting depends on the Mistral's tokenizer version
        used to train the model:

        - < v11: `content[BOT] [{tool_call1},{tool_call2}]`
        - >= v11: `content[BOT]tool_name1{args_call1}[BOT]tool_name2{args_call2}`

        with [BOT] the tool call token.

        Note:
            For tokenizer versions >= v11, tool calls with arguments wrongly formatted
            are still returned as tool calls. This is to allow the model to know it
            tried to make a tool call. It reduces chance of another failure and
            prevents that the context is filled with tool calls wrongly placed in
            assistant message contents.
        F)tools_called
tool_callscontentr      N{name	argumentsz7Only one BOT token should have been outputted, but got .z0Error in extracting tool call from response: {e}c                 S   s(   g | ]}|d  t j|d dddqS )rf   rg   F)ensure_asciire   )jsondumps.0	tool_callr#   r#   r$   
<listcomp>   s    z8MistralToolParser.extract_tool_calls.<locals>.<listcomp>c                 S   s(   g | ]}t d t|d |d ddqS )functionrf   rg   re   )typerp   )r%   r   rl   r#   r#   r$   ro      s    T)rL   r   splitrT   findappendr1   
ValueErrorstriprj   loadsJSONDecodeErrorrS   findall
IndexErrorrA   	exception)rV   r_   rY   content_and_raw_tool_callsrb   raw_tool_callsra   raw_tool_callend_name	tool_nameargsstringified_tool_callsmistral_tool_callsr#   r#   r$   extract_tool_calls   st   





z$MistralToolParser.extract_tool_callsprevious_textcurrent_text
delta_textprevious_token_idscurrent_token_idsdelta_token_idsNc                 C   s^   | j |vr
t|dS zt| jr| j||dW S | j||dW S  ty.   td Y d S w )N)rb   )r   r   z+Error trying to handle streaming tool call.)	rO   r   r;   r7   /_extract_tool_calls_streaming_pre_v11_tokenizer_extract_tool_calls_streaming	ExceptionrA   r{   )rV   r   r   r   r   r   r   rY   r#   r#   r$   extract_tool_calls_streaming   s   




z.MistralToolParser.extract_tool_calls_streamingc                 C   s   d}| j tjkr/| j|v sJ || js/||| jd 7 }| jd|| jdd  }| |}|sNt	|dkrN| j tj
tjtjtjfv rLt S dS t }|rV||_t	|dkr_||_|rj| jsjdi ig| _|S )z
        Extracts tool calls for Mistral models
        doing tool calls of the following format:
        `[TOOL_CALLS]add{"a": 3.5, "b": 4}`
        r*   r   rc   Nrg   )rE   r   r   rO   
startswithrL   rr   r-   _generate_delta_tool_callr1   r   r    r!   r"   r   rb   ra   rC   )rV   r   r   additional_contentdelta_tool_callsdeltar#   r#   r$   r     s4   


z/MistralToolParser._extract_tool_calls_streamingc              	   C   s|  |dks|d u r
g S d }d }| j tjtjfvr0|| jr0|  jd7  _tj| _ || jdd}| j tjkrj| jd u r>d| _d|v rat	
 }|dd }|  j|7  _|t|d  }tj| _ n	|  j|7  _g S | j tjkrd }| j|v rd}||| jd 7 }|t|d  }tj| _ n|}g }| js|r|t| jd|t| j|djddd	g7 }d | _|r|| |7 }|S g S )
Nr*   rc   rd   r   rp   re   T)exclude_none)indexrq   r)   rp   )rE   r   r   r   r   rL   rD   replacerF   r%   r&   rr   r1   r!   r   r   
model_dumpr   )rV   r   delta_function_nametool_idnext_function_textdelta_argumentsretr#   r#   r$   r   @  sf   






z+MistralToolParser._generate_delta_tool_callc                 c   s    	 d V \}}}|dkr|dkrt j| _|dkr$|dkr$|dkr$t j| _|dkr3|dkr3|| _t j| _|dkrC|dkrC|dkrCt j| _|d	krO|dkrOt j| _|d	kr[|d
kr[t j| _|dkrg|d
krgt j	| _|dkrs|dkrst j
| _q)NTitem	start_mapmap_keyrf   z	item.namestringrg   zitem.argumentsend_mapr*   	end_array)r   r   rE   r   rF   r   r   r   r    r!   r"   )rV   prefixeventvaluer#   r#   r$   rK   x  s*   z7MistralToolParser.update_stream_state_pre_v11_tokenizerc           
      C   s  | j dusJ d}g }t| jdd}d}| j|v r4|| js'|| jd }d|| jdd }t|dkr{| j	}| j	t
jkrN| j|dd\}}nv| j	t
jkr_| j|ddd	\}}ne| j	t
jkrp| j|ddd
\}}nT| j	t
jkr| j|dd\}}nD| j	t
jkr| j|dd\}}n4| j	t
jt
jfv r| j|ddd\}}n | j	t
jkr| j|ddd\}}n| j	t
jkr|}d}n|}d}| j	t
jkr| j |d || j	kr|t
jt
jfv r| j	t
jt
jt
jfvr|r| jdur| j|_d| _|| d}|  jd7  _t | _t| jdd}|jdu r!t |_| jdur1d}| j|j_d| _| j	t
jkr<t
j| _	| j	t
jt
jfv ru| j	t
jkrQt
j| _	d}|jj du r_||j_ n|j j |7  _ |t
jkru|jj ! |j_ t|dks;|r| jdur| j|_d| _|| |r| j"sdi ig| _"|st|dkrt# }	|r||	_$t|dkr||	_%|	S | j	t
jkrt# S dS )z
        Extracts tool calls for Mistral models
        doing tool calls of the following format:
        `[TOOL_CALLS][{"name": "add", "arguments":{"a": 3.5, "b": 4}}`
        Nrp   )r   rq   Fr   r*   rc   )r   stop_after_opening_curly_braces)r   stop_after_colonr   )r   stop_after_commastop_after_closing_brackets)r   stop_after_closing_curly_braces)r   r   r   )r   r   r   zutf-8Trg   )&rJ   r   rD   rO   r   rL   rr   r-   r1   rE   r   r   _split_deltar   r   r   r   r    r   r!   r"   sendencoderG   r)   rt   r%   r&   rp   r   rF   rf   rg   lstriprC   r   rb   ra   )
rV   r   r   rb   r   current_tool_callcurrent_tool_call_modifiedstreaming_state_before_parsedelta_to_be_parseddelta_messager#   r#   r$   r     s   








t
zAMistralToolParser._extract_tool_calls_streaming_pre_v11_tokenizerr>   stop_after_quotesr   r   r   r   c                 C   s  d}t |D ]\}	}
|
dv r'||
7 }|d8 }|dkr&|||	d d  f  S q|
dkrD||
7 }|d8 }|dkrC|||	d d  f  S q|
dkra||
7 }|d8 }|dkr`|||	d d  f  S q|
dkr~||
7 }|d8 }|dkr}|||	d d  f  S q|
dkr||
7 }|d8 }|dkr|||	d d  f  S q|
d	kr||
7 }|d8 }|dkr|||	d d  f  S q||
7 }q|dfS )
Nr*   )"'rc   r   rd   }]:,)	enumerate)rV   r   r   r   r   r   r   r   r   icr#   r#   r$   r   9  sP   

zMistralToolParser._split_delta)r>   r>   r>   r>   r>   r>   )r   r   r   r   r   r@   r
   r[   r3   r   r   r   intr   r   r   listr   r   rI   	coroutinerK   r   tupler   __classcell__r#   r#   rW   r$   r<   J   s     
j	

58

 .
	r<   )+rj   collections.abcr   enumr   r   randomr   r   r   r   typingr   rI   regexrP   pydanticr	   0vllm.entrypoints.openai.chat_completion.protocolr
   'vllm.entrypoints.openai.engine.protocolr   r   r   r   r   r   vllm.loggerr   vllm.tokenizersr   vllm.tokenizers.mistralr   &vllm.tool_parsers.abstract_tool_parserr   r   rA   r.   r   r%   r6   r;   r<   r#   r#   r#   r$   <module>   s*    