o
    ưi                     @   s  d dl Z d dlZd dl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mZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZmZ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)m*Z*m+Z+m,Z,m-Z-m.Z. d dl/m0Z0m1Z1m2Z2m3Z3m4Z4 erd dl&m5Z5 erd dl6m7Z8 d dl9m:Z; d dl9m<Z= e
e8ef Z7e;Z:e=Z<neZ7eZ:eZ<G dd deeZ>dS )    N)TYPE_CHECKINGAnyDictListLiteralOptionalUnioncast)HTTPException)Routerverbose_logger)uuid)	DualCache)CustomLogger)extract_file_data)BaseFileEndpoints)	CallTypesLiteLLM_ManagedFileTableLiteLLM_ManagedObjectTableUserAPIKeyAuth)"_is_base64_encoded_unified_file_id"get_batch_id_from_unified_batch_id!get_content_type_from_file_object"get_model_id_from_unified_batch_id normalize_mime_type_for_provider)AllMessageValuesAsyncCursorPageChatCompletionFileObjectCreateFileRequest
FileObjectOpenAIFileObjectOpenAIFilesPurposeResponsesAPIResponse)CallTypesLiteralLiteLLMBatchLiteLLMFineTuningJobLLMResponseTypesSpecialEnums)HttpxBinaryResponseContent)Span)InternalUsageCache)PrismaClientc                   @   s  e Zd ZdedefddZdedee dee	 de
eef d	ed
dfddZdedeeedf dee	 deded d	ed
dfddZ	dzdedee	 d
ee fddZ	dzdedee	 d
efddZded	ed
efddZded	ed
efddZ					d{d	edee dee d ee d!ee d"ee d
e
eef fd#d$Zd	ed%ee d
ee fd&d'Zd(e
d	ed
efd)d*Zd+ee d	ed
dfd,d-Zd	ed.e d(e
d/e!d
ee"ee
df f
d0d1Z#		d|d2ed3ed4eee$  d5ee
 d6ee	 d
ee
 fd7d8Z%d9e
eef d/ee& d
ee' fd:d;Z(d4ee$ d
ee fd<d=Z)d>eeee
eef  f d
ee fd?d@Z*dAee
eef  d
ee fdBdCZ+d+ee de	d
e'fdDdEZ,d"ee dFe-dGee de	d
ee f
dHdIZ.dJe-d"edGee de	d	ed
efdKdLZ/e0dMee dJe-dede	dGee d
efdNdOZ1dPedQed
efdRdSZ2dTedPed
efdUdVZ3dWedPedXee d
efdYdZZ4ded
efd[d\Z5ded
efd]d^Z6d(e
d	ed_e7d
efd`daZ8	dzdedee	 d
efdbdcZ9ddee: dee	 d(e
d
ee fdedfZ;d
efdgdhZ<ded
ee
eef  fdidjZ=ded
dfdkdlZ>dedee	 d"ed(e
d
ef
dmdnZ?dedee	 d"ed(e
d
dof
dpdqZ@d4ee$ d+ee dee	 d
dfdrdsZAdee d
efdtduZBd4ee$ dedvedwed
df
dxdyZCdS )}_PROXY_LiteLLMManagedFilesinternal_usage_cacheprisma_clientc                 C   s   || _ || _d S N)r-   r.   )selfr-   r.    r1   c/home/app/Keep/.python/lib/python3.10/site-packages/litellm_enterprise/proxy/hooks/managed_files.py__init__F   s   
z#_PROXY_LiteLLMManagedFiles.__init__file_idfile_objectlitellm_parent_otel_spanmodel_mappingsuser_api_key_dictreturnNc           
         s  t d| d |d ur,t|||t| |j|jd}| jj|| |dI d H  |t	
|t| |j|jd}|d urt| |d< t|di pNi }d|v rY|d |d< d	|v rc|d	 |d	< t d
|d d|d	  | jjjj|dI d H }	t d| d|	  d S )Nz,Storing LiteLLM Managed File object with id=	 in cache)unified_file_idr5   r7   flat_model_file_ids
created_by
updated_bykeyvaluer6   )r;   r7   r<   r=   r>   r5   _hidden_paramsstorage_backendstorage_urlz"Storage metadata: storage_backend=z, storage_url=)data$LiteLLM Managed File object with id=z stored in db: )r   infor   listvaluesuser_idr-   async_set_cache
model_dumpjsondumpsmodel_dump_jsongetattrdebuggetr.   dblitellm_managedfiletablecreate)
r0   r4   r5   r6   r7   r8   Zlitellm_managed_file_objectZdb_dataZhidden_paramsresultr1   r1   r2   store_unified_file_idL   sT   

	

z0_PROXY_LiteLLMManagedFiles.store_unified_file_idunified_object_idr"   model_object_idfile_purpose)batch	fine-tuneresponsec              
      s   t d| d| d t||||d}| jj|| |dI d H  | jjjj	d|i||
 |||j|j|jd|
 |j|jdd	d
I d H  d S )NzStoring LiteLLM Managed z object with id=r:   )rX   rY   rZ   r5   r?   rX   )rX   r5   rY   rZ   r=   r>   status)r5   r^   r>   )rU   update)whererE   )r   rG   r   r-   rK   rL   r.   rS   litellm_managedobjecttableZupsertrO   rJ   r^   )r0   rX   r5   r6   rY   rZ   r8   Zlitellm_managed_objectr1   r1   r2   store_unified_object_id   s>   	

z2_PROXY_LiteLLMManagedFiles.store_unified_object_idc                    sj   t tt | jj||dI d H }|rtdi |S | jjjj	d|idI d H }|r3tdi |
 S d S )N)r@   r6   r;   r`   r1   )r	   r   dictr-   Zasync_get_cacher   r.   rS   rT   
find_firstrL   )r0   r4   r6   rV   Z	db_objectr1   r1   r2   get_unified_file_id   s    

z._PROXY_LiteLLMManagedFiles.get_unified_file_idc                    sp   | j jjjd|idI d H }|d u rtd| d| jj|d |dI d H  | j jjjd|idI d H  |jS )Nr;   rc   rF   
 not foundr?   )	r.   rS   rT   re   	Exceptionr-   rK   deleter5   )r0   r4   r6   initial_valuer1   r1   r2   delete_unified_file_id   s   

z1_PROXY_LiteLLMManagedFiles.delete_unified_file_idr;   c                    D   |j }| jjjjd|idI d H }|r|j|kS tdd| d)Nr;   rc     zFile not found: status_codedetail)rJ   r.   rS   rT   re   r=   r
   )r0   r;   r8   rJ   Zmanaged_filer1   r1   r2   can_user_call_unified_file_id   s   

z8_PROXY_LiteLLMManagedFiles.can_user_call_unified_file_idc                    rl   )NrX   rc   rm   zObject not found: rn   )rJ   r.   rS   ra   re   r=   r
   )r0   rX   r8   rJ   Zmanaged_objectr1   r1   r2   can_user_call_unified_object_id   s   


z:_PROXY_LiteLLMManagedFiles.can_user_call_unified_object_idlimitafterprovidertarget_model_names
llm_routerc                    sV  |rt d|rt dddi}|jr|j|d< |r!d|i|d< |p$d}|r.t|d	 d
}| jjjj||ddidI d H }	g }
|	D ]L}z,t|
|pKdkrPW  n?t|j	t
r\t|j	n|j	}tdi |}|j|_|
| W qB t y } ztd|j d|  W Y d }~qBd }~ww d|
|
r|
d jnd |
r|
d jnd t|
|pdkdS )NzDFiltering by 'provider' is not supported when using managed batches.zNFiltering by 'target_model_names' is not supported when using managed batches.rZ   r[   r=   gtid      d   
created_atdescr`   ZtakeorderzFailed to parse batch object : rH   r   )objectrE   Zfirst_idZlast_idZhas_morer1   )rh   rJ   maxr.   rS   ra   	find_manylen
isinstancer5   strrM   loadsr$   rX   ry   appendr   warning)r0   r8   rs   rt   ru   rv   rw   Zwhere_clauseZfetch_limitbatchesZbatch_objectsr[   
batch_dataZ	batch_objer1   r1   r2   list_user_batches   sX   

z,_PROXY_LiteLLMManagedFiles.list_user_batchesmodel_object_idsc                    s4   | j jjj|jd|iddI dH }dd |D S )z
        Get all file ids created by the user for a list of model object ids

        Returns:
         - List of OpenAIFileObject's
        ZhasSome)r=   r<   rc   Nc                 S   s   g | ]
}t d i |jqS )r1   )r    r5   .0r5   r1   r1   r2   
<listcomp>W  s    zH_PROXY_LiteLLMManagedFiles.get_user_created_file_ids.<locals>.<listcomp>)r.   rS   rT   r   rJ   )r0   r8   r   file_idsr1   r1   r2   get_user_created_file_idsH  s   
	z4_PROXY_LiteLLMManagedFiles.get_user_created_file_idsrE   c                    sb   t tt |d}|rt|nd}|r/|r/| ||I d H r"dS tdd|j d| ddS )Nr4   FT  User " does not have access to the file rn   )r	   r   r   rR   r   rq   r
   rJ   )r0   rE   r8   retrieve_file_idpotential_file_idr1   r1   r2   check_managed_file_id_accessY  s    

z7_PROXY_LiteLLMManagedFiles.check_managed_file_id_accessr   c                    sH   |D ]}t |}|r!| ||I dH s!tdd|j d| dqdS )ar  
        Check if the user has access to a list of file IDs.
        Only checks managed (unified) file IDs.
        
        Args:
            file_ids: List of file IDs to check access for
            user_api_key_dict: User API key authentication details
            
        Raises:
            HTTPException: If user doesn't have access to any of the files
        Nr   r   r   rn   )r   rq   r
   rJ   )r0   r   r8   r4   Zis_unified_file_idr1   r1   r2   check_file_ids_accessn  s   
z0_PROXY_LiteLLMManagedFiles.check_file_ids_accesscache	call_typec                    s  |t jjks|t jjks|t jjks|t jjkr"| ||I dH  |t jjkp-|t jjk}|rw|d}|dd}|ru| 	|}|ru| 
||I dH  |oXd|v pXd| v }	|	rg| j|||jdI dH  | ||jI dH }
|
|d< |S |t jjks|t jjkrg }|d	}|r|| | |d
}|r|| | |r| 
||I dH  | ||jI dH }
|
|d< |S |t jjkrttt |d}|rt|nd}|r| |}|r||d< | ||d< |S |t jjkrttt |d}|r| |g|jI dH }
|
|d< |S |t jjks-|t jjks-|t jjks-|t jjkrd}d}|t jjks?|t jjkrBd}n|t jjksP|t jjkrRd}|r_ttt ||}|rft|nd}|r|r| ||I dH st dd|j! d| dt"|}|du rt#d| d| d||d< t$|||< |S |t j%jkrttt |d}|r| |g|jI dH }
|S )z
        - Detect litellm_proxy/ file_id
        - add dictionary of mappings of litellm_proxy/ file_id -> provider_file_id => {litellm_proxy/file_id: {"model_id": id, "file_id": provider_file_id}}
        Nmessagesmodel Z	vertex_aigemini)r   r   r6   model_file_id_mappinginputtoolsr4   Finput_file_idbatch_idZfine_tuning_job_idr   r   z$ does not have access to the object rn   zLiteLLM Managed z	 with id=z0 is invalid - does not contain encoded model_id.training_file)&r   afile_contentrA   afile_deleteafile_retriever   
completionZacompletionrR   get_file_ids_from_messagesr   lower _convert_storage_files_to_base64parent_otel_spanget_model_file_id_mappingZ
aresponses	responsesextend!get_file_ids_from_responses_input!get_file_ids_from_responses_toolsr	   r   r   r   !get_model_id_from_unified_file_id'get_output_file_id_from_unified_file_idacreate_batchZaretrieve_batchZacancel_batchZacancel_fine_tuning_jobZaretrieve_fine_tuning_jobrr   r
   rJ   r   rh   r   acreate_fine_tuning_job)r0   r8   r   rE   r   Zis_completion_callr   r   r   Zis_vertex_air   Z
input_datar   r   r   model_idr   accessor_keyZretrieve_object_idZpotential_llm_object_idZpotential_model_idr1   r1   r2   async_pre_call_hook  s   



e


O

C
9


z._PROXY_LiteLLMManagedFiles.async_pre_call_hookr   healthy_deploymentsr   request_kwargsr   c           	         s   |d u r|S t tt |d}t ttttttf f  |d}g  |r5|r5||i }t|  t dkr=|S  fdd|D S )Nr   r   r   c                    s&   g | ]}| d i  d v r|qS )
model_infory   )rR   )r   Z
deploymentZallowed_model_idsr1   r2   r   7  s
    zG_PROXY_LiteLLMManagedFiles.async_filter_deployments.<locals>.<listcomp>)r	   r   r   rR   r   rH   keysr   )	r0   r   r   r   r   r   r   r   Zmodel_id_dictr1   r   r2   async_filter_deployments  s"   
z3_PROXY_LiteLLMManagedFiles.async_filter_deploymentskwargsc                    s   d}|r|t jkrd}n|r|t jkrd}n|S |ruttt ||}tttttttf f  |d}ttt |di dd}|du r]ttt |di di dd}d}|ro|ro|ro||i |d}|ru|||< |S )zV
        Allow modifying the request just before it's sent to the deployment.
        Nr   r   r   r   ry   Zlitellm_metadata)r   r   r   r	   r   r   rR   r   )r0   r   r   r   r   r   r   Zmapped_file_idr1   r1   r2   async_pre_call_deployment_hook=  s4   z9_PROXY_LiteLLMManagedFiles.async_pre_call_deployment_hookc           	      C   sz   g }|D ]6}| ddkr:| d}|r:t|trq|D ]}|d dkr9tt|}|d }| d}|r9|| qq|S )z-
        Gets file ids from messages
        roleusercontenttypefiler4   )rR   r   r   r	   r   r   )	r0   r   r   messager   cr5   Zfile_object_file_fieldr4   r1   r1   r2   r   b  s    




z5_PROXY_LiteLLMManagedFiles.get_file_ids_from_messagesr   c                 C   s   g }t |tr	|S t |ts|S |D ]B}t |tsq|ddkr-|d}|r-|| |d}t |trT|D ]}t |trS|ddkrS|d}|rS|| q9q|S )a8  
        Gets file ids from responses API input.
        
        The input can be:
        - A string (no files)
        - A list of input items, where each item can have:
          - type: "input_file" with file_id
          - content: a list that can contain items with type: "input_file" and file_id
        r   Z
input_filer4   r   )r   r   rH   rd   rR   r   )r0   r   r   itemr4   r   Zcontent_itemr1   r1   r2   r   v  s*   








z<_PROXY_LiteLLMManagedFiles.get_file_ids_from_responses_inputr   c                 C   s   g }t |ts	|S |D ]2}t |tsq|ddkr=|d}t |tr=|d}t |tr=|D ]}t |tr<|| q0q|S )aD  
        Gets file ids from responses API tools parameter.
        
        The tools can contain code_interpreter with container.file_ids:
        [
            {
                "type": "code_interpreter",
                "container": {"type": "auto", "file_ids": ["file-123", "file-456"]}
            }
        ]
        r   Zcode_interpreter	containerr   )r   rH   rd   rR   r   r   )r0   r   r   Ztoolr   Zcontainer_file_idsr4   r1   r1   r2   r     s    







z<_PROXY_LiteLLMManagedFiles.get_file_ids_from_responses_toolsc                    s\   i }g }|D ]}t |}|r|| q|r,|D ]}| ||I dH }|r+|j||< q|S )a!  
        Get model-specific file IDs for a list of proxy file IDs.
        Returns a dictionary mapping litellm_proxy/ file_id -> model_id -> model_file_id

        1. Get all the litellm_proxy/ file_ids from the messages
        2. For each file_id, search for cache keys matching the pattern file_id:*
        3. Return a dictionary of mappings of litellm_proxy/ file_id -> model_id -> model_file_id

        Example:
        {
            "litellm_proxy/file_id": {
                "model_id": "model_file_id"
            }
        }
        N)r   r   rf   r7   )r0   r   r6   Zfile_id_mappingZlitellm_managed_file_idsr4   Zis_base64_unified_file_idZunified_file_objectr1   r1   r2   r     s"   


z4_PROXY_LiteLLMManagedFiles.get_model_file_id_mapping_create_file_requesttarget_model_names_listc                    sH   |d u r	t dg }|D ]}|jdd|i|I d H }|| q|S )Nz9LLM Router not initialized. Ensure models added to proxy.r   r1   )rh   acreate_filer   )r0   rw   r   r   r6   r   r   Zindividual_responser1   r1   r2   create_file_for_each_model  s   z5_PROXY_LiteLLMManagedFiles.create_file_for_each_modelcreate_file_requestc                    s   | j ||||dI d H }tj||| j||dI d H }i }|D ]}	|	jd}
|
r3t|
tr3||
 q| j	|j
||||dI d H  |S )N)rw   r   r   r6   )file_objectsr   r-   r6   r   r   r4   r5   r6   r7   r8   )r   r,   return_unified_file_idr-   rB   rR   r   rd   r_   rW   ry   )r0   r   rw   r   r6   r8   r   r]   r7   r5   r   r1   r1   r2   r     s<   	
z'_PROXY_LiteLLMManagedFiles.acreate_filer   c              
      s   t |d }|d }| d j}| d jd}tjj|tt	
 d|||}	t|	  d}
t|
d|d | d j| d j| d jd| d jd	}|S )
Nr   content_typer   r   ,=purposeZuploaded)ry   r   r   r}   bytesfilenamer^   
expires_at)r   ry   rB   rR   r'   !LITELLM_MANAGED_FILE_COMPLETE_STRrA   formatr   r   uuid4joinbase64urlsafe_b64encodeencodedecoderstripr    r}   r   r   r   )r   r   r-   r6   r   	file_data	file_typeoutput_file_idr   r;   Zbase64_unified_file_idr]   r1   r1   r2   r   &  s2   	


z1_PROXY_LiteLLMManagedFiles.return_unified_file_idr   generic_response_idc                 C   s(   t jj||}t|  dS Nr   )	r'   Z-LITELLM_MANAGED_GENERIC_RESPONSE_COMPLETE_STRrA   r   r   r   r   r   r   )r0   r   r   Zunified_generic_response_idr1   r1   r2   get_unified_generic_response_idR  s   z:_PROXY_LiteLLMManagedFiles.get_unified_generic_response_idr   c                 C   s(   t jj||}t|  dS r   )	r'   Z"LITELLM_MANAGED_BATCH_COMPLETE_STRrA   r   r   r   r   r   r   )r0   r   r   unified_batch_idr1   r1   r2   get_unified_batch_id`  s   z/_PROXY_LiteLLMManagedFiles.get_unified_batch_idr   
model_namec                 C   s:   t jjdtt |pd||}t|	 
 dS )Nzapplication/jsonr   r   )r'   r   rA   r   r   r   r   r   r   r   r   r   )r0   r   r   r   Zunified_output_file_idr1   r1   r2   get_unified_output_file_idf  s   

z5_PROXY_LiteLLMManagedFiles.get_unified_output_file_idc                 C      | dd  dd S )Nzllm_output_file_model_id,   ;r   splitr0   r4   r1   r1   r2   r   x     z<_PROXY_LiteLLMManagedFiles.get_model_id_from_unified_file_idc                 C   r   )Nzllm_output_file_id,r   r   r   r   r   r1   r1   r2   r   {  r   zB_PROXY_LiteLLMManagedFiles.get_output_file_id_from_unified_file_idr]   c                    s  t |tr|jd}|jd}ttt |jd}ttt |jd}|j}|s/|r|r| j|j|d|_dD ]}	t	||	d }
|
r|r|
}| j
|||d}t||	| d }zNdd lm  m} t	|d	d }|d ur|r||pvi }tjdd
|i|I d H }ntj|rd|v r|dd nd|dI d H }td|	 d|  W n# ty } ztd|	 d| dt| d W Y d }~nd }~ww | j|||j||i|dI d H  q<| j|j||j|d|dI d H  |S t |tr>|jd}|jd}ttt |jd}ttt |jd}|j}|s |r,|r,| j||jd|_| j|j||j|d|dI d H  |S t |trz	 t|drxt |jtrxt dd |jD rxdd tt!t" |jD }| #||I d H }||_|S |S |S )Nr;   r   r   r   )r   r   )r   error_file_id)r   r   r   r   rw   r4   /Zopenai)Zcustom_llm_providerr4   z'Successfully retrieved file object for r   z#Failed to retrieve file object for r   z-. Storing with None and will fetch on-demand.r   r[   )rX   r5   r6   rY   rZ   r8   unified_finetuning_job_id)r   r   r\   rE   c                 s   s    | ]}t |tV  qd S r/   )r   r   r   r1   r1   r2   	<genexpr>  s    

zJ_PROXY_LiteLLMManagedFiles.async_post_call_success_hook.<locals>.<genexpr>c                 S   s   g | ]}|j qS r1   )ry   r   r1   r1   r2   r     s    zK_PROXY_LiteLLMManagedFiles.async_post_call_success_hook.<locals>.<listcomp>r1   )$r   r$   rB   rR   r	   r   r   ry   r   rP   r   setattrlitellm.proxy.proxy_serverproxyproxy_server(get_deployment_credentials_with_providerlitellmr   r   r   rQ   rh   r   rW   r   rb   r%   r   r   hasattrrE   rH   allr   r   r   )r0   rE   r8   r]   r;   r   r   r   Zoriginal_response_idZ	file_attrZfile_id_valueZoriginal_file_idr5   proxy_server_moduleZ_llm_routerZ_credsr   r   r   Zuser_created_file_idsr1   r1   r2   async_post_call_success_hook~  s   
7 

z7_PROXY_LiteLLMManagedFiles.async_post_call_success_hookc           
   
      s   |  ||I d H }|std| d|r$|jr$|jjd|id}|S |s.td| dz%tt|j \}}||p@i }t	j
d	d|i|I d H }||_|W S  tyl }	 ztd| dt|	 |	d }	~	ww )
NrF   rg   ry   )r_   zE has no file_object and llm_router is required to fetch from providerr4   zFailed to retrieve file z from provider: r1   )rf   rh   r5   Z
model_copynextiterr7   itemsr   r   r   ry   r   )
r0   r4   r6   rw   stored_file_objectr]   r   model_file_idcredentialsr   r1   r1   r2   r     s.   


z)_PROXY_LiteLLMManagedFiles.afile_retriever   c                    s   g S )zHandled in files_endpoints.pyr1   )r0   r   r6   rE   r1   r1   r2   
afile_list  s   z%_PROXY_LiteLLMManagedFiles.afile_listc              
   C   s   z3ddl m  m} t|dd}|du rW dS z|d}|dur%W W dS W W dS  ty3   Y W dS w  tyO } ztd| d W Y d}~dS d}~ww )	z
        Check if batch cost tracking is actually enabled and running.
        Returns:
            bool: True if batch cost tracking is active, False otherwise
        r   N	schedulerFZcheck_batch_cost_jobTz,Error checking batch polling configuration: z. Assuming disabled.)r   r   r   rP   Zget_jobrh   r   r   )r0   r  r  Zjobr   r1   r1   r2   _is_batch_polling_enabled%  s,   

z4_PROXY_LiteLLMManagedFiles._is_batch_polling_enabledc                    s  |g z | j |gddI dH }|r#||v r#t||  } | W n tyB } ztd| d| d W Y d}~nd}~ww d}| jjj	j
ddd	g d
id|ddidI dH }g }|D ]a}zAt|jtrpt|jn|j}	|	d}
|	d}|	d}dd |
||fD }t fdd|D r||j|j|jd W qa ty } ztd|j d|  W Y d}~qad}~ww |S )a  
        Find batches that reference this file and still need cost tracking.
        Find batches that are in non-terminal state and have not yet been processed by CheckBatchCost.
        Args:
            file_id: The unified file ID to check
            
        Returns:
            List of batch objects referencing this file in non-terminal state
            (max 10 for error message display)
        N)r6   z(Could not get model file ID mapping for r   z". Will only check unified file ID.
   r[   FZnot_in)failedZexpired	cancelled)rZ   Zbatch_processedr^   r}   r~   r   r   r   r   c                 S   s   g | ]}|r|qS r1   r1   )r   Zfidr1   r1   r2   r   |  s    zL_PROXY_LiteLLMManagedFiles._get_batches_referencing_file.<locals>.<listcomp>c                 3   s    | ]}| v V  qd S r/   r1   )r   Zref_idZfile_ids_to_checkr1   r2   r     s    zK_PROXY_LiteLLMManagedFiles._get_batches_referencing_file.<locals>.<genexpr>)r   r^   r}   zError parsing batch object )r   rH   rI   r   rh   r   rQ   r.   rS   ra   r   r   r5   r   rM   r   rR   anyr   rX   r^   r}   r   )r0   r4   r   Zprovider_file_idsr   ZMAX_MATCHES_TO_RETURNr   referencing_batchesr[   r   r   r   r   Zreferenced_file_idsr1   r  r2   _get_batches_referencing_fileD  s`   






z8_PROXY_LiteLLMManagedFiles._get_batches_referencing_filec                    s   |   sdS | |I dH }|r`d}|d| }dd |D }t| }t|dkr-d}d| d| d	}t||krH|d
d| d7 }n|d| dd| d7 }|d7 }td|ddS )a  
        Check if file deletion should be blocked due to batch references.
        
        Blocks deletion if:
        1. File is referenced by any batch in non-terminal state, AND
        2. Batch polling is configured (user wants cost tracking)
        
        Args:
            file_id: The unified file ID to check
            
        Raises:
            HTTPException: If file deletion should be blocked
        N   c                 S   s"   g | ]}|d   d|d  qS )r   r   r^   r1   )r   br1   r1   r2   r     s   " zK_PROXY_LiteLLMManagedFiles._check_file_deletion_allowed.<locals>.<listcomp>r  z10+zCannot delete file z. The file is referenced by z  batch(es) in non-terminal stater   z, z. z
 (showing z most recent): zTo delete this file before complete cost tracking, please delete or cancel the referencing batch(es) first. Alternatively, wait for all batches to complete and for cost to be computed (batch_processed=true).i  rn   )r  r  r   r   r
   )r0   r4   r  ZMAX_BATCHES_IN_ERRORZbatches_to_showZbatch_statusesZcount_messageerror_messager1   r1   r2   _check_file_deletion_allowed  s4   
z7_PROXY_LiteLLMManagedFiles._check_file_deletion_allowedc                    s   |  |I d H  | |g|I d H }d }||}|r<dd | D }| D ]\}	}
|jd|	|
d|I d H }q)| ||I d H }|rI|S |rP||_|S td| d)Nc                 S   s   i | ]\}}|d vr||qS )r   r4   r1   )r   kvr1   r1   r2   
<dictcomp>  s    z;_PROXY_LiteLLMManagedFiles.afile_delete.<locals>.<dictcomp>r  rF   rg   r1   )r  r   rR   r  r   rk   ry   rh   )r0   r4   r6   rw   rE   r   Zdelete_responsespecific_model_file_id_mappingZfiltered_datar   r	  r  r1   r1   r2   r     s(   	


z'_PROXY_LiteLLMManagedFiles.afile_deleter(   c           
         s   | dd}|p| |g|I dH }||}|r]i }| D ]-\}}z|jd||d|I dH W   S  tyM }	 zt|	||< W Y d}	~	q d}	~	ww td| d|  d| td| d)	zH
        Get the content of a file from first model that has it
        r   Nr  rF   z  not found. Checked model id's: z
. Errors: rg   r1   )popr   rR   r  r   rh   r   r   )
r0   r4   r6   rw   rE   r   r  Zexception_dictr   r   r1   r1   r2   r     s&   

"z(_PROXY_LiteLLMManagedFiles.afile_contentc                    sF  |D ]}t |}|sq| jjjjd|idI dH }|r"|jr"|js#qz^ddlm} |j}|j}	z||}
W n# t	yY } zt
d| d| dt|  W Y d}~W qd}~ww |
|	I dH }| |j}t|d	}d
| d| }| |||| W q ty } zt
d| dt|  W Y d}~qd}~ww dS )a  
        Convert files stored in storage backends to base64 format for Vertex AI/Gemini.
        
        This method checks if any managed files are stored in storage backends,
        downloads them, and converts them to base64 format in the messages.
        r;   rc   Nr   )get_storage_backendzStorage backend 'z' error for file r   zutf-8zdata:z;base64,zError converting file z! from storage backend to base64: )r   r.   rS   rT   re   rC   rD   Z3litellm.llms.base_llm.files.storage_backend_factoryr  
ValueErrorr   r   r   Zdownload_file"_get_content_type_from_file_objectr5   r   	b64encoder   !_update_messages_with_base64_datarh   	exception)r0   r   r   r6   r4   Zdecoded_unified_file_idZdb_filer  Zstorage_backend_namerD   rC   r   Zfile_contentr   Zbase64_database64_data_urir1   r1   r2   r     sH   
z;_PROXY_LiteLLMManagedFiles._convert_storage_files_to_base64c                 C   s   t |}t|dd}|S )a~  
        Determine content type from file object.
        
        Uses the MIME type utility for consistent detection and normalization.
        
        Args:
            file_object: The file object from the database (can be dict, JSON string, or None)
        
        Returns:
            str: MIME type (defaults to "application/octet-stream" if cannot be determined)
        r   )ru   )r   r   )r0   r5   r   r1   r1   r2   r!  J  s   z=_PROXY_LiteLLMManagedFiles._get_content_type_from_file_objectr%  r   c           
      C   s   |D ]L}| ddkrN| d}|rNt|trN|D ]4}| ddkrMtt|}| di }	|	 d|krM||	d< ||	d< |	dd	 td
| d|  qqd	S )aa  
        Update messages to replace file_id with base64 data URI.
        
        Args:
            messages: List of messages to update
            file_id: The file ID to replace
            base64_data_uri: The base64 data URI to use as replacement
            content_type: The MIME type of the file (e.g., "image/jpeg", "application/pdf")
        r   r   r   r   r   r4   r   r   NzConverted file z, from storage backend to base64 with format )rR   r   rH   r	   r   r  r   rQ   )
r0   r   r4   r%  r   r   r   elementZfile_elementZfile_element_filer1   r1   r2   r#  ^  s"   

z<_PROXY_LiteLLMManagedFiles._update_messages_with_base64_datar/   )NNNNN)NN)D__name__
__module____qualname__r*   r+   r3   r   r   r    r)   r   r   rW   r   r$   r%   r   rb   r   rf   rk   boolrq   rr   intr   r   r   r   r   r   r   r   r#   rh   r   r   r   r   rd   r   r   r   r   r   r   r   r   staticmethodr   r   r   r   r   r   r&   r  r   r!   r  r  r  r  r   r   r   r!  r#  r1   r1   r1   r2   r,   D   sD   


9
-





H



 



%
)
#
)

)+


{
$
	
I8
$

Br,   )?asyncior   rM   typingr   r   r   r   r   r   r   r	   Zfastapir
   r   r   r   Zlitellm._uuidr   Zlitellm.caching.cachingr   Z"litellm.integrations.custom_loggerr   Z8litellm.litellm_core_utils.prompt_templates.common_utilsr   Z*litellm.llms.base_llm.files.transformationr   Zlitellm.proxy._typesr   r   r   r   Z1litellm.proxy.openai_files_endpoints.common_utilsr   r   r   r   r   Zlitellm.types.llms.openair   r   r   r   r   r    r!   r"   Zlitellm.types.utilsr#   r$   r%   r&   r'   r(   Zopentelemetry.tracer)   _SpanZlitellm.proxy.utilsr*   Z_InternalUsageCacher+   Z_PrismaClientr,   r1   r1   r1   r2   <module>   s:   ((
