
    ifY                     B   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	 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 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$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/m0Z0  G d de0e      Z1 G d de      Z2y)    N)AnyDictListOptionalTupleUnion)HeadersResponse)FileDeleted)uuid)FilesAPIUtils)extract_file_data)BaseLLMException)BaseFilesConfigLiteLLMLoggingObj)+_convert_vertex_datetime_to_openai_datetime)_transform_request_bodyVertexGeminiConfig)AllMessageValuesCreateFileRequest	FileTypesHttpxBinaryResponseContent%OpenAICreateFileRequestOptionalParamsOpenAIFileObjectPathLike)GcsBucketResponse)ExtractedFileDataLlmProviders   VertexAIError)
VertexBasec                       e Zd ZdZ fdZedefd       Z	 	 d/dede	de
e   ded	ed
ee	   dee	   defdZdede	fdZde
ee	ef      de	fdZdede	de	fdZdee	   d
ee	   de	ded	edede	fdZde	de
e   fdZdedede	dedef
dZdee	ef   dee	ef   fdZde
ee	ef      de
ee	ef      fdZde	deded	edeee	ef   f
dZdee	   de d e!d	ede"f
d!Z#d"e	d#e$deee%f   de&fd$Z'd%e	de(e	e	f   fd&Z)d%e	ded	ede*e	ef   fd'Z+de d e!d	ede"fd(Z,d%e	ded	ede*e	ef   fd)Z-de d e!d	ede.fd*Z/dee	   ded	ede*e	ef   fd+Z0de d e!d	ede
e"   fd,Z1ded	ede*e	ef   fd-Z2de d e!d	ede3fd.Z4 xZ5S )0VertexAIFilesConfigz#
    Config for VertexAI Files
    c                 @    t               | _        t        |           y N) VertexAIJsonlFilesTransformationjsonl_transformationsuper__init__)self	__class__s    |/Users/manta/Documents/Projects/TheRoad-I1/.venv/lib/python3.12/site-packages/litellm/llms/vertex_ai/files/transformation.pyr+   zVertexAIFilesConfig.__init__-   s    $D$F!    returnc                 "    t         j                  S r'   )r   	VERTEX_AI)r,   s    r.   custom_llm_providerz'VertexAIFilesConfig.custom_llm_provider1   s    %%%r/   headersmodelmessagesoptional_paramslitellm_paramsapi_keyapi_basec                     |sI| j                  |j                  d      |j                  d            \  }}|st        d      d| |d<   |S )Nvertex_credentialsvertex_project)credentials
project_idzapi_key is requiredzBearer Authorization)get_access_tokenget
ValueError)	r,   r4   r5   r6   r7   r8   r9   r:   _s	            r.   validate_environmentz(VertexAIFilesConfig.validate_environment5   se     ..*../CD)--.>? / JGQ  !677)0	':GO$r/   openai_file_contentc                    d}t        |t              r|d   }n|}t        |t              r|}nnt        |t              r|}n[t        |t              r/t        t        |      d      5 }|j                         }ddd       nt        |d      r|j                         }t        |t              r|j                  d      }|S # 1 sw Y   ,xY wa  
        Helper to extract content from various OpenAI file types and return as string.

        Handles:
        - Direct content (str, bytes, IO[bytes])
        - Tuple formats: (filename, content, [content_type], [headers])
        - PathLike objects
        r/      rbNreadzutf-8	
isinstancetuplestrbytesr   openrK   hasattrdecoder,   rF   contentfile_contentfs        r.   _get_content_from_openai_filez1VertexAIFilesConfig._get_content_from_openai_fileI        &))51.q1L.L lC("Ge,"Gh/c,'.!&&( /.\6*"'')G gu%nnW-G /.   &B??Copenai_jsonl_contentc                     |d   j                  di       j                  dd      }d|vrd| }d| dt        j                          }|S 	z
        Gets a unique GCS object name for the VertexAI batch prediction job

        named as: litellm-vertex-{model}-{uuid}
        r   bodyr5    zpublishers/google/modelszpublishers/google/models/zlitellm-vertex-files//rB   r   uuid4r,   r[   _modelobject_names       r.   %_get_gcs_object_name_from_batch_jsonlz9VertexAIFilesConfig._get_gcs_object_name_from_batch_jsonln   Z     &a(,,VR8<<WbI%V309F-fXQtzz|nEr/   extracted_file_datapurposec                    |j                  d      }|t        d      |dk(  rq| j                  |      }|j                         D cg c](  }|j	                         st        j                  |      * }}t        |      dkD  r| j                  |      S |j                  d      }|r|S t        t        t        j                                     S c c}w )z5
        Get the object name for the request
        rU   file content is requiredbatchr   filename)rB   rC   rX   
splitlinesstripjsonloadslenrf   rO   inttime)r,   rh   ri   extracted_file_data_contentrV   liner[   rm   s           r.   get_object_namez#VertexAIFilesConfig.get_object_name}   s     ':&=&=i&H#&.788g==+L .:-D-D-F$-FT$**,

4 -F ! $ '(1,AABVWW '**:6O3tyy{#$$$s   CCdatac                    |j                  d      xs9 |j                  di       j                  dd      xs t        j                  d      }|st	        d      |j                  d      }|j                  d      }	|t	        d	      |	t	        d
      t        |      }
| j                  |
|	      }d| d| }|xs d}|st	        d      | d| S )z6
        Get the complete url for the request
        bucket_namelitellm_metadatagcs_bucket_nameNGCS_BUCKET_NAMEzGCS bucket_name is requiredfileri   file is requiredzpurpose is requiredzupload/storage/v1/b/z/o?uploadType=media&name=zhttps://storage.googleapis.comzapi_base is requiredr`   )rB   poposgetenvrC   r   rw   )r,   r:   r9   r5   r7   r8   rx   rz   	file_datari   rh   re   endpoints                r.   get_complete_file_urlz)VertexAIFilesConfig.get_complete_file_url   s     }- ,!!"4b9==>OQUV,yy*+ 	
 :;;HHV$	((9%/00?233/	:**+>H";-/HV 	 ??3441XJ''r/   c                     g S r'    )r,   r5   s     r.   get_supported_openai_paramsz/VertexAIFilesConfig.get_supported_openai_params   s	     	r/   non_default_paramsdrop_paramsc                     |S r'   r   )r,   r   r7   r5   r   s        r.   map_openai_paramsz%VertexAIFilesConfig.map_openai_params   s
     r/   openai_request_bodyc                 n    ddl m}  |       }|j                  dd      }|j                  ||i d      }|S )F
        wrapper to call VertexGeminiConfig.map_openai_params
        r   r   r5   r_   Fr5   r   r7   r   )@litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_geminir   rB   r   )r,   r   r   configrd   vertex_paramss         r.   _map_openai_to_vertex_paramsz0VertexAIFilesConfig._map_openai_to_vertex_params   sL    	
 $%$(("5002	 1 
 r/   c           	          g }|D ]j  }|j                  d      xs i }t        |j                  dg       |j                  dd      | j                  |      di d      }|j                  d|i       l |S 	a  
        Transforms OpenAI JSONL content to VertexAI JSONL content

        jsonl body for vertex is {"request": <request_body>}
        Example Vertex jsonl
        {"request":{"contents": [{"role": "user", "parts": [{"text": "What is the relation between the following video and image samples?"}, {"fileData": {"fileUri": "gs://cloud-samples-data/generative-ai/video/animals.mp4", "mimeType": "video/mp4"}}, {"fileData": {"fileUri": "gs://cloud-samples-data/generative-ai/image/cricket.jpeg", "mimeType": "image/jpeg"}}]}]}}
        {"request":{"contents": [{"role": "user", "parts": [{"text": "Describe what is happening in this video."}, {"fileData": {"fileUri": "gs://cloud-samples-data/generative-ai/video/another_video.mov", "mimeType": "video/mov"}}]}]}}
        r^   r6   r5   r_   	vertex_aiN)r6   r5   r7   r3   r8   cached_contentrequestrB   r   r   appendr,   r[   vertex_jsonl_content_openai_jsonl_contentr   vertex_request_bodys         r.   :_transform_openai_jsonl_content_to_vertex_ai_jsonl_contentzNVertexAIFilesConfig._transform_openai_jsonl_content_to_vertex_ai_jsonl_content         "%9!"7";";F"C"Ir"9,00R@)--gr: $ A ABU V$/!## !''4G(HI &: $#r/   create_file_datac                    |j                  d      }|t        d      t        |      }|j                  d      }|t        d      t        j                  ||      r{| j                  |      }|j                         D 	cg c](  }	|	j                         st        j                  |	      * }
}	| j                  |
      }dj                  d |D              S t        |t              r|S t        d      c c}	w )	zk
        2 Cases:
        1. Handle basic file upload
        2. Handle batch file upload (.jsonl)
        r~   r   rU   rk   )r   rh   
c              3   F   K   | ]  }t        j                  |        y wr'   rp   dumps.0items     r.   	<genexpr>zDVertexAIFilesConfig.transform_create_file_request.<locals>.<genexpr>$  s     O:N$TZZ-:N   !zUnsupported file content type)rB   rC   r   r   is_batch_jsonl_filerX   rn   ro   rp   rq   r   joinrM   rP   )r,   r5   r   r7   r8   r   rh   ru   rV   rv   r[   r   s               r.   transform_create_file_requestz1VertexAIFilesConfig.transform_create_file_request   s    %((0	/00/	:&9&=&=i&H#&.788,,- 3

  ==+L .:-D-D-F$-FT$**,

4 -F ! $ OO( !
 99O:NOOO3U;..<==$s   C7C7raw_responselogging_objc                    |j                         }	 t        di |}|j                  dd      }|r#dj                  |j                  d      dd       nd}t        |j                  dd	      d
| |j                  dd      t        |j                  dd            dt        |j                  dd            d      S # t        $ r*}t        |j                  d| |j
                        d}~ww xY w)zV
        Transform VertexAI File upload response into OpenAI-style FileObject
        z#Error reading GCS bucket response: status_codemessager4   Nidr_   r`   ri   rl   gs://nametimeCreatedvertex_datetimeuploadedsizer   r~   ri   r   rm   
created_atstatusrP   objectr   )rp   r   	Exceptionr"   r   r4   rB   r   splitr   r   rs   )	r,   r5   r   r   r8   response_jsonresponse_objectegcs_ids	            r.   transform_create_file_responsez2VertexAIFilesConfig.transform_create_file_response*  s    %))+	/@-@O !$$T2.5;&,,s+CR01#''	7;vh$((4B / 3 3M2 F o))&!45

 
	
  	(44=aSA$,, 	s   B> >	C1%C,,C1error_messager   c                     t        |||      S )Nr   r!   )r,   r   r   r4   s       r.   get_error_classz#VertexAIFilesConfig.get_error_classO  s     #]G
 	
r/   file_idc                     ddl }|j                  j                  |      }|j                  d      r|dd }n|}d|v r|j	                  dd      \  }}n|}d}|j                  j                  |d      }||fS )	z
        Parse a GCS URI (gs://bucket/path/to/object) into (bucket, url-encoded-object-path).
        Handles both raw and URL-encoded input.
        r   Nr      r`   rI   r_   )safe)urllib.parseparseunquote
startswithr   quote)r,   r   urllibdecoded	full_pathrz   object_pathencoded_objects           r.   _parse_gcs_uriz"VertexAIFilesConfig._parse_gcs_uriV  s    
 	,,&&w/g&II)'0sA'>$K#KK++Kb+AN**r/   c                 B    | j                  |      \  }}d| d| }|i fS N,https://storage.googleapis.com/storage/v1/b//o/r   r,   r   r7   r8   bucketr   urls          r.   transform_retrieve_file_requestz3VertexAIFilesConfig.transform_retrieve_file_requestl  5     "&!4!4W!=<VHCGWXBwr/   c                    |j                         }|j                  dd      }|r#dj                  |j                  d      d d       nd}t	        d| t        |j                  dd            t        |j                  dd      	      |j                  d
d      d|j                  di       j                  dd      dd       S )Nr   r_   r`   r   r   r   r   r   r   r   r~   metadatari   rl   	processed)r   rP   r   rm   r   ri   r   status_details)rp   rB   r   r   r   rs   r   )r,   r   r   r8   r   r   s         r.    transform_retrieve_file_responsez4VertexAIFilesConfig.transform_retrieve_file_responsev  s     %))+""4,5;&,,s+CR01vhm''23B - 1 1- D #&&vr2!%%j"599)WM
 	
r/   c                 B    | j                  |      \  }}d| d| }|i fS r   r   r   s          r.   transform_delete_file_requestz1VertexAIFilesConfig.transform_delete_file_request  r   r/   c                    d}t        |d      r|j                  rt        |j                  j                        }d|v rud|v rqdd l}|j                  d      d   j                  d      d   }|j                  d      d   j                  d      d   }d| d	|j                  j                  |       }t        |d
d      S )Ndeletedr   z/b/r   r   r   ?r   r`   Tr~   )r   r   r   )	rR   r   rO   r   r   r   r   r   r   )	r,   r   r   r8   r   r   r   bucket_partencoded_names	            r.   transform_delete_file_responsez2VertexAIFilesConfig.transform_delete_file_response  s     <+0D0Dl**../C|#!ii.r288?B"yy/399#>qA!+a0D0D\0R/STgtFCCr/   c                     t        d      Nz1VertexAIFilesConfig does not support file listingNotImplementedError)r,   ri   r7   r8   s       r.   transform_list_files_requestz0VertexAIFilesConfig.transform_list_files_request       ""UVVr/   c                     t        d      r   r   r,   r   r   r8   s       r.   transform_list_files_responsez1VertexAIFilesConfig.transform_list_files_response  r   r/   c                 h    |j                  dd      }| j                  |      \  }}d| d| d}|i fS )Nr   r_   r   r   z
?alt=media)rB   r   )r,   file_content_requestr7   r8   r   r   r   r   s           r.   transform_file_content_requestz2VertexAIFilesConfig.transform_file_content_request  sJ     '**9b9!%!4!4W!=<VHCGWWabBwr/   c                     t        |      S )N)response)r   r   s       r.   transform_file_content_responsez3VertexAIFilesConfig.transform_file_content_response  s     *<@@r/   )NN)6__name__
__module____qualname____doc__r+   propertyr   r3   dictrO   r   r   r   rE   r   rX   r   r   rf   r   rw   r   r   r   r   boolr   r   r   r   rP   r   r
   r   r   r   rs   r	   r   r   r   r   rN   r   r   r   r   r   r   r   r   r   r  __classcell__)r-   s   @r.   r%   r%   (   s5    &\ & & "&"&  '(	
   # 3- 
(# #s #J"4S>2 
%#4%?B%	%>"(3-"( #"( 	"(
 "( "(  "( 
"(H	3	4
   	
  
!#s(^ 
c3h*$$(c3h$8$	d38n	$4+>+> ,+> 	+>
 +> 
uc4	 +>Z#
}#
 #
 '	#

 #
 
#
J
 
/2
=B4==Q
	
+c +eCHo +,  	
 
sDy	

 '
 	

 

,  	
 
sDy	DD 'D 	D
 
D"W#W W 	W
 
sDy	WWW 'W 	W
 
	W	 	 		
 
sDy		AA 'A 	A
 
$Ar/   r%   c                       e Zd ZdZ	 ddee   deeef   fdZde	e
eef      fdZde	e
eef      defdZd	e
eef   de
eef   fd
ZdedefdZdede
eef   defdZy)r(   zQ
    Transforms OpenAI /v1/files/* requests to VertexAI /v1/files/* requests
    NrF   r0   c                 H   |t        d      | j                  |      }|j                         D cg c](  }|j                         st	        j
                  |      * }}| j                  |      }dj                  d |D              }| j                  |      }||fS c c}w )zU
        Transforms OpenAI FileContentRequest to VertexAI FileContentRequest
        zcontents of file are Noner   c              3   F   K   | ]  }t        j                  |        y wr'   r   r   s     r.   r   zkVertexAIJsonlFilesTransformation.transform_openai_file_content_to_vertex_ai_file_content.<locals>.<genexpr>  s      (
)=DJJt)=r   )r[   )	rC   rX   rn   ro   rp   rq   r   r   _get_gcs_object_name)r,   rF   rV   rv   r[   r   vertex_jsonl_stringre   s           r.   7transform_openai_file_content_to_vertex_ai_file_contentzXVertexAIJsonlFilesTransformation.transform_openai_file_content_to_vertex_ai_file_content  s     &89999:MN *6)@)@)B 
)BdjjlDJJt)B 	  
 KK$ 	
 #ii (
)=(
 
 //!5 0 
 #K// 
s   BBr[   c           	          g }|D ]j  }|j                  d      xs i }t        |j                  dg       |j                  dd      | j                  |      di d      }|j                  d|i       l |S r   r   r   s         r.   r   z[VertexAIJsonlFilesTransformation._transform_openai_jsonl_content_to_vertex_ai_jsonl_content  r   r/   c                     |d   j                  di       j                  dd      }d|vrd| }d| dt        j                          }|S r]   ra   rc   s       r.   r  z5VertexAIJsonlFilesTransformation._get_gcs_object_name  rg   r/   r   c                 T    |j                  dd      }| j                  ||i d      }|S )r   r5   r_   Fr   )rB   r   )r,   r   rd   r   s       r.   r   z=VertexAIJsonlFilesTransformation._map_openai_to_vertex_params  s?     %(("5..2	 / 
 r/   c                    d}t        |t              r|d   }n|}t        |t              r|}nnt        |t              r|}n[t        |t              r/t        t        |      d      5 }|j                         }ddd       nt        |d      r|j                         }t        |t              r|j                  d      }|S # 1 sw Y   ,xY wrH   rL   rT   s        r.   rX   z>VertexAIJsonlFilesTransformation._get_content_from_openai_file&  rY   rZ   r   gcs_upload_responsec                 2   |j                  dd      }|r#dj                  |j                  d      dd       nd}t        |j                  dd      d| |j                  d	d      t	        |j                  d
d            d|j                  dd      d      S )zQ
        Transforms GCS Bucket upload file response to OpenAI FileObject
        r   r_   r`   Nr   ri   rl   r   r   r   r   r   r   r   r~   r   )rB   r   r   r   r   )r,   r   r  r   s       r.   3transform_gcs_bucket_response_to_openai_file_objectzTVertexAIJsonlFilesTransformation.transform_gcs_bucket_response_to_openai_file_objectK  s     %((r25;&,,s+CR01$((G<vh(,,VR8B 3 7 7r J %))&!4

 
	
r/   r'   )r  r  r  r  r   r   r   rO   r  r   r   r   r   r  r   rX   r   r   r  r   r/   r.   r(   r(     s    
 :>0#+I#60	sCx0:$$(c3h$8$4"4S>2 
!#s(^ 
c3h # #s #J
 1
HLSRUX
	
r/   r(   )3rp   r   rt   typingr   r   r   r   r   r   httpxr	   r
   openai.types.file_deletedr   litellm._uuidr   litellm.files.utilsr   8litellm.litellm_core_utils.prompt_templates.common_utilsr   )litellm.llms.base_llm.chat.transformationr   *litellm.llms.base_llm.files.transformationr   r   #litellm.llms.vertex_ai.common_utilsr   ,litellm.llms.vertex_ai.gemini.transformationr   r   r   litellm.types.llms.openair   r   r   r   r   r   r   litellm.types.llms.vertex_air   litellm.types.utilsr   r   common_utilsr"   vertex_llm_baser#   r%   r(   r   r/   r.   <module>r&     sz     	  : : # 1  - V F Q   ; ? ( (`A*o `AFT
'9 T
r/   