a
    bgV                     @   s4  d dl Z d dl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 d dl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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/m0Z0m1Z1 d dl2m3Z3m4Z4m5Z5 d dl6m7Z7m8Z8m9Z9 d dl:m;Z; d dl<m=Z=m>Z>m?Z? d dl@mAZA d dlBmCZC d dlDmEZEmFZFmGZGmHZH d dlImJZJ e5e4dddZKeLeLdddZMe
e  ee
eeLef  e
e  f dddZNe
e  eeLef ddd ZOe e
d!d"d#ZPeeLef ee
e$ e
e" f d$d%d&ZQG d'd( d(eZRdS ))    N)
itemgetter)AnyAsyncIteratorCallableDictIteratorListLiteralOptionalSequenceTupleTypeUnioncast)ClientSession)AsyncCallbackManagerForLLMRunCallbackManagerForLLMRun)LanguageModelInput)BaseChatModelagenerate_from_streamgenerate_from_stream)	AIMessageAIMessageChunkBaseMessageHumanMessageInvalidToolCallSystemMessageToolCallToolMessage)invalid_tool_call)	tool_call)tool_call_chunk)OutputParserLike)JsonOutputKeyToolsParserPydanticToolsParser)ChatGenerationChatGenerationChunk
ChatResult)RunnableRunnableMapRunnablePassthrough)BaseTool)convert_to_secret_strget_from_dict_or_envpre_initconvert_to_openai_tool)is_basemodel_subclass)	BaseModel
ConfigDictField	SecretStr)Requests)generated_resultreturnc                 C   s`   | j d j}t|trL|jd urLdd t|jD }t|j|d}t|dS t	t| j d S d S )Nr   c                 S   s2   g | ]*\}}t |d  t|d |d |dqS )nameargsid)r9   r:   r;   index)create_tool_call_chunkjsondumps).0idxr     rB   t/var/www/html/cobodadashboardai.evdpl.com/venv/lib/python3.9/site-packages/langchain_community/chat_models/edenai.py
<listcomp>D   s   z._result_to_chunked_message.<locals>.<listcomp>)contenttool_call_chunksmessage)
generationsrH   
isinstancer   
tool_calls	enumerater   rE   r&   r   )r7   rH   rF   Zmessage_chunkrB   rB   rC   _result_to_chunked_messageA   s    	
rM   )typer8   c                 C   s0   ddddd}| |v r||  S t d|  d S )NZ	assistantuser)ZaiZhumanZchatr   zUnknown type: )
ValueError)rN   Zrole_mappingrB   rB   rC   _message_roleV   s    rQ   )messagesr8   c                 C   sR   g }| dd }t | D ]0}t|trD|j|jdg|}|  q qJq||fS )z
    Get the last langchain tools messages to transform them into edenai tool_results
    Returns tool_results and messages without the extracted tool messages
    N)r;   result)reversedrJ   r   Ztool_call_idrE   pop)rR   tool_resultsother_messagesmsgrB   rB   rC   *_extract_edenai_tool_results_from_messagesd   s    

rY   c           	      C   s   d }g }t tdd | }|r&|d nd}t| \}}t|D ]n\}}t|trh|dkr`td|j}q>t|tr|	d|jd q>||kr>|	t
|j|jt|d	 q>t|d
d|||dS )Nc                 S   s
   t | tS N)rJ   r   )rX   rB   rB   rC   <lambda>}       z)_format_edenai_messages.<locals>.<lambda> r   z4System message must be at beginning of message list.tool)rolerH   )r`   rH   rK   rE   )textZprevious_historyZchatbot_global_actionrV   )listfilterrY   rL   rJ   r   rP   rE   r   appendrQ   rN   '_format_tool_calls_to_edenai_tool_callsgetattr)	rR   systemZformatted_messagesZhuman_messagesZlast_human_messagerV   rW   irH   rB   rB   rC   _format_edenai_messagesy   s0    

	
ri   )rH   r8   c              	   C   s   t | dg }t | dg }g }|D ](}||d|d|dd q |D ]T}|di }zt|}W n ty   t|}Y n0 |||d |d d qN|S )NrK   invalid_tool_callsr:   r;   r9   )	argumentsr;   r9   )rf   rd   getr>   r?   	TypeErrorstr)rH   rK   rj   Zedenai_tool_callsr   r    Z	tool_argsrk   rB   rB   rC   re      s.    re   )provider_responser8   c                 C   s   g }g }|  di d }| d }r|D ]}z*|t|d t|d |d d W q* tjy } z:|t| d| d| dd| d	 W Y d }~q*d }~0 0 q*||fS )
NrH      rK   r9   rk   r;   )r9   r:   r;   zReceived JSONDecodeError )r9   r:   r;   error)rl   rd   create_tool_callr>   loadsJSONDecodeErrorcreate_invalid_tool_call)ro   rK   rj   rH   Zraw_tool_callsZraw_tool_callexcrB   rB   rC   (_extract_tool_calls_from_edenai_response   s.    	rw   c                	       sb  e Zd ZU dZdZeed< dZee ed< dZ	e
ed< dZee ed	< d
Zeed< dZee ed< dZeed< edddZee ed< eddZeeedddZeedddZeedddZeedddZd4ee eee  ee  e!e"e# ddd Z$d5ee eee  ee% e!e&e# dd!d"Z'dd#e(e)eee!f e*e+ e,e-f  ee)e.ee/d$ ef  e!e0e1ef d% fd&d'Z2d
d(e)ee*e+ f ee!e0e1e)ee+f f d)d*d+Z3d6ee eee  ee  e!e4dd,d-Z5d7ee eee  ee% e!e4dd.d/Z6ee eee  ee  e!e#dd0d1Z7ee eee  ee% e!e#dd2d3Z8  Z9S )8
ChatEdenAIa(	  `EdenAI` chat large language models.

    `EdenAI` is a versatile platform that allows you to access various language models
    from different providers such as Google, OpenAI, Cohere, Mistral and more.

    To get started, make sure you have the environment variable ``EDENAI_API_KEY``
    set with your API key, or pass it as a named parameter to the constructor.

    Additionally, `EdenAI` provides the flexibility to choose from a variety of models,
    including the ones like "gpt-4".

    Example:
        .. code-block:: python

            from langchain_community.chat_models import ChatEdenAI
            from langchain_core.messages import HumanMessage

            # Initialize `ChatEdenAI` with the desired configuration
            chat = ChatEdenAI(
                provider="openai",
                model="gpt-4",
                max_tokens=256,
                temperature=0.75)

            # Create a list of messages to interact with the model
            messages = [HumanMessage(content="hello")]

            # Invoke the model with the provided messages
            chat.invoke(messages)

    `EdenAI` goes beyond mere model invocation. It empowers you with advanced features :

    - **Multiple Providers**: access to a diverse range of llms offered by various
     providers giving you the freedom to choose the best-suited model for your use case.

    - **Fallback Mechanism**: Set a fallback mechanism to ensure seamless operations
        even if the primary provider is unavailable, you can easily switches to an
        alternative provider.

    - **Usage Statistics**: Track usage statistics on a per-project
    and per-API key basis.
    This feature allows you to monitor and manage resource consumption effectively.

    - **Monitoring and Observability**: `EdenAI` provides comprehensive monitoring
    and observability tools on the platform.

    Example of setting up a fallback mechanism:
        .. code-block:: python

            # Initialize `ChatEdenAI` with a fallback provider
            chat_with_fallback = ChatEdenAI(
                provider="openai",
                model="gpt-4",
                max_tokens=256,
                temperature=0.75,
                fallback_provider="google")

    you can find more details here : https://docs.edenai.co/reference/text_chat_create
    ZopenaiproviderNmodel   
max_tokensr   temperatureF	streamingfallback_providerszhttps://api.edenai.run/v2edenai_api_urlzEdenAI API Token)descriptionedenai_api_keyZforbid)extra)valuesr8   c                 C   s   t t|dd|d< |S )z,Validate that api key exists in environment.r   ZEDENAI_API_KEY)r,   r-   )clsr   rB   rB   rC   validate_environment0  s    
zChatEdenAI.validate_environment)r8   c                  C   s   ddl m}  d|  S )Nr   __version__z
langchain/)Zlangchain_communityr   r   rB   rB   rC   get_user_agent8  s    zChatEdenAI.get_user_agentc                 C   s   dS )zReturn type of chat model.zedenai-chatrB   selfrB   rB   rC   	_llm_type>  s    zChatEdenAI._llm_typec                 C   s   | j r| j  S dS )Nr^   )r   Zget_secret_valuer   rB   rB   rC   _api_keyC  s    
zChatEdenAI._api_key)rR   stoprun_managerkwargsr8   c                 k   s  d|v r&| j |f||d|V  dS | j d}d| j |  d}t|d}| j| j| j| jd||}d	d
 |	 D }| j
dur| j| j
i|d< t|d}	|	j||dd}
|
  |
 D ]D}t| }|d }tt|dd}|r|j||d |V  qdS )#Call out to EdenAI's chat endpoint.available_toolsr   r   N/text/chat/streamBearer Authorizationz
User-AgentrR   	providersr|   r}   r   c                 S   s   i | ]\}}|d ur||qS rZ   rB   r@   kvrB   rB   rC   
<dictcomp>e  r\   z&ChatEdenAI._stream.<locals>.<dictcomp>settingsheadersT)urldatastreamra   rE   rG   )chunk)_stream_with_tools_as_generater   r   r   ri   ry   r|   r}   r   itemsrz   r6   postraise_for_status
iter_linesr>   rs   decoder&   r   on_llm_new_token)r   rR   r   r   r   r   r   formatted_datapayloadrequestresponsechunk_responser   tokencg_chunkrB   rB   rC   _streamI  sH    

	

zChatEdenAI._streamc              
   K  s  d|v r,| j |f||d|I d H V  d S | j d}d| j |  d}t|d}| j| j| j| jd||}dd	 |	 D }| j
d ur| j| j
i|d
< t 4 I d H }	|	j|||d4 I d H }
|
  |
j2 zV3 d H W }t| }|d }tt|dd}|r*|j|d |dI d H  |V  q6 W d   I d H  qb1 I d H sX0    Y  W d   I d H  q1 I d H s0    Y  d S )Nr   r   r   r   r   r   r   c                 S   s   i | ]\}}|d ur||qS rZ   rB   r   rB   rB   rC   r     r\   z'ChatEdenAI._astream.<locals>.<dictcomp>r   r>   r   ra   r   rG   )r   r   ) _astream_with_tools_as_agenerater   r   r   ri   ry   r|   r}   r   r   rz   r   r   r   rE   r>   rs   r   r&   r   r   )r   rR   r   r   r   r   r   r   r   sessionr   r   r   r   r   rB   rB   rC   _astreamv  sP    

	
zChatEdenAI._astreamtool_choice)autononerequiredany)toolsr   r   r8   c                   s6   dd |D }|dkrdn|}t  jf ||d|S )Nc                 S   s   g | ]}t |d  qS )functionr/   )r@   r_   rB   rB   rC   rD     r\   z)ChatEdenAI.bind_tools.<locals>.<listcomp>r   r   )r   r   )superbind)r   r   r   r   Zformatted_toolsZformatted_tool_choice	__class__rB   rC   
bind_tools  s    	zChatEdenAI.bind_tools)include_raw)schemar   r   r8   c          
      K   s   |rt d| | j|gdd}t|trDt|rDt|gdd}nt|d d }t|dd}|rtj	t
d	|B d
d d}tj	dd d}|j|gdd}	t|d|	B S ||B S d S )NzReceived unsupported arguments r   r   T)r   first_tool_onlyr   r9   )key_namer   rawc                 S   s   d S rZ   rB   _rB   rB   rC   r[     r\   z3ChatEdenAI.with_structured_output.<locals>.<lambda>)parsedparsing_errorc                 S   s   d S rZ   rB   r   rB   rB   rC   r[     r\   )r   r   )Zexception_key)r   )rP   r   rJ   rN   r1   r$   r0   r#   r*   Zassignr   Zwith_fallbacksr)   )
r   r   r   r   ZllmZoutput_parserr   Zparser_assignZparser_noneZparser_with_fallbackrB   rB   rC   with_structured_output  s*    z!ChatEdenAI.with_structured_outputc                 K   sZ  | j r:d|v rtd n | j|f||d|}t|S | j d}d| j |  d}t|d}| j	| j
| j| jd||}	d	d
 |	 D }	| jdur| j	| ji|	d< t|d}
|
j||	d}|  | }|| j	 }| jr|| j}|r|}|ddkr&|di d}t|t|\}}ttt|d pDd||ddg|dS )r   r   8stream: Tool use is not yet supported in streaming mode.r   
/text/chatr   r   r   r   c                 S   s   i | ]\}}|d ur||qS rZ   rB   r   rB   rB   rC   r     r\   z(ChatEdenAI._generate.<locals>.<dictcomp>Nr   r   )r   r   statusfailrq   rH   generated_textr^   )rE   rK   rj   rG   rI   Z
llm_output)r~   warningswarnr   r   r   r   r   ri   ry   r|   r}   r   r   rz   r6   r   r   r>   rl   	Exceptionrw   r'   r%   r   )r   rR   r   r   r   stream_iterr   r   r   r   r   r   r   ro   fallback_responseerr_msgrK   rj   rB   rB   rC   	_generate  sp    

	


	zChatEdenAI._generatec              
      s  | j r@d|v rtd n&| j|f||d|}t|I d H S | j d}d| j |  d}t|d}| j	| j
| j| jd||}	d	d
 |	 D }	| jd ur| j	| ji|	d< t 4 I d H  }
|
j||	|d4 I d H }|  | I d H }|| j	 }| jr || j}|r |}|ddkrJ|di d}t|ttt|d ddg|dW  d   I d H  W  d   I d H  S 1 I d H s0    Y  W d   I d H  q1 I d H s0    Y  d S )Nr   r   r   r   r   r   r   r   c                 S   s   i | ]\}}|d ur||qS rZ   rB   r   rB   rB   rC   r   >  r\   z)ChatEdenAI._agenerate.<locals>.<dictcomp>r   r   r   r   rq   rH   r   r   rG   r   )r~   r   r   r   r   r   r   r   ri   ry   r|   r}   r   r   rz   r   r   r   r>   rl   r   r'   r%   r   )r   rR   r   r   r   r   r   r   r   r   r   r   r   ro   r   r   rB   rB   rC   
_agenerate  sf    

	

zChatEdenAI._ageneratec                 K   s*   t d | j|f||d|}t|S Nr   r   )r   r   r   rM   r   rR   r   r   r   rS   rB   rB   rC   r   ]  s    
z)ChatEdenAI._stream_with_tools_as_generatec                    s0   t d | j|f||d|I d H }t|S r   )r   r   r   rM   r   rB   rB   rC   r   h  s    
z+ChatEdenAI._astream_with_tools_as_agenerate)NN)NN)NN)NN):__name__
__module____qualname____doc__ry   rn   __annotations__rz   r
   r|   intr}   floatr~   boolr   r   r4   r   r5   r3   Zmodel_configr.   r   r   staticmethodr   propertyr   r   r   r   r   r   r   r&   r   r   r   r   r   r   r   r2   r   r+   dictr	   r(   r   r   r   r'   r   r   r   r   __classcell__rB   rB   r   rC   rx      s   
<  
0  
5
#  
L  
B

rx   )Sr>   r   operatorr   typingr   r   r   r   r   r   r	   r
   r   r   r   r   r   Zaiohttpr   Zlangchain_core.callbacksr   r   Zlangchain_core.language_modelsr   Z*langchain_core.language_models.chat_modelsr   r   r   Zlangchain_core.messagesr   r   r   r   r   r   r   r   Zlangchain_core.messages.toolr   ru   r    rr   r!   r=   Z"langchain_core.output_parsers.baser"   Z*langchain_core.output_parsers.openai_toolsr#   r$   Zlangchain_core.outputsr%   r&   r'   Zlangchain_core.runnablesr(   r)   r*   Zlangchain_core.toolsr+   Zlangchain_core.utilsr,   r-   r.   Z%langchain_core.utils.function_callingr0   Zlangchain_core.utils.pydanticr1   Zpydanticr2   r3   r4   r5   Z&langchain_community.utilities.requestsr6   rM   rn   rQ   rY   ri   re   rw   rx   rB   rB   rB   rC   <module>   s@   <(
 
