o
    ZhH                     @  s  d Z ddlmZ ddl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 ddl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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.m/Z/ ddl0m1Z1 ddl2m3Z3m4Z4m5Z5m6Z6 erddl7m8Z8 ddl9m:Z: e;e<Z=dZ>dZ?dZ@G dd deAZBdGddZCdHd!d"ZDdId'd(ZE	dJdKd.d/ZFG d0d1 d1ee3ZGd2dd3dLd:d;ZH	<	dMdNdEdFZIdS )OzWrapper around Prem's Chat API.    )annotationsN)TYPE_CHECKINGAnyCallableDictIteratorListOptionalSequenceTupleTypeUnion)CallbackManagerForLLMRun)LanguageModelInput)BaseChatModel)create_base_retry_decorator)	AIMessageAIMessageChunkBaseMessageBaseMessageChunkChatMessageChatMessageChunkHumanMessageHumanMessageChunkSystemMessageSystemMessageChunkToolMessage)ChatGenerationChatGenerationChunk
ChatResult)Runnable)BaseTool)get_from_dict_or_envpre_initconvert_to_openai_tool)	BaseModel
ConfigDictField	SecretStr)ChatCompletionResponseStream)ChatCompletionResponsezM
Given the set of tools you used and the response, provide the final answer

z
{json}
z3
tool id: {tool_id}
tool_response: {tool_response}
c                   @  s   e Zd ZdZdS )ChatPremAPIErrorzError with the `PremAI` API.N)__name__
__module____qualname____doc__ r1   r1   ]/var/www/html/lang_env/lib/python3.10/site-packages/langchain_community/chat_models/premai.pyr,   J   s    r,   textstrstopOptional[List[str]]returnc                 C  s8   |du r| S |D ]}|  |}|dkr| d| } q| S )z0Truncates text at the earliest stop token found.N)find)r3   r5   Z
stop_tokenZstop_token_idxr1   r1   r2   _truncate_at_stop_tokensN   s   
r:   responser+   r   c              	   C  s$  | j stdg }| j D ]j}|jj}|du rtd| dt|jjp$d|d}|du r3td| |dkrX|jd	 }|du rCg }nd
d |D }|t|t||dd q|dkri|t|t	|dd q|t|t
||dd q| jdurt|ddd | jD idS t|ddidS )z4Converts a Prem API response into a LangChain resultz-ChatResponse must have at least one candidateNzChatResponse z must have a role. )r3   r5   z"ChatResponse must have a content: 	assistant
tool_callsc                 S  s,   g | ]}|d  |d d |d d dqS )idfunctionname	arguments)r?   rA   argsr1   ).0Z	tool_callr1   r1   r2   
<listcomp>u   s    

z'_response_to_result.<locals>.<listcomp>)contentr>   )r3   messageuserrF   rolerF   document_chunksc                 S  s   g | ]}|  qS r1   )to_dict)rD   chunkr1   r1   r2   rE      s    )generationsZ
llm_output)choicesr,   rG   rK   r:   rF   appendr   r   r   r   rL   r   )r;   r5   rO   choicerK   rF   r>   toolsr1   r1   r2   _response_to_result]   sP   


	rT   r*   default_classType[BaseMessageChunk]dTuple[Union[BaseMessageChunk, HumanMessageChunk, AIMessageChunk, SystemMessageChunk], Optional[str]]c                 C  s   | j d j}|dd}|dd}i }| j d j}|dks"|tkr)t|d|fS |dks1|tkr9t||d|fS |d	ksA|tkrHt|d|fS |sN|tkrVt||d
|fS ||d|fS )z(Converts delta response to message chunkr   rK   r<   rF   rH   rI   r=   )rF   additional_kwargssystem)rF   rK   )rP   deltagetfinish_reasonr   r   r   r   )r;   rU   Z_deltarK   rF   rX   Zfinish_reasonsr1   r1   r2   (_convert_delta_response_to_message_chunk   s    
r]   input_messagesList[BaseMessage]template_idOptional[str]*Tuple[Optional[str], List[Dict[str, Any]]]c                 C  s~  d}g }| D ]}t |trt|j}qt |trO|du r(|dt|jd qi }|jdur4|jdks;J tddt|j|t|j< |d||d qt |tr|j	du s`t
|j	dkrl|d	t|jd q|j|j|j|j	d
}|d	tj|dd qt |trqtdd}| D ]}t |tr|j}|j}	|tj||	d7 }q|dkrt}
|
|7 }
|d|
d ||fS )zcConverts a list of LangChain Messages into a simple dict
    which is the message structure in PremNrH   rJ   r<   z9When using prompt template there should be id associated zwith each HumanMessage)rK   r`   paramsr   r=   )r?   rF   response_metadatar>   )jsonzNo such role explicitly exists)tool_idZtool_response)
isinstancer   r4   rF   r   rQ   r?   
ValueErrorr   r>   lenrd   !INTERMEDIATE_TOOL_RESULT_TEMPLATEformatr   r,   Ztool_call_idSINGLE_TOOL_PROMPT_TEMPLATETOOL_PROMPT_HEADER)r^   r`   system_promptZexamples_and_messagesZ	input_msgrc   Zai_msg_to_jsonZtool_promptrf   Ztool_resultpromptr1   r1   r2   _messages_to_prompt_dict   sx   




rp   c                      sJ  e Zd ZU dZded< 	 edddZded< 	 edd	dZd
ed< 	 dZd
ed< 	 eddZ	ded< 	 dZ
ded< 	 eddZde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< edddd Zed@d$d%ZedAd'd(ZedBd*d+ZdCd-d.Z		dDdEd6d7Z		dDdFd9d:ZdG fd>d?Z  ZS )H
ChatPremAIzPremAI Chat models.

    To use, you will need to have an API key. You can find your existing API Key
    or generate a new one here: https://app.premai.io/api_keys/
    int
project_idNapi_key)defaultaliaszOptional[SecretStr]premai_api_keyZ
model_namera   model
session_id)ru   zOptional[float]temperaturetop_pzOptional[int]
max_tokens   max_retriesr<   rn   zOptional[dict]repositoriesFOptional[bool]	streamingr   clientTZforbid)Zpopulate_by_nameZarbitrary_types_allowedextravaluesr   r7   c              
   C  s   zddl m} W n ty } ztd|d}~ww zt|dd}|t|tr)|n|jd|d< W |S  tyC } ztd	|d}~ww )
zFValidate that the package is installed and that the API token is validr   )PremzQCould not import Prem Python package.Please install it with: `pip install premai`Nrw   ZPREMAI_API_KEY)rt   r   z,Your API Key is incorrect. Please try again.)	premair   ImportErrorr"   rg   r4   Z_secret_value	Exceptionrh   )clsr   r   errorrw   r1   r1   r2   validate_environmentsF  s0   
z ChatPremAI.validate_environmentsr4   c                 C  s   dS )Nr   r1   selfr1   r1   r2   	_llm_type^  s   zChatPremAI._llm_typeDict[str, Any]c                 C  s   | j | j| j| j| jdS )Nrx   rn   rz   r|   r   r   r   r1   r1   r2   _default_paramsb  s   zChatPremAI._default_paramskwargsc                 K  s   g d}g }|D ]}||v rt d| d || q|D ]}|| qi | j|}t| j D ]}||d u sE||dkrK||d  q5|S )N)r{   Zfrequency_penaltyZpresence_penaltyZ
logit_biasr5   seedzWARNING: Parameter z is not supported in kwargs.r<   )warningswarnrQ   popr   listkeysr[   )r   r   Zkwargs_to_ignoreZkeys_to_removekey
all_kwargsr1   r1   r2   _get_all_kwargsl  s   
zChatPremAI._get_all_kwargsmessagesr_   r5   r6   run_manager"Optional[CallbackManagerForLLMRun]r   c           	      K  sz   d|v rt ||d d\}}nt |\}}|d ur!|dkr!||d< | jdi |}t| f| j|d|d|}t||dS )	Nr`   r`   r<   rn   Frs   r   streamr   )r;   r5   r1   )rp   r   chat_with_retryrs   rT   )	r   r   r5   r   r   rn   messages_to_passr   r;   r1   r1   r2   	_generate  s&   	zChatPremAI._generateIterator[ChatGenerationChunk]c                 k  s   d|v rt ||d d\}}nt |\}}|d urtd d|vr/|d ur/|dkr/||d< | jdi |}t}t| f| j|d|d|D ]<}	z(t|	|d\}
}|d ur[t|d	nd }t	|
|d
}|rm|j
|j|d |V  W qG ty } zW Y d }~qGd }~ww d S )Nr`   r   z,stop is not supported in langchain streamingrn   r<   Tr   )r;   rU   )r\   )rG   generation_info)rN   r1   )rp   loggerwarningr   r   r   rs   r]   dictr   Zon_llm_new_tokenr3   r   )r   r   r5   r   r   rn   r   r   Zdefault_chunk_classZstreamed_responserN   r\   r   Zcg_chunk_r1   r1   r2   _stream  sT   




zChatPremAI._streamrS   DSequence[Union[Dict[str, Any], Type[BaseModel], Callable, BaseTool]])Runnable[LanguageModelInput, BaseMessage]c                   s$   dd |D }t  jdd|i|S )Nc                 S  s   g | ]}t |qS r1   r$   )rD   Ztoolr1   r1   r2   rE     s    z)ChatPremAI.bind_tools.<locals>.<listcomp>rS   r1   )superbind)r   rS   r   Zformatted_tools	__class__r1   r2   
bind_tools  s   zChatPremAI.bind_tools)r   r   r7   r   )r7   r4   )r7   r   )r   r   r7   r   )NN)
r   r_   r5   r6   r   r   r   r   r7   r   )
r   r_   r5   r6   r   r   r   r   r7   r   )rS   r   r   r   r7   r   )r-   r.   r/   r0   __annotations__r(   rw   rx   ry   rz   r{   r|   r~   rn   r   r   r   r'   Zmodel_configr#   r   propertyr   r   r   r   r   r   __classcell__r1   r1   r   r2   rq     sX   
 
	 3rq   r}   r~   r   llmr~   rr   r   )Optional[Union[CallbackManagerForLLMRun]]Callable[[Any], Any]c                C  s~   ddl }|jjj|jjj|jjj|jjj	|jj
j|jjj|jjj|jjj|jjj|jjj|jjj|jjjg}t|||d}|S )z/Create a retry decorator for PremAI API errors.r   N)Zerror_typesr~   r   )Zpremai.modelsmodelsZapi_response_validation_errorZAPIResponseValidationErrorZconflict_errorZConflictErrorZmodel_not_found_errorZModelNotFoundErrorZpermission_denied_errorZPermissionDeniedErrorZprovider_api_connection_errorZProviderAPIConnectionErrorZprovider_api_status_errorZProviderAPIStatusErrorZprovider_api_timeout_errorZProviderAPITimeoutErrorZprovider_internal_server_errorZProviderInternalServerErrorZprovider_not_found_errorZProviderNotFoundErrorZrate_limit_errorZRateLimitErrorZunprocessable_entity_errorZUnprocessableEntityErrorZvalidation_errorZValidationErrorr   )r   r~   r   r   errors	decoratorr1   r1   r2   create_prem_retry_decorator  s$   r   Frs   r   
List[dict]r   boolr   r   r   c                   s<   t   j|d}|	dd fdd}|d|||d|S )z+Using tenacity for retry in completion callr   Frs   rr   r   r   r   r   r   r   r7   c                   s"    j jjjd| ||d|}|S )Nrs   r   r   r1   )r   ZchatZcompletionscreate)rs   r   r   r   r;   r   r1   r2   _completion_with_retry	  s   z/chat_with_retry.<locals>._completion_with_retryr   N)F)
rs   rr   r   r   r   r   r   r   r7   r   r1   )r   r~   )r   rs   r   r   r   r   Zretry_decoratorr   r1   r   r2   r     s   	r   )r3   r4   r5   r6   r7   r4   )r;   r+   r5   r6   r7   r   )r;   r*   rU   rV   r7   rW   )N)r^   r_   r`   ra   r7   rb   )r   rq   r~   rr   r   r   r7   r   )FN)r   rq   rs   rr   r   r   r   r   r   r   r   r   r7   r   )Jr0   
__future__r   loggingr   typingr   r   r   r   r   r   r	   r
   r   r   r   Zlangchain_core.callbacksr   Zlangchain_core.language_modelsr   Z*langchain_core.language_models.chat_modelsr   Z#langchain_core.language_models.llmsr   Zlangchain_core.messagesr   r   r   r   r   r   r   r   r   r   r   Zlangchain_core.outputsr   r   r   Zlangchain_core.runnablesr    Zlangchain_core.toolsr!   Zlangchain_core.utilsr"   r#   Z%langchain_core.utils.function_callingr%   Zpydanticr&   r'   r(   r)   Z6premai.api.chat_completions.v1_chat_completions_creater*   Z&premai.models.chat_completion_responser+   	getLoggerr-   r   rm   rj   rl   r   r,   r:   rT   r]   rp   rq   r   r   r1   r1   r1   r2   <module>   sJ    44



=R Z"