o
    ZhM                  	   @   s  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mZ d dlZd dlmZ d dl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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* d d
l+m,Z,m-Z-m.Z.m/Z/m0Z0 d dl1m2Z2 dZ3e 4e5Z6dedee defddZ7dedee8ef fddZ9dedefddZ:dedefddZ;dee dee fddZ<dej=ddfdd Z>dej=ddfd!d"Z?G d#d$ d$eZ@	d)d%e@d&e	eeef  deegef fd'd(ZAdS )*    N)AnyAsyncContextManagerAsyncIteratorCallableDictIteratorListOptionalTupleTypeUnioncast)SSEError)AsyncCallbackManagerForLLMRunCallbackManagerForLLMRun)BaseChatModelLangSmithParams)create_base_retry_decorator)
	AIMessageAIMessageChunkBaseMessageBaseMessageChunkChatMessageChatMessageChunkHumanMessageHumanMessageChunkSystemMessageSystemMessageChunk)ChatGenerationChatGenerationChunk
ChatResult)convert_to_secret_strget_from_env)AliasChoices
ConfigDictField	SecretStrmodel_validator)Selfz%https://clovastudio.stream.ntruss.comssedefault_classreturnc                 C   s   |   }| jdkrt|}td|dS |d}|d}|dp#d}|dks,|tkr1t|dS |d	ks9|tkr>t|dS |d
ksF|tkrKt|dS |sQ|tkrWt||dS ||dS )Nresult )contentresponse_metadatamessageroler.   user)r.   	assistantsystem)r.   r1   )jsonevent_sse_data_to_response_metadatar   getr   r   r   )r)   r*   sse_datar/   r0   r1   r.    r:   \/var/www/html/lang_env/lib/python3.10/site-packages/langchain_community/chat_models/naver.py_convert_chunk_to_message_chunk5   s    






r<   r9   c                 C   sl   i }d| v r| d |d< d| v r| d |d< d| v r | d |d< d| v r*| d |d< d| v r4| d |d	< |S )
N
stopReasonstop_reasoninputLengthinput_lengthoutputLengthoutput_lengthseedaiFilter	ai_filterr:   )r9   r/   r:   r:   r;   r7   L   s   r7   r0   c                 C   sz   t | trt| j| jdS t | trtd| jdS t | tr%td| jdS t | tr1td| jdS t	d t
d|  )N)r1   r.   r2   r4   r3   zmFunctionMessage, ToolMessage not yet supported (https://api.ncloud-docs.com/docs/clovastudio-chatcompletions)zGot unknown type )
isinstancer   dictr1   r.   r   r   r   loggerwarning
ValueErrorr0   r:   r:   r;   &_convert_message_to_naver_chat_message[   s   



rL   _messagec                 C   s   | d }|dv sJ d| t t| d }i }|dkr"t||dS |dkr,t||dS |dkr6t||dS td	| td
| )Nr1   )r3   r4   r2   z7Expected role to be 'assistant', 'system', 'user', got r.   r2   )r.   additional_kwargsr4   r3   zGot unknown role %szGot unknown role )r   strr   r   r   rH   rI   rJ   )rM   r1   r.   rN   r:   r:   r;   &_convert_naver_chat_message_to_messagen   s.   
rP   event_source_mgrc              	   C  s   | 4 I dH K}t |jI dH  | 2 z13 dH W }| }|jdkr7|di dkr7 W d  I dH  dS |jdkrBt|jd|V  q6 W d  I dH  dS 1 I dH sXw   Y  dS )z$Iterate over the server-sent events.Nsignaldata[DONE]errorrK   )_araise_on_errorresponseZ	aiter_sser5   r6   r8   r   rS   )rQ   event_sourcer)   
event_datar:   r:   r;   
_aiter_sse   s   
.rZ   rW   c                 C   sH   t j| jr"|  d}t jd| j d| j d| | j| ddS )+Raise an error if the response is an error.utf-8Error response  while fetching : requestrW   N)	httpxcodesis_errorstatus_codereaddecodeHTTPStatusErrorurlra   rW   error_messager:   r:   r;   _raise_on_error   s   
rl   c                    sP   t j| jr&|  I dH d}t jd| j d| j d| | j| ddS )r[   Nr\   r]   r^   r_   r`   )	rb   rc   rd   re   Zareadrg   rh   ri   ra   rj   r:   r:   r;   rV      s   
rV   c                       s"  e Zd ZU dZeddZeej e	d< eddZ
eej e	d< ededdd	d
Zee	d< edddZee e	d< edddZee	d< edddZee e	d< 	 edddZee e	d< 	 edddZee	d< 	 eddddZee e	d< eddddZee e	d < eddd!dZee e	d"< edd#d$dZee e	d%< edd&d'dZee e	d(< edd)dZeee  e	d*< eddZee e	d+< edd,ddZ ee e	d-< edd.d/Z!ee	d0< ed1d2d3Z"ee	d4< e#d5d6d7Z$e%d8e&ee'f fd9d:Z(e%d8e&ee'f fd;d<Z)e%d8e&eef fd=d>Z*e%d8efd?d@Z+	ded)ee,e  dAe'd8e-f fdBdCZ.e%d8e&ee'f fdDdEZ/e%d8efdFdGZ0e1dHdId8e2fdJdKZ3d8efdLdMZ4dfdNdOZ5d8e&ee'f fdPdQZ6dRe,e7 d)ee,e  d8e8e,e& e&ee'f f fdSdTZ9dAe'd8e'fdUdVZ:	dedWee; dAe'd8e'fdXdYZ<dZe&d8e=fd[d\Z>		dgdRe,e7 d)ee,e  dWee? dAe'd8e=f
d]d^Z@		dgdRe,e7 d)ee,e  dWee? dAe'd8eAeB f
d_d`ZC		dgdRe,e7 d)ee,e  dWee; dAe'd8e=f
dadbZD		dgdRe,e7 d)ee,e  dWee; dAe'd8eEeB f
dcddZF  ZGS )h
ChatClovaXa  `NCP ClovaStudio` Chat Completion API.

    following environment variables set or passed in constructor in lower case:
    - ``NCP_CLOVASTUDIO_API_KEY``
    - ``NCP_APIGW_API_KEY``

    Example:
        .. code-block:: python

            from langchain_core.messages import HumanMessage

            from langchain_community import ChatClovaX

            model = ChatClovaX()
            model.invoke([HumanMessage(content="Come up with 10 names for a song about parrots.")])
    N)defaultclientasync_clientzHCX-003
model_namemodelzNCP ClovaStudio chat model name)rn   Zvalidation_aliasdescriptionz*NCP Clova Studio chat model tuning task ID)rn   rs   task_idFz=false: use testapp, true: use service app on NCP Clova Studioservice_appZapi_key)rn   aliasncp_clovastudio_api_keyapigw_api_keyncp_apigw_api_keyr-   base_urlg        g      ?g      ?)gtlern   temperaturer      )ger|   rn   top_kg?top_p
   g      @repeat_penaltyi   d   
max_tokensstopstop_beforeinclude_ai_filtersl    rC   Z   )r{   rn   timeout      )r   rn   max_retriesTr:   )Zpopulate_by_nameZprotected_namespacesr+   c              	   C   s<   | j | j| j| j| j| j| j| jd}dd | D }|S )z/Get the default parameters for calling the API.)r}   ZtopKZtopPZrepeatPenaltyZ	maxTokens
stopBeforeZincludeAiFiltersrC   c                 S   s   i | ]\}}|d ur||qS Nr:   ).0kvr:   r:   r;   
<dictcomp>   s    z.ChatClovaX._default_params.<locals>.<dictcomp>)	r}   r   r   r   r   r   r   rC   items)selfdefaultsfilteredr:   r:   r;   _default_params   s   
zChatClovaX._default_paramsc                 C   s   | j | jd< | jS )zGet the identifying parameters.rq   )rq   r   r   r:   r:   r;   _identifying_params   s   zChatClovaX._identifying_paramsc                 C   s   |   sddiS dddS )Nrw   NCP_CLOVASTUDIO_API_KEYNCP_APIGW_API_KEY)rw   ry   )_is_new_api_keyr   r:   r:   r;   
lc_secrets  s   zChatClovaX.lc_secretsc                 C   s   dS )zReturn type of chat model.z
chat-naverr:   r   r:   r:   r;   	_llm_type  s   zChatClovaX._llm_typekwargsc                    s"   t  jdd|i|}d|d< |S )z,Get the parameters used to invoke the model.r   ZnaverZls_providerNr:   )super_get_ls_params)r   r   r   params	__class__r:   r;   r     s   zChatClovaX._get_ls_paramsc                 C   s   | j S )z'Get the parameters used for the client.)r   r   r:   r:   r;   _client_params  s   zChatClovaX._client_paramsc                 C   sF   | j rdnd}| jr| j d| d| j dS | j d| d| j S )zGET chat completion api urlZ
serviceappZtestapp/z
/v1/tasks/z/chat-completionsz/v1/chat-completions/)ru   rt   rz   rq   )r   Zapp_typer:   r:   r;   _api_url$  s
   zChatClovaX._api_urlafter)modec                 C   s   | j s
| js
td| jsttdd| _|  s|   | js'tddt	| _| j
s7tj| j|  | jd| _
| jsGtj| j|  | jd| _| S )Nz6either model_name or task_id must be assigned a value.rw   r   rz   ZNCP_CLOVASTUDIO_API_BASE_URL)rz   headersr   )rq   rt   rJ   rw   r!   r"   r   _init_fields_on_old_api_keyrz   _DEFAULT_BASE_URLro   rb   Clientdefault_headersr   rp   AsyncClientr   r:   r:   r;   validate_model_after0  s2   zChatClovaX.validate_model_afterc                 C   s   | j r| j  dS dS )Nznv-F)rw   get_secret_value
startswithr   r:   r:   r;   r   R  s   zChatClovaX._is_new_api_keyc                 C   s    | j sttddd| _ d S d S )Nry   r   r-   )ry   r!   r"   r   r:   r:   r;   r   X  s
   

z&ChatClovaX._init_fields_on_old_api_keyc                 C   sh   ddd}| j r| j  nd }|  rd| |d< |S |r"||d< | jr*| j nd }|r2||d< |S )Nzapplication/json)zContent-TypeAcceptzBearer AuthorizationzX-NCP-CLOVASTUDIO-API-KEYzX-NCP-APIGW-API-KEY)rw   r   r   ry   )r   r   Zclovastudio_api_keyrx   r:   r:   r;   r   ^  s&   zChatClovaX.default_headersmessagesc                 C   s4   | j }|d urd|v r||d< dd |D }||fS )Nr   c                 S   s   g | ]}t |qS r:   )rL   )r   mr:   r:   r;   
<listcomp>  s    z4ChatClovaX._create_message_dicts.<locals>.<listcomp>)r   )r   r   r   r   message_dictsr:   r:   r;   _create_message_dicts|  s
   z ChatClovaX._create_message_dictsc                    s|   ddl m}m dvrdd< d }ttjj |r.dt| f fdd}| S  jj	d}t
| | S )	Nr   )ServerSentEventconnect_ssestreamFr+   c                  3   s     dj d=} t| j |  D ]*}| }|jdkr0|di dkr0 W d    d S |jdkr;t|jd|V  qW d    d S 1 sJw   Y  d S )NPOSTr5   rR   rS   rT   rU   rK   )	r   rl   rW   iter_sser5   r6   r8   r   rS   )rX   r)   rY   ro   r   r   r   r:   r;   r     s"   



"z3ChatClovaX._completion_with_retry.<locals>.iter_sseri   r5   )	httpx_sser   r   r   rb   r   ro   r   postr   rl   r5   )r   r   r   r   r   rW   r:   r   r;   _completion_with_retry  s   z!ChatClovaX._completion_with_retryrun_managerc                    sL   ddl m  	 t|d}|dtdtf fdd}|di |I d H S )	Nr   )aconnect_sse)r   r   r+   c                     sr   d| vr	d| d< | d }t tjj}|r# |dj| d}t|S |jj| dI d H }t|I d H  | S )Nr   Fr   r   r   )	r   rb   r   rp   r   rZ   r   rV   r5   )r   r   rp   rX   rW   r   r   r:   r;   r     s   
zBChatClovaX._acompletion_with_retry.<locals>._completion_with_retryr:   )r   r   _create_retry_decoratorr   )r   r   r   Zretry_decoratorr   r:   r   r;   _acompletion_with_retry  s   z"ChatClovaX._acompletion_with_retryrW   c                 C   s   g }| di }| di }t|}t|tr,| d| d| d| d d|_t|d}|| | d| d| d| d| d	d
}t||dS )Nr,   r0   r?   rA   )Zinput_tokensZoutput_tokensZtotal_tokensrK   r=   rC   rD   )r>   r@   rB   rC   rE   )generations
llm_output)r8   rP   rF   r   Zusage_metadatar   appendr    )r   rW   r   r,   msgr0   genr   r:   r:   r;   _create_chat_result  s(   

zChatClovaX._create_chat_resultc                 K   s:   |  ||\}}i ||}| jdd|i|}| |S )Nr   r:   )r   r   r   r   r   r   r   r   r   r   rW   r:   r:   r;   	_generate  s   
zChatClovaX._generatec                 k   s    |  ||\}}i ||ddi}t}| jd||d|D ]}t||}	|	j}t|	d}
|r<|jtt|	j	|
d |
V  q d S Nr   Tr   r   rK   )tokenchunkr:   )
r   r   r   r<   r   r   on_llm_new_tokenr   rO   r.   )r   r   r   r   r   r   r   default_chunk_classr)   	new_chunk	gen_chunkr:   r:   r;   _stream  s$   


zChatClovaX._streamc                    sD   |  ||\}}i ||}| jd||d|I d H }| |S )Nr   r:   )r   r   r   r   r:   r:   r;   
_agenerate  s   
zChatClovaX._ageneratec                 K  s   |  ||\}}i ||ddi}t}| jd||d|I d H 2 z&3 d H W }t||}	|	j}t|	d}
|rF|jtt|	j	|
dI d H  |
V  q#6 d S r   )
r   r   r   r<   r   r   r   r   rO   r.   )r   r   r   r   r   r   r   r   r   r   r   r:   r:   r;   _astream  s$   

zChatClovaX._astreamr   )r+   N)NN)H__name__
__module____qualname____doc__r%   ro   r	   rb   r   __annotations__rp   r   r#   rq   rO   rt   ru   boolrw   r&   ry   rz   r}   floatr   intr   r   r   r   listr   rC   r   r   r$   Zmodel_configpropertyr   r   r   r   r   r   r   r   r   r   r   r'   r(   r   r   r   r   r   r
   r   r   r   r   r    r   r   r   r   r   r   r   r   r   __classcell__r:   r:   r   r;   rm      s   
 
!



%







rm   llmr   c                 C   s   t jt jg}t|| j|dS )zFReturns a tenacity retry decorator, preconfigured to handle exceptions)Zerror_typesr   r   )rb   RequestErrorStreamErrorr   r   )r   r   errorsr:   r:   r;   r   1  s   r   r   )Bloggingtypingr   r   r   r   r   r   r   r	   r
   r   r   r   rb   r   r   Zlangchain_core.callbacksr   r   Z*langchain_core.language_models.chat_modelsr   r   Z#langchain_core.language_models.llmsr   Zlangchain_core.messagesr   r   r   r   r   r   r   r   r   r   Zlangchain_core.outputsr   r   r    Zlangchain_core.utilsr!   r"   Zpydanticr#   r$   r%   r&   r'   Ztyping_extensionsr(   r   	getLoggerr   rH   r<   rO   r7   rL   rP   rZ   Responserl   rV   rm   r   r:   r:   r:   r;   <module>   sj    80



 
   
