Ë
    uPêjŠG  ã                  ó>  — d 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 ddlmZmZ dd	lmZ dd
lmZ ddlmZ erddlmZ ddlmZ dd„Z G d„ ded¬«      Z G d„ ded¬«      Z G d„ ded¬«      Z G d„ de«      Z G d„ de«      Z  G d„ dee«      Z!y)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)ÚMapping)ÚTYPE_CHECKINGÚFinal)ÚReadOnlyÚ	TypedDict)Úverbose_logger)Úget_async_httpx_clientÚhttpxSpecialProvider)Úget_vertex_base_url)Ú
VertexBase)ÚBaseRAGIngestion)ÚRouter)ÚRAGIngestOptionsc                ó@   — | D ��ci c]  \  }}|sŒ	||“Œ c}}S c c}}w ©N© )ÚfieldsÚnameÚvalues      ún/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/rag/ingestion/vertex_ai_ingestion.pyÚ_present_fieldsr       s    € Ø+1×;™K˜D %²UˆD�%‰KÓ;Ð;ùÓ;s   †
‘c                  ó   — e Zd ZU ded<   y)ÚVertexRagResourceNameúReadOnly[str]r   N)Ú__name__Ú
__module__Ú__qualname__Ú__annotations__r   ó    r   r   r   $   s   … Ø
Ôr    r   F)Útotalc                  ó:   — e Zd ZU dZded<   ded<   ded<   ded	<   y
)ÚVertexRagOperationzNA Vertex AI long-running operation resource, as the RAG Engine API returns it.zReadOnly[bool]Údoner   r   zReadOnly[object]ÚerrorúReadOnly[VertexRagResourceName]ÚresponseN©r   r   r   Ú__doc__r   r   r    r   r#   r#   (   s   … ÙXà
ÓØ
ÓØÓØ-Ô-r    r#   c                  ó&   — e Zd ZU dZded<   ded<   y)ÚVertexRagFileUploadz'Body of a ``ragFiles:upload`` response.r   r   r&   ÚragFileNr(   r   r    r   r+   r+   1   s   … Ù1à
ÓØ,Ô,r    r+   c                  ó   — e Zd ZU dZded<   y)Ú_RagOperationViewzKHolds one decoded long-running operation so the JSON body reads back typed.zReadOnly[VertexRagOperation]Ú	operationNr(   r   r    r   r.   r.   8   s   … ÙUà+Ô+r    r.   c                  ó   — e Zd ZU dZded<   y)Ú_RagFileUploadViewzMHolds one decoded ``ragFiles:upload`` body so the JSON body reads back typed.zReadOnly[VertexRagFileUpload]ÚuploadNr(   r   r    r   r1   r1   >   s   … ÙWà)Ô)r    r1   c                  ó¾   — e Zd ZdZ	 d
	 	 	 dd„Z	 	 	 	 dd„Z	 d
	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Z	 d
	 	 	 	 	 dd„Z	 	 d	 	 	 	 	 	 	 	 	 dd„Z	 	 	 	 	 	 	 	 	 	 dd„Z		 	 	 	 	 	 dd	„Z
y)Ú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)
    Nc                ó  — t        j                  | ||¬«       t        j                  | «       t        | j                  «      }| j                  |«      | _        | j                  |«      xs d| _        | j                  |«      | _
        y )N)Úingest_optionsÚrouterzus-central1)r   Ú__init__r   ÚdictÚvector_store_configÚsafe_get_vertex_ai_projectÚ
project_idÚget_vertex_ai_locationÚlocationÚsafe_get_vertex_ai_credentialsÚvertex_credentials)Úselfr6   r7   Úlitellm_paramss       r   r8   zVertexAIRAGIngestion.__init__P   st   € ô
 	×!Ñ! $°~ÈfÕUÜ×Ñ˜DÔ!ô !% T×%=Ñ%=Ó >ˆð ×9Ñ9¸.ÓIˆŒØ×3Ñ3°NÓCÒTÀ}ˆŒØ"&×"EÑ"EÀnÓ"UˆÕr    c              ƒ  ó   K  — y­w)z±
        Vertex AI RAG Engine handles embedding internally - skip this step.

        Returns:
            None (Vertex AI embeds when files are uploaded to RAG corpus)
        Nr   )rA   Úchunkss     r   ÚembedzVertexAIRAGIngestion.embed`   s   è ø€ ð ùs   ‚c              ƒ  óP  K  — | j                   st        d«      ‚| j                  j                  d«      }|sB| j	                  | j
                  xs d| j                  j                  d«      ¬«      ƒ d{  –—† }d}|r!|r|r| j                  ||||¬«      ƒ d{  –—† }||fS 7 Œ-7 Œ
­w)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
            existing_file_id: Existing provider file ID, unsupported for Vertex AI

        Returns:
            Tuple of (rag_corpus_id, file_id)
        zVvertex_project is required for Vertex AI RAG ingestion. Set it in vector_store config.Úvector_store_idzlitellm-rag-corpusÚdescription)Údisplay_namerH   N)Úrag_corpus_idÚfilenameÚfile_contentÚcontent_type)r<   Ú
ValueErrorr:   ÚgetÚ_create_rag_corpusÚingest_nameÚ_upload_file_to_corpus)	rA   rL   rK   rM   rD   Ú
embeddingsÚexisting_file_idrJ   Úresult_file_ids	            r   ÚstorezVertexAIRAGIngestion.storem   sÀ   è ø€ ð6 �ŠÜÐuÓvÐvð ×0Ñ0×4Ñ4Ð5FÓGˆÙØ"&×"9Ñ"9Ø!×-Ñ-ÒEÐ1EØ ×4Ñ4×8Ñ8¸ÓGð #:ó #÷ ˆMð ˆÙ™H©Ø#'×#>Ñ#>Ø+Ø!Ø)Ø)ð	 $?ó $÷ ˆNð ˜nÐ,Ð,ðøðús$   ‚A2B&Á4B"Á5$B&ÂB$Â	B&Â$B&c              ƒ  óÞ  K  — | j                  | j                  | j                  d¬«      \  }}| j                  s|| _        t        | j                  «      }|› d| j                  › d| j                  › d�}| j
                  j                  d«      }| j
                  j                  d«      }|rdd	d
|iiind}	|	r
i |xs i ¥|	¥n|}
d|it        d|fd|
ff«      ¥}t        j                  d|«       t        j                  dt        j                  |d¬«      «       t        t        j                  ddi¬«      }|j                  ||d|› �ddœ¬«      ƒ d{  –—† }|j                   dvr/d|j"                  › �}t        j$                  |«       t'        |«      ‚d|j                  «       i}|d   }t        j                  dt        j                  |d¬«      «       |j                  d«      r#|j                  di «      j                  d d!«      }nC|j                  d d!«      }t        j                  d"|«       | j)                  ||¬#«      ƒ d{  –—† }t        j                  d$|«       |S 7 �Œ7 Œ­w)%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<   Úcustom_llm_providerz/v1beta1/projects/z/locations/z/ragCorporaÚvector_db_configÚembedding_modelÚragEmbeddingModelConfigÚvertexPredictionEndpointÚendpointNÚdisplayNamerH   ÚvectorDbConfigzCreating RAG corpus: %súRequest body: %sé   ©ÚindentÚtimeoutç      N@©Úllm_providerÚparamsúBearer úapplication/json©ÚAuthorizationzContent-Type©ÚjsonÚheaders©éÈ   éÉ   zFailed to create RAG corpus: r/   zCreate corpus response: %sr$   r'   r   Ú zPolling operation: %s)Úoperation_nameÚaccess_tokenzCreated RAG corpus: %s)Ú_ensure_access_tokenr@   r<   r   r>   r:   rO   r   r	   Údebugrq   Údumpsr
   r   ÚRAGÚpostÚstatus_codeÚtextr%   Ú	ExceptionÚ_poll_operation)rA   rI   rH   rx   r<   Úbase_urlÚurlr\   r]   Úembedding_model_configÚvector_db_sectionÚrequest_bodyÚclientr'   Ú	error_msgÚoperation_viewÚresponse_dataÚcorpus_namerw   s                      r   rP   z'VertexAIRAGIngestion._create_rag_corpusŸ   s¤  è ø€ ð  $(×#<Ñ#<Ø×/Ñ/Ø—‘Ø +ð $=ó $
Ñ ˆ�jð �ŠØ(ˆDŒOô .¨d¯m©mÓ<ˆØ �zÐ!3°D·O±OÐ3DÀKÐPT×P]ÑP]ÈÐ^iÐjˆð #'×":Ñ":×">Ñ">Ð?QÓ"RÐØ!%×!9Ñ!9×!=Ñ!=Ð>OÓ!Pˆñ ð 'Ð)CÀjÐRaÐEbÐ(cÑdàð 	ñ G]ÐBÐ Ò& BÐBÐ+AÑBÐbrð 	ð ˜<ð
ä ¨{Ð;Ð>NÐPaÐ=bÐcÓdð
ˆô
 	×ÑÐ6¸Ô<Ü×ÑÐ/´·±¸LÐQRÔ1SÔTä.Ü-×1Ñ1Ø˜tÐ$ô
ˆð
 !'§¡ØØà#*¨<¨.Ð!9Ø 2ñð !,ó !
÷ 
ˆð ×Ñ zÑ1Ø!>¸x¿}¹}¸oÐNˆIÜ× Ñ  Ô+Ü˜IÓ&Ð&à4?ÀÇÁÃÐ3QˆØ-¨kÑ:ˆÜ×ÑÐ9¼4¿:¹:ÀmÐ\]Ô;^Ô_ð ×Ñ˜VÔ$à'×+Ñ+¨J¸Ó;×?Ñ?ÀÈÓK‰Kð %2×$5Ñ$5°f¸bÓ$AˆNÜ× Ñ Ð!8¸.ÔIØ $× 4Ñ 4Ø-Ø)ð !5ó !÷ ˆKô
 	×ÑÐ5°{ÔCØÐðA
ùð4ús%   ‚EI-ÅI(ÅC5I-ÉI+ÉI-É+I-c              ƒ  óô  K  — ddl }t        | j                  «      }|› d|› �}t        t        j
                  ddi¬«      }t        |«      D �]  }	|j                  |dd|› �i¬	«      ƒ d{  –—† }
|
j                  d
k7  r/d|
j                  › �}t        j                  |«       t        |«      ‚d|
j                  «       i}|d   }|j                  d«      rYd|v r|j                  d«      }t        d|› �«      ‚|j                  di «      j                  dd«      }|r|c S t        d|› �«      ‚t        j                  d|	dz   |«       |j                  |«      ƒ d{  –—†  �Œ t        d|› d�«      ‚7 �Œ	7 Œ­w)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/rg   rh   ri   ro   rl   )rr   rt   zFailed to poll operation: r/   r$   r%   zOperation failed: r'   r   rv   z&No corpus name in operation response: z%Operation not done yet, attempt %s/%sé   zOperation timed out after z	 attempts)Úasyncior   r>   r
   r   r|   ÚrangerO   r~   r   r	   r%   r€   rq   rz   Úsleep)rA   rw   rx   Úmax_retriesÚretry_delayr�   r‚   rƒ   r‡   Úattemptr'   rˆ   r‰   Úoperation_datar%   r‹   s                   r   r�   z$VertexAIRAGIngestion._poll_operation÷   s¡  è ø€ ó, 	ä-¨d¯m©mÓ<ˆð !�z ¨>Ð*:Ð;ˆä.Ü-×1Ñ1Ø˜tÐ$ô
ˆô
 ˜[Ó)ó 	-ˆGØ#ŸZ™ZØà# w¨|¨nÐ%=ðð (ó ÷ ˆHð ×#Ñ# sÒ*Ø8¸¿¹¸ÐH�	Ü×$Ñ$ YÔ/Ü 	Ó*Ð*à1<¸h¿m¹m»oÐ0NˆNØ1?ÀÑ1LˆNà×!Ñ! &Ô)à˜nÑ,Ø*×.Ñ.¨wÓ7�EÜ#Ð&8¸¸Ð$@ÓAÐAð -×0Ñ0°¸RÓ@×DÑDÀVÈRÓP�ÙØ&Ò&ä#Ð&LÈ^ÐL\Ð$]Ó^Ð^ä× Ñ Ð!HÈ'ÐTUÉ+ÐWbÔcØ—-‘- Ó,×,Ò,ð=	-ô@ Ð4°[°MÀÐKÓLÐLð?ùð: -ús%   ‚A(E8Á*E3Á+C1E8ÅE6ÅE8Å6E8c              ƒ  ó˜  K  — | j                  | j                  | j                  d¬«      \  }}t        | j                  «      }|› d|› d�}| j
                  j                  d«      }	d|it        d|	ff«      ¥}
| j                  }|j                  d«      }|j                  d	«      }t        d|fd	|ff«      }|rd
dd|iiind}d|
it        d|ff«      ¥}t        j                  d|«       t        j                  dt        j                  |d¬«      «       dt        j                  |«      df|||xs dfdœ}t        t        j                  ddi¬«      }|j!                  ||d|› �ddœ¬«      ƒ d{  –—† }|j"                  dvr/d|j$                  › �}t        j&                  |«       t)        |«      ‚	 d |j                  «       i}|d    }|j                  d!i «      j                  d"d#«      }|xs |j                  d"d#«      }t        j                  d$|«       |S 7 Œ©# t(        $ r }t        j*                  d%|«       Y d}~y&d}~ww xY 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
        rX   rY   z/upload/v1beta1/z/ragFiles:uploadÚfile_descriptionrI   rH   Ú
chunk_sizeÚchunk_overlapÚrag_file_transformation_configÚrag_file_chunking_configÚfixed_length_chunkingNÚrag_fileÚupload_rag_file_configz Uploading file to RAG corpus: %szMetadata: %srd   re   rm   zapplication/octet-stream)ÚmetadataÚfilerg   g     Àr@ri   rl   Ú	multipart)ro   zX-Goog-Upload-Protocol)Úfilesrr   rs   zFailed to upload file: r2   r,   r   rv   zUpload complete. File ID: %sz#Could not parse upload response: %sÚuploaded)ry   r@   r<   r   r>   r:   rO   r   Úchunking_strategyr	   rz   rq   r{   r
   r   r|   r}   r~   r   r%   r€   Úwarning)rA   rJ   rK   rL   rM   rx   Ú_r‚   rƒ   rH   r�   r¤   r˜   r™   rœ   rž   rŸ   r¢   r‡   r'   rˆ   Úupload_viewrŠ   Úrag_file_nameÚfile_idÚes                             r   rR   z+VertexAIRAGIngestion._upload_file_to_corpus;  s¨  è ø€ ð( ×3Ñ3Ø×/Ñ/Ø—‘Ø +ð 4ó 
‰ˆ�aô .¨d¯m©mÓ<ˆØ �zÐ!1°-°Ð@PÐQˆð "×5Ñ5×9Ñ9Ð:LÓMˆà˜Hð
ä ¨{Ð;Ð=Ó>ð
ˆð :>×9OÑ9OÐØ-×1Ñ1°,Ó?ˆ
Ø0×4Ñ4°_ÓEˆÜ'6¸ÀzÐ8RÐUdÐfsÐTtÐ7uÓ'vÐñ %ð	 1Ø.Ð1HÐJ_Ð0`ð3ñð ð 	ð ˜ð
äÐ 8Ð:PÐQÐSÓTð
ˆô
 	×ÑÐ?ÀÔEÜ×Ñ˜^¬T¯Z©Z¸ÈÔ-KÔLð œtŸz™z¨(Ó3Ð5GÐHàØØÒ:Ð :ðñ
ˆô /Ü-×1Ñ1Ø˜uÐ%ô
ˆð
 !'§¡ØØà#*¨<¨.Ð!9Ø*5ñð !,ó !
÷ 
ˆð ×Ñ zÑ1Ø!8¸¿¹¸ÐHˆIÜ× Ñ  Ô+Ü˜IÓ&Ð&ð	Ø6>ÀÇÁÃÐ5PˆKØ#.¨xÑ#8ˆMà#0×#4Ñ#4°YÀÓ#C×#GÑ#GÈÐPRÓ#SˆMØ*ÒK¨m×.?Ñ.?ÀÈÓ.KˆGä× Ñ Ð!?ÀÔIØˆNð/
ùô0 ò 	Ü×"Ñ"Ð#HÈ!ÔLÜûð	üs>   ‚E0I
Å2HÅ3AI
Æ5A&H ÈI
È	IÈ'IÈ=I
ÉIÉI
c              ƒ  óˆ  K  — | j                  | j                  | j                  d¬«      \  }}t        | j                  «      }|› d|› d�}| j
                  }|j                  d«      }|j                  d«      }	| j                  j                  d«      }
|s|	r|xs d|	xs d	d
œnd}dd|iit        d|fd|
ff«      ¥}d|i}t        j                  d|«       t        j                  dt        j                  |d¬«      «       t        t        j                  ddi¬«      }|j!                  ||d|› �ddœ¬«      ƒ d{  –—† }|j"                  dvr/d|j$                  › �}t        j&                  |«       t)        |«      ‚d|j                  «       i}|d   }|j                  dd «      }t        j                  d!|«       |S 7 Œ‚­w)"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
        rX   rY   r�   z/ragFiles:importr˜   r™   Úmax_embedding_requests_per_mini   rt   )Ú	chunkSizeÚchunkOverlapNÚ	gcsSourceÚurisÚragFileChunkingConfigÚmaxEmbeddingRequestsPerMinÚimportRagFilesConfigzImporting files from GCS: %src   rd   re   rg   rh   ri   rl   rm   rn   rp   rs   zFailed to import files: r/   r   rv   zImport operation started: %s)ry   r@   r<   r   r>   r¤   rO   r:   r   r	   rz   rq   r{   r
   r   r|   r}   r~   r   r%   r€   )rA   rJ   Úgcs_urisrx   r¦   r‚   rƒ   r¤   r˜   r™   Úmax_embedding_qpmÚchunking_configÚimport_configr†   r‡   r'   rˆ   r‰   rŠ   rw   s                       r   Ú_import_files_from_gcsz+VertexAIRAGIngestion._import_files_from_gcs   s   è ø€ ð  ×3Ñ3Ø×/Ñ/Ø—‘Ø +ð 4ó 
‰ˆ�aô .¨d¯m©mÓ<ˆØ �z ¨=¨/Ð9IÐJˆð :>×9OÑ9OÐØ-×1Ñ1°,Ó?ˆ
Ø0×4Ñ4°_ÓEˆð $(×#;Ñ#;×#?Ñ#?Ð@`Ó#aÐñ
 ™]ð %Ò,¨¸mÒ>RÈsÒSàð 	ð ˜& (Ð+ð 
äà,¨oÐ>Ø1Ð3DÐEðóð 
ˆð  6°}ÐEˆä×ÑÐ;¸SÔAÜ×ÑÐ/´·±¸LÐQRÔ1SÔTä.Ü-×1Ñ1Ø˜tÐ$ô
ˆð
 !'§¡ØØà#*¨<¨.Ð!9Ø 2ñð !,ó !
÷ 
ˆð ×Ñ zÑ1Ø!9¸(¿-¹-¸ÐIˆIÜ× Ñ  Ô+Ü˜IÓ&Ð&à4?ÀÇÁÃÐ3QˆØ-¨kÑ:ˆØ -× 1Ñ 1°&¸"Ó =ˆä×ÑÐ;¸^ÔLØÐð'
ús   ‚D;GÄ=G Ä>BGr   )r6   r   r7   zRouter | None)rD   ú	list[str]Úreturnúlist[list[float]] | None)rL   zbytes | NonerK   ú
str | NonerM   r¼   rD   r¹   rS   r»   rT   r¼   rº   ztuple[str | None, str | None])rI   ÚstrrH   r¼   rº   r½   )é   g       @)
rw   r½   rx   r½   r’   Úintr“   Úfloatrº   r½   )
rJ   r½   rK   r½   rL   ÚbytesrM   r¼   rº   r½   )rJ   r½   r´   r¹   rº   r½   )r   r   r   r)   r8   rE   rV   rP   r�   rR   r¸   r   r    r   r4   r4   D   sb  „ ñ	ð !%ðVà(ðVð óVð àðð 
"óð( (,ð0-à"ð0-ð ð0-ð !ð	0-ð
 ð0-ð -ð0-ð %ð0-ð 
'ó0-ðj #'ðVàðVð  ðVð 
ó	Vðx Ø ðBMàðBMð ðBMð ð	BMð
 ðBMð 
óBMðHcàðcð ðcð ð	cð
 !ðcð 
ócðJNàðNð ðNð 
ô	Nr    r4   )r   ztuple[tuple[str, object], ...]rº   zMapping[str, object])"r)   Ú
__future__r   rq   Úcollections.abcr   Útypingr   r   Útyping_extensionsr   r   Úlitellm._loggingr	   Ú&litellm.llms.custom_httpx.http_handlerr
   r   Ú#litellm.llms.vertex_ai.common_utilsr   Ú&litellm.llms.vertex_ai.vertex_llm_baser   Ú$litellm.rag.ingestion.base_ingestionr   Úlitellmr   Úlitellm.types.ragr   r   r   r#   r+   r.   r1   r4   r   r    r   ú<module>rÍ      s�   ðñõ #ã Ý #ß 'ç 1å +÷õ DÝ =Ý AáÝÝ2ó<ô˜I¨Uõ ô.˜¨%õ .ô-˜)¨5õ -ô,˜	ô ,ô*˜ô *ôjÐ+¨Zõ jr    