a
    bgSV                     @   s  d dl Z d dl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mZ d dlZd dlmZmZ d dlmZ d dlmZmZ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$m%Z% d dl&m'Z'm(Z( d d	l)m*Z*m+Z+m,Z, d d
l-m.Z. d dl/m0Z0 d dl1m2Z2m3Z3m4Z4 d dl5m6Z6 d dl7m8Z8m9Z9m:Z:m;Z;m<Z< d dl=m>Z>m?Z? e@eAZBdZCeeDdddZEeeFef edddZGeeFef ee edddZHeeeFeFeedddZIG dd deZJdS )    N)asynccontextmanager)AnyAsyncIteratorCallableDictIteratorListMappingOptionalSequenceTypeUnion)AsyncCallbackManagerForLLMRunCallbackManagerForLLMRun)LanguageModelInput)BaseChatModelagenerate_from_streamgenerate_from_stream)	AIMessageAIMessageChunkBaseMessageBaseMessageChunkChatMessageChatMessageChunkHumanMessageHumanMessageChunkSystemMessageSystemMessageChunkToolMessage)make_invalid_tool_callparse_tool_call)ChatGenerationChatGenerationChunk
ChatResult)Runnable)BaseTool)convert_to_secret_strget_from_dict_or_envget_pydantic_field_namesconvert_to_openai_tool)	BaseModel
ConfigDictField	SecretStrmodel_validator))_lc_invalid_tool_call_to_openai_tool_call!_lc_tool_call_to_openai_tool_callz/https://api.baichuan-ai.com/v1/chat/completions)messagereturnc                 C   s   | j }t| tr| j|d}nt| tr4d|d}nt| trd|d}d| jv rb| jd |d< q| jsn| jrdd | jD dd | jD  |d< nNt| t	rd| j
|| jp| jd	d
}n$t| trd|d}ntd|  |S )N)rolecontentuser	assistant
tool_callsc                 S   s   g | ]}t |qS  )r1   .0Ztcr9   r9   v/var/www/html/cobodadashboardai.evdpl.com/venv/lib/python3.9/site-packages/langchain_community/chat_models/baichuan.py
<listcomp>V   s   z,_convert_message_to_dict.<locals>.<listcomp>c                 S   s   g | ]}t |qS r9   )r0   r:   r9   r9   r<   r=   X   s   toolname)r4   tool_call_idr5   r?   systemzGot unknown type )r5   
isinstancer   r4   r   r   additional_kwargsr8   invalid_tool_callsr   r@   r?   getr   	TypeError)r2   r5   Zmessage_dictr9   r9   r<   _convert_message_to_dictI   s6    







rG   )_dictr3   c           	      C   s  | d }|  dd}|dkr&t|dS |dkrg }g }i }|  d }r||d< |D ]T}z|t|dd	 W qT ty } z |t|t| W Y d }~qTd }~0 0 qTt||||d
S |dkri }d| v r| d |d< t||  d|dS |dkrt	|dS t
||dS d S )Nr4   r5    r6   r5   r7   r8   T)Z	return_id)r5   rC   r8   rD   r>   r?   r@   )r5   r@   rC   rA   r5   r4   )rE   r   appendr    	Exceptionr   strr   r   r   r   )	rH   r4   r5   r8   rD   rC   Zraw_tool_callsZraw_tool_caller9   r9   r<   _convert_dict_to_messagel   sF    


rP   )rH   default_classr3   c                 C   s   |  d}|  dpd}|dks(|tkr2t|dS |dksB|tkrLt|dS |dks\|tkrft|dS |sr|tkr~t||dS ||dS d S )	Nr4   r5   rI   r6   rJ   r7   rA   rK   )rE   r   r   r   r   )rH   rQ   r4   r5   r9   r9   r<   _convert_delta_to_message_chunk   s    



rR   )clientmethodurlkwargsr3   c              	   K  sb   ddl m} | j||fi |4 I dH  }||V  W d  I dH  q^1 I dH sT0    Y  dS )a  Async context manager for connecting to an SSE stream.

    Args:
        client: The httpx client.
        method: The HTTP method.
        url: The URL to connect to.
        kwargs: Additional keyword arguments to pass to the client.

    Yields:
        An EventSource object.
    r   )EventSourceN)Z	httpx_sserW   stream)rS   rT   rU   rV   rW   responser9   r9   r<   aconnect_httpx_sse   s    rZ   c                       s  e Zd ZU dZeeeef dddZeedddZ	e
eddZeed	< e
d
dZeed< dZee ed< dZeed< dZee ed< e
dddZeed< dZeed< e
ddZee ed< dZeed< dZeed< dZeed< e
edZeeef ed < ed!d"Z e!d#d$e"eeef ed%d&d'Z#e!d#d$e"eed%d(d)Z$eeeef dd*d+Z%dFe&e' ee&e  ee( ee)d,d-d.Z*dGe&e' ee&e  ee( ee+e, d,d/d0Z-dHe&e' ee&e  ee. ee ee)d1d2d3Z/dIe&e' ee&e  ee. ee0e, d,d4d5Z1e&e' ee2j3d6d7d8Z4e&e' eeef d9d:d;Z5eeef dd<d=Z6e7eef e)d>d?d@Z8eeddAdBZ9e:e;eeef e<e= e>e?f  ee@eAe'f dC fdDdEZB  ZCS )JChatBaichuanu  Baichuan chat model integration.

    Setup:
        To use, you should have the environment variable``BAICHUAN_API_KEY`` set with
    your API KEY.

        .. code-block:: bash

            export BAICHUAN_API_KEY="your-api-key"

    Key init args — completion params:
        model: Optional[str]
            Name of Baichuan model to use.
        max_tokens: Optional[int]
            Max number of tokens to generate.
        streaming: Optional[bool]
            Whether to stream the results or not.
        temperature: Optional[float]
            Sampling temperature.
        top_p: Optional[float]
            What probability mass to use.
        top_k: Optional[int]
            What search sampling control to use.

    Key init args — client params:
        api_key: Optional[str]
            Baichuan API key. If not passed in will be read from env var BAICHUAN_API_KEY.
        base_url: Optional[str]
            Base URL for API requests.

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

    Instantiate:
        .. code-block:: python

            from langchain_community.chat_models import ChatBaichuan

            chat = ChatBaichuan(
                api_key=api_key,
                model='Baichuan4',
                # temperature=...,
                # other params...
            )

    Invoke:
        .. code-block:: python

            messages = [
                ("system", "你是一名专业的翻译家，可以将用户的中文翻译为英文。"),
                ("human", "我喜欢编程。"),
            ]
            chat.invoke(messages)

        .. code-block:: python

            AIMessage(
                content='I enjoy programming.',
                response_metadata={
                    'token_usage': {
                        'prompt_tokens': 93,
                        'completion_tokens': 5,
                        'total_tokens': 98
                    },
                    'model': 'Baichuan4'
                },
                id='run-944ff552-6a93-44cf-a861-4e4d849746f9-0'
            )

    Stream:
        .. code-block:: python

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

        .. code-block:: python

            content='I' id='run-f99fcd6f-dd31-46d5-be8f-0b6a22bf77d8'
            content=' enjoy programming.' id='run-f99fcd6f-dd31-46d5-be8f-0b6a22bf77d8

        .. code-block:: python

            stream = chat.stream(messages)
            full = next(stream)
            for chunk in stream:
                full += chunk
            full

        .. code-block:: python

            AIMessageChunk(
                content='I like programming.',
                id='run-74689970-dc31-461d-b729-3b6aa93508d2'
            )

    Async:
        .. code-block:: python

            await chat.ainvoke(messages)

            # stream
            # async for chunk in chat.astream(messages):
            #     print(chunk)

            # batch
            # await chat.abatch([messages])

        .. code-block:: python

            AIMessage(
                content='I enjoy programming.',
                response_metadata={
                    'token_usage': {
                        'prompt_tokens': 93,
                        'completion_tokens': 5,
                        'total_tokens': 98
                    },
                    'model': 'Baichuan4'
                },
                id='run-952509ed-9154-4ff9-b187-e616d7ddfbba-0'
            )
    Tool calling:

        .. code-block:: python
            class get_current_weather(BaseModel):
                '''Get current weather.'''

                location: str = Field('City or province, such as Shanghai')


            llm_with_tools = ChatBaichuan(model='Baichuan3-Turbo').bind_tools([get_current_weather])
            llm_with_tools.invoke('How is the weather today?')

        .. code-block:: python

            [{'name': 'get_current_weather',
            'args': {'location': 'New York'},
            'id': '3951017OF8doB0A',
            'type': 'tool_call'}]

    Response metadata
        .. code-block:: python

            ai_msg = chat.invoke(messages)
            ai_msg.response_metadata

        .. code-block:: python

            {
                'token_usage': {
                    'prompt_tokens': 93,
                    'completion_tokens': 5,
                    'total_tokens': 98
                },
                'model': 'Baichuan4'
            }

    )r3   c                 C   s   ddiS )Nbaichuan_api_keyBAICHUAN_API_KEYr9   selfr9   r9   r<   
lc_secrets[  s    zChatBaichuan.lc_secretsc                 C   s   dS )NTr9   r^   r9   r9   r<   lc_serializablea  s    zChatBaichuan.lc_serializablebase_url)defaultaliasbaichuan_api_baseapi_key)rd   r\   Nbaichuan_secret_keyF	streaming
max_tokens<   timeoutrequest_timeoutzBaichuan2-Turbo-192Kmodel333333?)rc   temperature   top_k333333?top_pwith_search_enhance)default_factorymodel_kwargsT)Zpopulate_by_namebefore)mode)valuesr3   c              
   C   s   t | }|di }t|D ]P}||v r8td| d||vrtd| d| d| d ||||< q|| }|rtd| d	||d< |S )
z>Build extra kwargs from additional params that were passed in.rv   zFound z supplied twice.z	WARNING! z/ is not default parameter.
                    zJ was transferred to model_kwargs.
                    Please confirm that z is what you intended.zParameters za should be specified explicitly. Instead they were passed in as part of `model_kwargs` parameter.)	r(   rE   list
ValueErrorloggerwarningpopintersectionkeys)clsry   Zall_required_field_namesextra
field_nameZinvalid_model_kwargsr9   r9   r<   build_extra  s*    
zChatBaichuan.build_extrac                 C   s.   t |ddt|d< tt |ddgd|d< |S )Nre   ZBAICHUAN_API_BASEr\   rf   r]   )r'   DEFAULT_API_BASEr&   )r   ry   r9   r9   r<   validate_environment  s    z!ChatBaichuan.validate_environmentc                 C   s,   | j | j| j| j| j| jd}i || jS )z4Get the default parameters for calling Baichuan API.)rm   ro   rs   rq   rX   ri   )rm   ro   rs   rq   rh   ri   rv   )r_   Znormal_paramsr9   r9   r<   _default_params  s    	zChatBaichuan._default_params)messagesstoprun_managerrV   r3   c                 K   sb   | j r&| jf |||d|}t|S | j|fi |}|jdkrPtd| | }| |S )N)r   r   r      "Error from Baichuan api response: )rh   _streamr   _chatstatus_coder{   json_create_chat_result)r_   r   r   r   rV   stream_iterresrY   r9   r9   r<   	_generate  s    
zChatBaichuan._generatec                 k   s   | j |fddi|}|jdkr.td| t}| D ]}|dd}|dd}t|dkrn|d nd }|d u r|q:|d	kr qt	
|}	|	d
D ]>}
t|
d|}|j}t|d}|r|j|j|d |V  qq:d S )NrX   Tr   r   zutf-8z
zdata:    z[DONE]choicesdeltar2   chunk)r   r   r{   r   
iter_linesdecodestripsplitlenr   loadsrE   rR   	__class__r"   on_llm_new_tokenr5   )r_   r   r   r   rV   r   Zdefault_chunk_classr   partsrY   mZcg_chunkr9   r9   r<   r     s,    



zChatBaichuan._stream)r   r   r   rX   rV   r3   c              	      s   |d ur|n| j }|r<| j|f||d|}t|I d H S | jf i |}| j|fi |}	dd l}
|
j|| jd4 I d H 4}|j| j	|	dI d H }|
  W d   I d H  q1 I d H s0    Y  | | S )N)r   r   r   headersrk   r   )rh   _astreamr   _create_headers_parameters_create_payload_parametershttpxAsyncClientrl   postre   raise_for_statusr   r   )r_   r   r   r   rX   rV   Zshould_streamr   r   payloadr   rS   rY   r9   r9   r<   
_agenerate  s(    2zChatBaichuan._ageneratec              
   K  sp  | j f i |}| j|fddi|}dd l}|j|| jd4 I d H }t|d| j|d4 I d H }	|	 2 z3 d H W }
t	|
j
}t|d dkrqn|d d }t|d t}|d	d }|d urd	|ind }t||d
}|r|j|j|dI d H  |V  |d urn qqn6 W d   I d H  q>1 I d H s40    Y  W d   I d H  ql1 I d H sb0    Y  d S )NrX   Tr   r   POSTr   r   r   finish_reason)r2   generation_infor   )r   r   r   r   rl   rZ   re   Z	aiter_sser   r   datar   rR   r   rE   r"   r   text)r_   r   r   r   rV   r   r   r   rS   Zevent_sourceZsser   choicer   r   r9   r9   r<   r     s@    

zChatBaichuan._astream)r   rV   r3   c                 K   sD   | j |fi |}| j}| jf i |}tj|| j||| jd}|S )N)rU   rk   r   r   rX   )r   re   r   requestsr   rl   rh   )r_   r   rV   r   rU   r   r   r9   r9   r<   r   4  s    zChatBaichuan._chat)r   r3   c              	   K   s   i | j |}|dd}|dd}|dd}|d}|dd	}|d
d	}	|dg }
|dd |D |||||	|
d}|S )Nro   rn   rq   rp   rs   rr   rm   rt   FrX   toolsc                 S   s   g | ]}t |qS r9   )rG   )r;   r   r9   r9   r<   r=   P      z;ChatBaichuan._create_payload_parameters.<locals>.<listcomp>)rm   r   rq   rs   ro   rt   rX   r   )r   r~   )r_   r   rV   
parametersro   rq   rs   rm   rt   rX   r   r   r9   r9   r<   r   B  s$    
z'ChatBaichuan._create_payload_parametersc                 K   sF   i | j |}|di }d}| jr.| j }dd| d|}|S )Nr   rI   zapplication/jsonzBearer )zContent-TypeAuthorization)r   r~   r\   Zget_secret_value)r_   rV   r   default_headersrf   r   r9   r9   r<   r   [  s    
z'ChatBaichuan._create_headers_parameters)rY   r3   c                 C   sR   g }|d D ]$}t |d }t|d}|| q|d }|| jd}t||dS )Nr   r2   r   usage)token_usagerm   )generations
llm_output)rP   r!   rL   rm   r#   )r_   rY   r   cr2   genr   r   r9   r9   r<   r   i  s    
z ChatBaichuan._create_chat_resultc                 C   s   dS )Nzbaichuan-chatr9   r^   r9   r9   r<   	_llm_typet  s    zChatBaichuan._llm_type)r   rV   r3   c                    s$   dd |D }t  jf d|i|S )a  Bind tool-like objects to this chat model.

        Args:
            tools: A list of tool definitions to bind to this chat model.
                Can be a dictionary, pydantic model, callable, or BaseTool.
                Pydantic
                models, callables, and BaseTools will be automatically converted to
                their schema dictionary representation.
            **kwargs: Any additional parameters to pass to the
                :class:`~langchain.runnable.Runnable` constructor.
        c                 S   s   g | ]}t |qS r9   r)   )r;   r>   r9   r9   r<   r=     r   z+ChatBaichuan.bind_tools.<locals>.<listcomp>r   )superbind)r_   r   rV   Zformatted_toolsr   r9   r<   
bind_toolsx  s    zChatBaichuan.bind_tools)NN)NN)NNN)NN)D__name__
__module____qualname____doc__propertyr   rN   r`   boolra   r-   r   re   __annotations__r\   r.   rg   r
   rh   ri   intrl   rm   ro   floatrq   rs   rt   dictrv   r   r,   Zmodel_configr/   classmethodr   r   r   r   r   r   r#   r   r   r"   r   r   r   r   r   r   Responser   r   r   r	   r   r   r   r   r   r+   r   r%   r$   r   r   __classcell__r9   r9   r   r<   r[      s   
   
  
!   
  
)

r[   )Kr   logging
contextlibr   typingr   r   r   r   r   r   r	   r
   r   r   r   r   Zlangchain_core.callbacksr   r   Zlangchain_core.language_modelsr   Z*langchain_core.language_models.chat_modelsr   r   r   Zlangchain_core.messagesr   r   r   r   r   r   r   r   r   r   r   Z*langchain_core.output_parsers.openai_toolsr   r    Zlangchain_core.outputsr!   r"   r#   Zlangchain_core.runnablesr$   Zlangchain_core.toolsr%   Zlangchain_core.utilsr&   r'   r(   Z%langchain_core.utils.function_callingr*   Zpydanticr+   r,   r-   r.   r/   Z(langchain_community.chat_models.llamacppr0   r1   	getLoggerr   r|   r   r   rG   rN   rP   rR   rZ   r[   r9   r9   r9   r<   <module>   s8   44
#*