U
    hI                      @  s   d Z ddlmZ ddlZddlZddlZddlmZmZm	Z	m
Z
 ddlZddlmZ ddlmZmZmZ ddlmZmZ ddlmZ dd	lmZmZ dd
lmZ erddlZeeZdZ dZ!G dd deZ"dS )z>Anyscale Endpoints chat wrapper. Relies heavily on ChatOpenAI.    )annotationsN)TYPE_CHECKINGDictOptionalSet)BaseMessage)Field	SecretStrroot_validator)convert_to_secret_strget_from_dict_or_envconvert_message_to_dict)
ChatOpenAI_import_tiktoken)is_openai_v1z%https://api.endpoints.anyscale.com/v1z#meta-llama/Meta-Llama-3-8B-Instructc                      s   e Zd ZU dZeddddZeddddZed	dd
dZe	ddZ
ded< e	eddZded< e	edZded< dZded< dZded< edefddddddZedddddd d!Zd"dd#d$Zd%d&d' fd(d)Z  ZS )*ChatAnyscalea  `Anyscale` Chat large language models.

    See https://www.anyscale.com/ for information about Anyscale.

    To use, you should have the ``openai`` python package installed, and the
    environment variable ``ANYSCALE_API_KEY`` set with your API key.
    Alternatively, you can use the anyscale_api_key keyword argument.

    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 ChatAnyscale
            chat = ChatAnyscale(model_name="meta-llama/Llama-2-7b-chat-hf")
    str)returnc                 C  s   dS )zReturn type of chat model.zanyscale-chat selfr   r   L/tmp/pip-unpacked-wheel-9gdii04g/langchain_community/chat_models/anyscale.py	_llm_type2   s    zChatAnyscale._llm_typezDict[str, str]c                 C  s   ddiS )Nanyscale_api_keyANYSCALE_API_KEYr   r   r   r   r   
lc_secrets7   s    zChatAnyscale.lc_secretsboolc                 C  s   dS )NFr   )clsr   r   r   is_lc_serializable;   s    zChatAnyscale.is_lc_serializableNdefaultr	   r   model)r!   alias
model_nameanyscale_api_basezOptional[str]anyscale_proxyzOptional[Set[str]]available_modelszSet[str])r   r%   r   c              
   C  s   z| pt jd } W n, tk
r> } ztd|W 5 d}~X Y nX | d}tj|dd|  id}|jdkrtd	| d
|j dd | d D S )z'Get available models from Anyscale API.r   zdAnyscale API key must be passed as keyword argument or set in environment variable ANYSCALE_API_KEY.Nz/modelsAuthorizationzBearer )headers   zError getting models from z: c                 S  s   h | ]}|d  qS )idr   ).0r"   r   r   r   	<setcomp>g   s     z4ChatAnyscale.get_available_models.<locals>.<setcomp>data)osenvironKeyError
ValueErrorrequestsgetstatus_codejson)r   r%   eZ
models_urlZmodels_responser   r   r   get_available_modelsK   s(    
 
z!ChatAnyscale.get_available_modelsT)predict)valuesr   c              
   C  s  t t|dd|d< t|ddtd|d< t|dddd|d	< zd
dl}W n, tk
rt } ztd|W 5 d}~X Y nX zt r|d  |d d}|ds|jf |j	j
|d< |ds|jf |j	j
|d< n&|d |d< |d  |d< |j|d< W n. tk
r( } ztd|W 5 d}~X Y nX d| kr@t|d< |d }| |d  |d }||krtd| d| d||d< |S )z?Validate that api key and python package exists in environment.r   r   r%   ZANYSCALE_API_BASEr    r&   ZANYSCALE_PROXY Zopenai_proxyr   NzTCould not import openai python package. Please install it with `pip install openai`.)Zapi_keybase_urlclientZasync_clientZopenai_api_baseZopenai_api_keyz`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$   zModel name z  not found in available models: .r'   )r   r   DEFAULT_API_BASEopenaiImportErrorr   Zget_secret_valuer4   ZOpenAIZchatZcompletionsZAsyncOpenAIZChatCompletionAttributeErrorr2   keysDEFAULT_MODELr8   )r   r;   rA   r7   Zclient_paramsexcr$   r'   r   r   r   validate_environmenti   sx    






z!ChatAnyscale.validate_environmentztuple[str, tiktoken.Encoding]c                 C  sb   t  }| jd k	r| j}n| j}z|d}W n, tk
rX   td d}||}Y nX ||fS )Nzgpt-3.5-turbo-0301z5Warning: model not found. Using cl100k_base encoding.Zcl100k_base)r   Ztiktoken_model_namer$   Zencoding_for_modelr1   loggerwarningZget_encoding)r   Z	tiktoken_r"   encodingr   r   r   _get_encoding_model   s    

z ChatAnyscale._get_encoding_modelzlist[BaseMessage]int)messagesr   c                   s   t jd dkrt |S |  \}}d}d}d}dd |D }|D ]D}||7 }| D ].\}	}
|t|t|
7 }|	dkrX||7 }qXqD|d7 }|S )zCalculate num tokens with tiktoken package.
        Official documentation: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb
                 r   c                 S  s   g | ]}t |qS r   r   )r,   mr   r   r   
<listcomp>   s     z=ChatAnyscale.get_num_tokens_from_messages.<locals>.<listcomp>name)	sysversion_infosuperget_num_tokens_from_messagesrK   itemslenencoder   )r   rM   r"   rJ   Ztokens_per_messageZtokens_per_nameZ
num_tokensZmessages_dictmessagekeyvalue	__class__r   r   rW      s    z)ChatAnyscale.get_num_tokens_from_messages)__name__
__module____qualname____doc__propertyr   r   classmethodr   r   r   __annotations__rE   r$   r@   r%   r&   r'   staticmethodr8   r
   rG   rK   rW   __classcell__r   r   r^   r   r      s(   
Nr   )#rc   
__future__r   loggingr/   rT   typingr   r   r   r   r3   Zlangchain_core.messagesr   Zlangchain_core.pydantic_v1r   r	   r
   Zlangchain_core.utilsr   r   Z#langchain_community.adapters.openair   Z&langchain_community.chat_models.openair   r   Z langchain_community.utils.openair   Ztiktoken	getLoggerr`   rH   r@   rE   r   r   r   r   r   <module>   s$   
