o
    Zh8                     @  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
rddl0m1Z1m2Z2m3Z3m4Z4 ddl5m6Z6 e7e8Z9eG dd dZ:d0ddZ;d1ddZ<d2d d!Z=d3d$d%Z>d4d(d)Z?ed*d+d,d-G d.d/ d/e*eZ@dS )5z1Wrapper 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   _/var/www/html/lang_env/lib/python3.10/site-packages/langchain_community/chat_models/vertexai.pyr&   6   s   
 r&   r(   List[BaseMessage]returnc           	      C  s   ddl m} g d}}t| D ]F\}}tt|j}|dkr%t|tr%|}qt|tr7||jdd}|	| qt|t
rI||jdd}|	| qtdt| d| d	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)contentZ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"   


rE   sr<   boolc              
   C  sR   zt | }t|j|jgW S  ty( } ztd|  W Y d }~dS d }~ww )NzUnable to parse URL: F)r   allschemenetloc	Exceptionloggerdebug)rF   resulter1   r1   r2   _is_url^   s   rP   projectr)   List['Content']c           
        s   ddl m}m m d fddg }t| D ]M\}}|dkr*t|tr*td	t|tr2d
}nt|t	r:d}ntdt
| d| d|j}t|trR|g}fdd|D }|||d}	||	 q|S )Nr   )r%   ImagePartpartUnion[str, Dict]r4   rT   c                   s  t | tr
| S t | tstdt|  d| d dkr&| d S | d dkrx| d d }|dr>t|d}n>|d	r^t	d
|}|rQ|
d}ntd t|}nt|rrt|}|   |j}n
 |}ntd|S )Nz0Message's content is expected to be a dict, got !r@   textZ	image_urlurlzgs://)pathrQ   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?   r@   
startswithr   researchgroup
from_bytesbase64	b64decoderP   requestsgetraise_for_statusr5   Zload_from_fileZ
from_image)rU   rZ   imageencodedresponse)rS   rT   rQ   r1   r2   _convert_to_promptl   s6   






z6_parse_chat_history_gemini.<locals>._convert_to_promptz%SystemMessages are not yet supported!modelr6   r7   r8   r9   c                   s   g | ]} |qS r1   r1   ).0rU   )ri   r1   r2   
<listcomp>   s    z._parse_chat_history_gemini.<locals>.<listcomp>)roleparts)rU   rV   r4   rT   )"vertexai.preview.generative_modelsr%   rS   rT   r;   r=   r   r?   r   r   r@   r5   r<   r>   )
r(   rQ   r%   rA   rB   rC   rm   Zraw_contentrn   rD   r1   )rS   rT   ri   rQ   r2   _parse_chat_history_geminig   s(   #


rp   examplesList['InputOutputTextPair']c                 C  s   ddl m} t| d dkrtdt|  dg }d }t| D ]C\}}|d dkr?t|ts<tdt| d| d|j}|d d	krct|t	sWtd
t| d| d|||jd}|
| q |S )Nr   )r$      z8Expect examples to have an even amount of messages, got r9   z;Expected the first message in a part to be from human, got z	 for the zth message.r[   z9Expected the second message in a part to be from AI, got )
input_textZoutput_text)r:   r$   lenr?   r;   r=   r   r@   r5   r   r>   )rq   r$   Zexample_pairsrt   rB   Zexamplepairr1   r1   r2   _parse_examples   sB   


rw   messagesr   c                 C  s4   | st d| d }t|tst 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 r9   )r?   r=   r   r@   )rx   questionr1   r1   r2   _get_question   s   
r{   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Zed,ddZ	e
d-ddZ			d.d/ddZ		d0d1d!d"Z		d0d2d$d%Zd3d)d*ZdS )4ChatVertexAIz+`Vertex AI` Chat large language models API.z
chat-bisonr<   
model_nameNzOptional[List[BaseMessage]]rq   r4   rG   c                 C  s   dS )NTr1   )selfr1   r1   r2   is_lc_serializable   s   zChatVertexAI.is_lc_serializable	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_namespacevaluesr   c                 C  s   t |d }| | zddlm}m} |rddlm} W n ty)   t  Y nw |r7||d d|d< |S 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_environmentrx   r3   stopOptional[List[str]]run_manager"Optional[CallbackManagerForLLMRun]streamOptional[bool]kwargsr   r   c                 K  s  |dur|n| j }|r| j|f||d|}t|S t|}| jd|dd|}	i }
d|	v r7|	d|
d< | jrTt|| jd}| }| j	j
|d}|j||	d}n+t|dd	 }|d
pc| j}|rlt||	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rQ   r(   generation_configry   rq   c                 S     g | ]}t t|jd dqS r5   rC   r   r   rX   rk   rr1   r1   r2   rl   ,      z*ChatVertexAI._generate.<locals>.<listcomp>generationsr1   )Z	streaming_streamr   r{   _prepare_paramspop_is_gemini_modelrp   rQ   r   
start_chatsend_messagerE   rd   rq   rw   _start_chatr5   
candidatesr   )r~   rx   r   r   r   r   Zshould_streamZstream_iterrz   params
msg_paramshistory_geminirC   chatrh   r(   rq   r   r1   r1   r2   	_generate   s<   
zChatVertexAI._generate'Optional[AsyncCallbackManagerForLLMRun]c                   s  d|v r| d td | jdd|i|}i }d|v r&| d|d< | jrFt|| jd}|  }| jj|d}	|	j	||dI dH }
n0t
|}t|dd	 }|d
d}|r`t||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   Nry   rq   c                 S  r   r   r   r   r1   r1   r2   rl   ^  r   z+ChatVertexAI._agenerate.<locals>.<listcomp>r   r1   )r   rL   warningr   r   rp   rQ   r   r   Zsend_message_asyncr{   rE   rd   rw   r   r5   r   r   )r~   rx   r   r   r   r   r   r   rC   r   rh   rz   r(   rq   r   r1   r1   r2   
_agenerate2  s0   


zChatVertexAI._agenerateIterator[ChatGenerationChunk]c                 k  s    | j d|dd|}| jr*t|| jd}| }| jj|d}|j|d|d}	n-t|}
t	|d d }|
dd }|rDt||d< | j|fi |}|j|
jfi |}	|	D ]}tt|jdd	}|rn|j|j|d
 |V  qYd S )NTr   r   r   )r   r   ry   rq   r   r   )chunkr1   )r   r   rp   rQ   r   r   r   r   r{   rE   rd   rw   r   Zsend_message_streamingr5   r   r   rX   Zon_llm_new_token)r~   rx   r   r   r   r   r   rC   r   	responsesrz   r(   rq   rh   r   r1   r1   r2   r   d  s,   zChatVertexAI._streamr(   r&   #Union[ChatSession, CodeChatSession]c                 K  s:   | j s| jjd|j|jd|S | jjdd|ji|S )N)r*   message_historyr   r1   )r   r   r   r*   r(   )r~   r(   r   r1   r1   r2   r     s   zChatVertexAI._start_chat)r4   rG   )r4   r   )r   r   r4   r   )NNN)rx   r3   r   r   r   r   r   r   r   r   r4   r   )NN)
rx   r3   r   r   r   r   r   r   r4   r   )
rx   r3   r   r   r   r   r   r   r4   r   )r(   r&   r   r   r4   r   )r+   r,   r-   r.   r}   r0   rq   classmethodr   r   r   r   r   r   r   r   r1   r1   r1   r2   r|      s,   
 95r|   )r(   r3   r4   r&   )rF   r<   r4   rG   )r(   r3   rQ   r)   r4   rR   )rq   r3   r4   rr   )rx   r3   r4   r   )Ar.   
__future__r   ra   loggingr]   dataclassesr   r   typingr   r   r   r   r	   r
   r   r   urllib.parser   rc   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+   rL   r&   rE   rP   rp   rw   r{   r|   r1   r1   r1   r2   <module>   sD    (


 
	
>
