o
    ưiC                     @  s   d Z ddlmZ ddlZddl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 dd	lmZ erJdd
lmZ ddlmZ G dd deeZdS )aG  
Vertex AI-specific RAG Ingestion implementation.

Vertex AI RAG Engine handles embedding and chunking internally when files are uploaded,
so this implementation skips the embedding step and directly uploads files to RAG corpora.

Based on: https://docs.cloud.google.com/vertex-ai/generative-ai/docs/model-reference/rag-api-v1
    )annotationsN)TYPE_CHECKINGAnyDictListOptionalTuple)verbose_logger)get_async_httpx_clienthttpxSpecialProvider)get_vertex_base_url)
VertexBase)BaseRAGIngestion)Router)RAGIngestOptionsc                   @  sd   e Zd ZdZ	d.d/ddZd0ddZd1ddZ	d.d2ddZ		d3d4d%d&Zd5d)d*Z	d6d,d-Z
dS )7VertexAIRAGIngestiona  
    Vertex AI RAG Engine ingestion implementation.

    Key differences from base:
    - Embedding is handled by Vertex AI RAG Engine when files are uploaded
    - Files are uploaded using the RAG API (import or upload)
    - Chunking is done by Vertex AI RAG Engine (supports custom chunking config)
    - Supports Google Cloud Storage (GCS) and Google Drive sources
    - Supports custom parsing configurations (layout parser, LLM parser)
    Ningest_options'RAGIngestOptions'routerOptional['Router']c                 C  sP   t j| ||d t|  t| j}| || _| |pd| _| 	|| _
d S )N)r   r   zus-central1)r   __init__r   dictvector_store_configZsafe_get_vertex_ai_project
project_idZget_vertex_ai_locationlocationZsafe_get_vertex_ai_credentialsvertex_credentials)selfr   r   Zlitellm_params r   `/home/app/Keep/.python/lib/python3.10/site-packages/litellm/rag/ingestion/vertex_ai_ingestion.pyr   )   s   

zVertexAIRAGIngestion.__init__chunks	List[str]returnOptional[List[List[float]]]c                   s   dS )z
        Vertex AI RAG Engine handles embedding internally - skip this step.

        Returns:
            None (Vertex AI embeds when files are uploaded to RAG corpus)
        Nr   )r   r   r   r   r   embed9   s   zVertexAIRAGIngestion.embedfile_contentOptional[bytes]filenameOptional[str]content_type
embeddings#Tuple[Optional[str], Optional[str]]c                   sr   | j std| jd}|s!| j| jpd| jddI dH }d}|r5|r5|r5| j||||dI dH }||fS )a
  
        Store content in Vertex AI RAG corpus.

        Vertex AI workflow:
        1. Create RAG corpus (if not provided)
        2. Upload file using RAG API (Vertex AI handles chunking/embedding)

        Args:
            file_content: Raw file bytes
            filename: Name of the file
            content_type: MIME type
            chunks: Ignored - Vertex AI handles chunking
            embeddings: Ignored - Vertex AI handles embedding

        Returns:
            Tuple of (rag_corpus_id, file_id)
        zVvertex_project is required for Vertex AI RAG ingestion. Set it in vector_store config.Zvector_store_idzlitellm-rag-corpusdescription)display_namer+   N)rag_corpus_idr&   r$   r(   )r   
ValueErrorr   get_create_rag_corpusZingest_name_upload_file_to_corpus)r   r$   r&   r(   r   r)   r-   Zresult_file_idr   r   r   storeF   s(   
zVertexAIRAGIngestion.storer,   strr+   c                   s  | j | j| jdd\}}| js|| _t| j}| d| j d| j d}d|i}|r/||d< | jd}|r;||d	< | jd
}	|	rUd	|vrKi |d	< dd|	ii|d	 d< td|  tdt	j
|dd  ttjddid}
|
j||d| dddI dH }|jdvrd|j }t| t||	 }tdt	j
|dd  |dr|di dd }n|dd }td!|  | j||d"I dH }td#|  |S )$a  
        Create a Vertex AI RAG corpus.

        Args:
            display_name: Display name for the corpus
            description: Optional description

        Returns:
            RAG corpus ID (format: projects/{project}/locations/{location}/ragCorpora/{corpus_id})
        	vertex_aicredentialsr   Zcustom_llm_providerz/v1beta1/projects/z/locations/z/ragCorporaZdisplayNamer+   vector_db_configZvectorDbConfigembedding_modelZvertexPredictionEndpointZendpointZragEmbeddingModelConfigzCreating RAG corpus: Request body:    indenttimeout      N@Zllm_providerparamsBearer application/jsonAuthorizationzContent-TypejsonheadersN      zFailed to create RAG corpus: zCreate corpus response: doneresponsename zPolling operation: )operation_nameaccess_tokenzCreated RAG corpus: )_ensure_access_tokenr   r   r   r   r   r/   r	   debugrF   dumpsr
   r   RAGpoststatus_codetexterror	Exception_poll_operation)r   r,   r+   rP   r   base_urlurlrequest_bodyr7   r8   clientrL   	error_msgresponse_datacorpus_namerO   r   r   r   r0   y   sv   




z'VertexAIRAGIngestion._create_rag_corpus          @rO   rP   max_retriesintretry_delayfloatc                   s   ddl }t| j}| d| }ttjddid}t|D ]i}	|j|dd| id	I dH }
|
jd
krCd|
j	 }t
| t||
 }|drrd|v r[|d }td| |di dd}|rk|  S td| t
d|	d  d|  ||I dH  qtd| d)a  
        Poll a long-running operation until it completes.

        Args:
            operation_name: The operation name (e.g., "operations/123456")
            access_token: Access token for authentication
            max_retries: Maximum number of polling attempts
            retry_delay: Delay between polling attempts in seconds

        Returns:
            The corpus name from the completed operation

        Raises:
            Exception: If operation fails or times out
        r   N	/v1beta1/r=   r>   r?   rD   rA   )rG   rI   zFailed to poll operation: rK   rX   zOperation failed: rL   rM   rN   z&No corpus name in operation response: z Operation not done yet, attempt    /zOperation timed out after z	 attempts)asyncior   r   r
   r   rT   ranger/   rV   rW   r	   rX   rY   rF   rR   sleep)r   rO   rP   rd   rf   rk   r[   r\   r^   attemptrL   r_   Zoperation_datarX   ra   r   r   r   rZ      s<   




z$VertexAIRAGIngestion._poll_operationr-   bytesc              
     s  | j | j| jdd\}}t| j}| d| d}dd|ii}	| jd}
|
r.|
|	d d< | j}|rnt|t	rn|d	}|d
}|sF|rnd|	vrNi |	d< ddi ii|	d d< |	d d d d }|rh||d	< |rn||d
< t
d|  t
dtj|	dd  dt|	df|||pdfd}ttjddid}|j||d| dddI dH }|jdvrd|j }t
| t|z!| }|d i d!d"}|s|d!d"}t
d#|  |W S  ty } zt
d$|  W Y d}~d%S d}~ww )&aA  
        Upload a file to Vertex AI RAG corpus using multipart upload.

        Args:
            rag_corpus_id: RAG corpus resource name
            filename: Name of the file
            file_content: File content bytes
            content_type: MIME type

        Returns:
            File ID or resource name
        r4   r5   z/upload/v1beta1/z/ragFiles:uploadZrag_filer,   Zfile_descriptionr+   
chunk_sizechunk_overlapZupload_rag_file_configZrag_file_chunking_configZfixed_length_chunkingZrag_file_transformation_configzUploading file to RAG corpus: z
Metadata: r:   r;   NrB   zapplication/octet-stream)metadatafiler=   g     r@r?   rA   	multipart)rD   zX-Goog-Upload-Protocol)filesrG   rH   zFailed to upload file: ZragFilerM   rN   zUpload complete. File ID: z!Could not parse upload response: Zuploaded)rQ   r   r   r   r   r   r/   chunking_strategy
isinstancer   r	   rR   rF   rS   r
   r   rT   rU   rV   rW   rX   rY   warning)r   r-   r&   r$   r(   rP   _r[   r\   rr   r+   rv   rp   rq   Zchunking_configru   r^   rL   r_   r`   Zfile_ider   r   r   r1     s   




	
z+VertexAIRAGIngestion._upload_file_to_corpusgcs_urisc                   sX  | j | j| jdd\}}t| j}| d| d}ddd|iii}| j}|rGt|trG|d}	|d	}
|	s:|
rG|	p=d
|
p@dd|d d< | j	d}|rU||d d< t
d|  t
dtj|dd  ttjddid}|j||d| dddI dH }|jdvrd|j }t
| t|| }|dd}t
d |  |S )!a  
        Import files from Google Cloud Storage into RAG corpus.

        Args:
            rag_corpus_id: RAG corpus resource name
            gcs_uris: List of GCS URIs (e.g., ["gs://bucket/file.pdf"])

        Returns:
            Operation name for tracking import progress
        r4   r5   rh   z/ragFiles:importZimportRagFilesConfigZ	gcsSourceurisrp   rq   i   rI   )Z	chunkSizeZchunkOverlapZragFileChunkingConfigZmax_embedding_requests_per_minZmaxEmbeddingRequestsPerMinzImporting files from GCS: r9   r:   r;   r=   r>   r?   rA   rB   rC   rE   NrH   zFailed to import files: rM   rN   zImport operation started: )rQ   r   r   r   r   rv   rw   r   r/   r   r	   rR   rF   rS   r
   r   rT   rU   rV   rW   rX   rY   )r   r-   r{   rP   ry   r[   r\   r]   rv   rp   rq   Zmax_embedding_qpmr^   rL   r_   r`   rO   r   r   r   _import_files_from_gcs  sb   

	


	
z+VertexAIRAGIngestion._import_files_from_gcs)N)r   r   r   r   )r   r    r!   r"   )r$   r%   r&   r'   r(   r'   r   r    r)   r"   r!   r*   )r,   r3   r+   r'   r!   r3   )rb   rc   )
rO   r3   rP   r3   rd   re   rf   rg   r!   r3   )
r-   r3   r&   r3   r$   ro   r(   r'   r!   r3   )r-   r3   r{   r    r!   r3   )__name__
__module____qualname____doc__r   r#   r2   r0   rZ   r1   r}   r   r   r   r   r      s    

6f
Cor   )r   
__future__r   rF   typingr   r   r   r   r   r   Zlitellm._loggingr	   Z&litellm.llms.custom_httpx.http_handlerr
   r   Z#litellm.llms.vertex_ai.common_utilsr   Z&litellm.llms.vertex_ai.vertex_llm_baser   Z$litellm.rag.ingestion.base_ingestionr   Zlitellmr   Zlitellm.types.ragr   r   r   r   r   r   <module>   s    	 