U
    h                     @   s   d Z ddlmZmZmZmZ ddlmZmZ ddl	m
Z
 ddlmZmZmZmZmZ ddlmZmZmZmZ ddlmZ dZG d	d
 d
e
ZdS )zMLX Chat Wrapper.    )AnyIteratorListOptional)AsyncCallbackManagerForLLMRunCallbackManagerForLLMRun)BaseChatModel)	AIMessageAIMessageChunkBaseMessageHumanMessageSystemMessage)ChatGenerationChatGenerationChunk
ChatResult	LLMResult)MLXPipelinez4You are a helpful, respectful, and honest assistant.c                       s  e Zd ZU dZeed< eedZeed< dZ	e
ed< e
d fdd	Zdee eee  ee e
ed
ddZdee eee  ee e
ed
ddZd ee eee edddZeedddZeeedddZeedddZd!ee eee  ee e
ee d
ddZ   Z!S )"ChatMLXa  MLX chat models.

    Works with `MLXPipeline` LLM.

    To use, you should have the ``mlx-lm`` python package installed.

    Example:
        .. code-block:: python

            from langchain_community.chat_models import chatMLX
            from langchain_community.llms import MLXPipeline

            llm = MLXPipeline.from_model_id(
                model_id="mlx-community/quantized-gemma-2b-it",
            )
            chat = chatMLX(llm=llm)

    llmcontentsystem_messageN	tokenizer)kwargsc                    s   t  jf | | jj| _d S )N)super__init__r   r   )selfr   	__class__ G/tmp/pip-unpacked-wheel-9gdii04g/langchain_community/chat_models/mlx.pyr   5   s    zChatMLX.__init__)messagesstoprun_managerr   returnc                 K   s0   |  |}| jjf |g||d|}| |S N)Zpromptsr"   r#   )_to_chat_promptr   	_generate_to_chat_resultr   r!   r"   r#   r   	llm_input
llm_resultr   r   r    r'   9   s    
  zChatMLX._generatec                    s6   |  |}| jjf |g||d|I d H }| |S r%   )r&   r   
_agenerater(   r)   r   r   r    r,   F   s    
  zChatMLX._agenerateF)r!   tokenizereturn_tensorsr$   c                    sH   |st dt|d ts"t d fdd|D } jj||d|dS )zHConvert a list of messages into a prompt format expected by wrapped LLM.z+At least one HumanMessage must be provided!z$Last message must be a HumanMessage!c                    s   g | ]}  |qS r   )_to_chatml_format).0mr   r   r    
<listcomp>`   s     z+ChatMLX._to_chat_prompt.<locals>.<listcomp>T)r-   Zadd_generation_promptr.   )
ValueError
isinstancer   r   Zapply_chat_template)r   r!   r-   r.   Zmessages_dictsr   r3   r    r&   S   s    zChatMLX._to_chat_prompt)messager$   c                 C   sN   t |trd}n2t |tr d}n"t |tr0d}ntdt| ||jdS )z+Convert LangChain message to ChatML format.systemZ	assistantuserzUnknown message type: )roler   )r6   r   r	   r   r5   typer   )r   r7   r:   r   r   r    r0   i   s    


zChatMLX._to_chatml_format)r+   r$   c                 C   sB   g }| j d D ]$}tt|jd|jd}|| qt|| jdS )Nr   r   )r7   generation_info)generations
llm_output)r=   r   r	   textr<   appendr   r>   )r+   Zchat_generationsgZchat_generationr   r   r    r(   w   s    
  zChatMLX._to_chat_result)r$   c                 C   s   dS )Nzmlx-chat-wrapperr   r3   r   r   r    	_llm_type   s    zChatMLX._llm_typec                 k   sL  dd l m} ddlm} zdd l m} ddlm} W n tk
rP   tdY nX |d| jj}|dd}|dd}	|d	d }
|d
d }| j|ddd}|	|d }| j
j}t||| jj||
|t|	D ]p\\}}}d }| j
| }|r&tt|dd}|r |j||d |V  ||ks@|d k	r||kr qHqd S )Nr   )generate_stepzTCould not import mlx_lm python package. Please install it with `pip install mlx_lm`.model_kwargstempg        Z
max_tokensd   repetition_penaltyrepetition_context_sizeTnp)r-   r.   r   )r7   )chunk)Zmlx.corecoreZmlx_lm.utilsrC   ImportErrorgetr   Zpipeline_kwargsr&   arrayr   eos_token_idzipmodelrangedecodeitemr   r
   Zon_llm_new_token)r   r!   r"   r#   r   ZmxrC   rD   rE   Zmax_new_tokensrG   rH   r*   Zprompt_tokensrO   tokenZprobnr?   rJ   r   r   r    _stream   sT    
  zChatMLX._stream)NN)NN)FN)NN)"__name__
__module____qualname____doc__r   __annotations__r   DEFAULT_SYSTEM_PROMPTr   r   r   r   r   r   r   strr   r   r'   r   r,   boolr&   dictr0   staticmethodr   r(   propertyrB   r   r   rW   __classcell__r   r   r   r    r      sZ   
  
  
    
r   N)r[   typingr   r   r   r   Z langchain_core.callbacks.managerr   r   Z*langchain_core.language_models.chat_modelsr   Zlangchain_core.messagesr	   r
   r   r   r   Zlangchain_core.outputsr   r   r   r   Z%langchain_community.llms.mlx_pipeliner   r]   r   r   r   r   r    <module>   s   