o
    ưiK,                     @  s   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rBddlmZ dd	lmZ G d
d deZdS )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                      sb   e Zd ZdZ	d)d* fddZd+ddZd,ddZd-ddZd.d d!Zd/d$d%Z	d0d'd(Z
  ZS )1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
    Ningest_options'RAGIngestOptions'routerOptional['Router']c                   s   t  j||d t | _d S )N)r   r   )super__init__r   Z
model_info)selfr   r   	__class__ ]/home/app/Keep/.python/lib/python3.10/site-packages/litellm/rag/ingestion/gemini_ingestion.pyr   $   s   zGeminiRAGIngestion.__init__chunks	List[str]returnOptional[List[List[float]]]c                   s   dS )z
        Gemini handles embedding internally - skip this step.

        Returns:
            None (Gemini embeds when files are uploaded to File Search store)
        Nr   )r   r   r   r   r   embed,   s   zGeminiRAGIngestion.embedfile_contentOptional[bytes]filenameOptional[str]content_type
embeddings#Tuple[Optional[str], Optional[str]]c                   s   | j d}ttttf | j }ttt |dpt }ttt |dp,t	 }	|s3t
d|	s9t
dd}
|	 d|
 }|sR| j||| jpLdd	I d
H }d
}|rh|rh|rh| j||||||dI d
H }||fS )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 requiredZv1beta/zlitellm-rag-ingest)r*   base_urldisplay_nameN)r*   r-   r)   r$   r"   r&   )vector_store_configgetr	   r   strr   r   r   Zget_api_keyZget_api_base
ValueError_create_file_search_storeZingest_name_upload_to_file_search_store)r   r"   r$   r&   r   r'   r)   r/   r*   r+   api_versionr-   Zresult_file_idr   r   r   store9   s8   	zGeminiRAGIngestion.storer*   r1   r-   r.   c                   s   | d| }d|i}t tjddid}|j||ddidI d	H }|jd
kr6d|j }t| t||	 }	|	
dd}
td|
  |
S )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@Z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	Exceptionr?   r0   debug)r   r*   r-   r.   urlrequest_bodyclientresponse	error_msgresponse_dataZ
store_namer   r   r   r3   y   s*   

z,GeminiRAGIngestion._create_file_search_storer)   bytesc           	        s>   | j ||||t||pddI dH }| j||dI dH }|S )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&   rS   file_idr   r   r   r4      s   
z/GeminiRAGIngestion._upload_to_file_search_storerR   intc                   sN  | dd}| d| d| }d|i}	| j}
|
r7t|
tr7|
d}|r7d|dd	|d
ddi|	d< ttttt	t
f   | jd}|rN||	d< ddt	||dd}td|  ttjddid}|j||	|dI dH }|jdvrd|j }t| t|td|j  |jd}|stdtd|  |S ) zy
        Initiate a resumable upload session.

        Returns:
            Upload URL for the resumable session
        z/v1betarC   z/upload/v1beta/z:uploadToFileSearchStore?key=r7   white_space_configZwhiteSpaceConfigZmax_tokens_per_chunki   Zmax_overlap_tokensi  )ZmaxTokensPerChunkZmaxOverlapTokensZchunkingConfigcustom_metadataZcustomMetadataZ	resumablestartr=   )zX-Goog-Upload-ProtocolX-Goog-Upload-Commandz#X-Goog-Upload-Header-Content-Lengthz!X-Goog-Upload-Header-Content-Typer<   zInitiating resumable upload: r8   r9   r:   r>   NrA      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dictr0   r	   r   r   r   r1   r   r/   r
   rJ   r   r   rD   rE   rF   rG   rH   rI   r@   )r   r*   r-   r)   r$   rR   r&   r+   rK   rL   r`   rY   rZ   r@   rM   rN   rO   rS   r   r   r   rT      sV   


"

z-GeminiRAGIngestion._initiate_resumable_uploadrS   c           
   
     s   t t|ddd}tdt| d ttjddid}|j|||d	I d
H }|jdvr>d|j	 }t
| t|z| }|ddpR|di dd}td|  |W S  tyx }	 ztd|	  W Y d
}	~	dS d
}	~	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-Offsetr\   zUploading file content (z bytes)r8   g     r@r:   )contentr@   Nr]   zFailed to upload file: rB   rC   filezUpload complete. File ID: z!Could not parse upload response: Zuploaded)r1   rU   r
   rJ   r   r   rD   putrF   rG   rH   rI   r?   r0   warning)
r   rS   r"   r@   rM   rN   rO   rP   rW   er   r   r   rV     s:   


 z'GeminiRAGIngestion._upload_file_content)N)r   r   r   r   )r   r   r   r    )r"   r#   r$   r%   r&   r%   r   r   r'   r    r   r(   )r*   r1   r-   r1   r.   r1   r   r1   )r*   r1   r-   r1   r)   r1   r$   r1   r"   rQ   r&   r%   r   r1   )r*   r1   r-   r1   r)   r1   r$   r1   rR   rX   r&   r1   r   r1   )rS   r1   r"   rQ   r   r1   )__name__
__module____qualname____doc__r   r!   r6   r3   r4   rT   rV   __classcell__r   r   r   r   r      s    


@
,
)Lr   N)rl   
__future__r   typingr   r   r   r   r   r   r	   Zlitellm._loggingr
   Z&litellm.llms.custom_httpx.http_handlerr   r   Z litellm.llms.gemini.common_utilsr   Z$litellm.rag.ingestion.base_ingestionr   Zlitellmr   Zlitellm.types.ragr   r   r   r   r   r   <module>   s    $