U
    h                     @   s   d Z ddlmZmZmZmZmZ ddlmZ ddl	m
Z
mZ ddlmZmZ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d	lmZ dd
lm Z  ddl!m"Z" dZ#eddddG dd deZ$dS )zHugging Face Chat Wrapper.    )AnyAsyncIteratorIteratorListOptional)
deprecated)AsyncCallbackManagerForLLMRunCallbackManagerForLLMRun)BaseChatModelagenerate_from_streamgenerate_from_stream)	AIMessageAIMessageChunkBaseMessageHumanMessageSystemMessage)ChatGenerationChatGenerationChunk
ChatResult	LLMResult)root_validator)HuggingFaceEndpoint)HuggingFaceHub)HuggingFaceTextGenInferencez4You are a helpful, respectful, and honest assistant.z0.0.37z1.0z%langchain_huggingface.ChatHuggingFace)ZsinceZremovalZalternative_importc                       s  e Zd ZU dZeed< eedZeed< dZ	eed< dZ
ee ed< dZeed	< ed
 fddZedddeedddZd)ee eee  ee eee dddZd*e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e eedddZee edddZeeddd Z e!e"ed!d"d#Z#dd$d%d&Z$e%ed$d'd(Z&  Z'S )-ChatHuggingFacea  
    Wrapper for using Hugging Face LLM's as ChatModels.

    Works with `HuggingFaceTextGenInference`, `HuggingFaceEndpoint`,
    and `HuggingFaceHub` LLMs.

    Upon instantiating this class, the model_id is resolved from the url
    provided to the LLM, and the appropriate tokenizer is loaded from
    the HuggingFace Hub.

    Adapted from: https://python.langchain.com/docs/integrations/chat/llama2_chat
    llmcontentsystem_messageN	tokenizermodel_idF	streaming)kwargsc                    sD   t  jf | ddlm} |   | jd kr8|| jn| j| _d S )Nr   )AutoTokenizer)super__init__Ztransformersr#   _resolve_model_idr   Zfrom_pretrainedr    )selfr"   r#   	__class__ O/tmp/pip-unpacked-wheel-9gdii04g/langchain_community/chat_models/huggingface.pyr%   B   s    zChatHuggingFace.__init__T)preZskip_on_failure)valuesreturnc                 C   s.   t |d tttfs*tdt|d  |S )Nr   zeExpected llm to be one of HuggingFaceTextGenInference, HuggingFaceEndpoint, HuggingFaceHub, received )
isinstancer   r   r   	TypeErrortype)clsr-   r*   r*   r+   validate_llmO   s    zChatHuggingFace.validate_llm)messagesstoprun_managerr"   r.   c           	      k   sP   |  |}| jj|f|D ]0}|}tt|dd}|rD|j||d |V  qd S Nr   )message)chunk)_to_chat_promptr   streamr   r   on_llm_new_token	r'   r4   r5   r6   r"   requestdatadeltar9   r*   r*   r+   _stream[   s    
zChatHuggingFace._streamc           	      K  s`   |  |}| jj|f|2 z>3 d H W }|}tt|dd}|rR|j||dI d H  |V  q6 d S r7   )r:   r   Zastreamr   r   r<   r=   r*   r*   r+   _astreamk   s    
zChatHuggingFace._astreamc                 K   sV   | j r&| j|f||d|}t|S | |}| jjf |g||d|}| |S N)r5   r6   )Zpromptsr5   r6   )r!   rA   r   r:   r   	_generate_to_chat_resultr'   r4   r5   r6   r"   Zstream_iterZ	llm_input
llm_resultr*   r*   r+   rD   z   s&     
  zChatHuggingFace._generatec                    sb   | j r,| j|f||d|}t|I d H S | |}| jjf |g||d|I d H }| |S rC   )r!   rB   r   r:   r   
_ageneraterE   rF   r*   r*   r+   rH      s&     
  zChatHuggingFace._agenerate)r4   r.   c                    sF   |st dt|d ts"t d fdd|D } jj|d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     z3ChatHuggingFace._to_chat_prompt.<locals>.<listcomp>FT)tokenizeZadd_generation_prompt)
ValueErrorr/   r   r   Zapply_chat_template)r'   r4   Zmessages_dictsr*   rM   r+   r:      s      zChatHuggingFace._to_chat_prompt)r8   r.   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   )r/   r   r   r   rP   r1   r   )r'   r8   rS   r*   r*   r+   rJ      s    


z!ChatHuggingFace._to_chatml_format)rG   r.   c                 C   sB   g }| j d D ]$}tt|jd|jd}|| qt|| jdS )Nr   r   )r8   generation_info)generations
llm_output)rU   r   r   textrT   appendr   rV   )rG   Zchat_generationsgZchat_generationr*   r*   r+   rE      s    
  zChatHuggingFace._to_chat_result)r.   c                 C   s   ddl m} |d}t| jts4t| jdrB| jjrB| jj| _dS t| jtrX| jj	}n| jj
}|D ]}|j|krd|j| _qd| jstd| ddS )z8Resolve the model_id from the LLM's inference_server_urlr   )list_inference_endpoints*repo_idNzIFailed to resolve model_id:Could not find model id for inference server: zBMake sure that your Hugging Face token has access to the endpoint.)Zhuggingface_hubrZ   r/   r   r   hasattrr\   r    r   Zinference_server_urlendpoint_urlurl
repositoryrP   )r'   rZ   Zavailable_endpointsr^   Zendpointr*   r*   r+   r&      s&    





z!ChatHuggingFace._resolve_model_idc                 C   s   dS )Nzhuggingface-chat-wrapperr*   rM   r*   r*   r+   	_llm_type   s    zChatHuggingFace._llm_type)NN)NN)NN)NN)(__name__
__module____qualname____doc__r   __annotations__r   DEFAULT_SYSTEM_PROMPTr   r   r    r   strr!   boolr%   r   dictr3   r   r   r	   r   r   rA   r   r   rB   r   rD   rH   r:   rJ   staticmethodr   rE   r&   propertyra   __classcell__r*   r*   r(   r+   r   '   sl   

  
  
  
  
r   N)%re   typingr   r   r   r   r   Zlangchain_core._api.deprecationr   Z langchain_core.callbacks.managerr   r	   Z*langchain_core.language_models.chat_modelsr
   r   r   Zlangchain_core.messagesr   r   r   r   r   Zlangchain_core.outputsr   r   r   r   Zlangchain_core.pydantic_v1r   Z-langchain_community.llms.huggingface_endpointr   Z(langchain_community.llms.huggingface_hubr   Z7langchain_community.llms.huggingface_text_gen_inferencer   rg   r   r*   r*   r*   r+   <module>   s"   