a
    bg8                     @  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 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ZddlmZ ddlmZmZ dd	lmZmZ dd
l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*m+Z+m,Z, ddl-m.Z.m/Z/ e
r*ddl0m1Z1m2Z2m3Z3m4Z4 ddl5m6Z6 e7e8Z9eG dd dZ:dddddZ;dddddZ<dddddd Z=dd!d"d#d$Z>dd%d&d'd(Z?ed)d*d+d,G d-d. d.e*eZ@dS )/z1Wrapper around Google VertexAI chat-based models.    )annotationsN)	dataclassfield)TYPE_CHECKINGAnyDictIteratorListOptionalUnioncast)urlparse)
deprecated)AsyncCallbackManagerForLLMRunCallbackManagerForLLMRun)BaseChatModelgenerate_from_stream)	AIMessageAIMessageChunkBaseMessageHumanMessageSystemMessage)ChatGenerationChatGenerationChunk
ChatResult)pre_init)_VertexAICommonis_codey_modelis_gemini_model)load_image_from_gcsraise_vertex_import_error)ChatMessageChatSessionCodeChatSessionInputOutputTextPair)Contentc                   @  s0   e Zd ZU dZeedZded< dZded< dS )_ChatHistoryz/Represents a context and a history of messages.)default_factoryzList['ChatMessage']historyNOptional[str]context)	__name__
__module____qualname____doc__r   listr(   __annotations__r*    r1   r1   v/var/www/html/cobodadashboardai.evdpl.com/venv/lib/python3.9/site-packages/langchain_community/chat_models/vertexai.pyr&   6   s   
r&   List[BaseMessage])r(   returnc           	      C  s   ddl m} g d }}t| D ]\}}tt|j}|dkrJt|trJ|}qt|trn||jdd}|	| qt|t
r||jdd}|	| qtdt| d| d	qt||d
}|S )a  Parse a sequence of messages into history.

    Args:
        history: The list of messages to re-create the history of the chat.
    Returns:
        A parsed chat history.
    Raises:
        ValueError: If a sequence of message has a SystemMessage not at the
        first place.
    r   )r!   NZbot)contentauthoruserUnexpected message with type  at the position .)r*   r(   )vertexai.language_modelsr!   	enumerater   strr5   
isinstancer   r   appendr   
ValueErrortyper&   )	r(   r!   vertex_messagesr*   imessager5   vertex_messageZchat_historyr1   r1   r2   _parse_chat_history>   s"    


rF   r=   bool)sr4   c              
   C  sV   zt | }t|j|jgW S  tyP } ztd|  W Y d }~dS d }~0 0 d S )NzUnable to parse URL: F)r   allschemenetloc	Exceptionloggerdebug)rH   resulter1   r1   r2   _is_url^   s    rQ   r)   zList['Content'])r(   projectr4   c           
        s   ddl m}m m ddd fddg }t| D ]\}}|dkr\t|tr\tdn:t|trld	}n*t|t	r|d
}ntdt
| d| d|j}t|tr|g}fdd|D }|||d}	||	 q8|S )Nr   )r%   ImagePartzUnion[str, Dict]rT   )partr4   c                   s  t | tr| S t | ts2tdt|  d| d dkrL| d S | d dkr| d d }|dr|t|d}q|d	rt	d
|}|r|
d}ntd t|}qt|rt|}|   |j}q |}ntd|S )Nz0Message's content is expected to be a dict, got !rA   textZ	image_urlurlzgs://)pathrR   zdata:image/zdata:image/\w{2,4};base64,(.*)   zdInvalid image uri. It should be in the format data:image/<image_type>;base64,<base64_encoded_image>.z,Only text and image_url types are supported!)r>   r=   Z	from_textr   r@   rA   
startswithr   researchgroup
from_bytesbase64	b64decoderQ   requestsgetraise_for_statusr5   Zload_from_fileZ
from_image)rU   rY   imageencodedresponse)rS   rT   rR   r1   r2   _convert_to_promptl   s6    





z6_parse_chat_history_gemini.<locals>._convert_to_promptz%SystemMessages are not yet supported!modelr7   r8   r9   r:   c                   s   g | ]} |qS r1   r1   ).0rU   )rh   r1   r2   
<listcomp>       z._parse_chat_history_gemini.<locals>.<listcomp>)roleparts)"vertexai.preview.generative_modelsr%   rS   rT   r<   r>   r   r@   r   r   rA   r5   r=   r?   )
r(   rR   r%   rB   rC   rD   rm   Zraw_contentrn   rE   r1   )rS   rT   rh   rR   r2   _parse_chat_history_geminig   s(    #



rp   zList['InputOutputTextPair'])examplesr4   c                 C  s   ddl m} t| d dkr0tdt|  dg }d }t| D ]\}}|d dkr~t|tsxtdt| d| d|j}|d d	kr@t|t	std
t| d| d|||jd}|
| q@|S )Nr   )r$      z8Expect examples to have an even amount of messages, got r:   z;Expected the first message in a part to be from human, got z	 for the zth message.rZ   z9Expected the second message in a part to be from AI, got )
input_textZoutput_text)r;   r$   lenr@   r<   r>   r   rA   r5   r   r?   )rq   r$   Zexample_pairsrs   rC   Zexamplepairr1   r1   r2   _parse_examples   s@    

rv   r   )messagesr4   c                 C  s4   | st d| d }t|ts0t d|j d|S )zMGet the human message at the end of a list of input messages to a chat model.z:You should provide at least one message to start the chat!z3Last message in the list should be from human, got r:   )r@   r>   r   rA   )rw   questionr1   r1   r2   _get_question   s    
rz   z0.0.12z1.0z&langchain_google_vertexai.ChatVertexAI)ZsinceZremovalZalternative_importc                   @  s   e Zd ZU dZdZded< dZded< edd	d
dZedd	ddZ	e
dddddZd(dddddddddZd)ddddddddZd*ddddd dd!d"Zd#dd$d%d&d'ZdS )+ChatVertexAIz+`Vertex AI` Chat large language models API.z
chat-bisonr=   
model_nameNzOptional[List[BaseMessage]]rq   rG   )r4   c                 C  s   dS )NTr1   )selfr1   r1   r2   is_lc_serializable   s    zChatVertexAI.is_lc_serializablez	List[str]c                 C  s   g dS )z*Get the namespace of the langchain object.)Z	langchainZchat_modelsZvertexair1   )clsr1   r1   r2   get_lc_namespace   s    zChatVertexAI.get_lc_namespacer   )valuesr4   c                 C  s   t |d }| | z$ddlm}m} |r8ddlm} W n tyR   t  Y n0 |rl||d d|d< n(t	|d r~|}n|}|
|d |d< |S )z7Validate that the python package exists in environment.r|   r   )	ChatModelCodeChatModel)GenerativeModel)r|   client)r   Z_try_init_vertexair;   r   r   ro   r   ImportErrorr    r   Zfrom_pretrained)r   r   Z	is_geminir   r   r   Z	model_clsr1   r1   r2   validate_environment   s    
z!ChatVertexAI.validate_environmentr3   zOptional[List[str]]z"Optional[CallbackManagerForLLMRun]zOptional[bool]r   r   )rw   stoprun_managerstreamkwargsr4   c                 K  s  |dur|n| j }|r6| j|f||d|}t|S t|}| jf |dd|}	i }
d|	v rn|	d|
d< | jrt|| jd}| }| j	j
|d}|j||	d}nVt|dd	 }|d
p| j}|rt||	d
< | j|fi |	}|j|jfi |
}dd |jD }t|dS )a>  Generate next turn in the conversation.

        Args:
            messages: The history of the conversation as a list of messages. Code chat
                does not support context.
            stop: The list of stop words (optional).
            run_manager: The CallbackManager for LLM run, it's not used at the moment.
            stream: Whether to use the streaming endpoint.

        Returns:
            The ChatResult that contains outputs generated by the model.

        Raises:
            ValueError: if the last message in the list is not from human.
        N)r   r   Fr   r   candidate_countrR   r(   generation_configrx   rq   c                 S  s   g | ]}t t|jd dqS r5   rD   r   r   rW   rj   rr1   r1   r2   rk   ,  s   z*ChatVertexAI._generate.<locals>.<listcomp>generations)Z	streaming_streamr   rz   _prepare_paramspop_is_gemini_modelrp   rR   r   
start_chatsend_messagerF   rc   rq   rv   _start_chatr5   
candidatesr   )r}   rw   r   r   r   r   Zshould_streamZstream_iterry   params
msg_paramshistory_geminirD   chatrg   r(   rq   r   r1   r1   r2   	_generate   s<    zChatVertexAI._generatez'Optional[AsyncCallbackManagerForLLMRun])rw   r   r   r   r4   c                   s  d|v r| d td | jf d|i|}i }d|v rJ| d|d< | jrt|| jd}|  }| jj|d}	|	j	||dI dH }
n`t
|}t|dd	 }|d
d}|rt||d
< | j|fi |}	|	j	|jfi |I dH }
dd |
jD }t|dS )a  Asynchronously generate next turn in the conversation.

        Args:
            messages: The history of the conversation as a list of messages. Code chat
                does not support context.
            stop: The list of stop words (optional).
            run_manager: The CallbackManager for LLM run, it's not used at the moment.

        Returns:
            The ChatResult that contains outputs generated by the model.

        Raises:
            ValueError: if the last message in the list is not from human.
        r   z8ChatVertexAI does not currently support async streaming.r   r   r   r   r   Nrx   rq   c                 S  s   g | ]}t t|jd dqS r   r   r   r1   r1   r2   rk   ^  s   z+ChatVertexAI._agenerate.<locals>.<listcomp>r   )r   rM   warningr   r   rp   rR   r   r   Zsend_message_asyncrz   rF   rc   rv   r   r5   r   r   )r}   rw   r   r   r   r   r   r   rD   r   rg   ry   r(   rq   r   r1   r1   r2   
_agenerate2  s.    

zChatVertexAI._ageneratezIterator[ChatGenerationChunk]c                 k  s   | j f |dd|}| jrRt|| jd}| }| jj|d}|j|d|d}	nZt|}
t	|d d }|
dd }|rt||d< | j|fi |}|j|
jfi |}	|	D ]0}tt|jdd	}|r|j|j|d
 |V  qd S )NTr   r   r   )r   r   rx   rq   r   r   )chunk)r   r   rp   rR   r   r   r   r   rz   rF   rc   rv   r   Zsend_message_streamingr5   r   r   rW   Zon_llm_new_token)r}   rw   r   r   r   r   r   rD   r   	responsesry   r(   rq   rg   r   r1   r1   r2   r   d  s(    zChatVertexAI._streamr&   z#Union[ChatSession, CodeChatSession])r(   r   r4   c                 K  s>   | j s"| jjf |j|jd|S | jjf d|ji|S d S )N)r*   message_historyr   )r   r   r   r*   r(   )r}   r(   r   r1   r1   r2   r     s    zChatVertexAI._start_chat)NNN)NN)NN)r+   r,   r-   r.   r|   r0   rq   classmethodr~   r   r   r   r   r   r   r   r1   r1   r1   r2   r{      s(   
   9  5  r{   )Ar.   
__future__r   r`   loggingr\   dataclassesr   r   typingr   r   r   r   r	   r
   r   r   urllib.parser   rb   Zlangchain_core._api.deprecationr   Zlangchain_core.callbacksr   r   Z*langchain_core.language_models.chat_modelsr   r   Zlangchain_core.messagesr   r   r   r   r   Zlangchain_core.outputsr   r   r   Zlangchain_core.utilsr   Z!langchain_community.llms.vertexair   r   r   Z&langchain_community.utilities.vertexair   r    r;   r!   r"   r#   r$   ro   r%   	getLoggerr+   rM   r&   rF   rQ   rp   rv   rz   r{   r1   r1   r1   r2   <module>   sB   (
 	>