Ë
    uPêj’·  ã                   óh  — U d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlmZm	Z	m
Z
mZ d dlmZmZmZ d dlmZ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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.m/Z/m0Z0m1Z1 d dl2m3Z3 d dl4m5Z5 d dl6m7Z7 d dl8m9Z9 d dl:m;Z; d dl<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZD d dlEmFZFmGZG d dlHmIZImJZJmKZKmLZLmMZM ddlNmOZO ddlPmQZQ dZReeSd<   dZTeeSd<   dZUeeSd<    ej¬                  d «      ZWeeSd!<   d"ZXeeSd#<    ej¬                  d$«      ZYeeSd%<    G d&„ d'ed(¬)«      ZZ G d*„ d+ed(¬)«      Z[ G d,„ d-ed(¬)«      Z\ G d.„ d/ed(¬)«      Z] G d0„ d1e«      Z^ G d2„ d3e«      Z_ G d4„ d5e«      Z`d6ead7eafd8„Zbd6ead7ecea   fd9„Zdd:ecea   d7eadz  fd;„Zed<efeaeaf   d=egd7dfd>„Zhd?eeaegf   d7eafd@„Zid<eeaegf   dz  d7eafdA„Zjd?eeaef   d7ekfdB„Zl	 	 	 djd=eadCeeaef   dz  dDeadz  dEead7e`f
dF„Zmd?eeaef   d7eneaeoeof   fdG„ZpdHeeaef   d7eofdI„Zqd=eadJeneeaef   dKf   dLeneodKf   dMeodNeadz  d7e`fdO„ZrdJe	eeaef      dNeadz  d7ene`dKf   fdP„ZsdQead7eadz  fdR„ZtdSeeaef   d7ekfdT„ZudUeGd7eneaecea   z  dKf   fdV„Zvd=eadWeodXeod7eafdY„Zwdeadz  dZeeaef   d7eeaef   fd[„ZxdSeeaef   d7eneeaef   dKf   fd\„ZydSefeaef   d]eefeaef   gefeaef   f   d7eneeaef   dKf   fd^„Zzd_e	eae{z     d7e
ea   fd`„Z|dae?d7e
ea   fdb„Z}dae?d7e
efeaef      fdc„Z~ddead7e]fde„Z G df„ dge0«      Z€ G dh„ dieQe/«      Z�y)ké    N)ÚCallableÚIterableÚIteratorÚMapping)ÚAnyÚFinalÚ	TypedDict)ÚquoteÚunquote)ÚHeadersÚResponse)ÚFileDeleted)ÚReadOnly)Úuuid)ÚFilesAPIUtils)ÚVERTEX_AI_MANAGED_GCS_PREFIXÚbuild_managed_cloud_object_nameÚencode_gcs_object_name_for_urlÚsanitize_cloud_object_pathÚ"should_allow_legacy_cloud_file_idsÚ"split_configured_cloud_bucket_nameÚvalidate_managed_cloud_file_id)ÚLogging)Úextract_file_dataÚextract_file_metadata)ÚBaseLLMException)ÚBaseFilesConfigÚBaseFileUploadStreamÚLiteLLMLoggingObj)Ú+_convert_vertex_datetime_to_openai_datetime)Ú_transform_request_body©ÚVertexGeminiConfig)Ú+transform_openai_input_gemini_embed_content)ÚStreamingMediaUploadConfig)ÚAllMessageValuesÚCreateFileRequestÚ	FileTypesÚHttpxBinaryResponseContentÚ%OpenAICreateFileRequestOptionalParamsÚOpenAIFileObjectÚOpenAIFilesPurposeÚPathLike)ÚGcsBucketResponseÚGeminiEmbeddingInput)Ú	EmbeddingÚEmbeddingResponseÚLlmProvidersÚModelResponseÚUsageé   ©ÚVertexAIError)Ú
VertexBaseé?   Ú_GCP_LABEL_VALUE_MAX_LENÚb32_Ú_CUSTOM_ID_RAW_LABEL_PREFIXÚkeyÚ_VERTEX_BATCH_KEY_FIELDz publishers/[^/]+/models/([^/?]+)Ú_MANAGED_GCS_MODEL_PATH_PATTERN))ÚoutputDimensionalityÚoutput_dimensionality)ÚtaskTypeÚ	task_type)ÚtitlerD   Ú$_EMBED_REQUEST_FIELD_BY_GEMINI_PARAMz2(?P<custom_id>[^#]*)#(?P<index>\d+)/(?P<total>\d+)Ú$_VERTEX_BATCH_FANNED_OUT_KEY_PATTERNc                   ó   — e Zd ZU ee   ed<   y)Ú_GcsObjectMetadataJsonÚpurposeN)Ú__name__Ú
__module__Ú__qualname__r   r,   Ú__annotations__© ó    úp/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/llms/vertex_ai/files/transformation.pyrH   rH   U   s   … ØÐ(Ñ)Ô)rO   rH   F)Útotalc                   ó^   — e Zd ZU ee   ed<   ee   ed<   ee   ed<   ee   ed<   ee   ed<   y)Ú_GcsObjectJsonÚidÚnameÚsizeÚtimeCreatedÚmetadataN)rJ   rK   rL   r   ÚstrrM   rH   rN   rO   rP   rS   rS   Y   s6   … Ø�‰ÓØ
�3‰-ÓØ
�3‰-ÓØ˜#‘ÓØÐ-Ñ.Ô.rO   rS   c                   ó(   — e Zd ZU eeeef      ed<   y)Ú_VertexBatchRowRequestÚlabelsN)rJ   rK   rL   r   r   rY   ÚobjectrM   rN   rO   rP   r[   r[   a   s   … Ø�W˜S &˜[Ñ)Ñ*Ô*rO   r[   c                   ó>   — e Zd ZU ee   ed<   ee   ed<   ee   ed<   y)Ú_VertexBatchRowÚrequestÚstatusÚprocessed_timeN)rJ   rK   rL   r   r[   rM   rY   rN   rO   rP   r_   r_   e   s"   … ØÐ,Ñ-Ó-Ø�S‰MÓØ˜S‘MÔ!rO   r_   c                   ó.   — e Zd ZU ee   ed<   ee   ed<   y)Ú_OpenAIBatchOutputErrorÚcodeÚmessageN)rJ   rK   rL   r   rY   rM   rN   rO   rP   rd   rd   k   s   … Ø
�3‰-ÓØ�c‰]ÔrO   rd   c                   óH   — e Zd ZU ee   ed<   ee   ed<   eeeef      ed<   y)Ú_OpenAIBatchOutputResponseÚstatus_codeÚ
request_idÚbodyN)	rJ   rK   rL   r   ÚintrM   rY   r   r]   rN   rO   rP   rh   rh   p   s*   … Ø˜#‘ÓØ˜‘ÓØ
�7˜3 ˜;Ñ'Ñ
(Ô(rO   rh   c                   óZ   — e Zd ZU ee   ed<   ee   ed<   eedz     ed<   eedz     ed<   y)Ú_OpenAIBatchOutputRowrT   Ú	custom_idNÚresponseÚerror)rJ   rK   rL   r   rY   rM   rh   rd   rN   rO   rP   rn   rn   v   s8   … Ø�‰ÓØ˜‰}ÓØÐ1°DÑ8Ñ9Ó9ØÐ+¨dÑ2Ñ3Ô3rO   rn   ÚvalueÚreturnc                 ó^   — t        j                  dd| j                  «       «      }|dt         S )aC  
    Sanitize a string to meet GCP label value constraints.

    GCP label values must:
    - Be lowercase
    - Contain only letters, numbers, underscores, and hyphens
    - Be max 63 characters

    Args:
        value: The string to sanitize

    Returns:
        A sanitized string that meets GCP label constraints
    z[^a-z0-9_-]Ú_N)ÚreÚsubÚlowerr:   )rr   Ú	sanitizeds     rP   Ú_sanitize_gcp_label_valuerz   }   s+   € ô —v‘v˜n¨c°5·;±;³=ÓA€IØÐ.Ô.Ð/Ð/rO   c                 óN  — t         t        t        «      z
  }t        j                  | j                  d«      «      j                  d«      j                  d«      j                  «       }t        dt        |«      |«      D �cg c]  }t        › ||||z    › �‘Œ c}xs t        gS c c}w )z?Encode arbitrary text across one or more GCP-label-safe values.úutf-8Úasciiú=r   )
r:   Úlenr<   Úbase64Ú	b32encodeÚencodeÚdecodeÚrstriprx   Úrange)rr   Úmax_encoded_lenÚencodedÚis       rP   Ú_encode_gcp_label_value_chunksr‰   �   sž   € ä5¼Ô<WÓ8XÑX€OÜ×%Ñ% e§l¡l°7Ó&;Ó<×CÑCÀGÓL×SÑSÐTWÓX×^Ñ^Ó`€Gô �qœ#˜g›,¨Ó8öàô 'Ð
'¨°°A¸Ñ4GÐ(HÐ'IÒJòò 'ô &Ð	&ð'ùò s   Á?B"Úvaluesc                 óT  — g }| D ]:  }|j                  t        «      s y|j                  |t        t        «      d «       Œ< dj	                  |«      j                  «       }dt        |«       dz  z  }	 t        j                  ||z   «      j                  d«      S # t        $ r Y yw xY w)z9Decode values produced by _encode_gcp_label_value_chunks.NÚ r~   é   r|   )
Ú
startswithr<   Úappendr   ÚjoinÚupperr€   Ú	b32decoderƒ   Ú	Exception)rŠ   Úencoded_partsrr   r‡   Úpaddings        rP   Ú_decode_gcp_label_value_chunksr–   š   s¬   € à€MØò HˆØ×ÑÔ ;Ô<ÙØ×Ñ˜U¤3Ô'BÓ#CÐ#EÐFÕGðHð —W‘W˜]Ó+×1Ñ1Ó3€GØœS ›\˜M¨AÑ-Ñ.€GðÜ×Ñ ¨'Ñ 1Ó2×9Ñ9¸'ÓBÐBøÜò Ùðús   Á4&B Â	B'Â&B'r\   ro   c                 óœ   — t        |«      }t        |«      | d<   t        |«      }|d   | d<   t        |dd d¬«      D ]  \  }}|| d|› �<   Œ y)a	  
    Store OpenAI batch custom_id for Vertex batch correlation.

    ``litellm_custom_id`` is GCP-label-safe (may alter casing and characters).
    ``litellm_custom_id_raw`` encodes the original string for
    round-trip correlation in batch output transforms.
    Úlitellm_custom_idr   Úlitellm_custom_id_rawé   N)ÚstartÚlitellm_custom_id_raw_)rY   rz   r‰   Ú	enumerate)r\   ro   Úcustom_id_strÚraw_label_chunksÚindexÚraw_label_chunks         rP   Ú#_set_litellm_batch_custom_id_labelsr¢   ©   so   € ô ˜y›>€MÜ";¸MÓ"J€FÐÑÜ<¸]ÓKÐØ&6°qÑ&9€FÐ"Ñ#Ü"+Ð,<¸Q¸RÐ,@ÈÔ"Jò CÑˆˆØ3BˆÐ'¨ wÐ/Ò0ñCrO   Úvertex_output_rowc                 óÖ   — | j                  t        «      }|�t        t        |«      «      S | j                  d«      }t	        |t
        «      r|j                  d«      nd}t        |«      S )a+  
    Resolve the OpenAI `custom_id` for a Vertex batch output row.

    Embedding rows carry it in the top-level `key` field that Vertex echoes back;
    `generateContent` rows have no such field, so it is smuggled through request
    labels instead (see `_set_litellm_batch_custom_id_labels`).
    Nr`   r\   )Úgetr>   r   rY   Ú
isinstancer   Ú(_get_litellm_batch_custom_id_from_labels)r£   r=   Úrequest_datar\   s       rP   Ú_get_litellm_batch_custom_idr©   ¹   s`   € ð ×
Ñ
Ô 7Ó
8€CØ
€Ü”s˜3“xÓ Ð Ø$×(Ñ(¨Ó3€LÜ+5°lÄGÔ+Lˆ\×Ñ˜hÔ'ÐRV€FÜ3°FÓ;Ð;rO   c           	      óð  — | sy| j                  d«      }|rÆt        |«      g}d}g }| j                  «       D ]e  \  }}|j                  |«      sŒ|t	        |«      d j                  «       sŒ5|j                  t        |t	        |«      d «      t        |«      f«       Œg |j                  d„ t        |d„ ¬«      D «       «       t        |«      }|�|S t        |«      S t        | j                  dd«      «      S )	zPPrefer encoded custom_id when present (see _set_litellm_batch_custom_id_labels).Úunknownr™   rœ   Nc              3   ó&   K  — | ]	  \  }}|–— Œ y ­w©NrN   )Ú.0ru   r¡   s      rP   ú	<genexpr>z;_get_litellm_batch_custom_id_from_labels.<locals>.<genexpr>Õ   s   è ø€ ÒuÑ.@¨a°œ/Ñuùó   ‚c                 ó   — | d   S ©Nr   rN   )Úitems    rP   ú<lambda>z:_get_litellm_batch_custom_id_from_labels.<locals>.<lambda>Õ   s   € ÐlpÐqrÑls€ rO   ©r=   r˜   )r¥   rY   ÚitemsrŽ   r   Úisdigitr�   rl   ÚextendÚsortedr–   )r\   ÚrawÚ
raw_chunksÚchunk_prefixÚindexed_chunksr=   rr   Údecodeds           rP   r§   r§   É   sê   € áØØ—‘Ð3Ó4€CÙ
Ü  ›X˜Jˆ
Ø6ˆØ "ˆØ Ÿ,™,›.ò 	S‰JˆC�Ø�~‰~˜lÕ+°´C¸Ó4EÐ4GÐ0H×0PÑ0PÕ0RØ×%Ñ%¤s¨3¬s°<Ó/@Ð/BÐ+CÓ'DÄcÈ%ÃjÐ&QÕRð	Sð 	×ÑÑuÄFÈ>Ñ_sÔDtÔuÔuÜ7¸
ÓCˆØÐØˆNÜ�3‹xˆÜˆv�z‰zÐ-¨yÓ9Ó:Ð:rO   c                 ó  — d| vry| j                  d«      }t        |t        «      r t        |j                  d«      t        «      ry| j                  d«      }t        | j                  d«      «      xr t        |t        «      xr d|v S )a"  
    Whether a Vertex batch output row came from an `EmbedContentRequest`.

    Successful rows hold the vector under `response.embedding.values`; failed rows only
    carry `status`, so they are recognized from the singular `content` that the
    embeddings request shape echoes back.
    r`   Frp   Ú	embeddingTra   Úcontent)r¥   r¦   ÚdictÚbool)r£   rp   r¨   s      rP   Ú&_is_vertex_embeddings_batch_output_rowrÄ   Ý   s~   € ð Ð)Ñ)ØØ ×$Ñ$ ZÓ0€HÜ�(œDÔ!¤j°·±¸kÓ1JÌDÔ&QØØ$×(Ñ(¨Ó3€LÜÐ!×%Ñ% hÓ/Ó0Òq´ZÀÌdÓ5SÒqÐXaÐeqÐXqÐqrO   rk   Ú
error_codeÚerror_messagec                 ó|   — dt        j                  «       › �| |€dnd|j                  dd«      |dœ|€ddœS ||dœdœS )	z‘
    One row of an OpenAI batch output file. Per the OpenAI Batch spec, failed rows set
    `response` to null and populate `error` instead.
    Ú
batch_req_NéÈ   rT   rŒ   )ri   rj   rk   )re   rf   )rT   ro   rp   rq   )r   Úuuid4r¥   )ro   rk   rÅ   rÆ   s       rP   Ú_openai_batch_output_rowrË   î   sf   € ð œ4Ÿ:™:›<˜.Ð)Øàˆ<ñ ð ØŸ(™( 4¨Ó,Øñ
ð
 $Ð+�ñð ð ;EÐQ^Ñ1_ñð rO   c                 ó  — | j                  t        «      }|€t        | «      ddfS t        j	                  t        |«      «      }|€t        t        |«      «      ddfS t        |d   «      t        |d   «      t        |d   «      fS )ar  
    Resolve `(custom_id, index within that custom_id, group size)` for a Vertex batch
    output row.

    A `/v1/embeddings` entry whose `input` is an array fans out into one Vertex row per
    element, tagged `<percent-encoded custom_id>#<index>/<total>` (see
    `_vertex_batch_embeddings_key`), so the rows can be reassembled into a single OpenAI
    response.
    r   rš   ro   r    rQ   )r¥   r>   r©   rF   Ú	fullmatchrY   r   rl   )r£   r=   Úmatchs      rP   Ú_split_vertex_batch_keyrÏ     s…   € ð ×
Ñ
Ô 7Ó
8€CØ
€{Ü+Ð,=Ó>ÀÀ1ÐDÐDÜ0×:Ñ:¼3¸s»8ÓD€EØ€}Ü”s˜3“xÓ  ! QÐ&Ð&Ü�5˜Ñ%Ó&¬¨E°'©NÓ(;¼SÀÀwÁÓ=PÐPÐPrO   Úvertex_responsec                 ó¼   — | j                  d«      }t        |t        «      rt        |j                  d«      xs d«      S t        | j                  d«      xs d«      S )z³
    Prompt tokens billed for one Vertex Gemini Embedding batch row.

    Live rows report usage under `usageMetadata`; the documented `tokenCount` is kept as
    a fallback.
    ÚusageMetadataÚpromptTokenCountr   Ú
tokenCount)r¥   r¦   r   rl   )rÐ   Úusage_metadatas     rP   Ú_embedding_prompt_token_countrÖ     sU   € ð %×(Ñ(¨Ó9€NÜ�.¤'Ô*Ü�>×%Ñ%Ð&8Ó9Ò>¸QÓ?Ð?Üˆ×"Ñ" <Ó0Ò5°AÓ6Ð6rO   Úvertex_output_rows.Úelement_indicesÚelement_countÚmodelc                 óÒ  — t        d„ |D «       d«      }|rt        | d|¬«      S |t        t        |«      «      k7  rt        | ddt	        |«      › d|› d�¬«      S t        d„ |D «       «      }t        d	„ |D «       «      }t        |xs dt        |«      D ��	cg c]  \  }}	t        |	d
   d   |d
¬«      ‘Œ c}	}t        ||¬«      ¬«      j                  «       }
t        | |
¬«      S c c}	}w )a  
    Transforms the Vertex Gemini Embedding batch output rows belonging to one OpenAI
    batch entry into an OpenAI batch output row holding an `/v1/embeddings` response.

    Example Vertex jsonl
    {"key": "id_1", "request": {...}, "response": {"embedding": {"values": [-0.015, 0.024]}, "usageMetadata": {"promptTokenCount": 2}}}

    An entry that asked for several embeddings at once maps to several rows here, which
    become the indexed elements of a single `data` array. One failed or missing element
    fails the whole entry, since an OpenAI batch row is either a response or an error and
    a partial `data` array would silently shift the remaining embeddings onto the wrong
    input positions. Rows carry no `modelVersion`, so the model comes from the batch they
    belong to.
    c              3   óJ   K  — | ]  }|j                  d «      sŒ|d    –— Œ y­w)ra   N)r¥   ©r®   Úrows     rP   r¯   zE_vertex_embeddings_rows_to_openai_batch_output_row.<locals>.<genexpr>;  s   è ø€ ÒT SÀ#Ç'Á'È(ÕBS�3�x•=ÑTùs   ‚#™
#rŒ   Úvertex_ai_error©ro   rÅ   rÆ   z/Vertex returned embeddings for input positions z of the z
 requestedc              3   ó&   K  — | ]	  }|d    –— Œ y­w)rp   NrN   rÝ   s     rP   r¯   zE_vertex_embeddings_rows_to_openai_batch_output_row.<locals>.<genexpr>M  s   è ø€ ÒD¨#�c˜*•oÑDùr°   c              3   ó2   K  — | ]  }t        |«      –— Œ y ­wr­   )rÖ   )r®   rp   s     rP   r¯   zE_vertex_embeddings_rows_to_openai_batch_output_row.<locals>.<genexpr>N  s   è ø€ ÒXÀ(Ô3°H×=ÑXùs   ‚rÀ   rŠ   )rÀ   r    r]   )Úprompt_tokensÚtotal_tokens)rÚ   ÚdataÚusage©ro   rk   )ÚnextrË   Útupler…   ÚlistÚsumr1   r�   r0   r4   Ú
model_dump)ro   r×   rØ   rÙ   rÚ   ra   Ú	responsesÚtoken_countr    rp   rk   s              rP   Ú2_vertex_embeddings_rows_to_openai_batch_output_rowrï   &  s  € ô* ÑTÐ,>ÔTÐVXÓY€FÙÜ'ØØ(Ø ô
ð 	
ð œ%¤ mÓ 4Ó5Ò5Ü'ØØ(àAÄ$ÀÓBWÐAXð YØ'˜¨
ð4ô	
ð 	
ô ÑDÐ1CÔDÓD€IÜÑXÈiÔXÓX€KÜØŠk�rô $-¨YÓ#7÷
ñ  ��xô Ø" ;Ñ/°Ñ9ØØ"öó
ô  +¸KÔHô÷ �jƒlð 	ô $¨i¸dÔCÐCùó
s   ÂC#c                 ó  ‡‡— t        d„ | D «       «      }t        j                  t        |d„ ¬«      d„ ¬«      D ��ci c]  \  }}|t        |«      “Œ c}}Št        ˆˆfd„t        j                  d„ |D «       «      D «       «      S c c}}w )aH  
    Transforms a whole Vertex Gemini Embedding batch output into OpenAI batch output
    rows, one per OpenAI batch entry, in the order the entries first appear.

    Rows are grouped rather than mapped one to one because a single entry can fan out
    into several Vertex rows, and Vertex returns them in arbitrary order.
    c              3   ó6   K  — | ]  }t        |«      |f–— Œ y ­wr­   )rÏ   rÝ   s     rP   r¯   zF_transform_vertex_embeddings_batch_output_to_openai.<locals>.<genexpr>i  s   è ø€ ÒY¸sÔ/°Ó4°cÔ:ÑYùs   ‚c                 ó   — | d   S r²   rN   ©Úkrs    rP   r´   zE_transform_vertex_embeddings_batch_output_to_openai.<locals>.<lambda>l  s   € ÐTVÐWXÑTY€ rO   rµ   c                 ó   — | d   d   S r²   rN   ró   s    rP   r´   zE_transform_vertex_embeddings_batch_output_to_openai.<locals>.<lambda>l  s   € ÐkmÐnoÑkpÐqrÑks€ rO   c              3   ó°   •K  — | ]M  }t        |t        d „ ‰|   D «       «      t        d„ ‰|   D «       «      t        d„ ‰|   D «       «      ‰¬«      –— ŒO y­w)c              3   ó&   K  — | ]	  \  }}|–— Œ y ­wr­   rN   )r®   ru   rÞ   s      rP   r¯   zP_transform_vertex_embeddings_batch_output_to_openai.<locals>.<genexpr>.<genexpr>q  s   è ø€ Ò$O©V¨Q°¤SÑ$Oùr°   c              3   ó.   K  — | ]  \  \  }}}}|–— Œ y ­wr­   rN   )r®   ru   r    s      rP   r¯   zP_transform_vertex_embeddings_batch_output_to_openai.<locals>.<genexpr>.<genexpr>r  s   è ø€ Ò!XÑ,<©M¨Q°°q¸1¤%Ñ!Xùó   ‚c              3   ó.   K  — | ]  \  \  }}}}|–— Œ y ­wr­   rN   )r®   ru   rQ   s      rP   r¯   zP_transform_vertex_embeddings_batch_output_to_openai.<locals>.<genexpr>.<genexpr>s  s   è ø€ ÒTÑ(8©¨¨A¨u°qœeÑTùrù   )ro   r×   rØ   rÙ   rÚ   N)rï   ré   Úmax)r®   ro   Úgrouped_rowsrÚ   s     €€rP   r¯   zF_transform_vertex_embeddings_batch_output_to_openai.<locals>.<genexpr>n  sd   øè ø€ ò 	ð ô 	;ØÜ$Ñ$O°|ÀIÑ7NÔ$OÓOÜ!Ñ!XÀÈYÑ@WÔ!XÓXÜÑT¸LÈÑ<SÔTÓTØ÷	
ð 	
ñ	ùs   ƒAAc              3   ó.   K  — | ]  \  \  }}}}|–— Œ y ­wr­   rN   )r®   ro   ru   s      rP   r¯   zF_transform_vertex_embeddings_batch_output_to_openai.<locals>.<genexpr>v  s   è ø€ Ò&XÑ5IÑ5F°iÀÀAÈ¤yÑ&Xùrù   )ré   Ú	itertoolsÚgroupbyr¹   rÂ   Úfromkeys)r×   rÚ   Ú
keyed_rowsro   Úgrouprü   s    `   @rP   Ú3_transform_vertex_embeddings_batch_output_to_openair  ^  s…   ù€ ô ÑYÐFXÔYÓY€Jô !*× 1Ñ 1´&¸ÑIYÔ2ZÑ`sÔ t÷áˆI�uð 	”5˜“<Ñó€Lô ô 	ô Ÿ™Ñ&XÈZÔ&XÓXô	ó 	ð 	ùó	s   ¼BÚurlc                 óh   — t         j                  t        | «      «      }|r|j                  d«      S dS )ae  
    Extracts the model from a LiteLLM-managed Vertex batch GCS url.

    Batch inputs and their sibling outputs are stored under
    `.../publishers/google/models/<model>/...`, which is the only place the model of an
    embeddings batch output row can be recovered from; unlike `generateContent`
    responses, embedding rows carry no `modelVersion`.
    rš   N)r?   Úsearchr   r  )r  rÎ   s     rP   Ú_model_from_managed_gcs_urlr  z  s-   € ô ,×2Ñ2´7¸3³<Ó@€EÙ"ˆ5�;‰;�q‹>Ð,¨Ð,rO   Úopenai_entryc                 ó¼   — | j                  d«      }t        |t        «      sy|j                  d«      d   j	                  d«      }|dk(  xs |j                  d«      S )a"  
    Whether an OpenAI batch JSONL line targets the embeddings endpoint.

    OpenAI puts the target route on each line's `url` (e.g. `/v1/embeddings`); Vertex
    has no equivalent per-line field, so the route decides which Vertex request shape
    the line has to be translated into.
    r  Fú?r   ú/Ú
embeddingsz/embeddings)r¥   r¦   rY   Úsplitr„   Úendswith)r  r  Úpaths      rP   Ú_is_embeddings_batch_entryr  ‡  sW   € ð ×
Ñ
˜5Ó
!€CÜ�cœ3ÔØØ�9‰9�S‹>˜!Ñ×#Ñ# CÓ(€DØ�<ÑÒ? 4§=¡=°Ó#?Ð?rO   Úembedding_inputc                 ó>   — t        | t        «      rt        | «      S | fS )a  
    Split an OpenAI `input` into the elements that each get their own embedding.

    A string is one embedding, a flat array is one embedding per element, and a nested
    array is one combined embedding per inner array, matching the online
    `batchEmbedContents` path.
    )r¦   rê   ré   )r  s    rP   Ú _openai_embedding_input_elementsr  –  s"   € ô �/¤4Ô(Ü�_Ó%Ð%ØÐÐrO   r    rQ   c                 ó>   — t        | d¬«      }|dk  r|S |› d|› d|› �S )a�  
    The top-level `key` Vertex echoes back on an embeddings row.

    An entry asking for several embeddings needs several Vertex rows, so its key also
    carries the element index and the group size; `_split_vertex_batch_key` reads them
    back out. The `custom_id` is percent-encoded so that a customer one ending in
    `#<index>/<total>` cannot be mistaken for that tag, which would merge two entries.
    rŒ   )Úsafer5   ú#r  )r
   )ro   r    rQ   Úencoded_custom_ids       rP   Ú_vertex_batch_embeddings_keyr  ¥  s6   € ô ˜i¨bÔ1ÐØ %¨¢	ÐÐUÐ2CÐ1DÀAÀeÀWÈAÈeÈWÐ/UÐUrO   Úembed_content_requestc                 ó~   — d|d   it         D ��ci c]  \  }}||v r|||   “Œ c}}¥}| €d|iS t        | d|iS c c}}w )zö
    One Vertex Gemini Embedding batch input row.

    The config fields live inside the `EmbedContentRequest` under their snake_case batch
    names, and the OpenAI `custom_id` rides along in the top-level `key` that Vertex
    echoes back.
    rÁ   r`   )rE   r>   )r=   r  Úgemini_paramÚrequest_fieldr`   s        rP   Ú_vertex_embeddings_rowr  ²  sr   € ð 	Ð(¨Ñ3ðô 0T÷
á+�˜mØÐ4Ñ4ð Ð0°Ñ>Ñ>ó
ð€Gð €{Ø˜7Ð#Ð#Ü# S¨)°WÐ=Ð=ùó
s   �9c                 óR  ‡‡‡— | j                  d«      Št        ‰t        «      st        d«      ‚‰j                  d«      }|€t	        d«      ‚t        |«      }|st	        d«      ‚t        ˆfd„|D «       «      Š| j                  d«      Št        ˆˆfd„t        ‰«      D «       «      S )	aÝ  
    Transforms a single OpenAI `/v1/embeddings` batch entry into Vertex Gemini Embedding
    batch rows, one per requested embedding.

    Example Vertex jsonl
    {"key": "id_1", "request": {"content": {"parts": [{"text": "Hello World"}]}, "output_dimensionality": 768, "task_type": "RETRIEVAL_DOCUMENT"}}

    Note that `content` is singular (an `EmbedContentRequest`, not a
    `GenerateContentRequest`) and that the `custom_id` round-trips through the top-level
    `key`. An `EmbedContentRequest` returns exactly one vector, so an entry whose `input`
    is an array fans out into one row per element and is reassembled on the way back.
    The docs put the per-row config in an `embed_content_config` sibling of `request`,
    but the API rejects that key outright and fails the whole batch job, so the config
    fields go inside the `EmbedContentRequest` itself.

    API Ref: https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/batch-prediction-genai-embeddings
    rk   z_`body` on /v1/embeddings batch requests must be a JSON object, but was missing or not an objectÚinputzJ`input` is required on /v1/embeddings batch requests, but was not providedz:`input` on /v1/embeddings batch requests must not be emptyc              3   óZ   •K  — | ]"  }t        |‰j                  d d«      ‰¬«      –— Œ$ y­w)rÚ   rŒ   )r  rÚ   Úoptional_paramsN)r$   r¥   )r®   ÚelementÚopenai_request_bodys     €rP   r¯   zF_openai_batch_jsonl_entry_to_vertex_embeddings_rows.<locals>.<genexpr>è  s;   øè ø€ ò #ð ô 	4ØØ%×)Ñ)¨'°2Ó6Ø/÷	
ð 	
ñ#ùs   ƒ(+ro   c           
   3   ó‚   •K  — | ]6  \  }}t        ‰€d nt        t        ‰«      |t        ‰«      ¬«      |¬«      –— Œ8 y ­w)N)ro   r    rQ   )r=   r  )r  r  rY   r   )r®   r    r  ro   Úembed_content_requestss      €€rP   r¯   zF_openai_batch_jsonl_entry_to_vertex_embeddings_rows.<locals>.<genexpr>ñ  sU   øè ø€ ò ñ )ˆEÐ(ô 	àÐ ñ ä-Ü˜i›.ØÜÐ0Ó1ôð
 #8÷		
ð 		
ñùs   ƒ<?)r¥   r¦   rÂ   Ú	TypeErrorÚ
ValueErrorr  ré   r�   )r  r  Úelementsro   r%  r#  s      @@@rP   Ú3_openai_batch_jsonl_entry_to_vertex_embeddings_rowsr)  Ç  s¼   ú€ ð( '×*Ñ*¨6Ó2ÐÜÐ)¬4Ô0ÜØmó
ð 	
ð *×-Ñ-¨gÓ6€OØÐÜÐeÓfÐfä/°Ó@€HÙÜÐUÓVÐVä"ó #ð  ô#ó Ðð × Ñ  Ó-€IÜô ô -6Ð6LÓ,Môó ð rO   Úmap_openai_to_vertex_paramsc                 ó&  — t        | «      rt        | «      S | j                  d«      xs i }t        |j                  dg «      |j                  dd«       ||«      di d¬«      }| j                  d«      }|�d	|vri |d	<   t	        |d	   |«       d
|ifS )a  
    Transforms a single OpenAI JSONL batch entry into the Vertex rows it maps to.

    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"}}]}]}}
    rk   ÚmessagesrÚ   rŒ   Ú	vertex_aiN)r,  rÚ   r!  Úcustom_llm_providerÚlitellm_paramsÚcached_contentro   r\   r`   )r  r)  r¥   r!   r¢   )r  r*  r#  Úvertex_request_bodyro   s        rP   Ú(_openai_batch_jsonl_entry_to_vertex_rowsr2     sµ   € ô " ,Ô/ÜBÀ<ÓPÐPà!-×!1Ñ!1°&Ó!9Ò!?¸RÐÜ!8Ø$×(Ñ(¨°RÓ8Ø!×%Ñ% g¨rÓ2Ù3Ð4GÓHØ'ØØô"Ðð $×'Ñ'¨Ó4€IØÐØÐ.Ñ.Ø,.Ð Ñ)Ü+Ð,?ÀÑ,IÈ9ÔUàÐ+Ð,Ð.Ð.rO   Ú	raw_linesc              #   óš   K  — | D ]B  }t        |t        t        f«      r|j                  d«      n|}|j	                  «       }|sŒ?|–— ŒD y­w)zLDecode (when needed), strip, and drop blank lines from an iterable of lines.r|   N)r¦   ÚbytesÚ	bytearrayrƒ   Ústrip)r3  rº   Úlines      rP   Ú_iter_stripped_linesr9  !  sF   è ø€ àò ˆÜ&0°´u¼iÐ6HÔ&Iˆs�z‰z˜'Ô"ÈsˆØ�z‰z‹|ˆÚØ‹Jñ	ùs   ‚AAÁAÚopenai_file_contentc              #   ó@  K  — | }t        |t        «      r|d   }t        |t        t        f«      rrt	        d«      }dt        |«      }}||k  rT|j                  ||«      }|dk(  r||d |}}n
||| |dz   }}|j                  d«      j                  «       }|r|–— ||k  rŒTyt        |t        «      r't        t        j                  |«      «      E d{  –—†  yt        |t        «      r2t        t        |«      d«      5 }t        |«      E d{  –—†  ddd«       yt        |d«      r7t!        |d	d«      }	|	€t#        d
«      ‚	  |	d«       t        |«      E d{  –—†  yt#        d«      ‚7 Œ•7 Œ]# 1 sw Y   yxY w# t$        t"        f$ r}
t#        d«      |
‚d}
~
ww xY w7 ŒC­w)zø
    Yield non-empty JSONL lines one at a time without materializing the whole
    payload, so peak memory stays bounded regardless of payload size. Mirrors
    ``str.splitlines()`` + ``line.strip()`` for ``\n`` / ``\r\n`` delimited
    JSONL.
    rš   ú
r   éÿÿÿÿNr|   ÚrbÚreadÚseekzoBatch upload file handle must be seekable; got a non-seekable stream. Pass bytes, a path, or a seekable handle.zkBatch upload file handle must be seekable so it can be re-read for the GCS object name and the upload body.úUnsupported file content type)r¦   ré   r5  r6  Úordr   Úfindrƒ   r7  rY   r9  ÚioÚStringIOr-   ÚopenÚhasattrÚgetattrr'  ÚOSError)r:  rÁ   Únewliner›   ÚlengthÚidxÚchunkr8  Úhandler@  Úes              rP   Ú_iter_openai_jsonl_linesrP  *  s²  è ø€ ð  3€GÜ�'œ5Ô!Ø˜!‘*ˆä�'œE¤9Ð-Ô.ô ˜T›ˆØœ3˜w›<ˆvˆØ�fŠnØ—,‘,˜w¨Ó.ˆCØ�bŠyØ& u v˜°�u‘à& u¨SÐ1°3¸±7�u�Ø—<‘< Ó(×.Ñ.Ó0ˆDÙØ’
ð �f‹nð 	ä�'œ3ÔÜ'¬¯©°GÓ(<Ó=×=Ð=Øä�'œ8Ô$Ü”#�g“, Ó%ð 	4¨Ü+¨FÓ3×3Ð3÷	4àäˆw˜Ôô
 ˜g v¨tÓ4ˆØˆ<ÜðDóð ð	Ù�ŒGô (¨Ó0×0Ð0Øä
Ð4Ó
5Ð5ð; 	>øð
 4ø÷	4àûô œÐ$ò 	Üð?óð ðûð	úð
 	1úsr   ‚BFÂ!2FÃE)Ã*FÃ>E-ÄE+ÄE-Ä/FÅE9 Å
FÅFÅFÅ+E-Å-E6Å2FÅ9FÆFÆFÆFc              #   óZ   K  — t        | «      D ]  }t        j                  |«      –— Œ y ­wr­   )rP  ÚjsonÚloads)r:  r8  s     rP   Ú_iter_openai_jsonl_entriesrT  f  s,   è ø€ ô )Ð)<Ó=ò ˆÜ�j‰j˜ÓÓñùs   ‚)+r8  c                 ó0   — t        j                  | «      }|S r­   ©rR  rS  )r8  rÞ   s     rP   Ú_parse_vertex_batch_output_rowrW  m  s   € Ü"&§*¡*¨TÓ"2€CØ€JrO   c                   óh   — e Zd ZdZdedeeeef   geeef   f   ddfd„Z	de
e   fd„Zde
e   fd„Zy)	Ú _OpenAIToVertexBatchUploadStreama   Streams an OpenAI batch JSONL upload as Vertex-wrapped JSONL one row at a
    time, so the transformed payload is never held in full.

    The transform runs lazily as the HTTP client pulls each chunk, which keeps
    peak memory at one row regardless of how large the batch file is.
    r:  r*  rs   Nc                 ó    — || _         || _        y r­   )Ú_openai_file_contentÚ_map_openai_to_vertex_params)Úselfr:  r*  s      rP   Ú__init__z)_OpenAIToVertexBatchUploadStream.__init__z  s   € ð
 %8ˆÔ!Ø,GˆÕ)rO   c              #   óÜ   K  — d}t        | j                  «      D ]N  }t        || j                  «      D ]3  }|rdnd}d}|t	        j
                  |«      j                  d«      z   –— Œ5 ŒP y ­w)NTrO   ó   
Fr|   )rT  r[  r2  r\  rR  Údumpsr‚   )r]  ÚfirstÚentryÚwrappedÚprefixs        rP   Ú_iter_vertex_jsonl_chunksz:_OpenAIToVertexBatchUploadStream._iter_vertex_jsonl_chunks‚  sr   è ø€ ØˆÜ/°×0IÑ0IÓJò 	CˆEÜCÀEÈ4×KlÑKlÓmò C�Ù %™¨5�Ø�ØœtŸz™z¨'Ó2×9Ñ9¸'ÓBÑBÓBñCñ	Cùs   ‚A*A,c                 ó"   — | j                  «       S r­   )rf  ©r]  s    rP   Ú
iter_bytesz+_OpenAIToVertexBatchUploadStream.iter_bytesŠ  s   € Ø×-Ñ-Ó/Ð/rO   )rJ   rK   rL   Ú__doc__r(   r   rÂ   rY   r   r^  r   r5  rf  ri  rN   rO   rP   rY  rY  r  sk   „ ñðHà&ðHð &.¨t°C¸°H©~Ð.>ÀÀSÈ#ÀXÁÐ.NÑ%OðHð 
ó	HðC¨8°E©?ó Cð0˜H U™Oô 0rO   rY  c                   ó  ‡ — e Zd ZdZˆ fd„Zedefd„«       Z	 	 d4dede	de
e   d	ed
ede	dz  de	dz  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de	fd„Zde	dz  de	dz  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	ded	ed
edee	z  ez  f
d„Zde	dz  deded
edef
d „Zd!e	d"edee z  de!fd#„Z"d5d$e	d
edz  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	dz  d	ed
ede#e	ef   fd*„Z*deded
ede
e   fd+„Z+d	ed
ede#e	ef   fd,„Z,deded
ede-fd-„Z.	 	 d4d.ededz  de	dz  defd/„Z/d0e0d1e1de2d2e3j6                  de4f
d3„Z5ˆ xZ6S )6ÚVertexAIFilesConfigz#
    Config for VertexAI Files
    c                 ó"   •— t         ‰| �  «        y r­   )Úsuperr^  )r]  Ú	__class__s    €rP   r^  zVertexAIFilesConfig.__init__“  s   ø€ Ü‰ÑÕrO   rs   c                 ó"   — t         j                  S r­   )r2   Ú	VERTEX_AIrh  s    rP   r.  z'VertexAIFilesConfig.custom_llm_provider–  s   € ä×%Ñ%Ð%rO   NÚheadersrÚ   r,  r!  r/  Ú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_tokenr¥   r'  )	r]  rr  rÚ   r,  r!  r/  rs  rt  ru   s	            rP   Úvalidate_environmentz(VertexAIFilesConfig.validate_environmentš  se   € ñ Ø×.Ñ.Ø*×.Ñ.Ð/CÓDØ)×-Ñ-Ð.>Ó?ð /ó ‰JˆG�Qñ Ü Ð!6Ó7Ð7Ø)0°°	Ð':ˆG�OÑ$ØˆrO   Úopenai_jsonl_contentc                 óº   — |d   j                  di «      j                  dd«      }d|vrd|› �}t        |d¬«      }t        › |› dt        j                  «       › �}|S )	z†
        Gets a unique GCS object name for the VertexAI batch prediction job

        named as: litellm-vertex-{model}-{uuid}
        r   rk   rÚ   rŒ   zpublishers/google/modelszpublishers/google/models/)Úfallbackr  )r¥   r   r   r   rÊ   )r]  r}  Ú_modelÚsafe_model_pathÚobject_names        rP   Ú%_get_gcs_object_name_from_batch_jsonlz9VertexAIFilesConfig._get_gcs_object_name_from_batch_jsonl®  sn   € ð & aÑ(×,Ñ,¨V°RÓ8×<Ñ<¸WÀbÓIˆØ%¨VÑ3Ø0°°Ð9ˆFÜ!;¸FÈWÔ!UˆÜ <Ð=¸oÐ=NÈaÔPT×PZÑPZÓP\È~Ð^ˆØÐrO   Ú	file_datarI   c                 ó¤   — |dk(  r)t        t        |«      d«      }|�| j                  |g«      S t        |«      \  }}t	        t
        › d�|d¬«      S )zÐ
        Get the object name for the request.

        Reads only the first JSONL entry (streamed) for batch files, so a large
        upload is never materialized just to derive the GCS object name.
        ÚbatchNzuploads/Úfile)re  ÚfilenameÚfallback_filename)rè   rT  rƒ  r   r   r   )r]  r„  rI   Úfirst_entryrˆ  ru   s         rP   Úget_object_namez#VertexAIFilesConfig.get_object_name¾  se   € ð �gÒä!%Ô&@ÀÓ&KÈTÓ!RˆKØÐ&Ø×AÑAÀ;À-ÓPÐPô ,¨IÓ6‰ˆ�!Ü.Ü2Ð3°8Ð<ØØ$ô
ð 	
rO   c                 ó–   — |j                  d«      xs( |j                  d«      xs t        j                  d«      }|st        d«      ‚|S )NÚgcs_bucket_nameÚbucket_nameÚGCS_BUCKET_NAMEzGCS bucket_name is required)r¥   ÚosÚgetenvr'  )r]  r/  rŽ  s      rP   Ú_get_configured_bucket_namez/VertexAIFilesConfig._get_configured_bucket_nameÓ  sO   € à×ÑÐ0Ó1Òv°^×5GÑ5GÈÓ5VÒvÔZ\×ZcÑZcÐduÓZvð 	ñ ÜÐ:Ó;Ð;ØÐrO   rå   c                 óH  — | j                  |«      }t        |«      \  }}|j                  d«      }	|j                  d«      }
|	€t        d«      ‚|
€t        d«      ‚| j	                  |	|
«      }|r|› d|› �}t        |«      }d|› d|› �}|xs d}|st        d	«      ‚|› d|› �S )
z6
        Get the complete url for the request
        r‡  rI   úfile is requiredzpurpose is requiredr  zupload/storage/v1/b/z/o?uploadType=media&name=zhttps://storage.googleapis.comzapi_base is required)r’  r   r¥   r'  r‹  r   )r]  rt  rs  rÚ   r!  r/  rå   rŽ  Úobject_prefixr„  rI   r‚  Úencoded_object_nameÚendpoints                 rP   Úget_complete_file_urlz)VertexAIFilesConfig.get_complete_file_urlÛ  sÒ   € ð ×6Ñ6°~ÓFˆÜ%GÈÓ%TÑ"ˆ�]ØŸ8™8 FÓ+ˆ	ØŸ™ )Ó,ˆØÐÜÐ/Ó0Ð0Øˆ?ÜÐ2Ó3Ð3Ø×*Ñ*¨9°gÓ>ˆÙØ*˜O¨1¨[¨MÐ:ˆKÜ%CÀKÓ%PÐØ0°°Ð=VÐWjÐVkÐlˆØÒ?Ð?ˆÙÜÐ3Ó4Ð4à�˜1˜X˜JÐ'Ð'rO   c                 ó   — g S r­   rN   )r]  rÚ   s     rP   Úget_supported_openai_paramsz/VertexAIFilesConfig.get_supported_openai_paramsú  s   € Øˆ	rO   Únon_default_paramsÚdrop_paramsc                 ó   — |S r­   rN   )r]  r›  r!  rÚ   rœ  s        rP   Úmap_openai_paramsz%VertexAIFilesConfig.map_openai_paramsý  s
   € ð ÐrO   r#  c                 ón   — ddl m}  |«       }|j                  dd«      }|j                  ||i d¬«      }|S )zF
        wrapper to call VertexGeminiConfig.map_openai_params
        r   r"   rÚ   rŒ   F)rÚ   r›  r!  rœ  )Ú@litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_geminir#   r¥   rž  )r]  r#  r#   Úconfigr€  Úvertex_paramss         rP   r\  z0VertexAIFilesConfig._map_openai_to_vertex_params  sL   € õ	
ñ +Ó,ˆØ+×/Ñ/°¸Ó<ˆØ%×7Ñ7ØØ2ØØð	  8ó  
ˆð ÐrO   Úcreate_file_datac                 ó<  — |j                  d«      }|€t        d«      ‚t        |«      \  }}t        j                  ||¬«      r#dt        t        || j                  «      d¬«      iS t        |«      j                  d«      }t        |t        «      r|S t        d«      ‚)	a  
        2 Cases:
        1. Handle basic file upload
        2. Handle batch file upload (.jsonl), staged to a temp file and uploaded
           in a single media request so large uploads stay memory-bounded without
           the per-chunk round-trips of a resumable session.
        r‡  r”  )r£  Úcontent_typeÚstreaming_media_uploadúapplication/json)Úbody_streamr¥  rÁ   rA  )r¥   r'  r   r   Úis_batch_jsonl_requestr%   rY  r\  r   r¦   r5  )	r]  rÚ   r£  r!  r/  r„  ru   r¥  Úextracted_file_data_contents	            rP   Útransform_create_file_requestz1VertexAIFilesConfig.transform_create_file_request  s­   € ð ,×/Ñ/°Ó7ˆ	ØÐÜÐ/Ó0Ð0ä/°	Ó:‰ˆˆ<Ü×/Ñ/Ø-Ø%õ
ð
 )Ô*DÜ @Ø!Ø×9Ñ9ó!ð "4ô+ðð ô .?¸yÓ-I×-MÑ-MÈiÓ-XÐ#ÜÐ1´5Ô9Ø.Ð.ÜÐ8Ó9Ð9rO   Ú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: ©ri   rf   rr  NrT   rŒ   r  r=  rI   r†  úgs://rU   rW   ©Úvertex_datetimeÚuploadedrV   r   r‡  )rI   rT   rˆ  Ú
created_atra   r5  r]   rN   )rR  r.   r“   r7   ri   rr  r¥   r�   r  r+   r    rl   )	r]  rÚ   r¬  r­  r/  Úresponse_jsonÚresponse_objectrO  Úgcs_ids	            rP   Útransform_create_file_responsez2VertexAIFilesConfig.transform_create_file_responseA  s  € ð 3?×2CÑ2CÓ2Eˆð	Ü%6Ñ%G¸Ñ%GˆOð !×$Ñ$ T¨2Ó.ˆá5;�—‘˜&Ÿ,™, sÓ+¨C¨RÐ0Ô1ÀˆäØ#×'Ñ'¨	°7Ó;Ø�v�hÐØ$×(Ñ(¨°Ó4ÜBØ /× 3Ñ 3°MÀ2Ó Fôð Ü�o×)Ñ)¨&°!Ó4Ó5Øô

ð 
	
øô ò 	ÜØ(×4Ñ4Ø=¸a¸SÐAØ$×,Ñ,ôð ûð	ús   ’B> Â>	C1Ã%C,Ã,C1rÆ   ri   c                 ó   — t        |||¬«      S )Nr¯  r6   )r]  rÆ   ri   rr  s       rP   Úget_error_classz#VertexAIFilesConfig.get_error_classf  s   € Ü¨¸mÐU\Ô]Ð]rO   Úfile_idc           	      óˆ   — | j                  |xs i «      }t        |d|t        ft        |«      ¬«      \  }}|t	        |«      fS )z^
        Validate a managed GCS file_id and return (bucket, url-encoded-object-path).
        r°  )r»  ÚschemeÚconfigured_bucket_nameÚallowed_object_prefixesÚallow_legacy_cloud_file_ids)r’  r   r   r   r   )r]  r»  r/  r¾  rŽ  Úobject_paths         rP   Ú_parse_gcs_uriz"VertexAIFilesConfig._parse_gcs_urii  sT   € ð )-×(HÑ(HÈÒI]Ð[]Ó(^ÐÜ#AØØØ#9Ü%AÐ$CÜ(JÈ>Ó(Zô$
Ñ ˆ�[ð Ô:¸;ÓGÐGÐGrO   c                 óD   — | j                  ||«      \  }}d|› d|› �}|i fS ©Nú,https://storage.googleapis.com/storage/v1/b/ú/o/©rÂ  ©r]  r»  r!  r/  ÚbucketÚencoded_objectr  s          rP   Útransform_retrieve_file_requestz3VertexAIFilesConfig.transform_retrieve_file_requestw  ó7   € ð "&×!4Ñ!4°W¸nÓ!MÑˆ�ØCÀFÀ8È3È~ÐN^Ð_ˆØ�BˆwˆrO   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 )NrT   rŒ   r  r=  r°  rV   r   rW   r±  rU   r‡  rX   rI   r†  Ú	processed)rT   r5  r´  rˆ  r]   rI   ra   Ústatus_details)rR  r¥   r�   r  r+   rl   r    )r]  r¬  r­  r/  rµ  r·  s         rP   Ú transform_retrieve_file_responsez4VertexAIFilesConfig.transform_retrieve_file_response�  sÂ   € ð 0<×/@Ñ/@Ó/BˆØ×"Ñ" 4¨Ó,ˆÙ5;�—‘˜&Ÿ,™, sÓ+¨C¨RÐ0Ô1ÀˆÜØ�v�hÐÜ�m×'Ñ'¨°Ó2Ó3ÜBØ -× 1Ñ 1°-ÀÓ Dôð #×&Ñ& v¨rÓ2ØØ!×%Ñ% j°"Ó5×9Ñ9¸)ÀWÓMØØô
ð 	
rO   c                 óD   — | j                  ||«      \  }}d|› d|› �}|i fS rÄ  rÇ  rÈ  s          rP   Útransform_delete_file_requestz1VertexAIFilesConfig.transform_delete_file_request—  rÌ  rO   c                 ó‚  — d}t        |d«      r¤|j                  r˜t        |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°  r  Tr‡  )rT   rÔ  r]   )	rG  r`   rY   r  Úurllib.parser  Úparser   r   )	r]  r¬  r­  r/  r»  r  ÚurllibÚbucket_partÚencoded_names	            rP   Útransform_delete_file_responsez2VertexAIFilesConfig.transform_delete_file_response¡  s¸   € ð ˆÜ�< Ô+°×0DÒ0DÜ˜\×1Ñ1×5Ñ5Ó6ˆCØ˜‰| ¨¡Û#à%(§Y¡Y¨uÓ%5°bÑ%9×%?Ñ%?ÀÓ%FÀqÑ%I�Ø&)§i¡i°Ó&6°rÑ&:×&@Ñ&@ÀÓ&EÀaÑ&H�Ø! + ¨a°·±×0DÑ0DÀ\Ó0RÐ/SÐT�Ü˜g¨t¸FÔCÐCrO   c                 ó   — t        d«      ‚©Nz1VertexAIFilesConfig does not support file listing©ÚNotImplementedError)r]  rI   r!  r/  s       rP   Útransform_list_files_requestz0VertexAIFilesConfig.transform_list_files_request²  ó   € ô "Ð"UÓVÐVrO   c                 ó   — t        d«      ‚rÜ  rÝ  )r]  r¬  r­  r/  s       rP   Útransform_list_files_responsez1VertexAIFilesConfig.transform_list_files_responseº  rà  rO   c                 ój   — |j                  dd«      }| j                  ||«      \  }}d|› d|› d�}|i fS )Nr»  rŒ   rÅ  rÆ  z
?alt=media)r¥   rÂ  )r]  Úfile_content_requestr!  r/  r»  rÉ  rÊ  r  s           rP   Útransform_file_content_requestz2VertexAIFilesConfig.transform_file_content_requestÂ  sL   € ð .×1Ñ1°)¸RÓ@ˆØ!%×!4Ñ!4°W¸nÓ!MÑˆ�ØCÀFÀ8È3È~ÐN^Ð^hÐiˆØ�BˆwˆrO   c           	      óØ  — 	 t        t        dd«      rt        |¬«      S |j                  }|r¤| j	                  ||t        t        |j                  j                  «      «      ¬«      }||k7  ret        |j                  «      }t        t        |«      «      |d<   t        j                  |j                  |||j                  ¬«      }t        |¬«      S t        |¬«      S # t        $ r Y Œw xY w)a¸  
        Transform file content response, converting Vertex AI batch output to OpenAI format if applicable.

        This method automatically detects and transforms Vertex AI batch prediction outputs
        (predictions.jsonl files) into OpenAI-compatible batch response format.

        If the file is not a batch output or transformation fails, the original content
        is returned as-is to maintain backward compatibility.
        Ú*disable_vertex_batch_output_transformationF)rp   )rÁ   r­  rÚ   zcontent-length)ri   rÁ   rr  r`   )rH  Úlitellmr)   rÁ   Ú,_try_transform_vertex_batch_output_to_openair  rY   r`   r  rÂ   rr  r   Úhttpxr   ri   r“   )r]  r¬  r­  r/  rÁ   Útransformed_contentÚnew_headersÚmock_responses           rP   Útransform_file_content_responsez3VertexAIFilesConfig.transform_file_content_responseÍ  sí   € ð	ô ”wÐ LÈeÔTÜ1¸<ÔHÐHð *×1Ñ1ˆGÙØ-1×-^Ñ-^Ø#Ø +Ü5´c¸,×:NÑ:N×:RÑ:RÓ6SÓTð ._ó .Ð#ð
 '¨'Ò1ô *.¨l×.BÑ.BÓ)C�KÜ47¼Ð<OÓ8PÓ4Q�KÐ 0Ñ1ä+0¯>©>Ø$0×$<Ñ$<Ø 3Ø +Ø ,× 4Ñ 4ô	,�Mô 6¸}ÔMÐMô
 *°<Ô@Ð@øô	 ò 	áð	ús   ‚C ŸB1C Ã	C)Ã(C)rÁ   c           	      óº  — 	 t        |«      }	 t        |«      }t        |«      }t	        |«      xsX d|v xrR d|v xrL d|v xrF d|j                  di «      v xs0 d|j                  di «      v xs t        |j                  d«      «      }|s|S t        «       }t        dg dd	t        j                  «       dd¬
«      }	i |	_
        t        j                  dddit        j                  dd¬«      ¬«      }
t        j                  |f|«      }t	        |«      r,t!        d„ |D «       |¬«      }dj#                  d„ |D «       «      S t%        «       }|D ]O  }	 | j'                  t        |«      ||	|
¬«      }|r|dz  }|t+        j,                  |«      j/                  d«      z  }ŒQ t1        |«      S # t        $ r |cY S w xY w# t(        $ r |cY c S w xY w# t(        $ r |cY S w xY w)aJ  
        Try to transform Vertex AI batch output to OpenAI format.
        If conversion fails at any point, return the original content as-is.

        Vertex AI batch output format (predictions.jsonl):
        {
          "request": {"contents": [...], "labels": {"litellm_custom_id": "request-1", "litellm_custom_id_raw": "..."}},
          "status": "",
          "response": {"candidates": [...], "modelVersion": "gemini-2.5-flash", ...},
          "processed_time": "2026-04-13T10:18:18.102004+00:00"
        }

        OpenAI batch output format:
        {
          "id": "batch_req_...",
          "custom_id": "request-1",
          "response": {
            "status_code": 200,
            "request_id": "chatcmpl-...",
            "body": {<OpenAI chat completion response>}
          },
          "error": null
        }
        r`   rp   rb   Ú
candidatesÚpromptFeedbackra   rŒ   FÚbatch_transform)rÚ   r,  ÚstreamÚ	call_typeÚ
start_timeÚlitellm_call_idÚfunction_idrÉ   zcontent-typer§  ÚPOSTzhttps://example.com)Úmethodr  )ri   rr  r`   c              3   óF   K  — | ]  }t        j                  |«      –— Œ y ­wr­   rV  )r®   r8  s     rP   r¯   zSVertexAIFilesConfig._try_transform_vertex_batch_output_to_openai.<locals>.<genexpr>S  s   è ø€ Ò'O¸T¬¯
©
°4×(8Ñ'Oùs   ‚!)r×   rÚ   r`  c              3   ód   K  — | ](  }t        j                  |«      j                  d «      –— Œ* y­w)r|   N)rR  ra  r‚   )r®   Úopenai_outputs     rP   r¯   zSVertexAIFilesConfig._try_transform_vertex_batch_output_to_openai.<locals>.<genexpr>V  s%   è ø€ Ò!pÐP]¤$§*¡*¨]Ó";×"BÑ"BÀ7×"KÑ!pùs   ‚.0)Úvertex_outputÚvertex_gemini_configr­  Úmock_httpx_responser|   )rP  rè   ÚStopIterationrW  rÄ   r¥   rÃ   r#   r   Útimer!  rê  r   ÚRequestrþ   Úchainr  r�   r6  Ú/_transform_single_vertex_batch_output_to_openair“   rR  ra  r‚   r5  )r]  rÁ   r­  rÚ   ÚlinesÚ
first_lineÚ	first_rowÚis_vertex_batch_outputrþ  Úbatch_transform_logging_objrÿ  Ú	all_linesÚopenai_outputsÚoutputr8  rü  s                   rP   ré  z@VertexAIFilesConfig._try_transform_vertex_batch_output_to_openaiý  s&  € ð<S	ô
 4°GÓ<ˆEðÜ$(¨£K�
ô  >¸jÓIˆIÜ,RÐS\Ó,]ò 	-Ø˜YÐ&ò Ø )Ð+òà$¨	Ð1òð ! I§M¡M°*¸bÓ$AÐAò 5Ø'¨9¯=©=¸ÀRÓ+HÐHò5ä˜IŸM™M¨(Ó3Ó4ð #ñ *Ø�ä*<Ó*>Ð ô 29ØØØØ+ÜŸ9™9›;Ø "Øô2Ð'ð ;=Ð'Ô7Ü).¯©ØØ'Ð);Ð<ÜŸ™¨VÐ9NÔOô*Ðô "Ÿ™¨¨°uÓ=ˆIô
 6°iÔ@Ü!TÙ'OÀYÔ'OØô"�ð —z‘zÑ!pÐaoÔ!pÓpÐpô
 “[ˆFØ!ò D�ð#Ø$(×$XÑ$XÜ&DÀTÓ&JØ-AØ$?Ø,?ð	 %Yó %�Mñ Ø˜e‘O�FØœ$Ÿ*™* ]Ó3×:Ñ:¸7ÓCÑC‘ðDô ˜“=Ð øôO !ò Ø’ðûôB !ò #Ø"”Nð#ûô ò 	àŠNð	úse   ‚G ŽF( ™A3G ÂB1G Ä?G ÅF9Å-:G Æ(F6Æ3G Æ5F6Æ6G Æ9G	ÇG ÇG	Ç	G ÇGÇGrý  rþ  rÿ  c                 ó´  — t        |«      }|j                  dd«      }t        |«      }|rt        |d|¬«      S |j                  di «      }|j                  dd«      }	d|	v r|	j	                  d«      d	   }		 t        «       }
|j                  ||
|	||¬
«      }|j                  «       }t        ||¬«      S # t        $ r}t        |dd|› �¬«      cY d}~S d}~ww xY w)z 
        Transform a single Vertex AI batch output line to OpenAI format.
        Uses the existing VertexGeminiConfig transformation for the response.
        ra   rŒ   rß   rà   rp   ÚmodelVersionzgemini-1.5-flash-001ú@r   )Úcompletion_responseÚmodel_responserÚ   r­  r¬  rç   Útransformation_errorzFailed to transform response: N)	r©   r¥   rÃ   rË   r  r3   Ú;_transform_google_generate_content_to_openai_model_responserì   r“   )r]  rý  rþ  r­  rÿ  ro   ra   Ú	has_errorrÐ   rÚ   r  Útransformed_responseÚresponse_dictrO  s                 rP   r  zCVertexAIFilesConfig._transform_single_vertex_batch_output_to_openaip  s  € ô 8¸ÓFˆ	ð &×)Ñ)¨(°BÓ7ˆÜ ›<ˆ	áÜ+Ø#Ø,Ø$ôð ð "/×!2Ñ!2°:¸rÓ!Bˆð  ×#Ñ# NÐ4JÓKˆØ�%‰<Ø—K‘K Ó$ QÑ'ˆEð	ä$1£OˆNà#7×#sÑ#sØ$3Ø-ØØ'Ø0ð $tó $Ð ð $8×#BÑ#BÓ#DˆMô ,°iÀmÔTÐTøäò 	Ü+Ø#Ø1Ø >¸q¸cÐBôõ ûð	ús   Á6<B3 Â3	CÂ<CÃCÃC)NNr­   )7rJ   rK   rL   rj  r^  Úpropertyr2   r.  rÂ   rY   rê   r&   r|  r   rƒ  r(   r‹  r’  r'   r˜  r*   rš  rÃ   rž  r\  r5  r«  r   r   r+   r¸  rl   r   r   rº  ré   rÂ  rË  rÐ  rÒ  r   rÚ  rß  râ  rå  r)   rî  ré  r_   r#   r   rê  rn   r  Ú__classcell__)ro  s   @rP   rl  rl  Ž  sŠ  ø„ ñôð ð& \ò &ó ð&ð #Ø#ñàðð ðð Ð'Ñ(ð	ð
 ðð ðð �t‘ðð ˜‘*ðð 
óð(à" 4¨¨S¨¡>Ñ2ðð 
óð 
¨ð 
¸Sð 
ÀSó 
ð*¸$ð À3ó ð(à˜‘*ð(ð �t‘ð(ð ð	(ð
 ð(ð ð(ð  ð(ð 
ó(ð>°ð ¸Ð>cÑ9dó ðà ðð ðð ð	ð
 ðð 
óðà! # s (™^ðð 
ˆc�3ˆh‰óð*$:àð$:ð ,ð$:ð ð	$:ð
 ð$:ð 
�‰�tÑ	ó$:ðL#
à�T‰zð#
ð ð#
ð 'ð	#
ð
 ð#
ð 
ó#
ðJ^¨Sð ^¸sð ^ÈTÐT[É^ð ^Ð`pó ^ñH cð H¸4À$¹;ð HÐRWÐX[Ð]`ÐX`ÑRaó Hðàðð ðð ð	ð
 
ˆs�DˆyÑ	óð
àð
ð 'ð
ð ð	
ð
 
ó
ð,àðð ðð ð	ð
 
ˆs�DˆyÑ	óðDàðDð 'ðDð ð	Dð
 
óDð"Wà�t‘ðWð ðWð ð	Wð
 
ˆs�DˆyÑ	óWðWàðWð 'ðWð ð	Wð
 
ÐÑ	óWð	ð ð	ð ð		ð
 
ˆs�DˆyÑ	ó	ð.Aàð.Að 'ð.Að ð	.Að
 
$ó.Aðf 15Ø ñ	qàðqð '¨Ñ-ðqð �T‰zð	qð
 
óqðf7à&ð7ð 1ð7ð ð	7ð
 #Ÿ^™^ð7ð 
÷7rO   rl  )NNrŒ   )‚r€   rD  rþ   rR  r�  rv   r  Úcollections.abcr   r   r   r   Útypingr   r   r	   rÕ  r
   r   rê  r   r   Úopenai.types.file_deletedr   Útyping_extensionsr   rè  Úlitellm._uuidr   Úlitellm.files.utilsr   Ú1litellm.litellm_core_utils.cloud_storage_securityr   r   r   r   r   r   r   Ú*litellm.litellm_core_utils.litellm_loggingr   Ú8litellm.litellm_core_utils.prompt_templates.common_utilsr   r   Ú)litellm.llms.base_llm.chat.transformationr   Ú*litellm.llms.base_llm.files.transformationr   r   r   Ú#litellm.llms.vertex_ai.common_utilsr    Ú,litellm.llms.vertex_ai.gemini.transformationr!   r   r#   ÚKlitellm.llms.vertex_ai.gemini_embeddings.batch_embed_content_transformationr$   Úlitellm.types.filesr%   Úlitellm.types.llms.openair&   r'   r(   r)   r*   r+   r,   r-   Úlitellm.types.llms.vertex_air.   r/   Úlitellm.types.utilsr0   r1   r2   r3   r4   Úcommon_utilsr7   Úvertex_llm_baser8   r:   rM   r<   r>   Úcompiler?   rE   rF   rH   rS   r[   r_   rd   rh   rn   rY   rz   rê   r‰   r–   rÂ   r]   r¢   r©   r§   rÃ   rÄ   rË   ré   rl   rÏ   rÖ   rï   r  r  r  r  r  r  r)  r2  r5  r9  rP  rT  rW  rY  rl  rN   rO   rP   ú<module>r.     s2  ðÜ Û 	Û Û Û 	Û 	Û ß AÓ Aß (Ñ (ß 'ã ß #Ý 1Ý &ã Ý Ý -÷÷ ñ õ ?÷õ G÷ñ õ
õ Qõõõ ;÷	÷ 	ó 	÷ Q÷õ õ )Ý (à"$Ð ˜%Ó $Ø%+Ð ˜UÓ +Ø!&Ð ˜Ó &Ø)3¨¯©Ð4WÓ)XÐ  Ó Xð/Ð $ eó ð
 /9¨b¯j©jÐ9nÓ.oÐ $ eÓ oô*˜Y¨eõ *ô/�Y eõ /ô+˜Y¨eõ +ô"�i uõ "ô˜iô ô
) ô )ô4˜Iô 4ð0 Sð 0¨Só 0ð&'¨#ð '°$°s±)ó 'ð¨4°©9ð ¸¸t¹ó ðC°°S¸#°X±ð CÈ6ð CÐVZó Cð <°G¸CÀ¸KÑ4Hð <ÈSó <ð ;°W¸SÀ&¸[Ñ5IÈDÑ5Pð ;ÐUXó ;ð(r¸gÀcÈ3ÀhÑ>Oð rÐTXó rð& &*Ø!Øñ	Øðà
�#�s�(Ñ
˜dÑ
"ðð �d‘
ðð ð	ð
 óð0Q¨w°s¸C°xÑ/@ð QÀUÈ3ÐPSÐUXÈ=ÑEYó Qð&
7°7¸3À¸8Ñ3Dð 
7Èó 
7ð5DØð5Dà˜g c¨3 hÑ/°Ð4Ñ5ð5Dð ˜3 ˜8‘_ð5Dð ð	5Dð
 �‰:ð5Dð ó5DðpØ  ¨¨c¨Ñ!2Ñ3ðà�‰:ðð Ð  #Ð%Ñ&óð8
- Sð 
-¨S°4©Zó 
-ð@¨W°S¸#°XÑ->ð @À4ó @ðØ)ðà
ˆ3��c‘‰?˜CÐÑ óð
V¨Cð 
V¸ð 
VÀCð 
VÈCó 
Vð>  d¡
ð >À7È3ÐPSÈ8ÑCTð >ÐY`ÐadÐfiÐaiÑYjó >ð*6Ø˜#˜s˜(Ñ#ð6à
ˆ7�3˜�8Ñ˜cÐ!Ñ"ó6ðr/Ø�s˜C�x‘.ð/à!)¨4°°S°©>Ð*:¸DÀÀcÀ¹NÐ*JÑ!Kð/ð ˆ7�3˜�8Ñ˜cÐ!Ñ"ó/ðB H¨S°5©[Ñ$9ð ¸hÀs¹mó ð96°)ð 96ÀÈÁó 96ðxØ"ðàˆd�3˜�8‰nÑóð¨ð °ó ô
0Ð';ô 0ô8Y˜* oõ YrO   