o
    c۷iC                     @   s   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mZmZmZ d dlmZmZ d dlmZmZmZ G d	d
 d
eeZG dd deeZG dd deZG dd deZG dd de
ee ZG dd deeeef ZdS )    )Enum)AnyGeneric)Field)MistralBase)BaseCompletionRequest)_check_openai_fields_names_is_openai_field_nameconvert_openai_messagesconvert_openai_tools)ChatMessageChatMessageType)Tool
ToolChoiceToolTypec                   @      e Zd ZdZdZdZdS )ResponseFormatszEnum of the different formats of an instruct response.

    Attributes:
        text: The response is a plain text.
        json: The response is a JSON object.

    Examples:
        >>> response_format = ResponseFormats.text
    textjson_objectN)__name__
__module____qualname____doc__r   json r   r   ^/home/ubuntu/vllm_env/lib/python3.10/site-packages/mistral_common/protocol/instruct/request.pyr      s    
r   c                   @   r   )ReasoningEffortzControls how much reasoning effort the model should apply.

    Attributes:
        none: No additional reasoning effort.
        high: High reasoning effort for complex tasks.
    nonehighN)r   r   r   r   r   r   r   r   r   r   r   $   s    r   c                   @   s\   e Zd ZU dZdZedB ed< edddZde	e
ef fddZed	edd fd
dZdS )ModelSettingsa  Model configuration settings for instruct requests.

    This class encapsulates various model configuration options that can be
    passed to the model during inference. Currently supports reasoning effort
    configuration, but can be extended with additional settings in the future.

    Attributes:
        reasoning_effort: Controls how much reasoning effort the model should apply when
            generating responses. Supported for tokenizer >= v15 and not supported for earlier versions.
    Nreasoning_effortreturnc                   C   s   t  S )z;Create a ModelSettings instance with default (None) values.)r   r   r   r   r   r   >   s   zModelSettings.nonec                 C   s   | j ddS )z@Convert ModelSettings to OpenAI API format with non-None values.T)exclude_none)
model_dump)selfr   r   r   	to_openaiC   s   zModelSettings.to_openaikwargsc                 K   s
   t |S )z5Create ModelSettings from OpenAI keywords API format.)r   model_validate)clsr&   r   r   r   from_openaiG   s   
zModelSettings.from_openai)r!   r   )r   r   r   r   r    r   __annotations__staticmethodr   dictstrr   r%   classmethodr)   r   r   r   r   r   0   s   
 r   c                   @   s    e Zd ZU dZejZeed< dS )ResponseFormatzThe format of the response.

    Attributes:
        type: The type of the response.

    Examples:
        >>> response_format = ResponseFormat(type=ResponseFormats.text)
    typeN)r   r   r   r   r   r   r0   r*   r   r   r   r   r/   M   s   
 	r/   c                   @   s  e Zd ZU dZdZedB ed< ee ed< e	e
dZe
ed< dZee dB ed< ejZeed< d	Zeed
< d	Zeed< dZedB ed< dedeeeeeef  f fddZe			ddeeeeeeeeeeef B f  B f  deeeef  dB dededd f
ddZdS )ChatCompletionRequesta  Request for a chat completion.

    Attributes:
        model: The model to use for the chat completion.
        messages: The messages to use for the chat completion.
        response_format: The format of the response.
        tools: The tools to use for the chat completion.
        tool_choice: The tool choice to use for the chat completion.
        truncate_for_context_length: Whether to truncate the messages for the context length.
        continue_final_message: Whether to continue the final message.
        reasoning_effort: Controls how much reasoning effort the model should apply.

    Examples:
        >>> from mistral_common.protocol.instruct.messages import UserMessage, AssistantMessage
        >>> from mistral_common.protocol.instruct.tool_calls import ToolTypes, Function
        >>> request = ChatCompletionRequest(
        ...     messages=[
        ...         UserMessage(content="Hello!"),
        ...         AssistantMessage(content="Hi! How can I help you?"),
        ...     ],
        ...     response_format=ResponseFormat(type=ResponseFormats.text),
        ...     tools=[Tool(type=ToolTypes.function, function=Function(name="get_weather", parameters={}))],
        ...     tool_choice=ToolChoice.auto,
        ...     truncate_for_context_length=True,
        ... )
    Nmodelmessagesdefault_factoryresponse_formattoolstool_choiceFtruncate_for_context_lengthcontinue_final_messager    r&   r!   c                 K   s   | j h ddd}|dd}|dur||d< | jrtd|D ]&}||v r-td| |tjv r:td	| d
t|sFtd| dq g }| jD ]	}|	|
  qL||d< | jduridd | jD |d< || |S )a	  Convert the request messages and tools into the OpenAI format.

        Args:
            kwargs: Additional parameters to be added to the request.

        Returns:
            The request in the OpenAI format.

        Examples:
            >>> from mistral_common.protocol.instruct.messages import UserMessage
            >>> from mistral_common.protocol.instruct.tool_calls import Tool, Function
            >>> request = ChatCompletionRequest(messages=[UserMessage(content="Hello, how are you?")], temperature=0.15)
            >>> request.to_openai(stream=True)
            {'temperature': 0.15, 'top_p': 1.0, 'response_format': {'type': 'text'}, 'tool_choice': 'auto', 'continue_final_message': False, 'messages': [{'role': 'user', 'content': 'Hello, how are you?'}], 'stream': True}
            >>> request = ChatCompletionRequest(messages=[UserMessage(content="Hello, how are you?")], tools=[
            ...     Tool(function=Function(
            ...         name="get_current_weather",
            ...         description="Get the current weather in a given location",
            ...         parameters={
            ...             "type": "object",
            ...             "properties": {
            ...                 "location": {
            ...                     "type": "string",
            ...                     "description": "The city and state, e.g. San Francisco, CA",
            ...                 },
            ...                 "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
            ...             },
            ...             "required": ["location"],
            ...         },
            ...     ),
            ... )])
            >>> request.to_openai()
            {'temperature': 0.7, 'top_p': 1.0, 'response_format': {'type': 'text'}, 'tool_choice': 'auto', 'continue_final_message': False, 'messages': [{'role': 'user', 'content': 'Hello, how are you?'}], 'tools': [{'type': 'function', 'function': {'name': 'get_current_weather', 'description': 'Get the current weather in a given location', 'parameters': {'type': 'object', 'properties': {'location': {'type': 'string', 'description': 'The city and state, e.g. San Francisco, CA'}, 'unit': {'type': 'string', 'enum': ['celsius', 'fahrenheit']}}, 'required': ['location']}, 'strict': False}}]}
        >   r7   r3   r9   Texcluder"   random_seedNseedzETruncating for context length is not implemented for OpenAI requests.Duplicate keyword argument: Keyword argument  is already set in the request.Invalid keyword argument: $, it should be an OpenAI field name.r3   c                 S      g | ]}|  qS r   r%   .0toolr   r   r   
<listcomp>       z3ChatCompletionRequest.to_openai.<locals>.<listcomp>r7   )r#   popr9   NotImplementedError
ValueErrorr1   model_fieldsr	   r3   appendr%   r7   update)r$   r&   openai_requestr>   kwargopenai_messagesmessager   r   r   r%      s0   %



zChatCompletionRequest.to_openaic                 K   s   d|v rd|v rt d|ddp|dd}tt| j t|  t|}|dur2t|nd}| d||||d|S )a  Create a chat completion request from the OpenAI format.

        Args:
            messages: The messages in the OpenAI format.
            tools: The tools in the OpenAI format.
            continue_final_message: Whether to continue the final message.
            **kwargs: Additional keyword arguments to pass to the constructor. These should be the same as the fields
                of the request class or the OpenAI API equivalent.


        Returns:
            The chat completion request.
        r>   r=   z-Cannot specify both `seed` and `random_seed`.N)r3   r7   r=   r:   r   )rM   rK   r   setrN   keysr
   r   )r(   r3   r7   r:   r&   r=   converted_messagesconverted_toolsr   r   r   r)      s   z!ChatCompletionRequest.from_openaiNF)r   r   r   r   r2   r-   r*   listr   r   r/   r6   r7   r   r   autor8   r9   boolr:   r    r   r   r,   r%   r.   r)   r   r   r   r   r1   Z   s2   
 &I*r1   c                   @   s   e Zd ZU dZee ed< dZedB ed< dZ	ee
 dB ed< dZedB ed< dZeed< eejd	Zeed
< dedeeeeeef  f fddZe		ddeeeeeeeeeeef B f  B f  deeeef  dB dededd f
ddZdS )InstructRequesta  A valid Instruct request to be tokenized.

    Attributes:
        messages: The history of the conversation.
        system_prompt: The system prompt to be used for the conversation.
        available_tools: The tools available to the assistant.
        truncate_at_max_tokens: The maximum number of tokens to truncate the conversation at.
        continue_final_message: Whether to continue the final message.
        settings: Model configuration settings for the request.

    Examples:
        >>> from mistral_common.protocol.instruct.messages import UserMessage, SystemMessage
        >>> request = InstructRequest(
        ...     messages=[UserMessage(content="Hello, how are you?")], system_prompt="You are a helpful assistant."
        ... )
    r3   Nsystem_promptavailable_toolstruncate_at_max_tokensFr:   r4   settingsr&   r!   c                 K   s   | j h ddd}|D ]&}||v rtd| |tjv r%td| dt|s1td| dqg }| jd	urB|d
| jd | jD ]	}||  qE||d< | j	d	urbdd | j	D |d< | j
d	urktd|| |jdi | j  |S )a  Convert the request messages and tools into the OpenAI format.

        Args:
            kwargs: Additional parameters to be added to the request.

        Returns:
            The request in the OpenAI format.

        Examples:
            >>> from mistral_common.protocol.instruct.messages import UserMessage
            >>> from mistral_common.protocol.instruct.tool_calls import Tool, Function
            >>> request = InstructRequest(messages=[UserMessage(content="Hello, how are you?")])
            >>> request.to_openai(temperature=0.15, stream=True)
            {'continue_final_message': False, 'messages': [{'role': 'user', 'content': 'Hello, how are you?'}], 'temperature': 0.15, 'stream': True}
            >>> request = InstructRequest(
            ...     messages=[UserMessage(content="Hello, how are you?")],
            ...     available_tools=[
            ...     Tool(function=Function(
            ...         name="get_current_weather",
            ...         description="Get the current weather in a given location",
            ...         parameters={
            ...             "type": "object",
            ...             "properties": {
            ...                 "location": {
            ...                     "type": "string",
            ...                     "description": "The city and state, e.g. San Francisco, CA",
            ...                 },
            ...                 "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
            ...             },
            ...             "required": ["location"],
            ...         },
            ...     ),
            ... )])
            >>> request.to_openai()
            {'continue_final_message': False, 'messages': [{'role': 'user', 'content': 'Hello, how are you?'}], 'tools': [{'type': 'function', 'function': {'name': 'get_current_weather', 'description': 'Get the current weather in a given location', 'parameters': {'type': 'object', 'properties': {'location': {'type': 'string', 'description': 'The city and state, e.g. San Francisco, CA'}, 'unit': {'type': 'string', 'enum': ['celsius', 'fahrenheit']}}, 'required': ['location']}, 'strict': False}}]}
        >   r3   ra   r_   r`   Tr;   r?   r@   rA   rB   rC   Nsystem)rolecontentr3   c                 S   rD   r   rE   rF   r   r   r   rI   K  rJ   z-InstructRequest.to_openai.<locals>.<listcomp>r7   z@Truncating at max tokens is not implemented for OpenAI requests.r   )r#   rM   r]   rN   r	   r^   rO   r3   r%   r_   r`   rL   rP   ra   )r$   r&   rQ   rR   rS   rT   r   r   r   r%   
  s0   '





zInstructRequest.to_openair7   c                    s   d|v r|du r| d}ntdtj  | j }| s%J d| B }t|t|  t|}|dur>t	|nd}tj
d	i  fdd| D }	 fdd| D }
| d	||||	d|
S )
a  Create an instruct request from the OpenAI format.

        Args:
            messages: The messages in the OpenAI format.
            tools: The tools in the OpenAI format.
            continue_final_message: Whether to continue the final message.
            **kwargs: Additional keyword arguments to pass to the constructor. These should be the same as the fields
                of the request class or the OpenAI API equivalent.

        Returns:
            The instruct request.
        r_   Nz2Cannot specify both `tools` and `available_tools`.zDModelSettings fields should not overlap with InstructRequest fields.c                    s   i | ]\}}| v r||qS r   r   rG   kvmodel_settings_fieldsr   r   
<dictcomp>}      z/InstructRequest.from_openai.<locals>.<dictcomp>c                    s   i | ]\}}| vr||qS r   r   re   rh   r   r   rj   ~  rk   )r3   r_   r:   ra   r   )rK   rM   r   rN   rV   
isdisjointr   rU   r
   r   r)   items)r(   r3   r7   r:   r&   instruct_request_fieldsvalid_fieldsrW   rX   model_settingsother_kwargsr   rh   r   r)   U  s.   

"zInstructRequest.from_openairY   )r   r   r   r   rZ   r   r*   r^   r-   r_   r   r`   intr:   r\   r   r   r   ra   r   r,   r%   r.   r)   r   r   r   r   r]      s.   
 &K*r]   N)enumr   typingr   r   pydanticr   mistral_common.baser   mistral_common.protocol.baser   +mistral_common.protocol.instruct.convertersr   r	   r
   r   )mistral_common.protocol.instruct.messagesr   r   +mistral_common.protocol.instruct.tool_callsr   r   r   r-   r   r   r   r/   r1   r]   r   r   r   r   <module>   s     