
    hF                         d Z ddlmZmZmZmZmZmZmZm	Z	m
Z
 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 ddlmZ dd	lmZ dd
lmZ ddlmZ  G d de      Zy)z
Transformation logic from OpenAI /v1/chat/completion format to Mistral's /chat/completion format.

Why separate file? Make it easy to see how transformation works

Docs - https://docs.mistral.ai/api/
    )	Any	CoroutineListLiteralOptionalTupleUnioncastoverloadN)Logging)3handle_messages_with_content_list_to_str_conversionstrip_none_values_from_message)OpenAIGPTConfig)get_secret_str)MistralToolCallMessage)AllMessageValues)ModelResponse) convert_to_model_response_objectc                       e Zd ZU dZdZee   ed<   dZee   ed<   dZ	ee   ed<   dZ
ee   ed<   dZeed      ed<   dZee   ed	<   dZee   ed
<   dZee   ed<   dZeeeef      ed<   	 	 	 	 	 	 	 	 	 d2dee   dee   dee   dee   deed      d	ee   d
ee   dee   deeeef      ddfdZe fd       Zdedee   fdZdedefdZedefd       Zdededededef
dZdee   dee   deeee   f   fdZ e!dee"   deded   de#e$e$ee"   f   fd       Z%e!	 d3dee"   deded   dee"   fd        Z%	 d3dee"   dededeee"   e#e$e$ee"   f   f   f fd!Z%dee"   dedee"   fd"Z&ed#e"de"fd$       Z'ed#e"de"fd%       Z(ed&edefd'       Z)dedee"   ded(ed)edef fd*Z*	 	 d4ded+e+jX                  d,e-d-e.d.edee"   ded(ed/e$dee   d0ee   de-fd1Z/ xZ0S )5MistralConfiga  
    Reference: https://docs.mistral.ai/api/

    The class `MistralConfig` provides configuration for the Mistral's Chat API interface. Below are the parameters:

    - `temperature` (number or null): Defines the sampling temperature to use, varying between 0 and 2. API Default - 0.7.

    - `top_p` (number or null): An alternative to sampling with temperature, used for nucleus sampling. API Default - 1.

    - `max_tokens` (integer or null): This optional parameter helps to set the maximum number of tokens to generate in the chat completion. API Default - null.

    - `tools` (list or null): A list of available tools for the model. Use this to specify functions for which the model can generate JSON inputs.

    - `tool_choice` (string - 'auto'/'any'/'none' or null): Specifies if/how functions are called. If set to none the model won't call a function and will generate a message instead. If set to auto the model can choose to either generate a message or call a function. If set to any the model is forced to call a function. Default - 'auto'.

    - `stop` (string or array of strings): Stop generation if this token is detected. Or if one of these tokens is detected when providing an array

    - `random_seed` (integer or null): The seed to use for random sampling. If set, different calls will generate deterministic results.

    - `safe_prompt` (boolean): Whether to inject a safety prompt before all conversations. API Default - 'false'.

    - `response_format` (object or null): An object specifying the format that the model must output. Setting to { "type": "json_object" } enables JSON mode, which guarantees the message the model generates is in JSON. When using JSON mode you MUST also instruct the model to produce JSON yourself with a system or a user message.
    Ntemperaturetop_p
max_tokenstools)autoanynonetool_choicerandom_seedsafe_promptresponse_formatstopreturnc
                     t               j                         }
|
j                         D ]%  \  }}|dk7  s|t        | j                  ||       ' y )Nself)localscopyitemssetattr	__class__)r%   r   r   r   r   r   r   r    r!   r"   locals_keyvalues                d/var/www/Befach/backend/env/lib/python3.12/site-packages/litellm/llms/mistral/chat/transformation.py__init__zMistralConfig.__init__<   sA     (--/!--/JCf}!2U3 *    c                      t         |          S N)super
get_config)clsr*   s    r.   r4   zMistralConfig.get_configM   s    w!##r0   modelc                 X    g d}d|j                         v r|j                  ddg       |S )N)streamr   r   r   max_completion_tokensr   r   seedr"   r!   parallel_tool_calls	magistralthinkingreasoning_effort)lowerextend)r%   r6   supported_paramss      r.   get_supported_openai_paramsz)MistralConfig.get_supported_openai_paramsQ   s4    
 %++-'##Z1C$DEr0   c                 (    |dk(  s|dk(  r|S |dk(  ryy)Nr   r   requiredr    )r%   r   s     r.   _map_tool_choicezMistralConfig._map_tool_choicef   s%    & K6$9J&r0   c                       y)z
        Returns the system prompt for Mistral reasoning models.
        Based on Mistral's documentation: https://huggingface.co/mistralai/Magistral-Small-2506

        Mistral recommends the following system prompt for reasoning:
        ay  
        <s>[SYSTEM_PROMPT]system_prompt
        A user will ask you to solve a task. You should first draft your thinking process (inner monologue) until you have derived the final answer. Afterwards, write a self-contained summary of your thoughts (i.e. your summary should be succinct but contain all the critical steps you needed to reach the conclusion). You should use Markdown to format your response. Write both your thoughts and summary in the same language as the task posed by the user. NEVER use oxed{} in your response.

        Your thinking process must follow the template below:
        <think>
        Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct answer.
        </think>

        Here, provide a concise summary that reflects your reasoning and presents a clear final answer to the user. Don't mention that this is a summary.

        Problem:

        [/SYSTEM_PROMPT][INST]user_message[/INST]<think>
        reasoning_traces
        </think>
        assistant_response</s>[INST]user_message[/INST]
        rE   rE   r0   r.   $_get_mistral_reasoning_system_promptz2MistralConfig._get_mistral_reasoning_system_promptn   s    r0   non_default_paramsoptional_paramsdrop_paramsc                    |j                         D ]  \  }}|dk(  r||d<   |dk(  r||d<   |dk(  r||d<   |dk(  r	|du r||d<   |dk(  r||d<   |dk(  r||d<   |dk(  r||d<   |d	k(  r%t        |t              r| j                  |
      |d	<   |dk(  rd|i|d<   |dk(  r||d<   |dk(  rd|j	                         v rd|d<   |dk(  rd|j	                         v rd|d<   |dk(  s||d<    |S )Nr   r9   r   r8   Tr   r   r"   r   )r   r:   r   
extra_bodyr!   r>   r<   _add_reasoning_promptr=   r;   )r(   
isinstancestrrF   r?   )r%   rI   rJ   r6   rK   paramr-   s          r.   map_openai_paramszMistralConfig.map_openai_params   sP    /446LE5$05-//05-+0( Ud],1)%16.+0(*/'%*UC*@151F1FSX1F1Y.1>0F-))5: 12**{ekkm/K;? 78
"{ekkm'C;? 78--9> 569 7: r0   api_baseapi_keyc                     |xs t        d      xs d}||j                  d      s|dz   }|xs t        d      xs t        d      }||fS )NMISTRAL_AZURE_API_BASEzhttps://api.mistral.ai/v1z/v1MISTRAL_AZURE_API_KEYMISTRAL_API_KEY)r   endswith)r%   rS   rT   dynamic_api_keys       r.   $_get_openai_compatible_provider_infoz2MistralConfig._get_openai_compatible_provider_info   sr    
  +67+* 	 (9(9%(@%'H 1561/0 	
 ((r0   messagesis_asyncTc                      y r2   rE   r%   r\   r6   r]   s       r.   _transform_messagesz!MistralConfig._transform_messages   s     7:r0   Fc                      y r2   rE   r_   s       r.   r`   z!MistralConfig._transform_messages   s     "%r0   c                    |D ]n  }|j                  d      }|st        |t              s(|D ]B  }|j                  d      dk(  s|rt        |   ||d      c c S t        |   ||d      c c S  p t        |      }g }|D ]H  }t        j                  |      }t        j                  |      }t        |      }|j                  |       J |rt        |   ||d      S t        |   ||d      S )ap  
        - handles scenario where content is list and not string
        - content list is just text, and no images
        - if image passed in, then just return as is (user-intended)
        - if `name` is passed, then drop it for mistral API: https://github.com/BerriAI/litellm/issues/6696

        Motivation: mistral api doesn't support content as a list
        contenttype	image_urlTF)getrO   listr3   r`   r   r   _handle_name_in_message_handle_tool_call_messager   append)	r%   r\   r6   r]   m_content_blockcnew_messagesr*   s	           r.   r`   z!MistralConfig._transform_messages   s     AUU9-N*^T"B'AuuV}3##(7#>xPT#UU#(7#>xPU#VV (  GxP 02A55a8A77:A.q1A"	  7.|UDII7.|UEJJr0   c                    |j                  dd      s|S t        d |D              }|rt        |      D ]  \  }}|j                  d      dk(  s|j                  dd      }| j                         }t	        |t
              r| d| }n-t	        |t              rd	|dz   d
g|z   }n| dt        |       }t        t        i |d|i      ||<    n) n't        t        d| j                         d      }	|	g|z   }|j                  dd       |S )zn
        Add reasoning system prompt for Mistral magistral models when reasoning_effort is specified.
        rN   Fc              3   D   K   | ]  }|j                  d       dk(    yw)rolesystemN)rf   ).0msgs     r.   	<genexpr>zGMistralConfig._add_reasoning_system_prompt_if_needed.<locals>.<genexpr>   s      QH!< Qs    rq   rr   rc    z

text)rd   rw   )rq   rc   N)
rf   r   	enumeraterH   rO   rP   rg   r
   r   pop)
r%   r\   rJ   has_system_messageirt   existing_contentreasoning_promptnew_contentreasoning_messages
             r.   &_add_reasoning_system_prompt_if_neededz4MistralConfig._add_reasoning_system_prompt_if_needed   s:    ""#:EBO ! Q QQ#H-3776?h.'*wwy"'=$'+'P'P'R$ ""2C8;K:LDQaPb8c#$4d;06@PSY@Y'Z&[^n&n *:(:$sCS?T>U&V"&'79XC9XK9X"YHQK# .( 37 8@i@i@k"l3 **X5H 	3T:r0   messagec                     |j                  d      }|Z|d   dk7  r|j                  dd       |S t        |t              r.t	        |j                               dk(  r|j                  dd       |S )z
        Mistral API only supports `name` in tool messages

        If role == tool, then we keep `name` if it's not an empty string
        Otherwise, we drop `name`
        nameNrq   toolr   )rf   ry   rO   rP   lenstrip)r5   r   _names      r.   rh   z%MistralConfig._handle_name_in_message!  sj     F#v&(FD)
  E3'C,>!,CFD)r0   c                     |j                  d      }g }|Yt        |t              rI|D ]?  }t        |j                  d      d|j                  d            }|j	                  |       A ||d<   |S )zc
        Mistral API only supports tool_calls in Messages in `MistralToolCallMessage` spec
        
tool_callsidfunction)r   rd   r   )rf   rO   rg   r   rj   )r5   r   _tool_callsmistral_tool_calls_tool_tool_call_messages         r.   ri   z'MistralConfig._handle_tool_call_message5  sx    
 kk,/;="z+t'D$%;yy#"YYz2&"
 #))*<= % %7GL!r0   response_datac                     | j                  d      rMt        | d         dkD  r<| d   D ]4  }|j                  d      s|d   j                  d      dk(  s-d|d   d<   6 | S )a  
        Handle Mistral-specific behavior where empty string content should be converted to None.

        Mistral API sometimes returns empty string content ('') instead of null,
        which can cause issues with downstream processing.

        Args:
            response_data: The raw response data from Mistral API

        Returns:
            dict: The response data with empty string content converted to None
        choicesr   r   rc   rv   N)rf   r   )r   choices     r.   _handle_empty_content_responsez,MistralConfig._handle_empty_content_responseG  sm     Y'Ci0H,IA,M'	2::i(VI->-B-B9-MQS-S37F9%i0 3 r0   litellm_paramsheadersc                     d|j                         v r$|j                  dd      r| j                  ||      }t        |   |||||      S )a  
        Transform the overall request to be sent to the API.
        For magistral models, adds reasoning system prompt when reasoning_effort is specified.

        Returns:
            dict: The transformed request. Sent as the body of the API call.
        r<   rN   F)r6   r\   rJ   r   r   )r?   rf   r   r3   transform_request)r%   r6   r\   rJ   r   r   r*   s         r.   r   zMistralConfig.transform_request[  s^      %++-'O,?,?@WY^,_BB8_]H w(+) ) 
 	
r0   raw_responsemodel_responselogging_objrequest_dataencoding	json_modec                 *   |j                  |j                         |j                  |j                  d<   |j	                         }| j                  |      }t        t        t        ||d|j                  it        |j                                    }|S )z
        Transform the raw response from Mistral API.
        Handles Mistral-specific behavior like converting empty string content to None.
        )original_responseresponse_headersr   )response_objectmodel_response_objecthidden_params_response_headers)
	post_callrw   r   model_call_detailsjsonr   r
   r   r   dict)r%   r6   r   r   r   r   r\   rJ   r   r   rT   r   r   final_response_objs                 r.   transform_responsez MistralConfig.transform_responsew  s    $ 	0A0AB=I=Q=Q&&'9: %))+;;MJ!, -&4(,*>*>?"&|';';"<	
 "!r0   )	NNNNNNNNN)F)NN)1__name__
__module____qualname____doc__r   r   int__annotations__r   r   r   rg   r   r   r   r    boolr!   r   r"   r	   rP   r/   classmethodr4   r   rB   rF   staticmethodrH   rR   r   r[   r   r   r   r   r`   r   rh   ri   r   r   httpxResponser   LiteLLMLoggingObjr   __classcell__)r*   s   @r.   r   r      s|   0 "&K#%E8C= $J$ E8D> <@K'"789@!%K#%"&K$&&*OXd^*'+D(5d#
$+ &*#$( $@D%)&**.+/4c]4 }4 SM	4
 ~4 g&;<=4 c]4 d^4 "$4 uS$Y'(4 
4" $ $   c  *C C  #  4$ $ $ 	$
 $ 
$L) )08)	sHSM!	")( :-.:7::FMdm:	3T"233	4: : 
 $)	%'(% % %.	%
 
	% % NS$K-.$K7:$KFJ$K	t$%yc4@P;Q1Q'RR	S$KL)-.)AE)		)V .> CS  & 0@ EU  " d t  &

 '(
 	

 
 
 

N "&$(#"#" nn#" &	#"
 '#" #" '(#" #" #" #" ##" D>#" 
#"r0   r   )r   typingr   r   r   r   r   r   r	   r
   r   r   *litellm.litellm_core_utils.litellm_loggingr   r   8litellm.litellm_core_utils.prompt_templates.common_utilsr   r   +litellm.llms.openai.chat.gpt_transformationr   litellm.secret_managers.mainr   litellm.types.llms.mistralr   litellm.types.llms.openair   litellm.types.utilsr   litellm.utilsr   r   rE   r0   r.   <module>r      sD    Y X X  S H 7 = 6 - :A"O A"r0   