a
    bg2G                  	   @  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r6ddl7m8Z8 ddl9m:Z: e;e<Z=dZ>dZ?dZ@G dd deAZBddddddZCdddddd ZDd!d"d#d$d%d&ZEd?d'd(d)d*d+d,ZFG d-d. d.ee3ZGd/dd0d.d1d2d3d4d5d6ZHd@d.d1d8d9d:d;d;d<d=d>ZIdS )Az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   t/var/www/html/cobodadashboardai.evdpl.com/venv/lib/python3.9/site-packages/langchain_community/chat_models/premai.pyr,   J   s   r,   strOptional[List[str]])textstopreturnc                 C  s8   |du r| S |D ]"}|  |}|dkr| d| } q| S )z0Truncates text at the earliest stop token found.N)find)r5   r6   Z
stop_tokenZstop_token_idxr1   r1   r2   _truncate_at_stop_tokensN   s    
r:   r+   r   )responser6   r7   c              	   C  s*  | j stdg }| j D ]}|jj}|du r<td| dt|jjpHd|d}|du rftd| |dkr|jd	 }|du rg }nd
d |D }|t|t||dd q|dkr|t|t	|dd q|t|t
||dd q| jdurt|ddd | jD idS t|ddidS dS )z4Converts a Prem API response into a LangChain resultz-ChatResponse must have at least one candidateNzChatResponse z must have a role. )r5   r6   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>   )r5   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;   r6   rO   choicerK   rF   r>   toolsr1   r1   r2   _response_to_result]   sP    

	rT   r*   zType[BaseMessageChunk]zdTuple[Union[BaseMessageChunk, HumanMessageChunk, AIMessageChunk, SystemMessageChunk], Optional[str]])r;   default_classr7   c                 C  s   | j d j}|dd}|dd}i }| j d j}|dksD|tkrRt|d|fS |dksb|tkrrt||d|fS |d	ks|tkrt|d|fS |s|tkrt||d
|fS ||d|fS dS )z(Converts delta response to message chunkr   rK   r<   rF   rH   rI   r=   )rF   additional_kwargssystem)rF   rK   N)rP   deltagetfinish_reasonr   r   r   r   )r;   rU   Z_deltarK   rF   rV   Zfinish_reasonsr1   r1   r2   (_convert_delta_response_to_message_chunk   s     
r[   List[BaseMessage]Optional[str]z*Tuple[Optional[str], List[Dict[str, Any]]])input_messagestemplate_idr7   c                 C  s  d}g }| D ]}t |tr(t|j}qt |tr|du rR|dt|jd nLi }|jdurj|jdksxJ tddt|j|t|j< |d||d qt |tr|j	du st
|j	dkr|d	t|jd n.|j|j|j|j	d
}|d	tj|dd qt |trqtdqd}| D ]0}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   r3   rF   r   rQ   r?   
ValueErrorr   r>   lenra   !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_msgr`   Zai_msg_to_jsonZtool_promptrc   Ztool_resultpromptr1   r1   r2   _messages_to_prompt_dict   sh    





rm   c                      s`  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"d#d$Zed%d&d'd(Zed)d&d*d+Zdd)d,d-d.Zd>d/d0d1dd2d3d4d5Zd?d/d0d1dd6d3d7d8Zd9dd:d; fd<d=Z  ZS )@
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_namer]   model
session_id)rr   zOptional[float]temperaturetop_pzOptional[int]
max_tokens   max_retriesr<   rk   zOptional[dict]repositoriesFOptional[bool]	streamingr   clientTZforbid)Zpopulate_by_nameZarbitrary_types_allowedextrar   )valuesr7   c              
   C  s   zddl m} W n. ty> } ztd|W Y d}~n
d}~0 0 z.t|dd}|t|tr^|n|jd|d< W n. ty } ztd	|W Y d}~n
d}~0 0 |S )
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`Nrt   ZPREMAI_API_KEY)rq   r   z,Your API Key is incorrect. Please try again.)	premair   ImportErrorr"   rd   r3   Z_secret_value	Exceptionre   )clsr   r   errorrt   r1   r1   r2   validate_environments<  s(     z ChatPremAI.validate_environmentsr3   )r7   c                 C  s   dS )Nr   r1   selfr1   r1   r2   	_llm_typeT  s    zChatPremAI._llm_typezDict[str, Any]c                 C  s   | j | j| j| j| jdS )Nru   rk   rw   ry   r|   r   r   r1   r1   r2   _default_paramsX  s    zChatPremAI._default_params)kwargsr7   c                 K  s   g d}g }|D ](}||v rt d| d || q|D ]}|| q>i | j|}t| j D ],}||d u s||dkrj||d  qj|S )N)rx   Zfrequency_penaltyZpresence_penaltyZ
logit_biasr6   seedzWARNING: Parameter z is not supported in kwargs.r<   )warningswarnrQ   popr   listkeysrY   )r   r   Zkwargs_to_ignoreZkeys_to_removekey
all_kwargsr1   r1   r2   _get_all_kwargsb  s    zChatPremAI._get_all_kwargsr\   r4   "Optional[CallbackManagerForLLMRun]r   )messagesr6   run_managerr   r7   c           	      K  sz   d|v rt ||d d\}}nt |\}}|d urB|dkrB||d< | jf i |}t| f| j|d|d|}t||dS )Nr_   r_   r<   rk   Frp   r   streamr   )r;   r6   )rm   r   chat_with_retryrp   rT   )	r   r   r6   r   r   rk   messages_to_passr   r;   r1   r1   r2   	_generate{  s&    	zChatPremAI._generatez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f i |}t}t| f| j|d|d|D ]}	zPt|	|d\}
}|d urt|d	nd }t	|
|d
}|r|j
|j|d |V  W q ty } zW Y d }~qW Y d }~qd }~0 0 qd S )Nr_   r   z,stop is not supported in langchain streamingrk   r<   Tr   )r;   rU   )rZ   )rG   generation_info)rN   )rm   loggerwarningr   r   r   rp   r[   dictr   Zon_llm_new_tokenr5   r   )r   r   r6   r   r   rk   r   r   Zdefault_chunk_classZstreamed_responserN   rZ   r   Zcg_chunk_r1   r1   r2   _stream  sL    



zChatPremAI._streamzDSequence[Union[Dict[str, Any], Type[BaseModel], Callable, BaseTool]]z)Runnable[LanguageModelInput, BaseMessage])rS   r   r7   c                   s$   dd |D }t  jf d|i|S )Nc                 S  s   g | ]}t |qS r1   r$   )rD   Ztoolr1   r1   r2   rE         z)ChatPremAI.bind_tools.<locals>.<listcomp>rS   )superbind)r   rS   r   Zformatted_tools	__class__r1   r2   
bind_tools  s    zChatPremAI.bind_tools)NN)NN)r-   r.   r/   r0   __annotations__r(   rt   ru   rv   rw   rx   ry   r{   rk   r|   r~   r   r'   Zmodel_configr#   r   propertyr   r   r   r   r   r   __classcell__r1   r1   r   r2   rn      s@   
	     3rn   rz   r{   r   ro   z)Optional[Union[CallbackManagerForLLMRun]]zCallable[[Any], Any])llmr{   r   r7   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   F
List[dict]boolr   r   )r   rp   r   r   r   r   r7   c                   sF   t   j|d}|ddddddd fdd	}|f |||d
|S )z+Using tenacity for retry in completion callr   Fro   r   r}   r   )rp   r   r   r   r7   c                   s"    j jjjf | ||d|}|S )Nrp   r   r   )r   ZchatZcompletionscreate)rp   r   r   r   r;   r   r1   r2   _completion_with_retry  s    z/chat_with_retry.<locals>._completion_with_retryr   )F)r   r{   )r   rp   r   r   r   r   Zretry_decoratorr   r1   r   r2   r     s    	 r   )N)FN)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   rj   rg   ri   r   r,   r:   rT   r[   rm   rn   r   r   r1   r1   r1   r2   <module>   sH   44
= H Z"  