U
    h;                     @  sr  d Z ddlmZ ddl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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%m&Z& dd	l'm(Z(m)Z)m*Z* dd
l+m,Z,m-Z-m.Z.m/Z/ ddl0m1Z1m2Z2m3Z3m4Z4m5Z5 e6e7Z8dddddZ9ddddddZ:ddddddZ;dddddZ<ddd d!d"Z=G d#d deZ>dS )$zJinaChat wrapper.    )annotationsN)AnyAsyncIteratorCallableDictIteratorListMappingOptionalTupleTypeUnion)AsyncCallbackManagerForLLMRunCallbackManagerForLLMRun)BaseChatModelagenerate_from_streamgenerate_from_stream)	AIMessageAIMessageChunkBaseMessageBaseMessageChunkChatMessageChatMessageChunkFunctionMessageHumanMessageHumanMessageChunkSystemMessageSystemMessageChunk)ChatGenerationChatGenerationChunk
ChatResult)Field	SecretStrroot_validator)convert_to_secret_strget_from_dict_or_envget_pydantic_field_namespre_init)before_sleep_logretryretry_if_exception_typestop_after_attemptwait_exponentialJinaChatCallable[[Any], Any])llmreturnc                 C  sr   dd l }d}d}tdt| jtd||dt|jjt|jjB t|jj	B t|jj
B t|jjB tttjdS Nr      <   T)Z
multiplierminmax)reraisestopwaitr)   Zbefore_sleepopenair)   r+   max_retriesr,   r*   errorTimeoutZAPIErrorZAPIConnectionErrorZRateLimitErrorZServiceUnavailableErrorr(   loggerloggingWARNING)r/   r:   min_secondsmax_seconds rC   L/tmp/pip-unpacked-wheel-9gdii04g/langchain_community/chat_models/jinachat.py_create_retry_decorator=   s$    





rE   r   )r/   kwargsr0   c                   s0   t  }|ddd fdd}|f |I dH S )z0Use tenacity to retry the async completion call.r   rF   r0   c                    s    j jf | I d H S N)clientZacreaterF   r/   rC   rD   _completion_with_retryW   s    z6acompletion_with_retry.<locals>._completion_with_retryNrE   )r/   rF   retry_decoratorrL   rC   rK   rD   acompletion_with_retryS   s    rO   Mapping[str, Any]zType[BaseMessageChunk]r   )_dictdefault_classr0   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 )	Nrolecontent userrT   	assistantsystemrT   rS   )getr   r   r   r   )rQ   rR   rS   rT   rC   rC   rD   _convert_delta_to_message_chunk_   s    



r\   r   )rQ   r0   c                 C  sf   | d }|dkrt | d dS |dkr<| d p0d}t|dS |dkrRt| d dS t| d |dS d S )	NrS   rV   rT   rW   rX   rU   rY   rZ   )r   r   r   r   )rQ   rS   rT   rC   rC   rD   _convert_dict_to_messageq   s    
r]   dict)messager0   c                 C  s   t | tr| j| jd}nrt | tr2d| jd}nZt | trJd| jd}nBt | trbd| jd}n*t | tr~d| j| jd}nt	d|  d| j
kr| j
d |d< |S )	N)rS   rT   rV   rX   rY   function)rS   namerT   zGot unknown type ra   )
isinstancer   rS   rT   r   r   r   r   ra   
ValueErrorZadditional_kwargs)r_   Zmessage_dictrC   rC   rD   _convert_message_to_dict~   s"    





rd   c                   @  s  e Zd ZU dZeddddZeddddZd	ed
< dZ	ded< e
edZded< dZded< dZded< dZded< dZded< dZded< G dd dZedd ddd!d"d#Zed$d$d!d%d&Zeddd'd(Zd)dd*d+Zd	d	d,d-d.Zd/d0d1d2d3ZdQd4d5d6d	d7d8d9d:ZdRd4d5d6d	d;d8d<d=Zd4d5d>d?d@dAZdBd;dCdDdEZdSd4d5dFd	dGd8dHdIZdTd4d5dFd	d;d8dJdKZ edBddLdMZ!edNddOdPZ"dS )Ur-   a  `Jina AI` Chat models API.

    To use, you should have the ``openai`` python package installed, and the
    environment variable ``JINACHAT_API_KEY`` set to your API key, which you
    can generate at https://chat.jina.ai/api.

    Any parameters that are valid to be passed to the openai.create call can be passed
    in, even if not explicitly saved on this class.

    Example:
        .. code-block:: python

            from langchain_community.chat_models import JinaChat
            chat = JinaChat()
    zDict[str, str])r0   c                 C  s   ddiS )Njinachat_api_keyJINACHAT_API_KEYrC   selfrC   rC   rD   
lc_secrets   s    zJinaChat.lc_secretsboolc                 C  s   dS )z9Return whether this model can be serialized by Langchain.FrC   )clsrC   rC   rD   is_lc_serializable   s    zJinaChat.is_lc_serializabler   rI   gffffff?floattemperature)default_factoryzDict[str, Any]model_kwargsNzOptional[SecretStr]re   z+Optional[Union[float, Tuple[float, float]]]request_timeout   intr;   F	streamingzOptional[int]
max_tokensc                   @  s   e Zd ZdZdS )zJinaChat.ConfigTN)__name__
__module____qualname__Zallow_population_by_field_namerC   rC   rC   rD   Config   s   ry   T)pre)valuesr0   c              
   C  s   t | }|di }t|D ]P}||kr8td| d||krtd| d| d| d ||||< q|| }|rtd| d	||d< |S )
z>Build extra kwargs from additional params that were passed in.rp   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&   r[   listrc   r>   warningpopintersectionkeys)rk   r{   Zall_required_field_namesextra
field_nameZinvalid_model_kwargsrC   rC   rD   build_extra   s"    
zJinaChat.build_extrar   c                 C  sn   t t|dd|d< zddl}W n tk
r<   tdY nX z|j|d< W n tk
rh   tdY nX |S )z?Validate that api key and python package exists in environment.re   rf   r   NzTCould not import openai python package. Please install it with `pip install openai`.rI   z`openai` has no `ChatCompletion` attribute, this is likely due to an old version of the openai package. Try upgrading it with `pip install --upgrade openai`.)r$   r%   r:   ImportErrorZChatCompletionAttributeErrorrc   )rk   r{   r:   rC   rC   rD   validate_environment   s     


zJinaChat.validate_environmentc                 C  s   | j | j| j| jd| jS )z4Get the default parameters for calling JinaChat API.)rq   ru   streamrn   )rq   ru   rt   rn   rp   rg   rC   rC   rD   _default_params   s    zJinaChat._default_paramsr.   c                 C  sr   dd l }d}d}tdt| jtd||dt|jjt|jjB t|jj	B t|jj
B t|jjB tttjdS r1   r9   )rh   r:   rA   rB   rC   rC   rD   rE      s$    





z JinaChat._create_retry_decoratorrG   c                   s*      }|ddd fdd}|f |S )z*Use tenacity to retry the completion call.r   rG   c                    s    j jf | S rH   )rI   createrJ   rg   rC   rD   rL     s    z>JinaChat.completion_with_retry.<locals>._completion_with_retryrM   )rh   rF   rN   rL   rC   rg   rD   completion_with_retry  s    zJinaChat.completion_with_retryzList[Optional[dict]]r^   )llm_outputsr0   c                 C  s\   i }|D ]J}|d krq|d }|  D ]*\}}||krH||  |7  < q&|||< q&qd|iS )Ntoken_usage)items)rh   r   Zoverall_token_usageoutputr   kvrC   rC   rD   _combine_llm_outputs  s    zJinaChat._combine_llm_outputszList[BaseMessage]zOptional[List[str]]z"Optional[CallbackManagerForLLMRun]zIterator[ChatGenerationChunk])messagesr7   run_managerrF   r0   c                 k  s   |  ||\}}||ddi}t}| jf d|i|D ]H}|d d d }	t|	|}|j}t|d}
|rx|j|j|
d |
V  q6d S 	Nr   Tr   choicesr   deltar_   )chunk)_create_message_dictsr   r   r\   	__class__r   on_llm_new_tokenrT   rh   r   r7   r   rF   message_dictsparamsZdefault_chunk_classr   r   Zcg_chunkrC   rC   rD   _stream,  s    

zJinaChat._streamr    c           	      K  s\   | j r&| jf |||d|}t|S | ||\}}||}| jf d|i|}| |S N)r   r7   r   r   )rt   r   r   r   r   _create_chat_result	rh   r   r7   r   rF   Zstream_iterr   r   responserC   rC   rD   	_generate@  s      zJinaChat._generatez+Tuple[List[Dict[str, Any]], Dict[str, Any]])r   r7   r0   c                 C  s@   t | j}|d k	r*d|kr"td||d< dd |D }||fS )Nr7   z2`stop` found in both the input and default params.c                 S  s   g | ]}t |qS rC   )rd   ).0mrC   rC   rD   
<listcomp>Z  s     z2JinaChat._create_message_dicts.<locals>.<listcomp>)r^   _invocation_paramsrc   )rh   r   r7   r   r   rC   rC   rD   r   R  s    
zJinaChat._create_message_dictsrP   )r   r0   c                 C  sJ   g }|d D ]$}t |d }t|d}|| qd|d i}t||dS )Nr   r_   r   r   usage)generations
llm_output)r]   r   appendr    )rh   r   r   resr_   genr   rC   rC   rD   r   ]  s    
zJinaChat._create_chat_resultz'Optional[AsyncCallbackManagerForLLMRun]z"AsyncIterator[ChatGenerationChunk]c                 K s   |  ||\}}||ddi}t}t| fd|i|I d H 2 zV3 d H W }|d d d }	t|	|}|j}t|d}
|r|j|j|
dI d H  |
V  q<6 d S r   )r   r   rO   r\   r   r   r   rT   r   rC   rC   rD   _astreamf  s"    

zJinaChat._astreamc           	        sh   | j r,| jf |||d|}t|I d H S | ||\}}||}t| fd|i|I d H }| |S r   )rt   r   r   r   rO   r   r   rC   rC   rD   
_agenerate|  s      zJinaChat._ageneratec                 C  s"   | j o| j  ddd}|| jS )z,Get the parameters used to invoke the model.zhttps://api.chat.jina.ai/v1jinachat)Zapi_keyZapi_basemodel)re   Zget_secret_valuer   )rh   Zjinachat_credsrC   rC   rD   r     s    zJinaChat._invocation_paramsstrc                 C  s   dS )zReturn type of chat model.r   rC   rg   rC   rC   rD   	_llm_type  s    zJinaChat._llm_type)NN)NN)NN)NN)#rv   rw   rx   __doc__propertyri   classmethodrl   __annotations__rn   r!   r^   rp   re   rq   r;   rt   ru   ry   r#   r   r'   r   r   rE   r   r   r   r   r   r   r   r   r   r   rC   rC   rC   rD   r-      sR   


        
)?r   
__future__r   r?   typingr   r   r   r   r   r   r	   r
   r   r   r   Zlangchain_core.callbacksr   r   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.outputsr   r   r    Zlangchain_core.pydantic_v1r!   r"   r#   Zlangchain_core.utilsr$   r%   r&   r'   Ztenacityr(   r)   r*   r+   r,   	getLoggerrv   r>   rE   rO   r\   r]   rd   r-   rC   rC   rC   rD   <module>   s"   44
