
    i,                        d Z ddlmZ ddl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 erddlmZ dd	lmZ  G d
 de      Zy)z
Gemini-specific RAG Ingestion implementation.

Gemini handles embedding and chunking internally when files are uploaded to File Search stores,
so this implementation skips the embedding step and directly uploads files.
    )annotations)TYPE_CHECKINGAnyDictListOptionalTuplecast)verbose_logger)get_async_httpx_clienthttpxSpecialProvider)GeminiModelInfo)BaseRAGIngestion)Router)RAGIngestOptionsc                       e Zd ZdZ	 d		 	 	 d
 fdZ	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ		 	 	 	 	 	 ddZ
 xZS )GeminiRAGIngestionaj  
    Gemini-specific RAG ingestion using File Search API.

    Key differences from base:
    - Embedding is handled by Gemini when files are uploaded to File Search stores
    - Files are uploaded using uploadToFileSearchStore API
    - Chunking is done by Gemini's File Search (supports custom white_space_config)
    - Supports custom metadata attachment
    c                F    t         |   ||       t               | _        y )N)ingest_optionsrouter)super__init__r   
model_info)selfr   r   	__class__s      w/Users/manta/Documents/Projects/TheRoad-I1/.venv/lib/python3.12/site-packages/litellm/rag/ingestion/gemini_ingestion.pyr   zGeminiRAGIngestion.__init__$   s!    
 	vF)+    c                   K   yw)z
        Gemini handles embedding internally - skip this step.

        Returns:
            None (Gemini embeds when files are uploaded to File Search store)
        N )r   chunkss     r   embedzGeminiRAGIngestion.embed,   s      s   c                z  K   | j                   j                  d      }t        t        t        t
        f   | j                         }t        t        t           |j                  d            xs t        j                         }t        t        t           |j                  d            xs t        j                         }	|st        d      |	st        d      d}
|	 d|
 }|s*| j                  ||| j                  xs d	       d
{   }d
}|r#|r!|r| j                  ||||||       d
{   }||fS 7 /7 
w)a  
        Store content in Gemini File Search store.

        Gemini workflow:
        1. Create File Search store (if not provided)
        2. Upload file using uploadToFileSearchStore (Gemini handles chunking/embedding)

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

        Returns:
            Tuple of (vector_store_id, file_id)
        vector_store_idapi_keyapi_basezCGEMINI_API_KEY or GOOGLE_API_KEY is required for Gemini File SearchzGEMINI_API_BASE is requiredv1beta/zlitellm-rag-ingest)r$   base_urldisplay_nameN)r$   r(   r#   filenamefile_contentcontent_type)vector_store_configgetr
   r   strr   r   r   get_api_keyget_api_base
ValueError_create_file_search_storeingest_name_upload_to_file_search_store)r   r+   r*   r,   r    
embeddingsr#   r-   r$   r%   api_versionr(   result_file_ids                r   storezGeminiRAGIngestion.store9   sa    2 22667HI"4S>43K3KL # 3 7 7	 BC -**, 	
 # 3 7 7
 CD .++- 	
 U  :;;Zq. $($B$B!!--E1E %C % O H#'#D#D! /!)) $E $ N ..%s$   DD;D7&D;.D9/	D;9D;c                  K   | d| }d|i}t        t        j                  ddi      }|j                  ||ddi       d	{   }|j                  d
k7  r/d|j
                   }t        j                  |       t        |      |j                         }	|	j                  dd      }
t        j                  d|
        |
S 7 ~w)a  
        Create a Gemini File Search store.

        Args:
            api_key: Gemini API key
            base_url: Base URL for Gemini API
            display_name: Display name for the store

        Returns:
            Store name (format: fileSearchStores/xxxxxxx)
        z/fileSearchStores?key=displayNametimeout      N@llm_providerparamsContent-Typeapplication/jsonjsonheadersN   z$Failed to create File Search store: name zCreated File Search store: )r   r   RAGpoststatus_codetextr   error	ExceptionrD   r.   debug)r   r$   r(   r)   urlrequest_bodyclientresponse	error_msgresponse_data
store_names              r   r3   z,GeminiRAGIngestion._create_file_search_store   s     " 
0	:%|4'-11t$
  #%78 % 
 
 3&>x}}oNI  +I&& "&&vr2
::,GH
s   ACCA?Cc           	        K   | j                  ||||t        |      |xs d       d{   }| j                  ||       d{   }|S 7 !7 w)a  
        Upload a file to Gemini File Search store using resumable upload.

        Args:
            api_key: Gemini API key
            base_url: Base URL for Gemini API
            vector_store_id: File Search store name
            filename: Name of the file
            file_content: File content bytes
            content_type: MIME type

        Returns:
            File ID or document name
        zapplication/octet-stream)r$   r(   r#   r*   	file_sizer,   N)
upload_urlr+   )_initiate_resumable_uploadlen_upload_file_content)	r   r$   r(   r#   r*   r+   r,   rY   file_ids	            r   r5   z/GeminiRAGIngestion._upload_to_file_search_store   ss     0  ::+,'%C)C ; 
 

 11!% 2 
 

 

s!   (AAAAAAc                  K   |j                  dd      }| d| d| }d|i}	| j                  }
|
rMt        |
t              r=|
j	                  d      }|r*d|j	                  dd	      |j	                  d
d      di|	d<   t        t        t        t        t        t        f         | j                  j	                  d            }|r||	d<   ddt        |      |dd}t        j                  d|        t        t        j                   ddi      }|j#                  ||	|       d{   }|j$                  dvr/d|j&                   }t        j(                  |       t+        |      t        j                  d|j,                          |j,                  j	                  d      }|st+        d      t        j                  d|        |S 7 w) zy
        Initiate a resumable upload session.

        Returns:
            Upload URL for the resumable session
        z/v1betarH   z/upload/v1beta/z:uploadToFileSearchStore?key=r;   white_space_configwhiteSpaceConfigmax_tokens_per_chunki   max_overlap_tokensi  )maxTokensPerChunkmaxOverlapTokenschunkingConfigcustom_metadatacustomMetadata	resumablestartrB   )zX-Goog-Upload-ProtocolX-Goog-Upload-Commandz#X-Goog-Upload-Header-Content-Lengthz!X-Goog-Upload-Header-Content-TyperA   zInitiating resumable upload: r<   r=   r>   rC   NrF      zFailed to initiate upload: z$Initiate resumable upload response: zx-goog-upload-urlz*No upload URL returned in response headerszGot upload URL: )replacechunking_strategy
isinstancedictr.   r
   r   r   r   r/   r   r-   r   rO   r   r   rI   rJ   rK   rL   rM   rN   rE   )r   r$   r(   r#   r*   rX   r,   r%   rP   rQ   rn   r_   rf   rE   rR   rS   rT   rY   s                     r   rZ   z-GeminiRAGIngestion._initiate_resumable_upload   s    $ ##Ir2
//)::WX_W`a )6x'@ !22,=t!D!2!6!67K!L!&-?-C-C2C. -?,B,B0#-	)	2-. T$sCx.)*$$(():;
 -<L)* '2%,36y>1=.
 	<SEBC'-11t$
   % 
 
 z15hmm_EI  +I&&CHDTDTCUVW%%))*=>
HII/
|<=#
s   D$G&G'B&Gc                  K   t        t        |            ddd}t        j                  dt        |       d       t	        t
        j                  ddi      }|j                  |||	       d
{   }|j                  dvr/d|j                   }t        j                  |       t        |      	 |j                         }|j                  dd      xs" |j                  di       j                  dd      }t        j                  d|        |S 7 # t        $ r"}	t        j                  d|	        Y d
}	~	yd
}	~	ww xY ww)z
        Upload file content to the resumable upload URL.

        Returns:
            File ID or document name from the response
        0zupload, finalize)zContent-LengthzX-Goog-Upload-Offsetrj   zUploading file content (z bytes)r<   g     r@r>   )contentrE   Nrk   zFailed to upload file: rG   rH   filezUpload complete. File ID: z!Could not parse upload response: uploaded)r/   r[   r   rO   r   r   rI   putrK   rL   rM   rN   rD   r.   warning)
r   rY   r+   rE   rR   rS   rT   rU   r]   es
             r   r\   z'GeminiRAGIngestion._upload_file_content%  sL     "#l"34$'%7
 	7L8I7J'RS'-11u%
    $ 
 
 z11(--AI  +I&&	$MMOM#''3 }7H7H8c&"o    #=gY!GHN'
(  	""%Fqc#JK	s>   A/E1D2AE4AD E	ED<7E<EE)N)r   z'RAGIngestOptions'r   zOptional['Router'])r    	List[str]returnOptional[List[List[float]]])r+   zOptional[bytes]r*   Optional[str]r,   r|   r    ry   r6   r{   rz   z#Tuple[Optional[str], Optional[str]])r$   r/   r(   r/   r)   r/   rz   r/   )r$   r/   r(   r/   r#   r/   r*   r/   r+   bytesr,   r|   rz   r/   )r$   r/   r(   r/   r#   r/   r*   r/   rX   intr,   r/   rz   r/   )rY   r/   r+   r}   rz   r/   )__name__
__module____qualname____doc__r   r!   r9   r3   r5   rZ   r\   __classcell__)r   s   @r   r   r      sk    &*,*, #, 
%F/%F/  F/ $	F/
 F/ 0F/ 
-F/P(( ( 	(
 
(T'' ' 	'
 ' ' $' 
'ROO O 	O
 O O O 
Ob.. . 
	.r   r   N)r   
__future__r   typingr   r   r   r   r   r	   r
   litellm._loggingr   &litellm.llms.custom_httpx.http_handlerr   r    litellm.llms.gemini.common_utilsr   $litellm.rag.ingestion.base_ingestionr   litellmr   litellm.types.ragr   r   r   r   r   <module>r      s@    # H H H + = A2z) zr   