U
    hI                     @  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mZ ddlmZmZ ddlmZ ddlmZ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'm(Z(m)Z)m*Z*m+Z+m,Z, dd
l-m.Z.m/Z/m0Z0 ddl1m2Z2m3Z3 ddl4m5Z5 ddl6m7Z7 ddl8m9Z9m:Z: ddl;m<Z< e=e>Z?G dd de@ZAd0ddddddZBdddddZCd1dddddd d!ZDdd"d#d$d%d&ZEd'd(d)d*d+ZFdd(d,d-d.ZGG d/d deZHdS )2z+Wrapper around LiteLLM's model I/O library.    )annotationsN)AnyAsyncIteratorCallableDictIteratorListMappingOptionalSequenceTupleTypeUnion)AsyncCallbackManagerForLLMRunCallbackManagerForLLMRun)LanguageModelInput)BaseChatModelagenerate_from_streamgenerate_from_stream)create_base_retry_decorator)	AIMessageAIMessageChunkBaseMessageBaseMessageChunkChatMessageChatMessageChunkFunctionMessageFunctionMessageChunkHumanMessageHumanMessageChunkSystemMessageSystemMessageChunkToolCallToolCallChunkToolMessage)ChatGenerationChatGenerationChunk
ChatResult)	BaseModelField)Runnable)BaseTool)get_from_dict_or_envpre_initconvert_to_openai_toolc                   @  s   e Zd ZdZdS )ChatLiteLLMExceptionz$Error with the `LiteLLM I/O` libraryN)__name__
__module____qualname____doc__ r5   r5   K/tmp/pip-unpacked-wheel-9gdii04g/langchain_community/chat_models/litellm.pyr0   @   s   r0   ChatLiteLLMzHOptional[Union[AsyncCallbackManagerForLLMRun, CallbackManagerForLLMRun]]zCallable[[Any], Any])llmrun_managerreturnc                 C  s,   ddl }|j|j|j|jg}t|| j|dS )zKReturns a tenacity retry decorator, preconfigured to handle PaLM exceptionsr   N)Zerror_typesmax_retriesr9   )litellmTimeoutZAPIErrorZAPIConnectionErrorZRateLimitErrorr   r;   )r8   r9   r<   errorsr5   r5   r6   _create_retry_decoratorD   s      r?   Mapping[str, Any]r   )_dictr:   c                 C  s   | d }|dkrt | d dS |dkrv| ddp4d}i }| drTt| d |d< | drj| d |d< t||d	S |d
krt| d dS |dkrt| d | d dS t| d |dS d S )NroleusercontentrD   	assistant function_call
tool_calls)rD   additional_kwargssystemfunctionnamerD   rM   rD   rB   )r   getdictr   r    r   r   )rA   rB   rD   rJ   r5   r5   r6   _convert_dict_to_messageX   s     

rR   'Optional[AsyncCallbackManagerForLLMRun]r   )r8   r9   kwargsr:   c                   s4   t  |d}|ddd fdd}|f |I dH S )z0Use tenacity to retry the async completion call.r9   r   rT   r:   c                    s    j jf | I d H S N)clientZacreaterT   r8   r5   r6   _completion_with_retryy   s    z6acompletion_with_retry.<locals>._completion_with_retryNr?   )r8   r9   rT   retry_decoratorr[   r5   rZ   r6   acompletion_with_retryq   s    r^   zType[BaseMessageChunk]r   )rA   default_classr:   c                 C  s  |  d}|  dpd}|  dr4dt| d i}ni }g }|  d }rz||d< zdd |D }W n tk
rx   Y nX |dks|tkrt|d	S |d
ks|tkrt|||dS |dks|tkrt|d	S |dks|tkrt|| d dS | s|tkrt||dS ||d	S d S )NrB   rD   rG   rH   rI   c                 S  s:   g | ]2}t |d  d|d  d|d|d dqS )rL   rM   	argumentsidindex)rM   argsra   rb   )r#   rP   ).0Zrtcr5   r5   r6   
<listcomp>   s   z3_convert_delta_to_message_chunk.<locals>.<listcomp>rC   rE   rF   )rD   rJ   tool_call_chunksrK   rL   rM   rN   rO   )rP   rQ   KeyErrorr   r   r!   r   r   )rA   r_   rB   rD   rJ   rf   Zraw_tool_callsr5   r5   r6   _convert_delta_to_message_chunk   s:    


	

rh   r"   rQ   )	tool_callr:   c                 C  s$   d| d | d t | d ddS )NrL   ra   rM   rc   )rM   r`   )typera   rL   )jsondumps)ri   r5   r5   r6   !_lc_tool_call_to_openai_tool_call   s    rm   )messager:   c                 C  s  d| j i}t| tr | j|d< nt| tr4d|d< nt| trd|d< d| jkr^| jd |d< | jrzdd | jD |d< qd| jkr| jd |d< n^t| trd	|d< nJt| t	rd
|d< | j
|d< n,t| trd|d< | j|d< ntd|  d| jkr| jd |d< |S )NrD   rB   rC   rF   rH   c                 S  s   g | ]}t |qS r5   )rm   )rd   Ztcr5   r5   r6   re      s    z,_convert_message_to_dict.<locals>.<listcomp>rI   rK   rL   rM   tooltool_call_idzGot unknown type )rD   
isinstancer   rB   r   r   rJ   rI   r    r   rM   r$   rp   
ValueError)rn   Zmessage_dictr5   r5   r6   _convert_message_to_dict   s6    










rs   c                      s   e Zd ZU 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< 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< dZde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%< edd&d'd(Zedd&d)d*ZdUd+ddd,d-d.Zed/d/d0d1d2Z dVd3d4d+d5dd6d7d8d9Z!d:d6d;d<d=Z"d3d4d>d?d@dAZ#dWd3d4d+ddBdCdDdEZ$dXd3d4dFddGdCdHdIZ%dYd3d4dFd5dd6d7dJdKZ&dLddMdN fdOdPZ'edd&dQdRZ(edd&dSdTZ)  Z*S )Zr7   z%Chat model that uses the LiteLLM API.r   rX   zgpt-3.5-turbostrmodelNzOptional[str]
model_nameopenai_api_keyazure_api_keyanthropic_api_keyreplicate_api_keycohere_api_keyopenrouter_api_keyFbool	streamingapi_baseorganizationcustom_llm_providerz+Optional[Union[float, Tuple[float, float]]]request_timeout   zOptional[float]temperature)default_factoryzDict[str, Any]model_kwargstop_pzOptional[int]top_kintn
max_tokens   r;   )r:   c                 C  s<   | j }| jdk	r| j}|| j| j| j| j| j| jd| jS )z2Get the default parameters for calling OpenAI API.N)ru   force_timeoutr   streamr   r   r   )	ru   rv   r   r   r~   r   r   r   r   selfset_model_valuer5   r5   r6   _default_params   s    
zChatLiteLLM._default_paramsc                 C  sD   | j }| jdk	r| j}| j| j_| j| j_|| j| jd}| j|S )z.Get the parameters used for the openai client.N)ru   r   r   )ru   rv   r   rX   r   r   r   )r   r   credsr5   r5   r6   _client_params  s    


zChatLiteLLM._client_paramsz"Optional[CallbackManagerForLLMRun])r9   rT   r:   c                   s.   t  |d}|ddd fdd}|f |S )z*Use tenacity to retry the completion call.rU   r   rV   c                    s    j jf | S rW   )rX   
completionrY   r   r5   r6   r[      s    zAChatLiteLLM.completion_with_retry.<locals>._completion_with_retryr\   )r   r9   rT   r]   r[   r5   r   r6   completion_with_retry  s    z!ChatLiteLLM.completion_with_retryr   )valuesr:   c                 C  s`  zddl }W n tk
r(   tdY nX t|dddd|d< t|dd	dd|d< t|d
ddd|d
< t|dddd|d< t|dddd|d< t|dddd|d< t|dddd|d< t|dddd|d< ||d< |d dk	rd|d   krdksn td|d dk	r8d|d   kr.dks8n td|d dk	r\|d dkr\td|S )zGValidate api key, python package exists, temperature, top_p, and top_k.r   NzUCould not import litellm python package. Please install it with `pip install litellm`rw   ZOPENAI_API_KEYrG   )defaultrx   ZAZURE_API_KEYry   ZANTHROPIC_API_KEYrz   ZREPLICATE_API_KEYr|   ZOPENROUTER_API_KEYr{   ZCOHERE_API_KEYZhuggingface_api_keyZHUGGINGFACE_API_KEYZtogether_ai_api_keyZTOGETHERAI_API_KEYrX   r   r   z+temperature must be in the range [0.0, 1.0]r   z%top_p must be in the range [0.0, 1.0]r   ztop_k must be positive)r<   ImportErrorr0   r,   rr   )clsr   r<   r5   r5   r6   validate_environment&  s|    
   
   
   
   
   
   
   
   
*,z ChatLiteLLM.validate_environmentzList[BaseMessage]zOptional[List[str]]zOptional[bool]r'   )messagesstopr9   r   rT   r:   c                 K  sn   |d k	r|n| j }|r6| j|f||d|}t|S | ||\}}	|	|}	| jf ||d|	}
| |
S )N)r   r9   r   r9   )r~   _streamr   _create_message_dictsr   _create_chat_resultr   r   r   r9   r   rT   Zshould_streamZstream_itermessage_dictsparamsresponser5   r5   r6   	_generateV  s(      zChatLiteLLM._generater@   )r   r:   c           	      C  sx   g }|d D ]2}t |d }t|t|ddd}|| q|di }| j}| jd k	rb| j}||d}t||dS )	Nchoicesrn   finish_reason)r   )rn   Zgeneration_infousage)token_usageru   )generations
llm_output)rR   r%   rQ   rP   appendru   rv   r'   )	r   r   r   resrn   genr   r   r   r5   r5   r6   r   l  s    

zChatLiteLLM._create_chat_resultz+Tuple[List[Dict[str, Any]], Dict[str, Any]])r   r   r:   c                 C  s<   | j }|d k	r&d|krtd||d< dd |D }||fS )Nr   z2`stop` found in both the input and default params.c                 S  s   g | ]}t |qS r5   )rs   )rd   mr5   r5   r6   re     s     z5ChatLiteLLM._create_message_dicts.<locals>.<listcomp>)r   rr   )r   r   r   r   r   r5   r5   r6   r   |  s    z!ChatLiteLLM._create_message_dictszIterator[ChatGenerationChunk])r   r   r9   rT   r:   c                 k  s   |  ||\}}||ddi}t}| jf ||d|D ]l}t|tsN| }t|d dkr`q8|d d d }	t|	|}|j}t	|d}
|r|j
|j|
d |
V  q8d S 	Nr   Tr   r   r   delta)rn   )chunk)r   r   r   rq   rQ   
model_dumplenrh   	__class__r&   on_llm_new_tokenrD   r   r   r   r9   rT   r   r   Zdefault_chunk_classr   r   Zcg_chunkr5   r5   r6   r     s(     



zChatLiteLLM._streamrS   z"AsyncIterator[ChatGenerationChunk]c                 K s   |  ||\}}||ddi}t}t| f||d|I d H 2 zz3 d H W }t|ts\| }t|d dkrnq>|d d d }	t|	|}|j}t	|d}
|r|j
|j|
dI d H  |
V  q>6 d S r   )r   r   r^   rq   rQ   r   r   rh   r   r&   r   rD   r   r5   r5   r6   _astream  s,     


zChatLiteLLM._astreamc                   sz   |d k	r|n| j }|r<| jf |||d|}t|I d H S | ||\}}	|	|}	t| f||d|	I d H }
| |
S )N)r   r   r9   r   )r~   r   r   r   r^   r   r   r5   r5   r6   
_agenerate  s*       zChatLiteLLM._ageneratezDSequence[Union[Dict[str, Any], Type[BaseModel], Callable, BaseTool]]z)Runnable[LanguageModelInput, BaseMessage])toolsrT   r:   c                   s$   dd |D }t  jf d|i|S )au  Bind tool-like objects to this chat model.

        LiteLLM expects tools argument in OpenAI format.

        Args:
            tools: A list of tool definitions to bind to this chat model.
                Can be  a dictionary, pydantic model, callable, or BaseTool. Pydantic
                models, callables, and BaseTools will be automatically converted to
                their schema dictionary representation.
            tool_choice: Which tool to require the model to call.
                Must be the name of the single provided function or
                "auto" to automatically determine which function to call
                (if any), or a dict of the form:
                {"type": "function", "function": {"name": <<tool_name>>}}.
            **kwargs: Any additional parameters to pass to the
                :class:`~langchain.runnable.Runnable` constructor.
        c                 S  s   g | ]}t |qS r5   r.   )rd   ro   r5   r5   r6   re     s     z*ChatLiteLLM.bind_tools.<locals>.<listcomp>r   )superbind)r   r   rT   Zformatted_toolsr   r5   r6   
bind_tools  s    zChatLiteLLM.bind_toolsc                 C  s.   | j }| jdk	r| j}|| j| j| j| jdS )zGet the identifying parameters.N)ru   r   r   r   r   )ru   rv   r   r   r   r   r   r5   r5   r6   _identifying_params  s    
zChatLiteLLM._identifying_paramsc                 C  s   dS )Nzlitellm-chatr5   r   r5   r5   r6   	_llm_type  s    zChatLiteLLM._llm_type)N)NNN)NN)NN)NNN)+r1   r2   r3   r4   __annotations__ru   rv   rw   rx   ry   rz   r{   r|   r~   r   r   r   r   r   r)   rQ   r   r   r   r   r   r;   propertyr   r   r   r-   r   r   r   r   r   r   r   r   r   r   __classcell__r5   r5   r   r6   r7      sf   
 2          )N)N)Ir4   
__future__r   rk   loggingtypingr   r   r   r   r   r   r	   r
   r   r   r   r   Zlangchain_core.callbacksr   r   Zlangchain_core.language_modelsr   Z*langchain_core.language_models.chat_modelsr   r   r   Z#langchain_core.language_models.llmsr   Zlangchain_core.messagesr   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   Zlangchain_core.outputsr%   r&   r'   Zlangchain_core.pydantic_v1r(   r)   Zlangchain_core.runnablesr*   Zlangchain_core.toolsr+   Zlangchain_core.utilsr,   r-   Z%langchain_core.utils.function_callingr/   	getLoggerr1   logger	Exceptionr0   r?   rR   r^   rh   rm   rs   r7   r5   r5   r5   r6   <module>   s4   8D
  ,