
    NggL                        d Z ddlmZ ddlmZmZmZmZmZm	Z	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 ddlmZmZmZmZmZmZ ddl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dl(m)Z) ddl*m+Z+ ddl,m-Z- dZ.e G d d                      Z/e G d d                      Z0dedefdZ1de0defdZ2dede3fdZ4dede3fdZ5dede3fdZ6dede3fdZ7 G d d e          Z8d!S )"zHugging Face Chat Wrapper.    )	dataclass)
AnyCallableDictListLiteralOptionalSequenceTypeUnioncast)AsyncCallbackManagerForLLMRunCallbackManagerForLLMRun)LanguageModelInput)BaseChatModel)	AIMessageBaseMessageChatMessageHumanMessageSystemMessageToolMessage)ChatGeneration
ChatResult	LLMResult)Runnable)BaseToolconvert_to_openai_tool)model_validator)Self)HuggingFaceEndpoint)HuggingFacePipelinez4You are a helpful, respectful, and honest assistant.c                   4    e Zd ZU dZee         ed<   eed<   dS )TGI_RESPONSEz'Response from the TextGenInference API.choicesusageN)__name__
__module____qualname____doc__r   r   __annotations__r        i/var/www/html/ai-engine/env/lib/python3.11/site-packages/langchain_huggingface/chat_models/huggingface.pyr$   r$   ,   s/         11#YKKKKKr-   r$   c                   >    e Zd ZU dZeed<   eed<   ee         ed<   dS )TGI_MESSAGEz,Message to send to the TextGenInference API.rolecontent
tool_callsN)r'   r(   r)   r*   strr+   r   r   r,   r-   r.   r0   r0   4   s:         66
IIILLLT
r-   r0   messagereturnc                    t          | t                    rt          | j        | j                  S t          | t
                    rt          d| j                  S t          | t                    r.d| j        v rd | j        d         D             }nd }d| j        |dS t          | t                    rt          d| j                  S t          | t                    rd| j        | j
        d	S t          d
|            )Nr1   r2   userr3   c                 L    g | ]!}d |d          d         |d          d         di"S )functionname	arguments)r<   r=   r,   ).0tcs     r.   
<listcomp>z4_convert_message_to_chat_message.<locals>.<listcomp>F   sQ          ":v 6%'
^K%@! !  r-   	assistant)r1   r2   r3   systemtool)r1   r2   r<   zGot unknown type )
isinstancer   dictr1   r2   r   r   additional_kwargsr   r   r<   
ValueError)r5   r3   s     r.    _convert_message_to_chat_messagerH   =   s/    ';'' 8w????	G\	*	* 89999	GY	'	' 87444  "3LA  JJ J$
 
 	

 
G]	+	+ 	87?;;;;	G[	)	) 8L
 
 	
 6W66777r-   _messagec                 ~   | j         }|dk    sJ d|             t          t          | j                  }|d}i }| j        x}rjd|d         d         v rUt          |d         d                             d                    }|                    dd          }||d         d         d<   ||d	<   t          ||
          S )NrA   z%Expected role to be 'assistant', got  r=   r   r;   '"r3   )r2   rF   )r1   r   r4   r2   r3   popreplacer   )rI   r1   r2   rF   r3   functions_stringcorrected_functionss          r.   "_convert_TGI_message_to_LC_messagerR   b   s     =D; N N N3())G ((z 5*Q-
333":a=#<#@#@#M#MNN"2":":3"D"D5HJqM*%k2*4,'W8IJJJJr-   llmc                 R    	 ddl m} t          | |          S # t          $ r Y dS w xY w)Nr   )HuggingFaceHubF)(langchain_community.llms.huggingface_hubrU   rD   ImportError)rS   rU   s     r.   _is_huggingface_hubrX   t   sY    	
 	
 	
 	
 	
 	
 #~...   uu    
&&c                 R    	 ddl m} t          | |          S # t          $ r Y dS w xY w)Nr   )HuggingFaceTextGenInferenceF)7langchain_community.llms.huggingface_text_gen_inferencer[   rD   rW   )rS   r[   s     r.   !_is_huggingface_textgen_inferencer]      sZ    	
 	
 	
 	
 	
 	
 #:;;;   uurY   c                 ,    t          | t                    S N)rD   r!   rS   s    r.   _is_huggingface_endpointra          c.///r-   c                 ,    t          | t                    S r_   )rD   r"   r`   s    r.   _is_huggingface_pipelinerd      rb   r-   c                       e Zd ZU dZeed<   	  ee          Zeed<   dZ	eed<   dZ
ee         ed<   def fd	Z ed
          defd            ZdedefdZ	 	 d"dee         deee                  dee         dedef
dZ	 	 d"dee         deee                  dee         dedef
dZdee         defdZdedefdZededefd            Zd#dZ ddde!e"e#eef         e$e%e&f                  dee"eee'd         e(f                  dede)e*ef         f fdZ+dee         deee                  dee#eef                  fd Z,e-defd!            Z. xZ/S )$ChatHuggingFaceu  Hugging Face LLM's as ChatModels.

    Works with `HuggingFaceTextGenInference`, `HuggingFaceEndpoint`,
    `HuggingFaceHub`, and `HuggingFacePipeline` 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.

    Setup:
        Install ``langchain-huggingface`` and ensure your Hugging Face token
        is saved.

        .. code-block:: bash

            pip install langchain-huggingface

        .. code-block:: python

            from huggingface_hub import login
            login() # You will be prompted for your HF key, which will then be saved locally

    Key init args — completion params:
        llm: `HuggingFaceTextGenInference`, `HuggingFaceEndpoint`, `HuggingFaceHub`, or
            'HuggingFacePipeline' LLM to be used.

    Key init args — client params:
        custom_get_token_ids: Optional[Callable[[str], List[int]]]
            Optional encoder to use for counting tokens.
        metadata: Optional[Dict[str, Any]]
            Metadata to add to the run trace.
        tags: Optional[List[str]]
            Tags to add to the run trace.
        tokenizer: Any
        verbose: bool
            Whether to print out response text.

    See full list of supported init args and their descriptions in the params
    section.

    Instantiate:
        .. code-block:: python

            from langchain_huggingface import HuggingFaceEndpoint,
            ChatHuggingFace

            llm = HuggingFaceEndpoint(
                repo_id="microsoft/Phi-3-mini-4k-instruct",
                task="text-generation",
                max_new_tokens=512,
                do_sample=False,
                repetition_penalty=1.03,
            )

            chat = ChatHuggingFace(llm=llm, verbose=True)

    Invoke:
        .. code-block:: python

            messages = [
                ("system", "You are a helpful translator. Translate the user
                sentence to French."),
                ("human", "I love programming."),
            ]

            chat(...).invoke(messages)

        .. code-block:: python

            AIMessage(content='Je ai une passion pour le programme.

In
            French, we use "ai" for masculine subjects and "a" for feminine
            subjects. Since "programming" is gender-neutral in English, we
            will go with the masculine "programme".

Confirmation: "J'aime
            le programme." is more commonly used. The sentence above is
            technically accurate, but less commonly used in spoken French as
            "ai" is used less frequently in everyday speech.',
            response_metadata={'token_usage': ChatCompletionOutputUsage
            (completion_tokens=100, prompt_tokens=55, total_tokens=155),
            'model': '', 'finish_reason': 'length'},
            id='run-874c24b7-0272-4c99-b259-5d6d7facbc56-0')

    Stream:
        .. code-block:: python

            for chunk in chat.stream(messages):
                print(chunk)

        .. code-block:: python

            content='Je ai une passion pour le programme.

In French, we use
            "ai" for masculine subjects and "a" for feminine subjects.
            Since "programming" is gender-neutral in English,
            we will go with the masculine "programme".

Confirmation:
            "J'aime le programme." is more commonly used. The sentence
            above is technically accurate, but less commonly used in spoken
            French as "ai" is used less frequently in everyday speech.'
            response_metadata={'token_usage': ChatCompletionOutputUsage
            (completion_tokens=100, prompt_tokens=55, total_tokens=155),
            'model': '', 'finish_reason': 'length'}
            id='run-7d7b1967-9612-4f9a-911a-b2b5ca85046a-0'

    Async:
        .. code-block:: python

            await chat.ainvoke(messages)

        .. code-block:: python

            AIMessage(content='Je déaime le programming.

Littérale : Je
            (j'aime) déaime (le) programming.

Note: "Programming" in
            French is "programmation". But here, I used "programming" instead
            of "programmation" because the user said "I love programming"
            instead of "I love programming (in French)", which would be
            "J'aime la programmation". By translating the sentence
            literally, I preserved the original meaning of the user's
            sentence.', id='run-fd850318-e299-4735-b4c6-3496dc930b1d-0')

    Tool calling:
        .. code-block:: python

            from pydantic import BaseModel, Field

            class GetWeather(BaseModel):
                '''Get the current weather in a given location'''

                location: str = Field(..., description="The city and state,
                e.g. San Francisco, CA")

            class GetPopulation(BaseModel):
                '''Get the current population in a given location'''

                location: str = Field(..., description="The city and state,
                e.g. San Francisco, CA")

            chat_with_tools = chat.bind_tools([GetWeather, GetPopulation])
            ai_msg = chat_with_tools.invoke("Which city is hotter today and
            which is bigger: LA or NY?")
            ai_msg.tool_calls

        .. code-block:: python

            [{'name': 'GetPopulation',
              'args': {'location': 'Los Angeles, CA'},
              'id': '0'}]

    Response metadata
        .. code-block:: python

            ai_msg = chat.invoke(messages)
            ai_msg.response_metadata

        .. code-block:: python
            {'token_usage': ChatCompletionOutputUsage(completion_tokens=100,
            prompt_tokens=8, total_tokens=108),
             'model': '',
             'finish_reason': 'length'}

    rS   r2   system_messageN	tokenizermodel_idkwargsc                      t                      j        di | ddlm} |                                  | j        |                    | j                  n| j        | _        d S )Nr   )AutoTokenizerr,   )super__init__transformersrm   _resolve_model_idri   from_pretrainedrj   )selfrk   rm   	__class__s      r.   ro   zChatHuggingFace.__init__<  sv    ""6"""......    ~% ))$-888 	r-   after)moder6   c                     t          | j                  s`t          | j                  sLt          | j                  s8t	          | j                  s$t          dt          | j                             | S )NzyExpected llm to be one of HuggingFaceTextGenInference, HuggingFaceEndpoint, HuggingFaceHub, HuggingFacePipeline received )rX   rS   r]   ra   rd   	TypeErrortypers   s    r.   validate_llmzChatHuggingFace.validate_llmI  s     $DH--
	5dh??
	 -TX66
	 -TX66	
	 - NN- -  
 r-   responsec                    g }|j         d         j        }t          t          |j         d         j                  d|i          }|                    |           |j        }| j        j        }||d}t          ||          S )Nr   finish_reasonr5   generation_info)token_usagemodelgenerations
llm_output)
r%   r~   r   rR   r5   appendr&   rS   inference_server_urlr   )rs   r|   r   r~   genr   model_objectr   s           r.   _create_chat_resultz#ChatHuggingFace._create_chat_resultX  s     (+96x7G7J7RSS,m<
 
 
 	3nx4%0<HH
kjIIIIr-   messagesstoprun_managerc                    t          | j                  rD|                     ||          } | j        j        j        dd|i|}|                     |          S t          | j                  rD|                     ||          } | j        j        j        dd|i|}|                     |          S |                     |          } | j        j	        d|g||d|}| 
                    |          S Nr   )promptsr   r   r,   )r]   rS   _create_message_dictsclientchatr   ra   chat_completion_to_chat_prompt	_generate_to_chat_result	rs   r   r   r   rk   message_dictsanswer	llm_input
llm_results	            r.   r   zChatHuggingFace._generatee  s    -TX66 	4 66xFFM)TX_)KK=KFKKF++F333%dh// 		4 66xFFM4TX_4VVmVvVVF++F333,,X66I++ "$K KQ J ''
333r-   c                 P  K   t          | j                  rJ|                     ||          } | j        j        j        dd|i| d {V }|                     |          S |                     |          } | j        j        d|g||d| d {V }|                     |          S r   )	r]   rS   r   async_clientr   r   r   
_agenerater   r   s	            r.   r   zChatHuggingFace._agenerate{  s       -TX66 		4 66xFFM54805WW}WPVWWWWWWWWF++F333,,X66I2tx2  "$K   KQ         J ''
333r-   c                      |st          d          t          |d         t                    st          d           fd|D             } 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                 :    g | ]}                     |          S r,   )_to_chatml_format)r>   mrs   s     r.   r@   z3ChatHuggingFace._to_chat_prompt.<locals>.<listcomp>  s'    FFF$0033FFFr-   FT)tokenizeadd_generation_prompt)rG   rD   r   ri   apply_chat_template)rs   r   messages_dictss   `  r.   r   zChatHuggingFace._to_chat_prompt  s    
  	LJKKK(2,55 	ECDDDFFFFXFFF~11U$ 2 
 
 	
r-   r5   c                     t          |t                    rd}nOt          |t                    rd}n7t          |t                    rd}nt	          dt          |                     ||j        dS )z+Convert LangChain message to ChatML format.rB   rA   r9   zUnknown message type: r8   )rD   r   r   r   rG   ry   r2   )rs   r5   r1   s      r.   r   z!ChatHuggingFace._to_chatml_format  s     g}-- 	GDD++ 	GDD.. 	GDDEd7mmEEFFF999r-   r   c                     g }| j         d         D ]@}t          t          |j                  |j                  }|                    |           At          || j                  S )Nr   rg   r   r   )r   r   r   textr   r   r   r   )r   chat_generationsgchat_generations       r.   r   zChatHuggingFace._to_chat_result  s    '* 	5 	5A,!!&1111CT  O ##O4444(Z5J
 
 
 	
r-   c                    ddl m} t          | j                  s!t	          | j        d          r| j        j        r| j        j        | _        dS t          | j                  r| j        j        }n3t          | j                  r| j        j        | _        dS | j        j
        } |d          }|D ]}|j        |k    r|j        | _        | j        st          d| d          dS )z8Resolve the model_id from the LLM's inference_server_urlr   )list_inference_endpointsrepo_idN*zIFailed to resolve model_id:Could not find model id for inference server: zBMake sure that your Hugging Face token has access to the endpoint.)huggingface_hubr   rX   rS   hasattrr   rj   r]   r   rd   endpoint_urlurl
repositoryrG   )rs   r   r   available_endpointsendpoints        r.   rq   z!ChatHuggingFace._resolve_model_id  s     	=<<<<<tx(( 	1DHi((	1-1X-=	1 !H,DMF.tx88 	1*.(*GLL%dh// 	1 H-DMF80L66s;;+ 	4 	4H||++ ( 3} 	UAMU U U  	 	r-   )tool_choicetoolsr   autononec                0   d |D             }||rt          |          dk    r t          dt          |           d          t          |t                    r|dvrdd|id	}nt          |t                    r	|d
         }ntt          |t
                    rM|d
         d         d         |d         d         k    r(t          d| d|d
         d         d          d          nt          d|           ||d<    t                      j        dd|i|S )a*  Bind tool-like objects to this chat model.

        Assumes model is compatible with OpenAI tool-calling API.

        Args:
            tools: A list of tool definitions to bind to this chat model.
                Supports any tool definition handled by
                :meth:`langchain_core.utils.function_calling.convert_to_openai_tool`.
            tool_choice: Which tool to require the model to call.
                Must be the name of the single provided function or
                "auto" to automatically determine which function to call
                (if any), or a dict of the form:
                {"type": "function", "function": {"name": <<tool_name>>}}.
            **kwargs: Any additional parameters to pass to the
                :class:`~langchain.runnable.Runnable` constructor.
        c                 ,    g | ]}t          |          S r,   r   )r>   rC   s     r.   r@   z.ChatHuggingFace.bind_tools.<locals>.<listcomp>  s!    JJJD1$77JJJr-   N   zKWhen specifying `tool_choice`, you must provide exactly one tool. Received z tools.r   r;   r<   )ry   r;   r   zTool choice z/ was specified, but the only provided tool was .zEUnrecognized tool_choice type. Expected str, bool or dict. Received: r   r   r,   )lenrG   rD   r4   boolrE   rn   bind)rs   r   r   rk   formatted_toolsrt   s        r.   
bind_toolszChatHuggingFace.bind_tools  s   0 KJEJJJ"{"?##q(( D&)/&:&:D D D   +s++ &666 *%+[$9# #K K.. -a0K.. #A&z26:":.v67 7 %W{ W W-<Q-?
-KF-SW W W  7 !/!,/ /   %0F=!uww|<</<V<<<r-   c                     d |D             }|S )Nc                 ,    g | ]}t          |          S r,   )rH   )r>   r   s     r.   r@   z9ChatHuggingFace._create_message_dicts.<locals>.<listcomp>  s!    OOO9!<<OOOr-   r,   )rs   r   r   r   s       r.   r   z%ChatHuggingFace._create_message_dicts  s     POhOOOr-   c                     dS )Nzhuggingface-chat-wrapperr,   rz   s    r.   	_llm_typezChatHuggingFace._llm_type  s    ))r-   )NN)r6   N)0r'   r(   r)   r*   r   r+   r   DEFAULT_SYSTEM_PROMPTrh   ri   rj   r	   r4   ro   r   r    r{   r$   r   r   r   r   r   r   r   r   r   rE   r   staticmethodr   r   rq   r
   r   r   r   r   r   r   r   r   r   r   r   propertyr   __classcell__)rt   s   @r.   rf   rf      s`        ] ]~ 
HHH3 %2M:O$P$P$PNMPPPIs"Hhsm"""
 
 
 
 
 
 
 _'"""d    #"JL JZ J J J J  %):>	4 4{#4 tCy!4 67	4
 4 
4 4 4 42 %)?C	4 4{#4 tCy!4 ;<	4
 4 
4 4 4 4$
{#
 

 
 
 
": : : : : : 
I 
* 
 
 
 \
   B RV	6= 6= 6=d38ndHhFGH6= eD#w~/F$LMN	6=
 6= 
$k1	26= 6= 6= 6= 6= 6=p[)19$s)1D	d38n	    *3 * * * X* * * * *r-   rf   N)9r*   dataclassesr   typingr   r   r   r   r   r	   r
   r   r   r    langchain_core.callbacks.managerr   r   langchain_core.language_modelsr   *langchain_core.language_models.chat_modelsr   langchain_core.messagesr   r   r   r   r   r   langchain_core.outputsr   r   r   langchain_core.runnablesr   langchain_core.toolsr   %langchain_core.utils.function_callingr   pydanticr   typing_extensionsr    /langchain_huggingface.llms.huggingface_endpointr!   /langchain_huggingface.llms.huggingface_pipeliner"   r   r$   r0   rH   rR   r   rX   r]   ra   rd   rf   r,   r-   r.   <module>r      sU       ! ! ! ! ! !                               > = = = = = D D D D D D                I H H H H H H H H H - - - - - - ) ) ) ) ) ) H H H H H H $ $ $ $ $ $ " " " " " " O O O O O O O O O O O OR                 "8"8	"8 "8 "8 "8JKKK K K K$	S 	T 	 	 	 		3 	4 	 	 	 	0# 0$ 0 0 0 00# 0$ 0 0 0 0C* C* C* C* C*m C* C* C* C* C*r-   